manage-mcp

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Manage MCP

管理MCP

Complete skill for managing Model Context Protocol (MCP) servers in Nuxt applications. Setup, create, customize with middleware and handlers, review, and troubleshoot.
这是一份在Nuxt应用中管理Model Context Protocol(MCP)服务器的完整指南,涵盖搭建、创建、使用中间件与处理器自定义、审核及故障排查等内容。

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"

  • 搭建:"在我的Nuxt应用中搭建MCP服务器"
  • 创建:"创建一个计算BMI的工具" / "添加一个读取README的资源"
  • 自定义:"为我的MCP服务器添加认证" / "创建限流中间件"
  • 审核:"审核我的MCP实现" / "检查最佳实践"
  • 故障排查:"我的自动导入功能无法工作" / "无法连接到端点"
  • 测试:"为我的MCP工具创建测试"

Setup MCP Server

搭建MCP服务器

Installation

安装

Automatic (recommended):
bash
npx nuxt module add mcp-toolkit
Manual:
bash
pnpm add -D @nuxtjs/mcp-toolkit zod
Add to
nuxt.config.ts
:
typescript
export default defineNuxtConfig({
  modules: ['@nuxtjs/mcp-toolkit'],
  mcp: {
    name: 'My MCP Server',
  },
})
自动安装(推荐):
bash
npx nuxt module add mcp-toolkit
手动安装:
bash
pnpm add -D @nuxtjs/mcp-toolkit zod
添加至
nuxt.config.ts
typescript
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
server/mcp/
├── tools/       # AI可执行的操作
├── resources/   # AI可读取的数据
└── prompts/     # 消息模板

Verification

验证

  1. Start:
    pnpm dev
  2. Check:
    http://localhost:3000/mcp
    (should redirect)
  3. Open DevTools (Shift+Alt+D) → MCP tab

  1. 启动服务:
    pnpm dev
  2. 检查:访问
    http://localhost:3000/mcp
    (应自动跳转)
  3. 打开开发者工具(Shift+Alt+D)→ MCP标签页

Create Tools

创建工具

Tools are functions AI assistants can call.
工具是AI助手可以调用的函数。

Basic Structure

基础结构

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

输入模式

typescript
// 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')
typescript
// 必填项
name: z.string().describe('User name')

// 带默认值的可选项
limit: z.number().default(10).describe('Max results')

// 枚举类型
format: z.enum(['json', 'xml']).describe('Format')

// 数组类型
tags: z.array(z.string()).describe('Tags')

Error Handling

错误处理

typescript
if (!param) {
  return {
    content: [{ type: 'text', text: 'Error: param required' }],
    isError: true,
  }
}
typescript
if (!param) {
  return {
    content: [{ type: 'text', text: 'Error: param required' }],
    isError: true,
  }
}

Caching

缓存设置

typescript
export default defineMcpTool({
  cache: '5m',  // 5 minutes
  // ...
})
See detailed examples →

typescript
export default defineMcpTool({
  cache: '5m',  // 5分钟
  // ...
})
查看详细示例 →

Create Resources

创建资源

Resources expose read-only data.
资源用于暴露只读数据。

File Resource

文件资源

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

API资源

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

动态资源

typescript
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 →

typescript
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',
      }],
    }
  },
})
查看详细示例 →

Create Prompts

创建提示词

Prompts are reusable message templates.
提示词是可复用的消息模板。

Static Prompt

静态提示词

typescript
export default defineMcpPrompt({
  description: 'Code review',
  handler: async () => {
    return {
      messages: [{
        role: 'user',
        content: {
          type: 'text',
          text: 'Review this code for best practices.',
        },
      }],
    }
  },
})
typescript
export default defineMcpPrompt({
  description: 'Code review',
  handler: async () => {
    return {
      messages: [{
        role: 'user',
        content: {
          type: 'text',
          text: 'Review this code for best practices.',
        },
      }],
    }
  },
})

Dynamic Prompt

动态提示词

typescript
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 →

