---
title: "Metadata, content & errors"
description: "Resource metadata, MIME types, binary payloads, and error responses."
canonical_url: "https://mcp-toolkit.nuxt.dev/resources/content-metadata-errors"
---
# Metadata, content & errors

> Resource metadata, MIME types, binary payloads, and error responses.

## Resource Metadata

Add a `metadata` block to help clients render the resource correctly. It carries the MIME type, behavior annotations, and any extra fields you want to surface in `resources/list`:

```typescript [server/mcp/resources/readme.ts]
import { defineMcpResource } from '@nuxtjs/mcp-toolkit/server'

export default defineMcpResource({
  name: 'readme',
  description: 'Project README file',
  file: 'README.md',
  metadata: {
    mimeType: 'text/markdown',
    annotations: {
      audience: ['user', 'assistant'],
      priority: 0.8,
      lastModified: new Date().toISOString(),
    },
  },
})
```

<table>
<thead>
  <tr>
    <th>
      Field
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        metadata.mimeType
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Hint to clients about the content type. Auto-detected when you use <code>
        file: '…'
      </code>
      
      ; set explicitly for custom URIs.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        metadata.annotations.audience
      </code>
    </td>
    
    <td>
      <code>
        ('user' | 'assistant')[]
      </code>
    </td>
    
    <td>
      Who should see this resource — the user, the AI, or both.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        metadata.annotations.priority
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
      
       (0–1)
    </td>
    
    <td>
      Suggested importance when clients have to choose which resources to include.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        metadata.annotations.lastModified
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
      
       (ISO 8601)
    </td>
    
    <td>
      When the resource last changed — clients may use this for caching.
    </td>
  </tr>
</tbody>
</table>

Anything else you put inside `metadata` is forwarded verbatim under `_meta` in the listing response, so you can carry custom fields for your own UI.

## Content Types

Resources can return different MIME types:

<code-group>

```typescript [Text/Markdown]
return {
  contents: [{
    uri: uri.toString(),
    mimeType: 'text/markdown',
    text: '# Markdown content',
  }],
}
```

```typescript [JSON]
return {
  contents: [{
    uri: uri.toString(),
    mimeType: 'application/json',
    text: JSON.stringify({ key: 'value' }),
  }],
}
```

```typescript [Binary Data]
return {
  contents: [{
    uri: uri.toString(),
    mimeType: 'image/png',
    blob: Buffer.from(binaryData),
  }],
}
```

</code-group>

## Error Handling

Handle errors gracefully in your handlers:

```typescript [server/mcp/resources/custom-readme.ts]
import { readFile } from 'node:fs/promises'
import { fileURLToPath } from 'node:url'
import { defineMcpResource } from '@nuxtjs/mcp-toolkit/server'

export default defineMcpResource({
  name: 'readme',
  uri: 'file:///README.md',
  handler: async (uri: URL) => {
    try {
      const filePath = fileURLToPath(uri)
      const content = await readFile(filePath, 'utf-8')

      return {
        contents: [{
          uri: uri.toString(),
          mimeType: 'text/markdown',
          text: content,
        }],
      }
    }
    catch (error) {
      return {
        contents: [{
          uri: uri.toString(),
          mimeType: 'text/plain',
          text: `Error: ${error instanceof Error ? error.message : String(error)}`,
        }],
        isError: true,
      }
    }
  },
})
```


## Sitemap

See the full [sitemap](https://mcp-toolkit.nuxt.dev/sitemap.md) for all pages.
