Skip to content

mountSpec

typescript
mountSpec(router, spec, options?: MountSpecOptions)
OptionDefaultDescription
basePath''Prefix for RPC paths and for paths baked into emitted documents
docstruePass false to disable /docs, /callspec.json, and /openapi.json at the mount root
visibility'public''public' — public-scope routes only. 'all' — also document scope: 'private' routes on this mount (dev/stage). See Auth and scope.
docsPath'/docs'Docs UI path on this router (callspec.json and openapi.json paths are fixed)
mcpPath'/mcp'MCP HTTP endpoint on this router
loggingtruejsout-express request log on this router + jsout error log on unhandled throws; pass false in tests
onCalljsout call info when loggingStructured per-call events for MCP tools/call (CallEvent). Custom sink for Logfox; () => {} to disable call events only
handleUnhandledErrorCatch handler exceptions — see Error handling: mountSpec flow.
logUnhandledErrorjsout logger.error when logging is onOptional (err, req) => void callback; replaces the default unhandled-throw sink

When docs is enabled, the docs UI fetches callspec.json at /callspec.json on this router (fixed path). Override only the UI mount:

typescript
mountSpec(router, spec, {docsPath: '/explorer'});
// UI at /explorer — still loads ../callspec.json relative to that path

Document private routes on this same /docs with visibility: 'all':

typescript
mountSpec(router, spec, {
visibility: process.env.NODE_ENV === 'production' ? 'public' : 'all',
});

See Error handling: mountSpec flow.

With app.use('/v1', router) and defaults, a server on port 3000 exposes:

SurfaceURL
Docs UIhttp://127.0.0.1:3000/v1/docs
Contracthttp://127.0.0.1:3000/v1/callspec.json
OpenAPIhttp://127.0.0.1:3000/v1/openapi.json
RPCPOST http://127.0.0.1:3000/v1/{methodName}
MCPhttp://127.0.0.1:3000/v1/mcp (when any route has mcp: true)

spec · Next: Auth and scope