typescript
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(', ')}`,
        },
      }],
    }
  },
})
查看详细示例 →

Middleware & Handlers

中间件与处理器

Customize MCP behavior with middleware and handlers for authentication, logging, rate limiting, and more.
使用中间件和处理器自定义MCP行为,支持认证、日志、限流等功能。

Basic Middleware

基础中间件

typescript
// 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()
  },
})
typescript
// server/mcp/middleware.ts
export default defineMcpMiddleware({
  handler: async (event, next) => {
    console.log('MCP Request:', event.path)

    // 检查认证
    const token = event.headers.get('authorization')
    if (!token) {
      return createError({ statusCode: 401, message: 'Unauthorized' })
    }

    return next()
  },
})

Custom Handler

自定义处理器

typescript
// server/mcp/handlers/custom.ts
export default defineMcpHandler({
  name: 'custom-mcp',
  route: '/mcp/custom',
  handler: async (event) => {
    return {
      tools: await loadCustomTools(),
      resources: [],
      prompts: [],
    }
  },
})
typescript
// 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 →

  • 认证:API密钥、JWT令牌
  • 限流:基于IP或用户
  • 日志:请求/响应追踪
  • CORS:跨域配置
  • 多端点:公共/管理员端点分离
查看详细中间件指南 →

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
❌ Generic descriptions ❌ Skip error handling ❌ Expose sensitive data ❌ No input validation
✅ 使用短横线命名法(kebab-case)的文件名 ✅ 为所有Zod字段添加
.describe()
✅ 错误返回时设置
isError: true
✅ 为耗时操作添加缓存 ✅ 清晰、可执行的描述 ✅ 验证所有输入
❌ 通用模糊的描述 ❌ 跳过错误处理 ❌ 暴露敏感数据 ❌ 不做输入验证

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
✅ 描述性URI(如
config:///app
) ✅ 设置合适的MIME类型 ✅ 必要时启用缓存 ✅ 优雅处理错误 ✅ 为集合使用URI模板
❌ 不清晰的URI协议 ❌ 跳过MIME类型设置 ❌ 暴露敏感数据 ❌ 返回无分页的超大数据集

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:
  1. Check
    modules: ['@nuxtjs/mcp-toolkit']
    in config
  2. Restart dev server
  3. Files in
    server/mcp/
    directory?
  4. Run
    pnpm nuxt prepare
解决方法:
  1. 检查配置中是否包含
    modules: ['@nuxtjs/mcp-toolkit']
  2. 重启开发服务器
  3. 文件是否在
    server/mcp/
    目录下?
  4. 运行
    pnpm nuxt prepare

Endpoint Not Accessible

端点无法访问

Fix:
  1. Dev server running?
  2. Test:
    curl http://localhost:3000/mcp
  3. Check
    enabled: true
    in config
  4. Review server logs
解决方法:
  1. 开发服务器是否在运行?
  2. 测试:
    curl http://localhost:3000/mcp
  3. 检查配置中
    enabled: true
    是否设置
  4. 查看服务器日志

Validation Errors

验证错误

Fix:
  • Required fields provided?
  • Types match schema?
  • Use
    .optional()
    for optional fields
  • Enum values exact match?
解决方法:
  • 是否提供了必填字段?
  • 类型是否与 schema 匹配?
  • 为可选项使用
    .optional()
  • 枚举值是否完全匹配?

Tool Not Discovered

工具未被发现

Fix:
  • File extension
    .ts
    or
    .js
    ?
  • Using
    export default
    ?
  • File in correct directory?
  • Restart dev server
See detailed troubleshooting →

解决方法:
  • 文件扩展名是否为
    .ts
    .js
  • 是否使用
    export default
    导出?
  • 文件是否在正确的目录下?
  • 重启开发服务器
查看详细故障排查指南 →

Testing with Evals

使用Evals测试

Setup

搭建测试环境

bash
pnpm add -D evalite vitest @ai-sdk/mcp ai
Add to
package.json
:
json
{
  "scripts": {
    "eval": "evalite",
    "eval:ui": "evalite watch"
  }
}
bash
pnpm add -D evalite vitest @ai-sdk/mcp ai
添加至
package.json
json
{
  "scripts": {
    "eval": "evalite",
    "eval:ui": "evalite watch"
  }
}

Basic Test

基础测试

Create
test/mcp.eval.ts
:
typescript
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,
    }),
  ],
})
创建
test/mcp.eval.ts
typescript
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

运行测试

bash
undefined
bash
undefined

Start server

启动服务器

pnpm dev
pnpm dev

Run tests (in another terminal)

运行测试(在另一个终端)

pnpm eval
pnpm eval

Or with UI

或使用UI界面

pnpm eval:ui # http://localhost:3006

See [detailed testing guide →](./references/testing.md)

---
pnpm eval:ui # http://localhost:3006

查看[详细测试指南 →](./references/testing.md)

---

Quick Reference

快速参考

Common Commands

常用命令

bash
undefined
bash
undefined

Setup

搭建

npx nuxt module add mcp-toolkit
npx nuxt module add mcp-toolkit

Dev

开发

pnpm dev
pnpm dev

Test endpoint

测试端点

Regenerate types

重新生成类型

pnpm nuxt prepare
pnpm nuxt prepare

Run evals

运行测试

pnpm eval
undefined
pnpm eval
undefined

Configuration

配置示例

typescript
// nuxt.config.ts
export default defineNuxtConfig({
  mcp: {
    name: 'My Server',
    route: '/mcp',
    enabled: true,
    dir: 'mcp',
  },
})
typescript
// 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
  • 开发者工具:Shift+Alt+D → MCP标签页
  • 日志:查看终端输出
  • curl:测试端点

Learn More

了解更多