Mcp - agbossjs/agboss GitHub Wiki
agboss/mcp works both ways:
-
Using MCP servers —
@McpServerdeclares a server and the server tools the workflow uses,@McpToolis a tool with that server injected. See Components → MCP and Tools. -
Exposing a workflow over MCP —
@McpExposelists the workflow's tools and workflow starts to offer to MCP clients (Claude Desktop, other agents);createMcpServiceserves them over stdio or HTTP. This page is about this side.
// src/mcp/job-scout.expose.ts
import { McpExpose } from "agboss/mcp";
@McpExpose({
name: "job-scout-mcp",
version: "1.0.0",
exports: [SearchIssues, ChatWorkflowStart], // tools of the workflow, and its workflow starts
})
export class JobScoutMcp {}- A
@Tool/@McpToolexport runs through the same adapter as an agent's tool call: its input and output DTOs become the JSON Schemas, both are validated, its timeout applies, it gets acallId. It must be a tool of the workflow (one of its agents' tools), elsecreateMcpServicefails naming it. - A
@WorkflowStartexport becomes a tool that runs the workflow (app.execute); with any start exported,resume_workflow(app.resume) is offered too.
For Claude Desktop and other local clients, the service talks over stdin/stdout:
import { createMcpService } from "agboss/mcp";
const app = await createApp(JobScout);
const service = createMcpService(app, JobScoutMcp);
await service.connectStdio(); // serves until stdin closesMcpService knows no HTTP framework: handleSse(res, messageEndpoint, context) opens a session's
event stream, handleMessage(req, res, sessionId, body) takes the client's messages. The context
given to a session is what its tool calls see as ctx.executionContext — authorization stays out of
the tools' code (Context and Authorization).
import { createServer } from "node:http";
createServer((req, res) => {
const url = new URL(req.url ?? "/", "http://localhost");
if (req.method === "GET" && url.pathname === "/mcp") {
const context = { tenant: req.headers.authorization }; // bound to this session
void service.handleSse(res, "/mcp/messages", context);
return;
}
if (req.method === "POST" && url.pathname === "/mcp/messages") {
void service.handleMessage(req, res, url.searchParams.get("sessionId") ?? "");
return;
}
res.writeHead(404).end();
}).listen(3001);service.connect(transport, context) takes any MCP SDK transport instead (e.g. in tests, an
in-memory pair).