- Manage MCP
- Complete skill for managing Model Context Protocol (MCP) servers in Nuxt applications. Setup, create, customize with middleware and handlers, review, and troubleshoot.
- When to Use
- Setup
-
- "Setup an MCP server in my Nuxt app"
- Create
-
- "Create a tool to calculate BMI" / "Add a resource to read the README"
- Customize
-
- "Add authentication to my MCP server" / "Create middleware for rate limiting"
- Review
-
- "Review my MCP implementation" / "Check for best practices"
- Troubleshoot
-
- "My auto-imports aren't working" / "Cannot connect to endpoint"
- Test
-
- "Create tests for my MCP tools"
- Setup MCP Server
- Installation
- Automatic (recommended):
- npx nuxt module
- add
- mcp-toolkit
- Manual:
- pnpm
- add
- -D
- @nuxtjs/mcp-toolkit zod
- Add to
- nuxt.config.ts
- :
- export
- default
- defineNuxtConfig
- (
- {
- modules
- :
- [
- '@nuxtjs/mcp-toolkit'
- ]
- ,
- mcp
- :
- {
- name
- :
- 'My MCP Server'
- ,
- }
- ,
- }
- )
- Directory Structure
- server/mcp/
- ├── tools/ # Actions AI can perform
- ├── resources/ # Data AI can read
- └── prompts/ # Message templates
- Verification
- Start:
- pnpm dev
- Check:
- http://localhost:3000/mcp
- (should redirect)
- Open DevTools (Shift+Alt+D) → MCP tab
- Create Tools
- Tools are functions AI assistants can call.
- Basic Structure
- import
- {
- z
- }
- from
- 'zod'
- export
- default
- defineMcpTool
- (
- {
- description
- :
- 'What the tool does'
- ,
- inputSchema
- :
- {
- param
- :
- z
- .
- string
- (
- )
- .
- describe
- (
- 'Parameter description'
- )
- ,
- }
- ,
- handler
- :
- async
- (
- {
- param
- }
- )
- =>
- {
- return
- {
- content
- :
- [
- {
- type
- :
- 'text'
- ,
- text
- :
- 'Result'
- ,
- }
- ]
- ,
- }
- }
- ,
- }
- )
- Input Patterns
- // Required
- name
- :
- z
- .
- string
- (
- )
- .
- describe
- (
- 'User name'
- )
- // Optional with default
- limit
- :
- z
- .
- number
- (
- )
- .
- default
- (
- 10
- )
- .
- describe
- (
- 'Max results'
- )
- // Enum
- format
- :
- z
- .
- enum
- (
- [
- 'json'
- ,
- 'xml'
- ]
- )
- .
- describe
- (
- 'Format'
- )
- // Array
- tags
- :
- z
- .
- array
- (
- z
- .
- string
- (
- )
- )
- .
- describe
- (
- 'Tags'
- )
- Error Handling
- if
- (
- !
- param
- )
- {
- return
- {
- content
- :
- [
- {
- type
- :
- 'text'
- ,
- text
- :
- 'Error: param required'
- }
- ]
- ,
- isError
- :
- true
- ,
- }
- }
- Annotations
- Behavioral hints that help MCP clients decide when to prompt for confirmation:
- export
- default
- defineMcpTool
- (
- {
- annotations
- :
- {
- readOnlyHint
- :
- true
- ,
- // Only reads data, no side effects
- destructiveHint
- :
- false
- ,
- // Does not delete or destroy data
- idempotentHint
- :
- false
- ,
- // Multiple calls may have different effects
- openWorldHint
- :
- false
- ,
- // No external API calls
- }
- ,
- // ...
- }
- )
- Common patterns: read-only tools →
- readOnlyHint: true
- , create →
- idempotentHint: false
- , update →
- idempotentHint: true
- , delete →
- destructiveHint: true, idempotentHint: true
- .
- Input Examples
- Type-safe usage examples that help AI models fill in parameters correctly:
- export
- default
- defineMcpTool
- (
- {
- inputSchema
- :
- {
- title
- :
- z
- .
- string
- (
- )
- .
- describe
- (
- 'Todo title'
- )
- ,
- content
- :
- z
- .
- string
- (
- )
- .
- optional
- (
- )
- .
- describe
- (
- 'Description'
- )
- ,
- }
- ,
- inputExamples
- :
- [
- {
- title
- :
- 'Buy groceries'
- ,
- content
- :
- 'Milk, eggs, bread'
- }
- ,
- {
- title
- :
- 'Fix login bug'
- }
- ,
- ]
- ,
- // ...
- }
- )
- Caching
- export
- default
- defineMcpTool
- (
- {
- cache
- :
- '5m'
- ,
- // 5 minutes
- // ...
- }
- )
- See
- detailed examples →
- Create Resources
- Resources expose read-only data.
- File Resource
- import
- {
- readFile
- }
- from
- 'node:fs/promises'
- export
- default
- defineMcpResource
- (
- {
- description
- :
- 'Read a file'
- ,
- uri
- :
- 'file:///README.md'
- ,
- mimeType
- :
- 'text/markdown'
- ,
- handler
- :
- async
- (
- uri
- :
- URL
- )
- =>
- {
- const
- content
- =
- await
- readFile
- (
- 'README.md'
- ,
- 'utf-8'
- )
- return
- {
- contents
- :
- [
- {
- uri
- :
- uri
- .
- toString
- (
- )
- ,
- text
- :
- content
- ,
- mimeType
- :
- 'text/markdown'
- ,
- }
- ]
- ,
- }
- }
- ,
- }
- )
- API Resource
- export
- default
- defineMcpResource
- (
- {
- description
- :
- 'Fetch API data'
- ,
- uri
- :
- 'api:///users'
- ,
- mimeType
- :
- 'application/json'
- ,
- cache
- :
- '5m'
- ,
- handler
- :
- async
- (
- uri
- :
- URL
- )
- =>
- {
- const
- data
- =
- await
- $fetch
- (
- 'https://api.example.com/users'
- )
- return
- {
- contents
- :
- [
- {
- uri
- :
- uri
- .
- toString
- (
- )
- ,
- text
- :
- JSON
- .
- stringify
- (
- data
- ,
- null
- ,
- 2
- )
- ,
- mimeType
- :
- 'application/json'
- ,
- }
- ]
- ,
- }
- }
- ,
- }
- )
- Dynamic Resource
- import
- {
- z
- }
- from
- 'zod'
- export
- default
- defineMcpResource
- (
- {
- description
- :
- 'Fetch by ID'
- ,
- uriTemplate
- :
- {
- uriTemplate
- :
- 'user:///{id}'
- ,
- arguments
- :
- {
- id
- :
- z
- .
- string
- (
- )
- .
- describe
- (
- 'User ID'
- )
- ,
- }
- ,
- }
- ,
- handler
- :
- async
- (
- uri
- :
- URL
- ,
- args
- )
- =>
- {
- const
- user
- =
- await
- fetchUser
- (
- args
- .
- id
- )
- return
- {
- contents
- :
- [
- {
- uri
- :
- uri
- .
- toString
- (
- )
- ,
- text
- :
- JSON
- .
- stringify
- (
- user
- )
- ,
- mimeType
- :
- 'application/json'
- ,
- }
- ]
- ,
- }
- }
- ,
- }
- )
- See
- detailed examples →
- Create Prompts
- Prompts are reusable message templates.
- Static Prompt
- export
- default
- defineMcpPrompt
- (
- {
- description
- :
- 'Code review'
- ,
- handler
- :
- async
- (
- )
- =>
- {
- return
- {
- messages
- :
- [
- {
- role
- :
- 'user'
- ,
- content
- :
- {
- type
- :
- 'text'
- ,
- text
- :
- 'Review this code for best practices.'
- ,
- }
- ,
- }
- ]
- ,
- }
- }
- ,
- }
- )
- Dynamic Prompt
- import
- {
- z
- }
- from
- 'zod'
- export
- default
- defineMcpPrompt
- (
- {
- description
- :
- 'Custom review'
- ,
- inputSchema
- :
- {
- language
- :
- z
- .
- string
- (
- )
- .
- describe
- (
- 'Language'
- )
- ,
- focus
- :
- z
- .
- array
- (
- z
- .
- string
- (
- )
- )
- .
- describe
- (
- 'Focus areas'
- )
- ,
- }
- ,
- handler
- :
- async
- (
- {
- language
- ,
- focus
- }
- )
- =>
- {
- return
- {
- messages
- :
- [
- {
- role
- :
- 'user'
- ,
- content
- :
- {
- type
- :
- 'text'
- ,
- text
- :
- `
- Review my
- ${
- language
- }
- code:
- ${
- focus
- .
- join
- (
- ', '
- )
- }
- `
- ,
- }
- ,
- }
- ]
- ,
- }
- }
- ,
- }
- )
- See
- detailed examples →
- Middleware & Handlers
- Customize MCP behavior with middleware and handlers for authentication, logging, rate limiting, and more.
- Basic Middleware
- // server/mcp/middleware.ts
- export
- default
- defineMcpMiddleware
- (
- {
- handler
- :
- async
- (
- event
- ,
- next
- )
- =>
- {
- console
- .
- log
- (
- 'MCP Request:'
- ,
- event
- .
- path
- )
- // Check auth
- const
- token
- =
- event
- .
- headers
- .
- get
- (
- 'authorization'
- )
- if
- (
- !
- token
- )
- {
- return
- createError
- (
- {
- statusCode
- :
- 401
- ,
- message
- :
- 'Unauthorized'
- }
- )
- }
- return
- next
- (
- )
- }
- ,
- }
- )
- Custom Handler
- // server/mcp/handlers/custom.ts
- export
- default
- defineMcpHandler
- (
- {
- name
- :
- 'custom-mcp'
- ,
- route
- :
- '/mcp/custom'
- ,
- handler
- :
- async
- (
- event
- )
- =>
- {
- return
- {
- tools
- :
- await
- loadCustomTools
- (
- )
- ,
- resources
- :
- [
- ]
- ,
- prompts
- :
- [
- ]
- ,
- }
- }
- ,
- }
- )
- Common Use Cases
- Authentication
-
- API keys, JWT tokens
- Rate limiting
-
- Per IP or per user
- Logging
-
- Request/response tracking
- CORS
-
- Cross-origin configuration
- Multiple endpoints
- Public/admin separation See detailed middleware guide → Review & Best Practices Tool Checklist ✅ Use kebab-case filenames ✅ Add .describe() to all Zod fields ✅ Return isError: true for errors ✅ Add caching for expensive ops ✅ Clear, actionable descriptions ✅ Validate all inputs ✅ Add annotations (readOnlyHint, destructiveHint, etc.) ✅ Add inputExamples for tools with optional/complex params ❌ Generic descriptions ❌ Skip error handling ❌ Expose sensitive data ❌ No input validation Resource Checklist ✅ Descriptive URIs ( config:///app ) ✅ Set appropriate MIME types ✅ Enable caching when needed ✅ Handle errors gracefully ✅ Use URI templates for collections ❌ Unclear URI schemes ❌ Skip MIME types ❌ Expose sensitive data ❌ Return huge datasets without pagination Prompt Checklist ✅ Clear descriptions ✅ Meaningful parameters ✅ Default values where appropriate ✅ Single, focused purpose ✅ Reusable design ❌ Overly complex ❌ Skip descriptions ❌ Mix multiple concerns Troubleshooting Auto-imports Not Working Fix: Check modules: ['@nuxtjs/mcp-toolkit'] in config Restart dev server Files in server/mcp/ directory? Run pnpm nuxt prepare Endpoint Not Accessible Fix: Dev server running? Test: curl http://localhost:3000/mcp Check enabled: true in config Review server logs Validation Errors Fix: Required fields provided? Types match schema? Use .optional() for optional fields Enum values exact match? Tool Not Discovered Fix: File extension .ts or .js ? Using export default ? File in correct directory? Restart dev server See detailed troubleshooting → Testing with Evals Setup pnpm add -D evalite vitest @ai-sdk/mcp ai Add to package.json : { "scripts" : { "eval" : "evalite" , "eval:ui" : "evalite watch" } } Basic Test Create test/mcp.eval.ts : import { experimental_createMCPClient as createMCPClient } from '@ai-sdk/mcp' import { generateText } from 'ai' import { evalite } from 'evalite' import { toolCallAccuracy } from 'evalite/scorers' evalite ( 'MCP Tool Selection' , { data : async ( ) => [ { input : 'Calculate BMI for 70kg 1.75m' , expected : [ { toolName : 'bmi-calculator' , input : { weight : 70 , height : 1.75 } , } ] , } , ] , task : async ( input ) => { const mcp = await createMCPClient ( { transport : { type : 'http' , url : 'http://localhost:3000/mcp' } , } ) try { const result = await generateText ( { model : 'openai/gpt-4o' , prompt : input , tools : await mcp . tools ( ) , } ) return result . toolCalls ?? [ ] } finally { await mcp . close ( ) } } , scorers : [ ( { output , expected } ) => toolCallAccuracy ( { actualCalls : output , expectedCalls : expected , } ) , ] , } ) Running
Start server
pnpm dev
Run tests (in another terminal)
pnpm eval
Or with UI
pnpm eval:ui
http://localhost:3006
See detailed testing guide → Quick Reference Common Commands
Setup
npx nuxt module add mcp-toolkit
Dev
pnpm dev
Test endpoint
curl http://localhost:3000/mcp
Regenerate types
pnpm nuxt prepare
Run evals
- pnpm
- eval
- Configuration
- // nuxt.config.ts
- export
- default
- defineNuxtConfig
- (
- {
- mcp
- :
- {
- name
- :
- 'My Server'
- ,
- route
- :
- '/mcp'
- ,
- enabled
- :
- true
- ,
- dir
- :
- 'mcp'
- ,
- }
- ,
- }
- )
- Debug Tools
- DevTools
-
- Shift+Alt+D → MCP tab
- Logs
-
- Check terminal
- curl
- Test endpoint Learn More Documentation Tools Guide Resources Guide Prompts Guide MCP Protocol