| name | mcpc-core |
| description | Build agentic MCP servers using @mcpc/core by composing existing MCP tools. Use when creating, extending, or debugging MCPC agentic servers — including setting up compositions, choosing execution modes, writing plugins, loading skills, and connecting transports. |
@mcpc/core — Build Agentic MCP Servers
@mcpc/core lets you compose existing MCP tools into agentic MCP tools. You
write a description that references tools via <tool> XML tags, and MCPC wires
everything up into a working MCP server.
Installation
deno add jsr:@mcpc/core
npm install @mcpc-tech/core
pnpm add jsr:@mcpc/core
Minimal Example
import { mcpc } from "@mcpc/core";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = await mcpc(
[{ name: "my-agent", version: "1.0.0" }, { capabilities: { tools: {} } }],
[{
name: "file-agent",
description: `I help manage files.
Available tools:
<tool name="@wonderwhy-er/desktop-commander.read_file"/>
<tool name="@wonderwhy-er/desktop-commander.write_file"/>`,
deps: {
mcpServers: {
"@wonderwhy-er/desktop-commander": {
command: "npx",
args: ["-y", "@wonderwhy-er/desktop-commander@latest"],
transportType: "stdio",
},
},
},
}],
);
await server.connect(new StdioServerTransport());
Core API
mcpc(serverConf, composeConf?, options?)
| Param | Type | Description |
|---|
serverConf | [ServerMeta, ServerCapabilities] | Name/version + capabilities tuple |
composeConf | ComposeInput[] | Array of ComposeDefinition objects or .md file paths |
options | McpcOptions | Loader plugins + setup callback |
Returns Promise<ComposableMCPServer>.
ComposeDefinition
{
name: string | null,
description?: string,
manual?: string,
deps?: MCPSetting,
plugins?: (ToolPlugin | string)[],
options?: {
mode?: "agentic" | "ai_sampling" | "ai_acp",
maxSteps?: number,
maxTokens?: number,
samplingConfig?: SamplingConfig,
providerOptions?: { modelPreferences?: {...} },
acpSettings?: { command, args, env, session, persistSession },
tracingEnabled?: boolean,
refs?: ToolRefXml[],
}
}
Tool References (<tool> XML)
In the description field, reference tools with XML tags:
<tool name="server.tool_name"/> — specific tool
<tool name="server.__ALL__"/> — all tools from a server
<tool name="server.tool" maxResultLength="2000"/> — truncate large results
<tool name="server.tool" hide/> — use internally, hide from public API
<tool name="server.tool" global/> — expose at top-level scope
MCP Server Dependencies (deps.mcpServers)
Three transport types:
"my-server": { command: "npx", args: ["-y", "pkg@latest"], transportType: "stdio" }
"remote": { transportType: "streamable-http", url: "https://api.example.com/mcp/",
headers: { "Authorization": "Bearer ${TOKEN}" } }
"sse-server": { transportType: "sse", url: "https://api.example.com/sse/" }
Execution Modes
| Mode | Description | Best For |
|---|
agentic | Fully autonomous, uses MCP sampling | Default; most flexible |
ai_sampling | Uses AI SDK streamText + MCP sampling provider | When you control the model |
ai_acp | AI SDK + ACP protocol for coding agents | Claude Code, Codex-style agents |
Plugins
Built-in Plugins (import from @mcpc/core/plugins)
import {
createBashPlugin,
createLargeResultPlugin,
createSearchPlugin,
createSkillsPlugin,
} from "@mcpc/core/plugins";
Using Plugins
plugins: [
createLargeResultPlugin({ maxSize: 8000 }),
createSkillsPlugin({ paths: [".agents/skills"] }),
createBashPlugin(),
"./my-plugin.ts?param=value",
];
await mcpc(serverConf, composeConf, {
plugins: ["@mcpc/plugin-markdown-loader"],
});
Writing a Custom Plugin (ToolPlugin)
import type { ToolPlugin } from "@mcpc/core";
const myPlugin: ToolPlugin = {
name: "my-plugin",
transformTool?: (tool: ComposedTool, ctx: TransformContext) => ComposedTool,
transformInput?: (args: unknown, ctx: BeforeToolExecuteContext) => unknown,
transformOutput?: (result: unknown, ctx: AfterToolExecuteContext) => unknown,
onComposeStart?: (ctx: ComposeStartContext) => void,
onComposeEnd?: (ctx: ComposeEndContext) => void,
onFinalize?: (ctx: FinalizeContext) => void,
};
Skills Plugin
createSkillsPlugin adds a {agent}__load-skill tool that lazy-loads skill
content:
createSkillsPlugin({
paths: [join(projectRoot, ".agents/skills")],
});
Skills directory structure:
.agents/skills/
└── my-skill/
├── SKILL.md ← main instructions (loaded by default)
└── references/
└── api.md ← loaded via { skill, ref: "references/api.md" }
Agent calls:
agent__load-skill({ skill: "my-skill" })
agent__load-skill({ skill: "my-skill", ref: "references/api.md" })
Markdown Agent Files
Load agent definitions from .md files (requires
@mcpc/plugin-markdown-loader):
await mcpc(
[{ name: "server", version: "1.0.0" }, { capabilities: { tools: {} } }],
["./agents/my-agent.md"],
{ plugins: ["@mcpc/plugin-markdown-loader"] },
);
Markdown format:
---
name: my-agent
deps:
mcpServers:
some-server:
command: npx
args: ["-y", "some-server"]
transportType: stdio
options:
mode: agentic
---
I am an agent that does X.
<tool name="some-server.tool"/>
Setup Callback (Custom Tools)
Register tools directly on the server before composition:
import { jsonSchema } from "@mcpc/core";
await mcpc(serverConf, composeConf, {
setup: async (server) => {
server.tool(
"my-tool",
"Description of tool",
jsonSchema({ type: "object", properties: { input: { type: "string" } } }),
async (args) => ({
content: [{ type: "text", text: `Got: ${args.input}` }],
}),
);
await server.addPlugin(myPlugin);
},
});
Gotchas
transportType is required in every mcpServers entry — omitting it
causes a silent failure.
name: null in ComposeDefinition skips creating the composed tool;
useful for composition-only (just wiring up deps + plugins).
- Plugin load order matters:
McpcOptions.plugins run before composition
(use for loaders). ComposeDefinition.plugins run after composition (use for
runtime transforms).
hide vs global on <tool>: hide keeps a tool internal to the agent.
global exposes it at top-level without a namespace prefix.
manual field: if set, description becomes a short summary and full
content is behind a man tool call — reduces initial context size.
- Environment variables in headers: use
${VAR_NAME} syntax inside strings
in deps.mcpServers[*].headers — MCPC expands them at runtime.
maxSteps default is 50 for ai_sampling/ai_acp modes — increase for
complex multi-step tasks.
References