Examples
MCP tool
Expose a capability as an MCP tool, and call a remote MCP server from a capability.
MCP is a two-sided adapter. The same mcp() adapter turns a capability into a tool an agent
can call (source mode), and lets a capability call a tool on a remote MCP server (destination
mode). This page shows both.
Expose a capability as an MCP tool
Use mcp() as a source. The tool name is the capability's .id(); the AI-facing
.title(), .description() and the .input() schema live on the builder, and Routecraft
validates every call against the schema before the pipeline runs. The direct() source beside
it lets other capabilities call the same tool in-process.
// capabilities/greet-user/route.ts
import { craft, direct, log, noop } from '@routecraft/routecraft'
import { mcp } from '@routecraft/ai'
import { z } from 'zod'
const GreetInput = z.object({
user: z.string().trim().min(1).describe('The user to greet.'),
})
export default craft()
.id('greet-user')
.title('Greet user')
.description('Greet a user by name')
.input({ body: GreetInput })
.from(direct(), mcp())
.transform((body) => `Hello, ${body.user}!`)
.tap(log())
.to(noop())
The mcp key in craft.config.ts serves every capability with an mcp() source as a tool
over stdio. A new project already has it:
// craft.config.ts
import { defineConfig } from '@routecraft/routecraft'
import '@routecraft/ai'
export const craftConfig = defineConfig({
mcp: {},
})
Over stdio the client starts the project itself and talks to it on its standard streams, so there is no process to run first. Register it with Claude Code from the project folder:
claude mcp add my-tools -- bunx craft start --log-file craft.log
The log goes to a file because standard output is the protocol. Then ask the client to
greet Ada: it calls greet-user with { "user": "Ada" } and gets Hello, Ada! back.
Cursor, Claude Desktop and VS Code take the same command in JSON, with absolute paths:
Expose to an agent has each
client's file, and the HTTP transport for a team. Securing capabilities
covers authentication once the tool is served over HTTP.
Call an external MCP server
Register the remote servers under the same mcp key's clients, then call any tool with the
server:tool shorthand. .to() and bare .enrich() replace the body with the tool result; pass an aggregator such as only() to .enrich() to merge it instead.
// craft.config.ts
import { defineConfig } from '@routecraft/routecraft'
import '@routecraft/ai'
export const craftConfig = defineConfig({
mcp: {
clients: {
search: { url: 'http://127.0.0.1:9000/mcp' },
},
},
})
// capabilities/web-search/route.ts
import { craft, simple, log } from '@routecraft/routecraft'
import { mcp } from '@routecraft/ai'
export default craft()
.id('web-search')
.from(simple({ query: 'Routecraft documentation' }))
.to(mcp('search:web_search'))
.to(log())
See Calling an MCP for custom argument mapping and inline-URL
calls, and the mcp() adapter reference for the full option
surface on both sides.
Related
Expose to an agent
Serve capabilities as MCP tools over stdio or HTTP, and wire up each client.
Calling an MCP
Call external MCP servers from within a capability, and govern the tools an agent holds.
mcp
The mcp() adapter: every option for serving a tool and for calling one.