Groups, files & dynamic registration
Advanced Examples
Tool with API Integration
Here's an example showing a typical API-backed tool:
import { z } from 'zod'
import { createError } from 'h3'
import { defineMcpTool } from '@nuxtjs/mcp-toolkit/server'
export default defineMcpTool({
name: 'get-weather',
description: 'Get current weather for a city',
inputSchema: {
city: z.string().describe('City name'),
},
handler: async ({ city }) => {
const data = await $fetch(`/api/weather/${city}`)
if (!data) throw createError({ statusCode: 404, message: `City "${city}" not found` })
return data
},
})
Groups and Tags
Organize your tools with group and tags for filtering and progressive discovery. Groups and tags are exposed in _meta and will map to SEP-1300 when adopted.
Explicit Group and Tags
Set group and tags directly on the definition:
import { z } from 'zod'
import { defineMcpTool } from '@nuxtjs/mcp-toolkit/server'
export default defineMcpTool({
group: 'admin',
tags: ['destructive', 'user-management'],
description: 'Delete a user account',
inputSchema: {
userId: z.string(),
},
handler: async ({ userId }) => {
// ...
},
})
Auto-Inferred Group from Directory
Place tools in subdirectories and the group is inferred automatically:
server/mcp/tools/
├── admin/
│ ├── delete-user.ts → group: 'admin'
│ └── stats.ts → group: 'admin'
├── content/
│ └── list-pages.ts → group: 'content'
└── search.ts → no group
An explicit group on the definition always takes precedence over the directory-inferred value.
How Clients See Groups and Tags
Groups and tags are included in the _meta field of tools/list responses:
{
"name": "delete-user",
"_meta": {
"group": "admin",
"tags": ["destructive", "user-management"]
}
}
MCP clients can use these values to filter, sort, or group tools in their UI.
group and tags are stored on the definition objects but are not yet exposed in protocol responses (resources/list, prompts/list). This will be supported when SEP-1300 is adopted by the MCP SDK.File Organization
Organize your tools in the server/mcp/tools/ directory. Both flat and nested layouts are supported:
server/
└── mcp/
└── tools/
├── echo.ts
├── calculator.ts
├── admin/
│ ├── delete-user.ts
│ └── stats.ts
└── content/
└── list-pages.ts
Each file should export a default tool definition. Subdirectories automatically set the group for all tools within them.
Type Safety
The module provides full TypeScript type inference:
// Input types are inferred from inputSchema
handler: async ({ message }) => {
// message is typed as string
}
// Output types are inferred from outputSchema
const result = {
structuredContent: {
bmi: 25.5, // number
category: '...', // string
},
}
Conditional Registration
You can control whether a tool is visible to clients using the enabled guard:
import { defineMcpTool } from '@nuxtjs/mcp-toolkit/server'
export default defineMcpTool({
name: 'admin-tool',
description: 'Admin-only tool',
enabled: event => event.context.user?.role === 'admin',
handler: async () => {
// ...
},
})
When enabled returns false, the tool is hidden from tools/list and cannot be called.