Skip to content

feat(nitro): install extension plugins from server/mcp/plugins.ts - #333

Open
HugoRCD wants to merge 1 commit into
feat/nitro-oauth-connectorsfrom
feat/nitro-plugins-convention
Open

feat(nitro): install extension plugins from server/mcp/plugins.ts#333
HugoRCD wants to merge 1 commit into
feat/nitro-oauth-connectorsfrom
feat/nitro-plugins-convention

Conversation

@HugoRCD

@HugoRCD HugoRCD commented Sep 3, 2026

Copy link
Copy Markdown
Member

📚 Description

Stacked on #332. Independent of the OAuth work below it — it sits here only because it rewrites renderHandler's signature, which #331 introduces.

An h3-mcp ExtensionPlugin is a live function, and mcp() options cross into generated code as JSON, so a plugin could never be passed as an option. A file beside tools/, resources/ and prompts/ can be: the generated handler imports its default export and hands it to createMcpHandler as extensionPlugins. ExtensionPlugin is now re-exported so the file can name the type it satisfies.

// server/mcp/plugins.ts
import { mcpTasks } from 'h3-mcp/tasks'
import type { ExtensionPlugin } from 'nitro-mcp-toolkit'

export default [mcpTasks({ max: 100 })] satisfies ExtensionPlugin[]

Like a definition, the file belongs to whichever mcp() scans its directory. discoverPlugins returns every match rather than picking one, so the module can refuse an ambiguous pair while naming the route it belongs to. The handler virtual becomes async for the same reason the registry is — a file written after setup has to be seen at rebuild — and the watcher treats it like a definition, since nothing imports it until the handler is generated again.

The nitro-playground app now ships one, and each build names the file it installed alongside the counts it reports.

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

An h3-mcp `ExtensionPlugin` is a live function, and `mcp()` options cross
into generated code as JSON, so a plugin could not be passed as an
option. A file beside `tools/`, `resources/` and `prompts/` can be: the
generated handler imports its default export and hands it to
`createMcpHandler` as `extensionPlugins`. `ExtensionPlugin` is now
re-exported so the file can name the type it satisfies.

Like a definition, the file belongs to whichever `mcp()` scans its
directory. `discoverPlugins` returns every match rather than picking one,
so the module can refuse an ambiguous pair while naming the route it
belongs to. The handler virtual is async for the same reason the registry
is — a file written after `setup` has to be seen at rebuild — and the
watcher treats it like a definition, since nothing imports it until the
handler is generated again.
@vercel

vercel Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
nuxt-mcp-toolkit-docs Ready Ready Preview Sep 3, 2026 3:40pm UTC

Request Review

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Thank you for following the naming conventions! 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant