
Define TypeScript capabilities that send emails, manage calendars, and automate work. Expose them to the Routecraft agent, Claude, ChatGPT, Cursor, or any AI agent via MCP.
Overview
Tools for agents. Or the agent harness itself. Routecraft is a TypeScript framework for AI automation. A capability is a route: a typed pipeline from a source, through operations, to a destination. The same route is an MCP tool for Claude or Cursor, a tool for an agent you run yourself, an HTTP endpoint, or a scheduled job, depending only on its source. Agents are routes too, with the same guardrails around a model call as around any other step. Nothing is reachable until you write a route for it. craft-harness is a complete agent built out of Routecraft capabilities: chat, a sandboxed shell, web fetch and search, a workspace, memory, a scheduler, human approvals, and the editor capabilities. Every one of them is an ordinary route in capabilities/ you can read on one screen and change. The instance is walled, the settings file carries the credential, and the transcript is a file --session names.
README
About
Routecraft is the open source AI automation platform your teams build on together. A capability is a route: a typed pipeline from a source, through operations, to a destination. The same route is an MCP tool for any agent or editor, a tool for an agent you run yourself, an HTTP endpoint, or a scheduled job, depending only on its source. Prove it on your laptop, promote it to a team harness, and every team can use it on service credentials instead of their own. Agents are routes too, with the same guardrails around a model call as around any other step. Nothing is reachable until you write a route for it.
Five minutes: an agent you own
craft-harness is a complete agent built out of Routecraft capabilities: chat, a sandboxed shell, web fetch and search, a workspace, memory, a scheduler, human approvals, and the editor capabilities. Every one of them is an ordinary route in capabilities/ you can read on one screen and change.
bunx create-routecraft my-agent --example https://github.com/routecraftjs/craft-harness
cd my-agent
bun run setup # generates the project's own secrets into .env and .routecraft/
# add LLM_API_KEY to .env
bun run dev
From another terminal:
bun run exec chat --session=demo --message="what can you do?"
The instance is walled, the settings file carries the credential, and the transcript is a file --session names. The same conversation is reachable over MCP at http://localhost:8081/mcp and from your editor over the Agent Client Protocol.
What a capability looks like
import { craft, mail } from '@routecraft/routecraft'
import { mcp } from '@routecraft/ai'
import { z } from 'zod'
const SendTeamEmail = z.object({
to: z
.string()
.email()
.refine((email) => email.endsWith('@company.com'), 'Can only send to @company.com addresses'),
subject: z.string(),
message: z.string(),
})
// The route id is the tool name; description and input schema live on the
// route, so every call is validated before any of your code runs.
export default craft()
.id('send-team-email')
.description('Send an email to a team member')
.input({ body: SendTeamEmail })
.from(mcp())
.transform(({ to, subject, message }) => ({ to, subject, text: message }))
.to(mail()) // the account comes from craft.config.ts
The source decides the door. .from(mcp()) makes it an MCP tool. .from(direct()) makes it a capability any local agent can call and craft exec can run. .from(http()) makes it an endpoint. The steps in between do not change. A cron() schedule brings no body, so it gets a small route of its own that builds this input and calls the capability through direct().
An agent is a route too
import { craft, direct } from '@routecraft/routecraft'
import { agent, tools } from '@routecraft/ai'
import { z } from 'zod'
export default craft()
.id('assistant')
.description('Answer a question with the tools this project defines')
.input({ body: z.object({ question: z.string() }) })
.from(direct())
.to(
agent({
model: 'anthropic:claude-opus-4-7',
system: 'Be useful. Say what you did.',
user: (ex) => ex.body.question,
tools: tools(['Direct(send-team-email)']),
}),
)
Tools are an allowlist of capabilities, never a blacklist. An agent can also be a markdown file under agents/ with frontmatter for its model and tools, which craft start discovers with everything else in the project. Because the agent is a step in a route, .authorize(), .throttle(), .retry(), .timeout() and .circuitBreaker() apply to the model call exactly as to any other step.
What you get
- Work that survives a restart.
.defer()defers an exchange in a store, and.resume()revives it by token, hours or days later, from any transport. Durable agents defer mid-conversation the same way. - Agents with sessions and background tools. A conversation is a record a person owns; a tool can hand a long job to a route and come back when it finishes. Agent adapter.
- Talk to your agents from your editor.
craft acpand theacpconfig key serve the Agent Client Protocol. Talk from your editor. - MCP both ways. Expose routes as tools with
mcp()and themcpplugin; call other servers’ tools asMCP(server:tool)in an agent’s tool list. Expose to an agent, call an MCP. - Isolated host execution.
shell()runs commands in an isolation tier, including a throwaway Docker container per command, with egress denied by default. - A management API and a CLI to drive it. The ops plugin serves health, readiness, a route listing and dispatch behind scope-gated tiers;
craft execandcraft opsare its clients. CLI reference. - Secure by design. JWT, JWKS and API-key validators,
.authorize()at route entry, principals that follow an exchange through every hop. Securing capabilities. - One way to extend it. A plugin is a descriptor with an
idand lifecycle hooks, and it may provide and require typed ports, add hooks to the fixed chain’s slots, declare builder steps and a facet on the exchange, and replace what fills a chain position. The framework’s own features are plugins built the same way. Plugins.
Add Routecraft to an existing project
bunx create-routecraft my-app
cd my-app
bun add @routecraft/ai nodemailer
The capability above uses mcp() from @routecraft/ai and sends through mail(), which needs nodemailer. An adapter that is missing its package names it when it runs.
Expose a capability to Claude Desktop by adding it to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"my-tools": {
"command": "bunx",
"args": ["@routecraft/cli", "run", "./capabilities/send-team-email.ts"]
}
}
}
Now talk to Claude: “Send an email to [email protected] thanking him for yesterday’s meeting”. Claude discovers the tool and calls it with validated input.
The
craftCLI runs on Bun (>=1.1.0). Node users embed@routecraft/routecraftprogrammatically; see the Programmatic Invocation guide.
📚 Get Started | Project structure | Examples | API Reference
Monorepo Structure
packages/routecraft– Core library (builder, DSL, context, adapters, consumers, the ops plugin)packages/ai– AI integrations: LLM providers, agents, embeddings, MCP server / client, ACPpackages/cli–craftCLI to run capabilities and start contexts (Bun >= 1.1.0)packages/create-routecraft– Project scaffolder (bunx create-routecraft)packages/eslint-plugin-routecraft– ESLint rules for capability authoringpackages/prettier-plugin-routecraft– Prettier plugin for compact DSL formattingpackages/os– System-native adapters: isolated subprocess execution viashell()packages/testing– Test utilities (testContext, spy logger,mockAdapter, fixtures)skills/– Agent Skills for authoring Routecraft (Claude Code, Cursor, Codex, Windsurf, Cline, Continue, Copilot, …;bunx skills add routecraftjs/routecraft). See skills/README.mdapps/routecraft.dev– Documentation site (docs, examples, guides)examples/– Runnable example capabilities
Examples
Browse runnable examples in examples/src/: hello-world.ts, mcp-greet.ts, agent.ts, find-product.ts, mail-noreply-notify.ts, jev-judge.ts, programmatic-invocation.ts, split.ts. Each demonstrates a different feature combination.
Try one:
bun install
bun run build
bunx craft run ./examples/dist/mcp-greet.js
For end-to-end walkthroughs, see the docs site.
Contributing
Contributions are welcome! Please read our contribution guide at https://routecraft.dev/docs/community/contribution-guide for guidelines on how to propose changes, add adapters, and write capabilities.
License
Licensed under the Apache 2.0 License.
Install
This server does not publish a one-line install command.
Open the repository installation guide New to MCP? Start with the mcpskill.org guide →Configuration
{
"mcpServers": {
"my-tools": {
"command": "bunx",
"args": ["@routecraft/cli", "run", "./capabilities/send-team-email.ts"]
}
}
}