Schema, handler & returns
Input Schema
The inputSchema is optional and uses Zod to define and validate input parameters. When provided, each field must be a Zod schema. Tools without parameters can omit inputSchema entirely:
import { defineMcpTool } from '@nuxtjs/mcp-toolkit/server'
export default defineMcpTool({
name: 'echo',
description: 'Echo back a message',
handler: async () => 'Echo: test',
})
For tools with parameters, define them using Zod schemas:
import { z } from 'zod'
import { defineMcpTool } from '@nuxtjs/mcp-toolkit/server'
export default defineMcpTool({
name: 'calculator',
inputSchema: {
// String input
operation: z.string().describe('Operation to perform'),
// Number input
a: z.number().describe('First number'),
b: z.number().describe('Second number'),
// Optional field
precision: z.number().optional().describe('Decimal precision'),
// Enum input
format: z.enum(['decimal', 'fraction']).describe('Output format'),
// Array input
numbers: z.array(z.number()).describe('List of numbers'),
},
handler: async ({ operation, a, b, precision, format, numbers }) => {
// Handler implementation
},
})
Common Zod Types
| Zod Type | Example | Description |
|---|---|---|
z.string() | z.string().min(1).max(100) | String with validation |
z.number() | z.number().min(0).max(100) | Number with validation |
z.boolean() | z.boolean() | Boolean value |
z.array() | z.array(z.string()) | Array of values |
z.object() | z.object({ ... }) | Nested object |
z.enum() | z.enum(['a', 'b']) | Enumeration |
z.optional() | z.string().optional() | Optional field |
z.default() | z.string().default('value') | Field with default |
Output Schema
Define structured output using outputSchema:
import { z } from 'zod'
import { defineMcpTool } from '@nuxtjs/mcp-toolkit/server'
export default defineMcpTool({
name: 'calculate-bmi',
description: 'Calculate Body Mass Index',
inputSchema: {
weightKg: z.number().describe('Weight in kilograms'),
heightM: z.number().describe('Height in meters'),
},
outputSchema: {
bmi: z.number(),
category: z.string(),
},
handler: async ({ weightKg, heightM }) => {
const bmi = weightKg / (heightM * heightM)
let category = 'Normal'
if (bmi < 18.5) category = 'Underweight'
else if (bmi >= 25) category = 'Overweight'
else if (bmi >= 30) category = 'Obese'
return {
structuredContent: {
bmi: Math.round(bmi * 100) / 100,
category,
},
}
},
})
The structuredContent field provides structured data that matches your outputSchema, making it easier for AI assistants to work with the results.
Handler Function
The handler is an async function that receives validated input and returns results. You can return simplified values directly — they are automatically wrapped into the MCP CallToolResult format.
Simplified Returns
Return a string, number, boolean, object, or array directly from your handler:
handler: async ({ name }) => `Hello ${name}`
// → { content: [{ type: 'text', text: 'Hello World' }] }
handler: async ({ a, b }) => a + b
// → { content: [{ type: 'text', text: '10' }] }
handler: async ({ id }) => {
const user = await getUser(id)
return user
}
// → { content: [{ type: 'text', text: '{ "id": ... }' }] }
handler: async ({ id }) => await exists(id)
// → { content: [{ type: 'text', text: 'true' }] }
You can also return the full CallToolResult format when you need more control (e.g., images, multiple content items, structuredContent).
Content Types
For advanced use cases, return a full CallToolResult with typed content:
return {
content: [{
type: 'image',
data: base64ImageData,
mimeType: 'image/png',
}],
}
return {
structuredContent: {
bmi: 25.5,
category: 'Normal',
},
}
// text content is auto-generated as fallback for older clients
return {
content: [{
type: 'resource',
resource: {
uri: 'file:///path/to/file',
text: 'File content',
mimeType: 'text/plain',
},
}],
}
Result Helpers
The module provides imageResult and audioResult helpers for binary media in tool responses (base64-encoded data plus MIME type):
import { z } from 'zod'
import { defineMcpTool, imageResult, audioResult } from '@nuxtjs/mcp-toolkit/server'
export default defineMcpTool({
description: 'Generate chart',
inputSchema: { data: z.array(z.number()) },
handler: async ({ data }) => {
const base64 = await generateChart(data)
return imageResult(base64, 'image/png')
},
})
import { z } from 'zod'
import { defineMcpTool, audioResult } from '@nuxtjs/mcp-toolkit/server'
export default defineMcpTool({
description: 'Text to speech',
inputSchema: { text: z.string() },
handler: async ({ text }) => {
const base64 = await synthesizeSpeech(text)
return audioResult(base64, 'audio/mp3')
},
})
textResult, jsonResult, and errorResult helpers are deprecated. Return values directly from your handler instead, and throw errors for error cases (see Errors & caching).