Connect Claude Code, Cursor, or any MCP client to inference shell and use all platform capabilities as tools.
What You Get
When you connect an MCP client to inference shell, it gets access to:
| Tool Group | Tools |
|---|---|
| Apps | app_list, app_get, app_run, task_get, task_list, task_logs, task_cancel |
| Workspace | open_workspace, open_thread_panel |
| Knowledge | knowledge_list, knowledge_search, knowledge_get, knowledge_create, knowledge_delete |
| Skills | skill_use, skill_files, skill_view, skill_upload, skill_store, skill_search |
| Artifacts | artifact_guidance, artifact_publish, artifact_get, artifact_list, artifact_comments, artifact_reply, artifact_resolve, artifact_asset_upload, artifact_asset_list, artifact_asset_delete |
| MCP Proxy | mcp_list, mcp_search, mcp_get, mcp_tools, mcp_run, mcp_connect, mcp_disconnect |
The MCP proxy tools are especially powerful — they let your coding agent discover, connect to, and call tools on any MCP server through inference shell, without running those servers locally.
Task tools
| Tool | Purpose | Key arguments |
|---|---|---|
app_run | Run an app; creates a task | app (required; namespace/name or namespace/name@version), input (required), function (multi-function apps), infrastructure (cloud, private, private_first; default cloud), wait (see Waiting for app_run) |
task_get | Get task status and output | task_id (required), wait (optional boolean; answers once the task finishes), include_logs (default false; returns the tail of each of the task's logs as structuredContent.logs), log_lines (lines per log with include_logs; default 200, max 2000) |
task_list | List recent tasks | limit (default 20, max 100), cursor, status (queued, running, completed, failed, cancelled, rejected) |
task_logs | Fetch logs for one phase | task_id (required), log_type (build, run, serve, setup, task; default run) |
task_cancel | Cancel a running task | task_id (required), force (optional boolean) |
REST equivalents: Tasks API.
Workspace entrypoints
Hosts that support the MCP Apps UI extension can open the full inference.sh web app inside the conversation. These tools take no arguments and are read-only.
| Tool | Entrypoint | Purpose |
|---|---|---|
open_workspace | global | Open the workspace fullscreen: run apps, talk to agents, edit flows, publish artifacts, and watch runs. |
open_thread_panel | thread | Open the same app beside the conversation so the flow, artifact, or run under discussion stays visible while you chat. |
When the host renders either tool, it loads the built-in workspace viewer, which fills the host panel and frames the deployment's web app (for example https://app.inference.sh). The viewer:
- Calls the app-only
workspace_sessiontool to mint a short-lived bound session (about 55 minutes) for the signed-in user on the MCP connection: the same identity as the host's OAuth session, not a separate API key pasted into the frame. The framed app uses that bearer token only (no cookies), stays locked to the connection's team, and disables workspace switching. - On navigation or selection, calls
workspace_focusso the MCP server remembers what the user is looking at on this MCP session. - On panel close, calls
workspace_session_endto revoke the frame session, and mints a fresh one when the app reports the previous one expired.
workspace_session, workspace_session_end, and workspace_focus are not exposed to the model (visibility: app only). Hosts and integrators should not surface them in tool lists meant for the agent.
Frame session limits. The credential minted for the iframe is narrower than a normal browser login:
| Property | Behavior |
|---|---|
| Team | Acts only as the MCP connection’s team (team_id in the mint response). The token ignores X-Team-ID and default-team fallback. If the user can no longer access that team, the frame session stops working. |
| Sign-in | A bound frame session is not the person’s own browser or CLI sign-in. Routes that require a personal session refuse it, for example approving an OAuth grant, approving a device login, or picking another team to mint long-lived credentials. Complete those flows in the host app or in a normal inference.sh login, not inside the embedded workspace. |
| Scopes | Standard developer API scopes except creating API keys, further limited to what the MCP connection itself is allowed to do (OAuth scope grants and scoped API keys). A grant with no overlap cannot open the workspace. |
| Lifetime | About 55 minutes, fixed TTL (not extended on use). At most one active frame session per MCP session: calling workspace_session again revokes the previous mint. |
| Revocation | workspace_session_end when the panel closes; terminating the MCP session (DELETE on the Streamable HTTP session) revokes the frame session too. If the MCP session only goes idle and lapses, the frame token may still work until its own expiry so an open panel is not cut off while the host reconnects. |
Session focus. workspace_focus stores a snapshot on the MCP session:
| Field | Meaning |
|---|---|
path | App-relative path the frame is showing (required), e.g. /flows/abc |
kind | Object type when known: flow, artifact, chat, agent, app, task, or empty for lists/home |
id | Id of the object named by the path, when applicable |
selection | Selected sub-part (node id, version, etc.) |
title | Display name for the model |
The next open_workspace or open_thread_panel call includes this focus in its text result and structuredContent.focus, so the model can refer to “this flow” without the user pasting an id. workspace_focus requires a stateful MCP session (Streamable HTTP with session id); stateless API-key-only clients get an error because there is nowhere to store focus.
workspace_session requires a signed-in user, a team on the MCP connection, and a stateful MCP session (Streamable HTTP with session id). Anonymous access, connections with no team context, or stateless API-key-only clients cannot mint a frame session.
Setup
Claude Code
Add to your MCP settings (~/.claude/settings.json or project .mcp.json):
1{2 "mcpServers": {3 "inference": {4 "type": "streamable-http",5 "url": "https://api.inference.sh/mcp",6 "headers": {7 "Authorization": "Bearer inf_your_api_key"8 }9 }10 }11}Cursor
Add to your Cursor MCP settings:
1{2 "mcpServers": {3 "inference": {4 "url": "https://api.inference.sh/mcp",5 "headers": {6 "Authorization": "Bearer inf_your_api_key"7 }8 }9 }10}Any MCP Client
The server card is at:
1GET https://api.inference.sh/.well-known/mcp-server-card1{2 "name": "sh.inference/mcp-server",3 "description": "inference shell MCP server",4 "remotes": [5 {6 "type": "streamable-http",7 "url": "https://api.inference.sh/mcp",8 "supportedProtocolVersions": ["2026-07-28", "2025-11-25", "2025-06-18", "2025-03-26", "2024-11-05"]9 }10 ]11}Server discovery proxy
The web app and CLI resolve custom MCP server URLs without browser CORS issues via a public proxy:
1GET https://api.inference.sh/mcps/discover?url=https://example.com| Step | What it tries |
|---|---|
| 1 | GET {origin}/.well-known/mcp-server-card (MCP server card) |
| 2 | OAuth authorization-server metadata at {origin} |
Returns the discovered JSON on success (200, cached five minutes). Use this when building UI that needs to preview a server before connect.
When you connect a custom MCP server through the API with a bare origin (https://host only), the platform also tries UCP at GET /.well-known/ucp and uses the first transport with "transport": "mcp" and a non-empty endpoint.
Authentication
API key (simplest)
All requests to the MCP server require a Bearer token:
1Authorization: Bearer inf_your_api_keyGet your API key from settings → workspace → api keys or via CLI:
1belt loginOAuth (MCP-native clients)
MCP clients that support OAuth can authorize against inference shell instead of pasting an API key. Discovery metadata is at /.well-known/oauth-authorization-server on the API host. After the user approves access in the browser, the client calls POST https://api.inference.sh/mcp with the issued access token.
Partner and first-party clients that use Client ID Metadata Documents show as verified on the consent screen; first-party documents hosted at https://inference.sh/oauth/clients/*.json keep the client_name from the document. See Authorization code flow and Verified clients on the consent screen.
Example: Running Apps from Claude Code
Once connected, Claude Code can run inference shell apps directly:
1You: Generate an image of a sunset over mountains23Claude: I'll use inference shell to generate that image.4 [Calling app_run with app="infsh/flux-schnell", input={prompt: "sunset over mountains"}]56 Here's your image: https://files.inference.sh/...Example: Using Connectors from Claude Code
Your connected MCP servers are available through the proxy tools:
1You: Check my Linear backlog for high-priority items23Claude: [Calling mcp_run with slug="linear", tool="list_issues", input={priority: 1}]45 You have 3 high-priority issues:6 - INF-201: Fix auth token refresh7 - INF-198: Billing webhook timeout8 - INF-195: Rate limit on /agents/runProtocol
The server implements the Model Context Protocol specification:
- Transport: Streamable HTTP (JSON-RPC 2.0)
- Endpoint:
POST https://api.inference.sh/mcp - Supported versions (newest first):
2026-07-28,2025-11-25,2025-06-18,2025-03-26,2024-11-05 - Handshake:
initialize/initialized(through2025-11-25), or statelessserver/discover(2026-07-28and later) - Tools:
tools/list,tools/call - Resources:
resources/list,resources/read(MCP Apps pages; see below) - Tasks extension (
io.modelcontextprotocol/tasks): advertised in server capabilities; see below - MCP Apps extension (
io.modelcontextprotocol/ui): advertised with MIME typetext/html;profile=mcp-app; see below - Progress:
notifications/progresswhen the client sends_meta.progressTokenontools/call - Cancellation:
notifications/cancelledcancels the in-flight JSON-RPC request (and the platform task forapp_run)
Send the negotiated protocol version on every request via the MCP-Protocol-Version header and in params._meta as io.modelcontextprotocol/protocolVersion. Clients on 2026-07-28 also mirror routing fields in Mcp-Method and Mcp-Name (for example taskId on tasks/get).
Capabilities advertise tools, resources, and the tasks and MCP Apps extensions. Logging and prompts are omitted rather than advertised as empty.
Stateless vs handshake connections
Under protocol version 2026-07-28, clients that support it start with server/discover. The server returns supported versions and capabilities; each HTTP request can stand alone without a persistent Streamable HTTP session id.
Older clients call initialize and keep a session id on later requests. Stateful features on this server, including workspace_focus, workspace_session, and the frame session described under Workspace entrypoints, require that stateful session.
Claude handshake fallback
Anthropic's chat products render MCP App tool cards only on connections they opened with initialize. On a purely stateless 2026-07-28 connection, tools/call and resources/read can succeed while every card shows "Unable to reach <connector>" (anthropics/claude-ai-mcp#636).
The server recognises those clients by the clientInfo.name they send in MCP request params (not by User-Agent). When the name is Anthropic, Anthropic/Toolbox, Anthropic/ClaudeAI, or claude-ai, a server/discover call receives method not found so the client falls back to initialize and keeps a session.
Claude Code, Cursor, Codex, and other clients still get a normal server/discover response and may stay stateless.
Tool list metadata
Each entry from tools/list includes optional annotations (MCP tool hints). On this server, every tool sets:
| Field | Meaning |
|---|---|
annotations.title | Human-readable name; always matches the top-level title (some clients, including the Claude connector directory, read only this field) |
readOnlyHint | Tool does not mutate remote state |
destructiveHint | Tool may delete or irreversibly change data (knowledge_delete, task_cancel, mcp_disconnect, and similar) |
idempotentHint | Repeated calls with the same input have no extra effect |
openWorldHint | Tool may reach arbitrary external systems |
Connector tools you reach through the MCP proxy (mcp_tools, mcp_run, or REST tool proxy) pass through annotations from the upstream server; inference.sh does not rewrite them.
Tasks extension and app_run
Long-running app runs use the MCP tasks extension when your client declares it:
- On each request, include client capabilities in
params._meta.io.modelcontextprotocol/clientCapabilitieswith:
1{2 "extensions": {3 "io.modelcontextprotocol/tasks": {}4 }5}- Call
tools/callwithname: "app_run". The server returnsresultType: "task"and ataskId(the platform task ID). - Poll
tasks/getwith thattaskIduntilstatusiscompletedorcancelled. Suggested poll interval is inpollIntervalMs(about 2 seconds). - When
statusiscompleted, the taskresultfield carries the same tool output shape as a synchronousapp_run(includingisErrorfor failed runs). Acancelledtask carriesresulttoo when its app returned something before stopping. - Call
tasks/cancelto stop a run in progress.
Waiting for app_run
Without the tasks extension, app_run takes an optional wait boolean:
wait: true: the HTTP connection streams progress notifications and ends with the final tool result.wait: false: the result comes back as soon as the task exists, withtask_idand a status such asreceived. Calltask_getwithwait: trueto get the output; the result text says so.
When wait is omitted, it defaults to false for hosts that declared the MCP Apps extension and true for every other client. A host that renders the task card gets the task ID at once, so the card shows the run live (queued, running, then the output) instead of waiting for the run to end. The model then waits on task_get.
task_get with wait: true holds the answer until the task is completed, failed, or cancelled, for up to 45 seconds. A task still running then comes back with its current status and a line asking to call again. Without wait, task_get answers at once with the current status.
tasks/update is accepted for protocol compliance; app_run does not use multi-step input, so updates are no-ops.
Task IDs are platform task IDs — use task_get, task_logs, or task_cancel tools (or the Tasks REST API) interchangeably.
MCP Apps (interactive UIs)
MCP Apps (SEP-1865) let a host render an HTML page beside a tool result. The inference shell MCP server acts as both a host (for connector tools your agents call) and a server (for platform tools such as app_run).
Declare the extension in client capabilities on every request (same shape as the tasks extension), or once in initialize params under capabilities on a session connection; the server keeps what initialize declared for the rest of the session:
1"io.modelcontextprotocol/clientCapabilities": {2 "extensions": {3 "io.modelcontextprotocol/ui": {}4 }5}Resources are HTML documents with MIME type text/html;profile=mcp-app. Built-in viewers cover tasks, artifacts, and the workspace; app and artifact pages are addressed as:
1ui://inference.sh/artifacts/{artifact_id}@{version_number}That resource is a small viewer that carries the page and nests it, so the host gets an MCP App and the page keeps speaking only to its viewer. The bare page, which the viewers read to nest it, is ui://inference.sh/artifact-pages/{artifact_id}@{version_number} with MIME type text/html. Viewers normally load that document with resources/read. Some hosts (for example ChatGPT) let an MCP App card read only the resource it was opened with, so the artifact viewer loads the nested page through the page-only artifact_page_get tool instead, which returns the same HTML and URI.
Use resources/list to enumerate built-in pages and resources/read to fetch one. Each resource carries _meta.ui.csp with connectDomains, resourceDomains, and frameDomains so the host can load scripts, styles, and nested frames safely. The same policy is also sent as _meta.openai/widgetCSP (connect_domains, resource_domains, frame_domains) on every client: Apps SDK hosts apply their default CSP when that key is missing, which blocks the app origin that serves viewer scripts. Only _meta.ui.domain (the Claude connector content domain) still depends on which client connected. The workspace viewer's resource also lists the deployment app origin in frameDomains, because it nests the full app in an iframe; no other resource does.
Built-in viewer URIs in tools/list and resources/list include a platform revision in the URI itself (derived from the viewer shell and its resource _meta). Hosts that cache a viewer by URI therefore pick up CSP or domain changes on deploy instead of reusing an older shell under stale framing rules.
Tool results name a page when one applies:
| Field | Where |
|---|---|
structuredContent.ui.resource_uri | JSON body on app_run, task_get, artifact_get, artifact_publish, and similar tools |
_meta.ui.resourceUri | MCP result metadata (hosts that read _meta use this URI with resources/read) |
Tools that render a card name their viewer in tools/list under _meta.ui.resourceUri: app_run (task viewer), artifact_get and artifact_publish (artifact viewer), and the workspace entrypoints. task_get has no card of its own: it usually follows an app_run whose card already shows the task.
When an app version declares an app UI artifact in metadata.ui, finished runs return that page URI so the host can replace the generic task output view.
Page-only tools — artifact_data_get, artifact_data_list, artifact_data_set, artifact_data_update, artifact_data_delete, artifact_viewer_get, and artifact_page_get are not for the model. They are marked with _meta.ui.visibility: ["app"] and back the artifact page runtime (window.inferencesh) when a page is nested in one of the server's viewers. artifact_page_get takes artifact_id and optional version_number and returns structuredContent with uri, version_number, and html, the rendered page at ui://inference.sh/artifact-pages/{id}@{n}. If the caller cannot read the requested version, the live version is served (same fallback as resources/read on that URI).
Outbound connectors — when agents call tools on connected MCP servers, the platform preserves tool _meta, reads the declared UI resource at call time (capped at 2 MiB), stores the document once by hash, and attaches ui.page_hash on the tool-call record (older rows may still inline ui.html). Chat and audit UIs fetch stored HTML with GET /mcp-ui-pages/{hash}. Follow-up tools/call and resources/read from the page use the connection id when the server is not in the directory. See MCP Servers API — tool calls.
Connecting to other MCP servers
When you use MCP proxy tools (mcp_run, etc.), the platform’s outbound MCP client also speaks the tasks extension and follows input_required flows (for example elicitation) on your behalf, polling remote tasks/get until a tool finishes.
MCP Apps (interactive UI)
Remote tools may return MCP Apps metadata (_meta.ui) with an HTML resource. In agent chat, that UI is rendered as an A2UI McpApp embed: sandboxed HTML, tool input/result over postMessage, and proxied tools/call through your workspace credential. See Connector tools on agents — MCP Apps UI.
Next
- Connectors Overview — what connectors are and how they work
- Browsing & Connecting — set up connections to MCP servers