Tools

Schema, handler & returns

Define tool inputs and outputs with Zod, and return text, structured data, or media from handlers.

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:

server/mcp/tools/echo.ts
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:

server/mcp/tools/calculator.ts
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 TypeExampleDescription
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:

server/mcp/tools/bmi.ts
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' }] }

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',
  }],
}

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')
  },
})
The textResult, jsonResult, and errorResult helpers are deprecated. Return values directly from your handler instead, and throw errors for error cases (see Errors & caching).
Copyright © 2026