npx skills add https://github.com/nuxt-modules/mcp-toolkit --skill manage-mcp用于在 Nuxt 应用程序中管理模型上下文协议(MCP)服务器的完整技能。设置、创建、使用中间件和处理程序进行自定义、审查以及故障排除。
自动安装(推荐):
npx nuxt module add mcp-toolkit
手动安装:
pnpm add -D @nuxtjs/mcp-toolkit zod
添加到 nuxt.config.ts:
export default defineNuxtConfig({
modules: ['@nuxtjs/mcp-toolkit'],
mcp: {
name: 'My MCP Server',
},
})
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
server/mcp/
├── tools/ # AI 可以执行的操作
│ ├── admin/ # 子目录 → 分组: 'admin'
│ └── content/ # 子目录 → 分组: 'content'
├── resources/ # AI 可以读取的数据
└── prompts/ # 消息模板
pnpm devhttp://localhost:3000/mcp(应该会重定向)工具是 AI 助手可以调用的函数。
import { z } from 'zod'
export default defineMcpTool({
description: '工具的功能描述',
inputSchema: {
param: z.string().describe('参数描述'),
},
handler: async ({ param }) => {
return {
content: [{
type: 'text',
text: '结果',
}],
}
},
})
// 必填
name: z.string().describe('用户名')
// 可选,带默认值
limit: z.number().default(10).describe('最大结果数')
// 枚举
format: z.enum(['json', 'xml']).describe('格式')
// 数组
tags: z.array(z.string()).describe('标签')
if (!param) {
throw createError({ statusCode: 400, message: '错误:参数必填' })
}
行为提示,帮助 MCP 客户端决定何时提示确认:
export default defineMcpTool({
annotations: {
readOnlyHint: true, // 仅读取数据,无副作用
destructiveHint: false, // 不删除或销毁数据
idempotentHint: false, // 多次调用可能产生不同效果
openWorldHint: false, // 无外部 API 调用
},
// ...
})
常见模式:只读工具 → readOnlyHint: true,创建 → idempotentHint: false,更新 → idempotentHint: true,删除 → destructiveHint: true, idempotentHint: true。
类型安全的使用示例,帮助 AI 模型正确填写参数:
export default defineMcpTool({
inputSchema: {
title: z.string().describe('待办事项标题'),
content: z.string().optional().describe('描述'),
},
inputExamples: [
{ title: '购买杂货', content: '牛奶、鸡蛋、面包' },
{ title: '修复登录 bug' },
],
// ...
})
使用 group 和 tags 组织工具,以便过滤和渐进式发现:
export default defineMcpTool({
group: 'admin',
tags: ['destructive', 'user-management'],
description: '删除用户账户',
// ...
})
分组根据子目录自动推断:server/mcp/tools/admin/delete-user.ts → group: 'admin'。显式的 group 优先级更高。
export default defineMcpTool({
cache: '5m', // 5 分钟
// ...
})
查看 详细示例 →
资源暴露只读数据。
import { readFile } from 'node:fs/promises'
export default defineMcpResource({
description: '读取文件',
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',
}],
}
},
})
export default defineMcpResource({
description: '获取 API 数据',
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',
}],
}
},
})
import { z } from 'zod'
export default defineMcpResource({
description: '根据 ID 获取',
uriTemplate: {
uriTemplate: 'user:///{id}',
arguments: {
id: z.string().describe('用户 ID'),
},
},
handler: async (uri: URL, args) => {
const user = await fetchUser(args.id)
return {
contents: [{
uri: uri.toString(),
text: JSON.stringify(user),
mimeType: 'application/json',
}],
}
},
})
查看 详细示例 →
提示是可重用的消息模板。
export default defineMcpPrompt({
description: '代码审查',
handler: async () => {
return {
messages: [{
role: 'user',
content: {
type: 'text',
text: '审查此代码是否符合最佳实践。',
},
}],
}
},
})
import { z } from 'zod'
export default defineMcpPrompt({
description: '自定义审查',
inputSchema: {
language: z.string().describe('语言'),
focus: z.array(z.string()).describe('关注领域'),
},
handler: async ({ language, focus }) => {
return {
messages: [{
role: 'user',
content: {
type: 'text',
text: `审查我的 ${language} 代码:${focus.join(', ')}`,
},
}],
}
},
})
查看 详细示例 →
使用中间件和处理程序自定义 MCP 行为,用于身份验证、日志记录、速率限制等。
// server/mcp/middleware.ts
export default defineMcpMiddleware({
handler: async (event, next) => {
console.log('MCP 请求:', event.path)
// 检查身份验证
const token = event.headers.get('authorization')
if (!token) {
return createError({ statusCode: 401, message: '未授权' })
}
return next()
},
})
// server/mcp/handlers/custom.ts
export default defineMcpHandler({
name: 'custom-mcp',
route: '/mcp/custom',
handler: async (event) => {
return {
tools: await loadCustomTools(),
resources: [],
prompts: [],
}
},
})
查看 详细中间件指南 →
✅ 使用 kebab-case 文件名
✅ 为所有 Zod 字段添加 .describe()
✅ 错误时返回 isError: true
✅ 为昂贵操作添加缓存
✅ 清晰、可操作的描述
✅ 验证所有输入
✅ 添加 annotations(readOnlyHint、destructiveHint 等)
✅ 为具有可选/复杂参数的工具添加 inputExamples
❌ 通用描述 ❌ 跳过错误处理 ❌ 暴露敏感数据 ❌ 无输入验证
✅ 描述性 URI(config:///app)
✅ 设置适当的 MIME 类型
✅ 需要时启用缓存
✅ 优雅地处理错误
✅ 对集合使用 URI 模板
❌ 不明确的 URI 方案 ❌ 跳过 MIME 类型 ❌ 暴露敏感数据 ❌ 返回没有分页的巨大数据集
✅ 清晰的描述 ✅ 有意义的参数 ✅ 在适当的地方使用默认值 ✅ 单一、专注的目的 ✅ 可重用设计
❌ 过于复杂 ❌ 跳过描述 ❌ 混合多个关注点
修复:
modules: ['@nuxtjs/mcp-toolkit']server/mcp/ 目录中?pnpm nuxt prepare修复:
curl http://localhost:3000/mcpenabled: true修复:
.optional()?修复:
.ts 或 .js?export default?查看 详细故障排除 →
pnpm add -D evalite vitest @ai-sdk/mcp ai
添加到 package.json:
{
"scripts": {
"eval": "evalite",
"eval:ui": "evalite watch"
}
}
创建 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 工具选择', {
data: async () => [
{
input: '计算 70kg 1.75m 的 BMI',
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,
}),
],
})
# 启动服务器
pnpm dev
# 运行测试(在另一个终端)
pnpm eval
# 或使用 UI
pnpm eval:ui # http://localhost:3006
查看 详细测试指南 →
# 设置
npx nuxt module add mcp-toolkit
# 开发
pnpm dev
# 测试端点
curl http://localhost:3000/mcp
# 重新生成类型
pnpm nuxt prepare
# 运行评估
pnpm eval
// nuxt.config.ts
export default defineNuxtConfig({
mcp: {
name: 'My Server',
route: '/mcp',
enabled: true,
dir: 'mcp',
},
})
每周安装量
167
仓库
GitHub Stars
128
首次出现
2026年2月7日
安全审计
已安装于
claude-code135
codex87
github-copilot87
opencode86
gemini-cli86
kimi-cli82
Complete skill for managing Model Context Protocol (MCP) servers in Nuxt applications. Setup, create, customize with middleware and handlers, review, and troubleshoot.
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',
},
})
server/mcp/
├── tools/ # Actions AI can perform
│ ├── admin/ # Subdirectory → group: 'admin'
│ └── content/ # Subdirectory → group: 'content'
├── resources/ # Data AI can read
└── prompts/ # Message templates
pnpm devhttp://localhost:3000/mcp (should redirect)Tools are functions AI assistants can call.
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',
}],
}
},
})
// 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')
if (!param) {
throw createError({ statusCode: 400, message: 'Error: param required' })
}
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.
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' },
],
// ...
})
Organize tools with group and tags for filtering and progressive discovery:
export default defineMcpTool({
group: 'admin',
tags: ['destructive', 'user-management'],
description: 'Delete a user account',
// ...
})
Groups are auto-inferred from subdirectories: server/mcp/tools/admin/delete-user.ts → group: 'admin'. Explicit group takes precedence.
export default defineMcpTool({
cache: '5m', // 5 minutes
// ...
})
Resources expose read-only data.
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',
}],
}
},
})
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',
}],
}
},
})
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',
}],
}
},
})
Prompts are reusable message templates.
export default defineMcpPrompt({
description: 'Code review',
handler: async () => {
return {
messages: [{
role: 'user',
content: {
type: 'text',
text: 'Review this code for best practices.',
},
}],
}
},
})
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(', ')}`,
},
}],
}
},
})
Customize MCP behavior with middleware and handlers for authentication, logging, rate limiting, and more.
// 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()
},
})
// server/mcp/handlers/custom.ts
export default defineMcpHandler({
name: 'custom-mcp',
route: '/mcp/custom',
handler: async (event) => {
return {
tools: await loadCustomTools(),
resources: [],
prompts: [],
}
},
})
See detailed middleware guide →
✅ 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
✅ 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
✅ Clear descriptions ✅ Meaningful parameters ✅ Default values where appropriate ✅ Single, focused purpose ✅ Reusable design
❌ Overly complex ❌ Skip descriptions ❌ Mix multiple concerns
Fix:
modules: ['@nuxtjs/mcp-toolkit'] in configserver/mcp/ directory?pnpm nuxt prepareFix:
curl http://localhost:3000/mcpenabled: true in configFix:
.optional() for optional fieldsFix:
.ts or .js?export default?See detailed troubleshooting →
pnpm add -D evalite vitest @ai-sdk/mcp ai
Add to package.json:
{
"scripts": {
"eval": "evalite",
"eval:ui": "evalite watch"
}
}
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,
}),
],
})
# Start server
pnpm dev
# Run tests (in another terminal)
pnpm eval
# Or with UI
pnpm eval:ui # http://localhost:3006
# 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
// nuxt.config.ts
export default defineNuxtConfig({
mcp: {
name: 'My Server',
route: '/mcp',
enabled: true,
dir: 'mcp',
},
})
Weekly Installs
167
Repository
GitHub Stars
128
First Seen
Feb 7, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
claude-code135
codex87
github-copilot87
opencode86
gemini-cli86
kimi-cli82
AI Elements:基于shadcn/ui的AI原生应用组件库,快速构建对话界面
62,200 周安装
Loom视频转录获取器 - 自动提取Loom视频字幕与文本,支持GraphQL API
163 周安装
bioRxiv数据库Python工具:高效搜索下载预印本,支持关键词/作者/日期/类别筛选
163 周安装
Magento 2 Hyvä CMS 组件创建器 - 快速构建自定义CMS组件
163 周安装
项目文档协调器 - 自动化文档生成与上下文管理工具
163 周安装
GPUI 布局与样式:Rust 类型安全的 CSS 样式库,Flexbox 布局与链式 API
163 周安装
Telegram自动化指南:通过Rube MCP与Composio实现消息发送、聊天管理
163 周安装