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.


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.

Previous
File to HTTP