Add MCP server
The built-in MCP server every plugin gets automatically, hosting several named servers, and declaring external MCP servers.
The built-in MCP server
You never have to “add” the first MCP server: as soon as the plugin has a tool or a prompt, it
is an MCP server. Add a class to src/tools/ (or src/prompts/) and export it from the mod.ts
barrel — the plugin then serves a complete MCP server with zero configuration:
- Endpoint:
/mcpon the plugin’s origin, speaking streamable HTTP — point Claude, ChatGPT, MCPJam or any MCP client athttp://localhost:4321/mcpin dev. - Name: the last segment of the plugin name (
my-pluginfor@my-org/my-plugin). Override it withmcp.nameinqrtl.config.ts. - Capabilities:
toolsalways;promptswhen the plugin has prompts;resourceswhen it has widgets (each widget is served as aui://widgets/<toolId>.htmlresource). - Declared everywhere: the server is emitted into the generated
mcp.json(and Claude’s.mcp.jsoninside/plugin.zip), listed in the plugin overview, and shown on the plugin’s own docs site with a live tool tester. - REST mirrors:
GET /mcp/tools.json,/mcp/prompts.jsonand/mcp/resources.jsonreturn the exacttools/list/prompts/list/resources/listresults as plain GETs — handy for debugging and for agents that just want to read the catalog.
Set mcp: false in qrtl.config.ts to turn the MCP server off (the REST API keeps working).
Host several named servers
One plugin can host multiple MCP servers, each exposing a subset of the tool classes. This
keeps a client’s tool list focused: a client interested only in reporting tools does not need to
see the admin tools. Define a mcp.servers map in qrtl.config.ts:
import { defineQrtlConfig } from "@quartal/plugin";
export default defineQrtlConfig({
title: "My Plugin",
mcp: {
servers: {
main: {
tools: ["Invoices", "Customers"],
description: "Day-to-day invoicing tools.",
},
admin: {
tools: ["UserAdmin"],
description: "Administrative tools.",
},
},
},
});
The rules:
- Each server is mounted at
/mcp/<name>; names must match[a-z0-9_-]+. - The server named
main(or the first entry, when none is namedmain) is the main server and is also served at/mcp. toolslists tool class names fromsrc/tools/. Omittingtoolson a hosted server means all tool classes.- Prompts are served on the main server; each widget is served by the server that owns its tool.
- Every server gets its own REST mirror, e.g.
GET /mcp/admin/tools.json.
Add an external MCP server
A plugin can also declare an MCP server that already exists elsewhere — an upstream service,
a server with special auth, or an old server you are migrating from. Use external instead of
tools:
export default defineQrtlConfig({
mcp: {
servers: {
main: { description: "This plugin's own tools." },
"astro-docs": {
external: { url: "https://mcp.docs.astro.build/mcp" },
description: "Astro documentation search.",
},
},
},
});
An external server is declaration-only: the plugin does not host or proxy it. The entry is
emitted into the generated mcp.json (and .mcp.json) next to the hosted servers, so a client
that installs the plugin connects to the original URL directly. external.headers adds HTTP
headers clients should send (e.g. an API-key header) — but note that mcp.json is public:
never put a secret value in headers.
external and tools are mutually exclusive; everything else about naming works as above (an
external server named main does not take over /mcp, though — only hosted servers mount there).
A complete example
The test1 sample
uses all three kinds of entries: a main server with the general demo tools, a hosted types
server exposing only the TypesTester class, and the external astro-docs server.
Where the servers show up
GET /mcp.json— the standard MCP configuration document: every server as astreamable-httpentry; hosted servers on the plugin’s origin, external servers at their original URL.- The plugin’s docs site — the front page lists every server with its endpoint URL, and the MCP Servers page shows the endpoints, tool counts and descriptions.
GET /com.quartal.plugin/contents.json— themcpServersarray of the plugin overview.GET /plugin.zip— the installable Agent Plugin, carrying both MCP config variants.
See the HTTP endpoints reference for the full endpoint list and
the configuration reference for every mcp option.