@McpExpose
The @McpExpose decorator and createMcpService(app, ConfigClass) ("@agboss/core/mcp") turn an AGBoss @Application into a standards-compliant Model Context Protocol (MCP) server. External MCP clients (Codex, Cursor, Windsurf, Claude Code, or another AGBoss application) can discover and call your exposed @WorkflowStart entry points and @Tool classes with full @Budget, @PiiPolicy, and @InputGuardrail / @OutputGuardrail enforcement.
Complete @McpExpose and createMcpService example
Section titled “Complete @McpExpose and createMcpService example”import { Tool, WorkflowStart, createApp, type ToolHandler } from "@agboss/core";import { Text, WorkflowStartTextDto } from "@agboss/core/dto";import { McpExpose, createMcpService } from "@agboss/core/mcp";import { JobScoutApplication } from "../job-scout.application.js";
export class JobQueryDto { @Text({ prompt: "Role keywords" }) query!: string;}
export class JobResultsDto { @Text({ prompt: "Formatted job matches" }) text!: string;}
@Tool({ name: "search_jobs", description: "Searches open engineering roles", input: JobQueryDto, output: JobResultsDto,})export class SearchJobsTool implements ToolHandler<JobQueryDto, JobResultsDto> { run({ query }: JobQueryDto): Promise<JobResultsDto> { return Promise.resolve({ text: `Matches for ${query}` }); }}
@WorkflowStart({ name: "chat-workflow-start", description: "Starts a Job Scout recruiting turn from an MCP client", input: WorkflowStartTextDto,})export class ChatWorkflowStart {}
@McpExpose({ name: "job-scout-mcp", version: "1.0.0", exports: [SearchJobsTool, ChatWorkflowStart],})export class JobScoutMcpExpose {}
export async function serveMcpStdio() { const app = await createApp(JobScoutApplication); const service = createMcpService(app, JobScoutMcpExpose); await service.connectStdio();}import { expect } from "vitest";import { ExecutionStatus } from "@agboss/core";import { replyWith, testTool, testWith } from "@agboss/core/testing";import { JobScoutApplication, ScoutAgent } from "../src/job-scout.application.js";import { ChatWorkflowStart, JobScoutMcpExpose, SearchJobsTool,} from "../src/mcp/job-scout.expose.js";
const test = testWith(JobScoutApplication);
test("executes the MCP-exposed tool and workflow start entry point", async ({ app, mockLlm }) => { expect(JobScoutMcpExpose).toBeDefined();
const runSearchTool = testTool(SearchJobsTool); const { output: toolOut } = await runSearchTool({ query: "Staff TypeScript" }); expect(toolOut.text).toContain("Staff TypeScript");
mockLlm(ScoutAgent).thenReturn(replyWith("Found 3 Staff TypeScript roles.")); const wfOut = await app.execute(ChatWorkflowStart, { text: "Find Staff TypeScript roles" }); expect(wfOut.status).toBe(ExecutionStatus.Finished);});What options does @McpExpose accept?
Section titled “What options does @McpExpose accept?”| Option | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | MCP server identifier advertised during protocol initialization (e.g., "job-scout-mcp"). |
version |
string |
Yes | Semantic version of the exposed MCP surface (e.g., "1.0.0"). |
exports |
readonly Class[] |
Yes | Array of @Tool and @WorkflowStart classes exposed as callable MCP tools. |