进阶主题

列出定义

从你自己的服务器路由中读取工具包发现的工具、资源和提示词,而无需重复它们的名称和描述。

概述

工具包会自动发现 server/mcp/ 下的每一个工具、资源和提示词。很多时候,你需要从自己的服务器路由中把这个目录再读回来——用于渲染 /.well-known/mcp/server-card.json、管理仪表盘、API 目录或站点地图。

使用 @nuxtjs/mcp-toolkit/server 中的 listMcp* 辅助函数,可以获取所有已发现定义的适合 JSON 的摘要,而无需在你自己的代码中重复它们的名称和描述。

HelperReturns
listMcpTools(options?)McpToolSummary[](适合 JSON)
listMcpResources(options?)McpResourceSummary[](适合 JSON)
listMcpPrompts(options?)McpPromptSummary[](适合 JSON)
listMcpDefinitions(options?){ tools, resources, prompts }
getMcpTools(options?)McpToolDefinitionListItem[](原始数据,含 handlers + Zod schemas)
getMcpResources(options?)McpResourceDefinition[](原始数据)
getMcpPrompts(options?)McpPromptDefinition[](原始数据)

每个摘要都包含 nametitledescriptiongrouptagshandler(资源还包括 uri)。从文件名自动生成的名称已经解析好,因此你得到的内容与 MCP 客户端在 tools/list 中看到的完全一致。

listMcp* 用于摘要(JSON 目录端点)。将 getMcp* 用于把原始定义回传到 defineMcpHandler({ tools: ev => getMcpTools(...) }) 中。

用法

服务器卡片

将工具包的目录以 server-card.json 的形式公开,这样其他代理就能发现你的服务器提供了什么:

server/routes/.well-known/mcp/server-card.json.get.ts
import { listMcpDefinitions } from '@nuxtjs/mcp-toolkit/server'

export default defineEventHandler(async (event) => {
  const { tools, resources, prompts } = await listMcpDefinitions({ event })
  return {
    name: 'My MCP Server',
    description: '由我的 Nuxt 应用公开的工具、资源和提示词。',
    tools: tools.map(t => ({ name: t.name, description: t.description })),
    resources: resources.map(r => ({ name: r.name, uri: r.uri, description: r.description })),
    prompts: prompts.map(p => ({ name: p.name, description: p.description })),
  }
})

工具目录

渲染一个可公开访问的可用工具列表,并可按需分组:

server/api/tools.get.ts
import { listMcpTools } from '@nuxtjs/mcp-toolkit/server'

export default defineEventHandler(async (event) => {
  const tools = await listMcpTools({ event })
  return Object.groupBy(tools, t => t.group ?? 'default')
})

选项

每个辅助函数都接受相同的 ListMcpDefinitionsOptions 对象。所有键都是可选的,并且采用 AND 语义组合——一个定义必须通过每一个启用中的筛选条件。

OptionTypeDescription
eventH3Event使用请求上下文为每个定义应用 enabled() 守卫
groupstring | string[]只保留其 group 匹配这些值之一(OR)的定义。
tagsstring | string[]只保留至少带有这些标签之一(OR)的定义。
handlerstring | string[]只保留通过 文件夹约定 附加到这些命名 handler 之一的定义。
orphansOnlyboolean只返回孤立定义(未附加到任何命名 handler 的定义)。与 handler 互斥。

enabled() 过滤

传入当前的 H3Event 以应用每个定义的 enabled 守卫。当前请求中被隐藏的定义会被排除,因此你公开的目录与请求在 tools/list 中实际看到的内容一致:

const all = await listMcpTools()
const visible = await listMcpTools({ event })

按 group 过滤

根据目录结构自动推断(例如 server/mcp/tools/admin/foo.ts'admin'),或者在定义上显式设置。

const adminTools = await listMcpTools({ group: 'admin' })
const adminOrContent = await listMcpTools({ group: ['admin', 'content'] })

按 tags 过滤

标签使用 OR 匹配——传入多个标签可以扩大结果范围。若要要求每一个列出的标签(AND),可对结果再使用 Array.filter 进行后过滤。

const publicTools = await listMcpTools({ tags: 'public' })
const publicOrDocs = await listMcpTools({ tags: ['public', 'docs'] })

const publicAndStable = (await listMcpTools({ tags: 'public' }))
  .filter(t => t.tags?.includes('stable'))

按 handler 归属过滤

使用 handler 将目录限定到单个 命名 handler,或使用 orphansOnly: true 仅枚举通过默认路由公开的定义:

const adminCatalog = await listMcpTools({ handler: 'admin' })
const adminOrPublic = await listMcpTools({ handler: ['admin', 'public'] })
const orphans = await listMcpTools({ orphansOnly: true })

组合使用

筛选条件可以自由组合——在一次调用中同时进行感知请求的可见性过滤,以及 group、tag 和 handler 的缩小范围筛选:

const adminDestructive = await listMcpTools({
  event,
  handler: 'admin',
  tags: 'destructive',
})

缓存

列表读取成本很低(从自动生成的注册表进行内存读取),但如果你将它们暴露在公开路由上,仍然可以用 defineCachedEventHandler 包装处理函数,以添加 HTTP 缓存头:

server/routes/.well-known/mcp/server-card.json.get.ts
import { listMcpDefinitions } from '@nuxtjs/mcp-toolkit/server'

export default defineCachedEventHandler(async (event) => {
  const definitions = await listMcpDefinitions({ event })
  return { name: 'My MCP Server', ...definitions }
}, {
  maxAge: 60 * 60,
  swr: true,
})
如果你传入 event 以应用依赖于每次请求上下文(认证、请求头)的 enabled() 守卫,就跳过缓存包装器。缓存会冻结第一次请求上下文下的响应。

下一步

  • 动态定义 — 使用 enabled() 守卫按请求隐藏或显示定义。
  • Hooks — 添加额外目录以扫描定义。
  • Handlers — 定义带有自己工具子集的自定义 MCP 端点。