MCP Integration
Execbox has two MCP adoption paths. Use MCP providers when guest code should call upstream MCP tools. Use the code MCP server when an MCP client should call execbox.
Wrap MCP tools as a provider
Section titled “Wrap MCP tools as a provider”Use @execbox/core/mcp to adapt an MCP tool catalog into a resolved provider.
The provider can then be passed to any execbox executor.
import { openMcpToolProvider } from "@execbox/core/mcp";import { QuickJsExecutor } from "@execbox/quickjs";
const handle = await openMcpToolProvider({ server: upstreamServer });
try { const executor = new QuickJsExecutor(); const result = await executor.execute( '(await mcp.search_docs({ query: "quickjs" })).structuredContent', [handle.provider], );
console.log(result);} finally { await handle.close();}Use createMcpToolProvider({ client }) when the caller owns an already
connected MCP client. Use openMcpToolProvider({ server }) when execbox opens a
local server connection and should return a cleanup handle.
Expose execbox as MCP tools
Section titled “Expose execbox as MCP tools”Use codeMcpServer() when downstream MCP clients should execute code against a
wrapped tool namespace.
import { codeMcpServer } from "@execbox/core/mcp";import { QuickJsExecutor } from "@execbox/quickjs";
const server = await codeMcpServer( { client: upstreamClient }, { executor: new QuickJsExecutor() },);The wrapper server exposes:
| Tool | Purpose |
|---|---|
mcp_search_tools | Search the wrapped MCP catalog with concise metadata |
mcp_get_tool_details | Inspect schemas and generated types for one selected tool |
mcp_execute_code | Execute guest JavaScript against the wrapped catalog |
The default codeMcpServer() mode is progressive: MCP clients can search the
catalog, inspect only the tools they need, then execute code. Use
mode: "single" only when a client needs the legacy all-in-one mcp_code tool
whose description embeds the full generated namespace. Use mode: "both" to
expose the progressive tools and mcp_code together.
const search = await client.callTool({ name: "mcp_search_tools", arguments: { query: "search docs" },});
const details = await client.callTool({ name: "mcp_get_tool_details", arguments: { safeName: "search_docs" },});mcp_search_tools returns only names, descriptions, and annotations.
mcp_get_tool_details returns the selected tool’s input schema, output schema,
and generated TypeScript declaration.
Result handling
Section titled “Result handling”Wrapped MCP tools preserve MCP CallToolResult envelopes. Guest code can read
structuredContent first and fall back to content when a tool only returns
text or other MCP content items.
const result = await mcp.search_docs({ query: "quickjs" });result.structuredContent?.hits ?? result.content;Boundaries
Section titled “Boundaries”MCP integration changes where tools come from or how execbox is exposed. The provider surface remains the capability boundary:
- wrap only the MCP tools a caller should be able to invoke
- keep upstream clients, secrets, and tenant routing in host code
- close handles returned by
openMcpToolProvider() - choose inline or worker-hosted QuickJS separately from the MCP adapter shape
The code-execution tools are annotated as potentially destructive because MCP tool annotations are static while guest code can call any wrapped tool exposed through the provider. Search and details tools are annotated read-only.
Examples
Section titled “Examples”execbox-mcp-provider.tswraps an upstream MCP server into a provider.execbox-mcp-server.tsexposes execbox execution through MCP tools.
Next:
- Providers & Tools for provider design
- Security & Boundaries for capability and deployment guidance
- Protocol for the advanced worker message contract