Advanced Topics

Listing Definitions

Read the toolkit's discovered tools, resources, and prompts from your own server routes — without duplicating their names and descriptions.

Overview

The toolkit auto-discovers every tool, resource, and prompt under server/mcp/. From your own server routes you sometimes need to read that catalog back — to render an /.well-known/mcp/server-card.json, an admin dashboard, an API catalog, or a sitemap.

Use the listMcp* helpers from @nuxtjs/mcp-toolkit/server to get JSON-friendly summaries of every discovered definition without duplicating their names and descriptions in your own code.

HelperReturns
listMcpTools(options?)McpToolSummary[] (JSON-friendly)
listMcpResources(options?)McpResourceSummary[] (JSON-friendly)
listMcpPrompts(options?)McpPromptSummary[] (JSON-friendly)
listMcpDefinitions(options?){ tools, resources, prompts }
getMcpTools(options?)McpToolDefinitionListItem[] (raw, with handlers + Zod schemas)
getMcpResources(options?)McpResourceDefinition[] (raw)
getMcpPrompts(options?)McpPromptDefinition[] (raw)

Each summary contains name, title, description, group, tags, and handler (plus uri for resources). Names auto-generated from the filename are already resolved, so what you get matches exactly what the MCP client sees in tools/list.

Use listMcp* for summaries (JSON catalog endpoints). Use getMcp* to feed raw definitions back into defineMcpHandler({ tools: ev => getMcpTools(...) }).

Usage

Server card

Expose the toolkit's catalog as a server-card.json so other agents can discover what your server provides:

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: 'Tools, resources and prompts exposed by my Nuxt app.',
    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 })),
  }
})

Tool catalog

Render a public list of available tools, optionally grouped:

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')
})

Options

Every helper accepts the same ListMcpDefinitionsOptions object. All keys are optional and combine with AND semantics — a definition must pass every active filter.

OptionTypeDescription
eventH3EventApply per-definition enabled() guards using the request context.
groupstring | string[]Keep only definitions whose group matches one of these (OR).
tagsstring | string[]Keep only definitions tagged with at least one of these (OR).
handlerstring | string[]Keep only definitions attached to one of these named handlers via folder convention.
orphansOnlybooleanReturn only orphan definitions (those not attached to any named handler). Mutually exclusive with handler.

Filter by enabled()

Pass the current H3Event to apply per-definition enabled guards. Definitions hidden for the current request are excluded so the catalog you expose matches what the request would actually see in tools/list:

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

Filter by group

Auto-inferred from the directory structure (e.g. server/mcp/tools/admin/foo.ts'admin') or set explicitly on the definition.

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

Filter by tags

Tags use OR-match — pass several to widen the result. To require every listed tag (AND), post-filter the result with 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'))

Filter by handler attribution

Use handler to scope the catalog to a single named handler, or orphansOnly: true to enumerate definitions only exposed via the default route:

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

Combine everything

Filters compose freely — request-aware visibility plus group, tag, and handler narrowing in one call:

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

Caching

Listings are cheap (in-memory reads of the auto-generated registry), but if you expose them on a public route you can still wrap the handler with defineCachedEventHandler to add HTTP cache headers:

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,
})
Skip the cache wrapper if you pass event to apply enabled() guards that depend on per-request context (auth, headers). Caching would freeze the response for the first request's context.

Next Steps

  • Dynamic Definitions — Hide or show definitions per request with enabled() guards.
  • Hooks — Add extra directories to scan for definitions.
  • Handlers — Define custom MCP endpoints with their own subset of tools.
Copyright © 2026