Resources

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:

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(),
    },
  },
})
FieldTypeDescription
metadata.mimeTypestringHint to clients about the content type. Auto-detected when you use file: '…'; set explicitly for custom URIs.
metadata.annotations.audience('user' | 'assistant')[]Who should see this resource — the user, the AI, or both.
metadata.annotations.prioritynumber (0–1)Suggested importance when clients have to choose which resources to include.
metadata.annotations.lastModifiedstring (ISO 8601)When the resource last changed — clients may use this for caching.

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:

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

Error Handling

Handle errors gracefully in your handlers:

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,
      }
    }
  },
})
Copyright © 2026