Model Context Protocol (MCP)
@heronjs/mcp exposes application services as Model Context Protocol tools,
fixed resources, and prompts. It supports HTTP and explicitly configured stdio
transport on Node.js 24 or later.
Define a tool catalog
import 'reflect-metadata';
import {Module} from '@heronjs/common';
import {HeronJS} from '@heronjs/core';
import {MCP, Tool} from '@heronjs/mcp';
import {z} from 'zod';
@MCP()
class Tools {
@Tool({name: 'echo', description: 'Echo text', inputSchema: z.object({text: z.string()})})
async echo(input: {text: string}) {
return {content: [{type: 'text' as const, text: input.text}]};
}
}
@Module({mcps: [Tools]})
class App {}
const app = await HeronJS.create({module: App});
// HTTP is the default; app.add({ mcp: {} }) may customize the options.
await app.listen({port: 3000, host: '127.0.0.1'});
// Connect an MCP client to http://127.0.0.1:3000/mcpTransport selection
Omitting runtime and McpOptions.transport selects HTTP. Registering MCP
controllers enables the MCP extension with its HTTP defaults. Explicit
runtime: { transport: 'stdio' } selects stdio when MCP transport is omitted.
For stdio use HeronJS.create({ module: App, runtime: { transport: 'stdio' } }),
app.add({ mcp: { transport: 'stdio' } }), then await app.start().
Never write application diagnostics to stdout in stdio mode; use stderr or Logger.
MCP and ACP cannot share process stdio. Call await app.close() for shutdown.
Handler contracts
Resource({ name, uri, mimeType? }) handlers receive a URL and return SDK
ReadResourceResult. Prompt({ name, argsSchema, description? }) handlers receive
validated arguments and return SDK GetPromptResult. Tools return CallToolResult.
Every handler’s second argument is McpContext, containing caller identity,
signal and the SDK protocol context. Shared service pools belong in DI; HTTP
controller instances are resolved per request. Handle cancellation cooperatively.
HTTP authentication and endpoint policy
HTTP options include path, allowedHosts and allowedOrigins (hostname lists;
SDK localhost defaults), publicAccess, verifyToken(token, request),
resourceMetadata and authorize(guard, context). A remote bind requires a verifier
or explicit publicAccess: true, plus the appropriate Host/Origin allowlists.
The token verifier must return SDK AuthInfo with token, clientId, scopes,
and expiresAt in epoch seconds. Verify token signatures and claims in that hook;
the SDK also checks expiry. Return undefined to reject the token.
Optional resourceMetadata accepts { resource, oauthMetadata, scopesSupported? },
where oauthMetadata is the authorization server metadata. The SDK validates it;
metadata is served at /.well-known/oauth-protected-resource followed by the MCP
path. Tokens must then identify the matching resource URL. Guard metadata is
evaluated against the authenticated identity, or by the configured authorize.
Notifications and limitations
SDK progress/notification APIs are available through context.protocol.mcpReq.
Unexpected errors are sanitized. Tool execution failures use isError: true.
Outgoing clients, custom WebSocket transports, dynamic catalogs and subscriptions
are not supported by this package in 4.0.0.
Multiple catalog endpoints
Declare @MCP('/mcp/search') and @MCP('/mcp/admin') on separate controllers.
Each path has its own tool/resource/prompt catalog. Tool names may repeat across
paths; duplicate entries within one catalog fail registration. Controllers sharing
a path contribute to the same catalog. @MCP() keeps the configured path,
defaulting to /mcp.
protocols.mcp.endpoints maps paths to per-endpoint settings such as name,
version, verifyToken, allowedHosts, and allowedOrigins. For example,
{ endpoints: { '/mcp/admin': { verifyToken } } } protects the admin catalog
independently. All paths share the application’s HTTP server and retain the SDK’s
HTTP transport, schema validation, and authentication handling.
For stdio with several catalogs, select one using
{ transport: 'stdio', endpoint: '/mcp/search' }. Ambiguous selection fails before
consuming stdin. The public decorators are MCP, Tool, Resource, and Prompt.
Based on 4.0.0 release source (4.0.0).