Add connected MCP server tools to your agents so they can interact with external services.
Adding via the UI
- Open your agent's settings → Tools tab
- Click Add Tool → Connector Tool
- Select a connected MCP server
- Choose which tools to expose to the agent
The agent sees each tool with its name, description, and input schema — just like any other tool.
Adding via YAML
In your agent's YAML config, add tools with type: mcp:
1tools:2 - name: list_issues3 type: mcp4 description: List Linear issues with filtering5 mcp:6 server: "linear"7 tool_name: "list_issues"89 - name: create_issue10 type: mcp11 description: Create a new Linear issue12 require_approval: true13 mcp:14 server: "linear"15 tool_name: "create_issue"| Field | Description |
|---|---|
server | The MCP server's slug (belt mcp list). Saving the agent refuses a server your workspace cannot use |
tool_name | The tool name as listed by belt mcp tools <slug> |
Each call signs in with the runner's own credential for the server's auth provider (linear-mcp): theirs, else their team's or org's. With none, the chat pauses and asks them to connect. A tool doesn't pin a credential; a credential_id from an older config is ignored.
Tool Schema and Description
When an agent loads a connector tool, the runtime resolves the name, description, and input schema the LLM sees:
| Step | Source | When it applies |
|---|---|---|
| 1. Cached schema | Credential metadata from connect time | Default. Populated when you connect via belt mcp connect, the web app, or POST /credentials |
| 2. Live fetch | MCP server tools/list | Cache is missing or the tool was added after connect |
| 3. Generic fallback | Single arguments object | Cache and live fetch both fail (unreachable server, legacy credential without a server URL) |
Description — The description on your agent tool overrides the MCP server's tool description. If you omit it, the runtime uses the server's description from the cached or live tool definition.
JSON Schema dialect
MCP tool inputSchema values are JSON Schema documents. Per the MCP specification (rev 2025-11-25, SEP-1613), schemas that omit "$schema" default to JSON Schema 2020-12. When a tool declares an explicit "$schema" (for example draft-07), inference shell parses the schema under that dialect.
When converting MCP schemas to the typed parameters agents and belt mcp tools display, the platform resolves array items across dialects — including 2020-12 single-schema arrays and draft-07 tuple forms.
Unions and enums — When an MCP tool parameter accepts more than one JSON Schema shape, the runtime keeps every non-null branch instead of picking a single “simplest” type:
| MCP / JSON Schema pattern | What the agent sees |
|---|---|
anyOf / oneOf with two or more non-null branches | One parameter whose schema includes anyOf with each branch converted recursively (for example string or integer for the same field) |
anyOf / oneOf where every branch is null | type: null (nothing useful to send — check the MCP server schema) |
Nullable idiom (anyOf: [{type: string}, {type: null}]) | The non-null branch only — whether a value may be omitted is controlled by top-level required, not by a null union member |
JSON Schema type array with multiple types (for example ["string", "number"]) | Treated as a union and emitted as anyOf when more than one type applies |
enum on a scalar | Closed set preserved as an enum array and appended to the description (Possible values: …) for older UIs |
Provider tool APIs (OpenAI, Anthropic, and others) accept anyOf in function parameters, so multi-shape MCP inputs reach the model intact. Reconnect MCP servers after platform upgrades if cached schemas were converted under the older single-branch rules.
Troubleshooting
If an agent tool shows a generic arguments parameter instead of typed fields, or array parameters look like untyped object[] instead of the element type the MCP server defines, reconnect the MCP server (belt mcp connect <slug>) so the platform can refresh cached tool schemas.
How It Works at Runtime
- Agent decides to call the tool based on the conversation
- Runtime loads your workspace's credentials
- Opens a fresh MCP session to the remote server
- Calls the tool with the agent's arguments
- Returns the result to the agent
Credentials are never exposed to the agent. Each tool call gets a fresh session — no state leaks between calls.
Require Approval
For destructive operations (creating issues, sending messages, deleting records), enable require_approval:
1- name: send_slack_message2 type: mcp3 description: Send a message to a Slack channel4 require_approval: true5 mcp:6 server: "slack"7 tool_name: "send_message"The agent pauses and waits for user confirmation before executing.
Example: Triage Agent
An agent that reads Linear issues and posts summaries to Slack:
1name: triage-agent2description: Summarizes new Linear issues and posts to Slack3core_app:4 ref: openrouter/claude-sonnet-455system_prompt: |-6 You triage incoming Linear issues. For each new issue:7 1. Read the issue details8 2. Categorize by severity and area9 3. Post a summary to the #triage Slack channel10tools:11 - name: list_issues12 type: mcp13 description: List recent Linear issues14 mcp:15 server: "linear"16 tool_name: "list_issues"1718 - name: get_issue19 type: mcp20 description: Get full issue details21 mcp:22 server: "linear"23 tool_name: "get_issue"2425 - name: post_to_slack26 type: mcp27 description: Post a message to Slack28 require_approval: true29 mcp:30 server: "slack"31 tool_name: "send_message"SDK Builders
Python
1from inferencesh import mcp_tool23list_issues = (4 mcp_tool("list_issues", server="linear", tool_name="list_issues")5 .describe("List Linear issues with filtering")6 .build()7)89create_issue = (10 mcp_tool("create_issue", server="linear", tool_name="create_issue")11 .describe("Create a new Linear issue")12 .require_approval()13 .build()14)The signature is mcp_tool(name, *, server, tool_name) (inferencesh ≥ v0.32.0; older versions also took credential_id).
JavaScript
1import { mcpTool } from '@inferencesh/sdk';23const listIssues = mcpTool('list_issues', { server: 'linear', toolName: 'list_issues' })4 .describe('List Linear issues with filtering')5 .build();67const createIssue = mcpTool('create_issue', { server: 'linear', toolName: 'create_issue' })8 .describe('Create a new Linear issue')9 .requireApproval()10 .build();mcpTool(name, { server, toolName }) needs @inferencesh/sdk ≥ v0.30.0 (older versions also took credentialId).
MCP Apps UI (interactive tool pages)
Some MCP tools ship an interactive HTML page alongside the tool result (MCP Apps, SEP-1865). When the platform attaches that UI to a chat message, it appears as an A2UI component with component: "McpApp" (catalog inferencesh/v1).
The host runs the page in a sandbox, passes the tool input and result over postMessage, and proxies any in-page tools/call requests back to the MCP server using the credential stored on the component. Content Security Policy from the resource (_meta.ui.csp) is applied as mcpCsp on the component.
| Field | Role |
|---|---|
mcpHtml | HTML document stored on the message so the chat can render without a separate fetch |
mcpPageHash | When the page is stored by hash, names GET /mcp-ui-pages/{hash} instead of inlining HTML |
mcpResourceUri | MCP Apps resource URI when the page came from a tool resource |
mcpServerSlug / mcpCredentialId / mcpToolName | Route proxied tool calls to the right connector (mcpCredentialId uses POST /mcp-credentials/{id}/tools/{tool} when mcpServerSlug is empty) |
mcpToolInput / mcpToolResult | Arguments and result in the shape the page expects (CallToolResult content blocks, not remapped platform output) |
mcpPrefersBorder | Optional chrome hint for the embed |
mcpArtifactId | When the page is a platform artifact (your app's own UI), runtime serves artifact data endpoints instead of /mcps |
Custom app UIs use the same sandbox model: set ui.artifact on an app version (AppVersionDTO.ui, mirrored from metadata.ui) to an artifact ref (namespace/name or @version) so task views can show the page beside generic JSON output. See Apps API — Custom UI page.
Agent and SDK consumers see the surface on ToolInvocationDTO.widget (A2UISurface / @inferencesh/sdk type Widget). TypeScript field names match A2UIComponent in @inferencesh/sdk (McpApp, MCPUICSP, A2UIMcpToolResult).
Next
- MCP Server — use inference shell as an MCP server for Claude Code and Cursor
- Adding Tools — all agent tool types