工具

分组、文件与动态注册

工具的分组和标签、目录布局、类型安全以及启用守卫。

高级示例

带 API 集成的工具

下面是一个展示典型 API 驱动工具的示例:

server/mcp/tools/get-weather.ts
import { z } from 'zod'
import { createError } from 'h3'
import { defineMcpTool } from '@nuxtjs/mcp-toolkit/server'

export default defineMcpTool({
  name: 'get-weather',
  description: '获取某个城市的当前天气',
  inputSchema: {
    city: z.string().describe('城市名称'),
  },
  handler: async ({ city }) => {
    const data = await $fetch(`/api/weather/${city}`)
    if (!data) throw createError({ statusCode: 404, message: `未找到城市 "${city}"` })
    return data
  },
})

分组和标签

使用 grouptags 来组织你的工具,以便进行筛选和渐进式发现。分组和标签会暴露在 _meta 中,并在采用 SEP-1300 后映射到它。

显式分组和标签

直接在定义上设置 grouptags

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

export default defineMcpTool({
  group: 'admin',
  tags: ['destructive', 'user-management'],
  description: '删除用户账户',
  inputSchema: {
    userId: z.string(),
  },
  handler: async ({ userId }) => {
    // ...
  },
})

从目录自动推断分组

将工具放在子目录中,系统会自动推断分组:

server/mcp/tools/
├── admin/
│   ├── delete-user.ts    → group: 'admin'
│   └── stats.ts          → group: 'admin'
├── content/
│   └── list-pages.ts     → group: 'content'
└── search.ts             → no group

在定义中显式设置的 group 始终优先于从目录推断的值。

客户端如何查看分组和标签

分组和标签包含在 tools/list 响应的 _meta 字段中:

{
  "name": "delete-user",
  "_meta": {
    "group": "admin",
    "tags": ["destructive", "user-management"]
  }
}

MCP 客户端可以使用这些值在其 UI 中筛选、排序或对工具分组。

对于 resourcespromptsgrouptags 会保存在定义对象上,但尚未在协议响应中暴露(resources/listprompts/list)。当 MCP SDK 采用 SEP-1300 时,将支持这一点。

文件组织

将你的工具组织在 server/mcp/tools/ 目录中。支持扁平和嵌套两种布局:

server/
└── mcp/
    └── tools/
        ├── echo.ts
        ├── calculator.ts
        ├── admin/
        │   ├── delete-user.ts
        │   └── stats.ts
        └── content/
            └── list-pages.ts

每个文件都应导出一个默认的工具定义。子目录会自动为其中的所有工具设置 group

类型安全

该模块提供完整的 TypeScript 类型推断:

// 输入类型会从 inputSchema 推断
handler: async ({ message }) => {
  // message 的类型为 string
}

// 输出类型会从 outputSchema 推断
const result = {
  structuredContent: {
    bmi: 25.5,      // number
    category: '...', // string
  },
}

条件注册

你可以使用 enabled 守卫来控制工具是否对客户端可见:

server/mcp/tools/admin-tool.ts
import { defineMcpTool } from '@nuxtjs/mcp-toolkit/server'

export default defineMcpTool({
  name: 'admin-tool',
  description: '仅管理员可用的工具',
  enabled: event => event.context.user?.role === 'admin',
  handler: async () => {
    // ...
  },
})

enabled 返回 false 时,该工具会从 tools/list 中隐藏,并且无法被调用。

有关基于认证过滤的详细文档,请参阅 动态定义 指南。

下一步