Handlers

Sharing & practices

Cross-handler tool sharing, file layout, use cases, and next steps.

Use Cases

1. Feature Separation

Separate different features into different handlers:

server/mcp/user-management.ts
import { defineMcpHandler } from '@nuxtjs/mcp-toolkit/server'

export default defineMcpHandler({
  name: 'users',
  tools: [getUserTool, createUserTool, updateUserTool],
})
server/mcp/content-management.ts
import { defineMcpHandler } from '@nuxtjs/mcp-toolkit/server'

export default defineMcpHandler({
  name: 'content',
  tools: [createPostTool, updatePostTool, deletePostTool],
})

2. Versioned APIs

Create versioned handlers:

server/mcp/api-v1.ts
import { defineMcpHandler } from '@nuxtjs/mcp-toolkit/server'

export default defineMcpHandler({
  name: 'api-v1',
  version: '1.0.0',
  route: '/api/v1/mcp',
  tools: [ ... ],
})
server/mcp/api-v2.ts
import { defineMcpHandler } from '@nuxtjs/mcp-toolkit/server'

export default defineMcpHandler({
  name: 'api-v2',
  version: '2.0.0',
  route: '/api/v2/mcp',
  tools: [ ... ],
})

3. Domain-Specific Handlers

Organize by domain:

server/mcp/ecommerce.ts
import { defineMcpHandler } from '@nuxtjs/mcp-toolkit/server'

export default defineMcpHandler({
  name: 'ecommerce',
  tools: [addToCartTool, checkoutTool, getProductsTool],
})
server/mcp/analytics.ts
import { defineMcpHandler } from '@nuxtjs/mcp-toolkit/server'

export default defineMcpHandler({
  name: 'analytics',
  tools: [getStatsTool, generateReportTool],
})

Sharing Tools Between Handlers

Prefer the multi-handler organization features (folder convention plus the getMcp* function form) for any new handler. The patterns below remain fully supported for explicit, hand-built handler configs.

You can share tool definitions between handlers by exporting them from a separate file:

server/mcp/shared-tools.ts
import { z } from 'zod'
import { defineMcpTool } from '@nuxtjs/mcp-toolkit/server'

export const sharedTool = defineMcpTool({
  name: 'shared-tool',
  description: 'A shared tool',
  inputSchema: {
    input: z.string(),
  },
  handler: async ({ input }) => `Shared: ${input}`,
})
server/mcp/handler1.ts
import { sharedTool } from './shared-tools'
import { defineMcpHandler } from '@nuxtjs/mcp-toolkit/server'

export default defineMcpHandler({
  name: 'handler1',
  tools: [sharedTool],
})
server/mcp/handler2.ts
import { sharedTool } from './shared-tools'
import { defineMcpHandler } from '@nuxtjs/mcp-toolkit/server'

export default defineMcpHandler({
  name: 'handler2',
  tools: [sharedTool],
})

File Organization

Two conventions can coexist in server/mcp/:

server/
└── mcp/
    ├── index.ts              # Default handler override (optional)
    ├── migration.ts          # Top-level handler (defaults to all tools)
    ├── tools/                # Default handler tools (orphans)
    ├── resources/            # Default handler resources (orphans)
    ├── prompts/              # Default handler prompts (orphans)
    └── handlers/             # ✨ Named handler folders (recommended)
        ├── admin/
        │   ├── index.ts      # Required: defineMcpHandler({ ... })
        │   ├── tools/        # Auto-attached to /mcp/admin
        │   └── prompts/
        └── apps/
            ├── index.ts
            └── tools/        # Auto-attached to /mcp/apps
The index.ts at the root of server/mcp/ overrides the default handler configuration. Inside a handlers/<name>/ directory, index.ts is required (even as a one-liner: export default defineMcpHandler({})) — it's what registers the /mcp/<name> route.

Best Practices

  1. Use descriptive names: Make handler names clear and specific
  2. Group related functionality: Put related tools/resources together
  3. Version your handlers: Use semantic versioning for handler versions
  4. Document your handlers: Add comments explaining what each handler does
  5. Keep handlers focused: Each handler should have a clear, single purpose

Next Steps

Copyright © 2026