MCP server

The Shardflux MCP server, hosted at mcp.shardflux.dev with OAuth or local as @shardflux/mcp. Client setup, configuration, every tool, wake and errors.

Overview

The Shardflux MCP server gives any MCP client or agent framework the tools of your Shardflux workspaces. It runs two ways, with the same tools:

  • Hosted at https://mcp.shardflux.dev/mcp: add the URL to your client and sign in. Nothing to install and no key to copy. See Hosted endpoint.
  • Local as @shardflux/mcp, a stdio server your client starts with npx and a project API key. See Client setup.

The rest of this page describes the local server. A feature marked with a version, such as (0.4.0+), is not in earlier releases.

  • It runs on your machine with a project API key you supply, and translates each tool call into one @shardflux/sdk request or wait.
  • It has no agent loop of its own and keeps no local workspace directory. Its only state is one workspace handle per key, so tool tokens are reused between calls.
  • It needs Node.js 24 or later. Run it with npx -y @shardflux/mcp; the package's binary is shardflux-mcp.
Shell
SHARDFLUX_API_KEY=sfk_... npx -y @shardflux/mcp

The server speaks MCP on stdin and stdout and logs to stderr. Your MCP client starts it; you do not run it by hand except to test it.

Hosted endpoint

https://mcp.shardflux.dev/mcp serves the Shardflux tools over MCP Streamable HTTP and signs your client in with OAuth. Any MCP client that supports Streamable HTTP and OAuth connects with the URL alone:

  1. Add the URL to your client.
  2. The client opens Shardflux in your browser. Sign in, choose the project the client works in, and select Connect.
  3. You are back in the client, connected. The connection is a project API key named <client> (MCP connector) with every tool permission, listed on the project's API keys page in the console. Revoke it there to disconnect the client.

The client renews its access on its own, so the connection lasts until you revoke it. A client that reads the standard mcpServers JSON config takes the URL as its entry:

JSON
{
  "mcpServers": {
    "shardflux": {
      "url": "https://mcp.shardflux.dev/mcp"
    }
  }
}

Set the client's tool timeout above the server's 120-second per-call deadline, so the server's own timeout result reaches the agent.

Hosted: API key header

A client configured with headers can send a project API key instead of signing in:

Text
Authorization: Bearer sfk_...

Hosted and local

The hosted endpoint is always on the current version. A few things are set differently:

  • template_build takes the recipe in the call (recipe). Building from a template.yaml on your machine (file) is done with the local server.
  • The environment settings of the local server (SHARDFLUX_WORKSPACE_KEY, SHARDFLUX_TEMPLATE and the deadlines) are arguments of each call instead: pass workspace_key and template to workspace_open. Each call has a 120-second deadline; start long commands with exec and background: true.

Client setup

Your MCP client starts the local server with npx -y @shardflux/mcp and passes the configuration as environment variables. Use a project API key whose tool permissions cover what the agent should do (see Permissions). In a client that reads the standard mcpServers JSON config:

JSON
{
  "mcpServers": {
    "shardflux": {
      "command": "npx",
      "args": ["-y", "@shardflux/mcp"],
      "env": {
        "SHARDFLUX_API_KEY": "sfk_...",
        "SHARDFLUX_TEMPLATE": "default"
      }
    }
  }
}

Add SHARDFLUX_WORKSPACE_KEY to give the agent one workspace (Pinning); every variable is in Configuration.

Set the client's tool timeout above the server's per-call deadline (SHARDFLUX_MCP_TOOL_TIMEOUT_MS, 120 seconds by default), or lower that deadline, so the server's own timeout result reaches the agent.

Configuration

The server reads its configuration from the environment when it starts. Invalid configuration exits with code 2 before serving, with one JSON line on stderr.

Variable Default Meaning
SHARDFLUX_API_KEY required Project API key, sfk_<key id>_<secret>. Its tool permissions decide which workspace tools are listed.
SHARDFLUX_API_URL https://api.shardflux.dev API origin. Must be https (plain http only for loopback hosts), without credentials, query or fragment.
SHARDFLUX_WORKSPACE_KEY none Pins one workspace (1-200 printable characters). See Pinning.
SHARDFLUX_TEMPLATE none Default template slug for workspace_open, for example default (the platform default template). With it, template becomes optional, and (0.9.0+) a workspace tool called with a key that has no workspace yet creates it from this template.
SHARDFLUX_WORKSPACE_MODE none (0.4.0+) processful or file_first: the mode workspace_open sends when the call names none (unset: the API's default, processful for a new key). A pinned server also lists the tools of this mode until its workspace exists.
SHARDFLUX_MCP_TOOL_TIMEOUT_MS 120000 Default and maximum deadline per tool call, 1000-3600000 ms. A call's timeout_ms can only shorten it.
SHARDFLUX_WAKE on on: workspace tools resume a suspended workspace, then run. off: they return the workspace_not_running refusal.
SHARDFLUX_WAKE_TIMEOUT_MS 120000 Longest wait per call for a workspace to wake or finish a transition, 1000-3600000 ms. Clamped to SHARDFLUX_MCP_TOOL_TIMEOUT_MS; each wake also ends 250 ms before the call's deadline.
SHARDFLUX_AGENT_LABEL mcp Attribution label of every tool token the server obtains (1-100 printable characters). It appears as an agent session in the console and in shard ws sessions.
SHARDFLUX_MCP_LOG_LEVEL info debug, info, warn or error.
SHARDFLUX_HTTP_KEEPALIVE unset 0.6.0+: pooled HTTP/1.1 on Node 26 by default; 0 forces close for diagnosis, 1 opts into native pooling.
SHARDFLUX_NO_UPDATE_CHECK unset (0.4.0+) 1, true, yes or on turns off the startup update check (see Updates).
NO_UPDATE_NOTIFIER unset (0.4.0+) The npm convention: any non-empty value also turns the check off.

Tools

Every tool takes an optional timeout_ms (1-3600000): the call's deadline, clamped to SHARDFLUX_MCP_TOOL_TIMEOUT_MS. Every tool that works on a workspace takes workspace_key, required unless the server is pinned. A workspace key is resolved by exact match within the API key's project, across every lifetime and purpose, so sessions, template drafts and test instances resolve too; the live workspace wins over tombstones of ended sessions with the same key.

Management tools

Tool Arguments (required in bold) Does
workspace_open workspace_key, template (optional with SHARDFLUX_TEMPLATE), cpu_millis, memory_mib, disk_gib, lifetime (persistent or session), inputs, mode (processful or file_first), wait (default true) Opens by key: creates the workspace on first use, reconnects to or resumes it afterwards, never resets it. Waits until it is ready, the template's start commands and services included, unless wait: false. inputs (0.3.0+) passes the template's text inputs, {"NAME": "value"}. mode (0.4.0+) opens a file-first workspace. (0.7.0+) memory_mib_held (at least 512) sets what the workspace holds while idle, and memory_mib the most it may use: elastic memory. allocation_mode is deprecated: accepted and ignored. (0.12.0+) like creates a fresh disk with the source's exact template and options; volumes sets the shared volumes: supplied volumes replace the set and omission preserves it. Returns {workspace, ready} and timing.
workspace_list prefix, state, lifetime (persistent, session, any), purpose (standard, template_draft, template_test, any), include_deleted, limit (1-200, default 50), cursor The project's workspaces: {workspaces, next_cursor}. By default only persistent standard workspaces.
workspace_status workspace_key One workspace plus its five most recent operations.
workspace_suspend workspace_key, wait (default false), durable (0.6.0+, default false), after_seconds (0-3600, 0.4.1+; 0 = as soon as it is idle, 0.5.1+) Suspends the workspace. Returns the operation; with wait: true, once it has finished (sealed on its host). (0.6.0+) The result has durable and durability (durable storage); durable: true implies wait and returns once the checkpoint is in durable storage. With after_seconds (0.4.1+), suspend when idle instead: the workspace is suspended once it has been idle that long; the agent's next tool call on it cancels that, and a running command or a keepalive postpones it. Returns suspend_request (not_before: the earliest suspend) and a message, or operation when a suspend was already in progress. Not with wait or durable (invalid_arguments). The server's instructions ask the agent to call it when it finishes its work. workspace_status shows a pending request as workspace.suspend_request.
workspace_suspend_progress workspace_key, operation_id (0.19.0+) A suspend operation's live progress, read without waking the workspace: {progress} with phase, phase_started_at, cancelable and safe_action.
workspace_suspend_cancel workspace_key, operation_id, wait (default true) (0.19.0+) Cancels a suspend before its capture starts; the workspace keeps running as it was. Returns {operation, progress} once the operation is canceled (suspend_canceled), or, with wait: false, as soon as the host accepts. Once capture has started the suspend completes (suspend_capture_started): wait for it, then resume.
workspace_resume workspace_key, wait (default false) Resumes a suspended workspace. (0.6.0+) The result includes lost_suspend when the resume's result has it (lifecycle). (0.7.1+) It includes host_lost the same way, with a notice for the agent (lifecycle).
workspace_fork workspace_key, new_key, cpu_millis, memory_mib, disk_gib, memory_mib_held (0.7.0+), wait (default false) Forks into a new key. allocation_mode is deprecated: accepted and ignored. Returns {operation, workspace}; (0.6.0+) with durable and durability for a fork of a running workspace.
workspace_expose_port workspace_key, port (0.8.0+) Serves a TCP port of the workspace at its own private HTTPS URL (inbound ports). Returns {port, url, created_at, callback, newly_exposed}. The server listens on 0.0.0.0:<port>. Idempotent.
workspace_list_ports workspace_key (0.8.0+) The exposed ports: {ports: [{port, url, created_at, callback}]}.
workspace_port_link workspace_key, port, path (default /), ttl_seconds (60-604800, default 86400) (0.8.0+) A link that opens the port in a browser: {url, expires_at}. Anyone with the link can open the port until it expires.
workspace_close_port workspace_key, port (0.8.0+) Closes the port: its links stop working at once.
workspace_resize workspace_key, memory_mib, memory_mib_held, cpu_millis, disk_gib (at least one) (0.8.0+) Resizes the workspace, running or suspended, without a restart, and stores the new caps. allocation_mode is deprecated: accepted and ignored. Returns per resource what applied and when (applies_at: now, resume or next_start), the stored caps and a one-line message.
volume_open name, quota_gib (0.12.0+) Creates or reuses a project volume by name, default 1 GiB. Shared volumes stay outside workspace snapshots and forks.
operation_wait operation_id, durable (0.6.0+, default false) Keeps waiting for a lifecycle operation, up to the call's deadline. With durable: true, a suspend or fork also waits until its checkpoint is in durable storage.
usage_summary organization_id (default: the key's organization) Usage of the organization in the current billing period: meters, allowances with their cap state, allowance_exhausted with exhausted_reason, and spend_cap (0.4.1+), the opt-in overage state, cap, charges and lines per allowance. (0.18.0+) gpu on plans with GPU-hours: hours used, included, past the allowance and billed, cap_state and blocked_reason; at gpu_blocked only the GPU stops and workspaces keep running. The description tells the model about them (0.4.0+).
workspace_set_computer_use workspace_key, state (on, off, inherit) (0.9.0+) Switches computer use on or off for the workspace, or back to its template's setting. Returns {enabled, workspace, template, available}.
workspace_computer_desktop workspace_key, action (status, start, stop), width, height (0.9.0+, permission computer) The workspace desktop's status, a start at a screen size (640x480 to 2560x1600), or a stop.
workspace_computer_stream workspace_key, interactive, ttl_seconds, stop (0.9.0+, permission computer) A link to watch the desktop live, or use it with interactive: true: {url, expires_at, port, interactive}. stop: true ends every view.
template_get slug, version, owner (platform or organization) (0.3.0+) A template's versions with their settings (env, inputs, start commands, services, defaults). With version, also that version's recipe in request form.
template_languages base (<slug>@<version>) (0.3.0+) The languages and versions a base offers build.languages.
send_feedback message (any length, 0.26.2+), category (bug, confusing, missing, idea, praise, other), user_approved, workspace, request_id, error_code, command (0.19.0+) Previews feedback; explicit approval via user_approved: true sends it. See Feedback. Approved result: {id, received_at, duplicate, note}.
template_build template_slug, exactly one of file or recipe, display_name, description, publish (default false), wait (default false) (0.3.0+) Builds a version of an organization template from a recipe v2: recipe (the document) or file (a template.yaml or .json path). Local from paths are uploaded first (folders as a tar). Every local path must resolve inside the server's working directory; others are refused before any request. Unpublished unless publish: true. Returns {build, uploads}.

workspace_resize accepts at_least: true (0.10.0+) to grow named resources independently and wait: false to return the held answer with its pending operation. The default waits for completion.

Deleting a workspace is deliberately not exposed to agents; use the CLI or the console.

Feedback

(0.19.0+) Local and hosted MCP both use user-directed feedback. Omitted or false user_approved returns {sent: false, authorization_required: true, preview, note} without submitting. Show the exact message and context to the user, then obtain explicit authorization before calling with the same content and user_approved: true. Earlier local versions encouraged proactive feedback; feedback: 'proactive' is now a deprecated alias for the consent policy.

Agents: report only when your user asks to send feedback. Show the exact message and context first, then obtain explicit authorization. A failure or request for a feature is not consent. Leave out private data, secrets and code the user did not mean to share; paraphrase, never paste transcripts. Tell the user what was sent.

  • The server adds client: shardflux-mcp/<version> and, as agent, the MCP client's name and version from initialize (else SHARDFLUX_AGENT_LABEL when it is not the default). A pinned server fills workspace with its key.
  • duplicate: true: the same message from this key in the last 24 hours; it is not emailed again.
  • Any API key may send it (no tool permission), so it is always listed. It is rate limited: 10 per 10 minutes and 50 per day per key, 200 per day per organization (rate_limited with details.retry_after_seconds, and a hint naming the wait and the fallback address, shardflux@shardflux.dev).
  • Anything shaped like an API key, token or private key is redacted before the message is stored or emailed.

Workspace tools

These are the TypeScript SDK's workspaceTools(), published with the SDK's JSON Schemas plus workspace_key and, where the SDK schema has none, timeout_ms:

Tool Permission Arguments (required in bold)
exec exec command (run with bash -lc), cwd (absolute; a relative one is an invalid_cwd error), timeout_ms, stdin, background (0.7.0+), resource_hint (auto, light or heavy) (0.8.0+)
exec_read exec (0.7.0+) session_id, stdout_offset, stderr_offset, wait_ms
exec_cancel exec (0.7.0+) session_id, grace_ms
read_file files path, offset, length
write_file files path, content, append, create_parents
list_files files path, limit
search_files files (0.4.0+) path, pattern, regex, case_insensitive, include, exclude, max_matches, context_lines. Read-only.
edit_file files (0.4.0+) path, edits ({old_text, new_text, replace_all}), expected_revision
list_processes process none
signal_process process pid, signal
terminal_open pty command, rows, cols
terminal_send pty session_id, input
terminal_read pty session_id, offset, wait_ms
terminal_close pty session_id
git_clone git url, path, branch, depth
git_status git path
git_commit git path, message
browser_screenshot browser url, width, height. Returns an MCP image content block.
browser_content browser url, format (text or html)
computer (0.9.0+) computer action (a computer toolset member), coordinate, start_coordinate, region, text, scroll_direction, scroll_amount, duration, repeat; screenshot, settle_ms, format, quality. Its screenshot comes back as an MCP image content block.
computer_batch (0.9.0+) computer actions (1-50 objects with the computer tool's action parameters); screenshot, settle_ms, format, quality. Each image (a zoom's, the screenshot after the batch) comes back as an MCP image content block.

The argument details are in the TypeScript SDK reference. For exec, timeout_ms is both the call's deadline and the command's timeout: it defaults to, and is capped by, the server's per-call deadline, and the command is killed 2 seconds before the deadline so its output comes back. (0.7.0+) With background: true the call returns session_id at once and timeout_ms is the command's own limit (up to 24 hours): read it with exec_read, stop it with exec_cancel (processful workspaces). (0.4.1+) A command that could not start (a cwd that is not a directory, a program not on PATH) returns exit_code: null and error (code, message, reason: "exec_failed_to_start") with the workspace's reason, as a failed file-first execution does.

With SHARDFLUX_TEMPLATE set (0.9.0+), a workspace tool (exec, workspace_exec_start and the file, process, terminal, git and browser tools) called with a key that has no workspace yet creates it from that template, so the agent needs no workspace_open call first; that result carries workspace_created: true and the open's timing. Without SHARDFLUX_TEMPLATE (and on the hosted endpoint), a key that was never opened is not_found: call workspace_open first.

(0.4.0+) search_files searches file contents and edit_file replaces exact text; without an expected_revision, edit_file reads the file's revision first, so a concurrent change fails the edit (conflict, reason: revision_mismatch) instead of being overwritten. See Search and edit files. If a workspace does not offer them, the call gets conflict, reason: host_feature_unavailable (details.feature), retryable: false, and a hint naming the fallback (exec with grep; read_file then write_file).

File-first workspaces

(0.4.0+) workspace_open with mode: "file_first" (or SHARDFLUX_WORKSPACE_MODE=file_first) opens a file-first workspace: a versioned file tree under /home/user with no VM between calls. It is ready at once and never suspended.

  • exec runs each command as an execution: a fresh VM on the workspace's files. Only files under /home/user persist between calls. The result adds execution_id, state, tree_revision and changed (up to 200 paths, changed_truncated). An execution runs to completion: when the call's deadline passes first, the error carries its execution_id, and the execution continues server side.
  • The files tools work as on a processful workspace; each change publishes the next tree revision.
  • The process, terminal, git and browser tools and workspace_suspend, workspace_resume, workspace_fork and operation_wait do not apply. A pinned server lists only the tools of its workspace's mode (once it is known, else SHARDFLUX_WORKSPACE_MODE, else processful) and sends notifications/tools/list_changed when that changes what it listed. An unpinned server lists every tool and refuses one the named workspace's mode lacks before any request (conflict, reason: not_supported_for_mode, with a hint).

Results

A successful call returns the result as JSON text content and as structuredContent. Workspace results include id, key, ready, observed_state, desired_state, template (slug, version and, 0.7.0+, immutable_version: the version its immutable paths show), active_operation, pending_reason, failure (0.27.1+: a failed workspace's reason, the error of the operation that failed it; else null), lifetime, purpose, disk_layout, idle_timeout_seconds, ended_reason, startup (0.3.0+: the state of the template's start commands and services; failed names the step, its exit code and output tail), and mode and, for a file-first workspace, tree_revision (0.4.0+), suspend_request (0.4.1+: a pending suspend when idle, else null), and memory (0.7.0+: allocation_mode, promised_mib, held_mib, plugged_mib). An exec result adds memory_grow (0.7.0+) when the command's start grew the workspace's memory. Tool tokens are never returned to the model.

Permissions

tools/list shows the management tools and the workspace tools the API key's tool permissions allow (exec, files, pty, process, git, browser), read from GET /v1/me. If the server cannot read them, it lists every workspace tool and logs a warning; a call the key may not make is then refused by the API.

Choose the key's permissions to match what the agent should be able to do: for example, a key with only files gives the agent read_file, write_file, delete_file (0.23.0+) and list_files and no command execution.

Account actions

Registering, signing in, organizations, projects, API keys, members, invitations, billing and plan upgrades, spend alerts and the audit export are not tools. The server authenticates with a project API key, and the API refuses a project API key for them: 403 forbidden ("API keys cannot perform this action.") on the account routes, 401 on the /v1/auth session routes. They need a person's session. (0.4.0+) The server instructions tell the agent to use the shard CLI for them (shard --help; for example shard auth login, shard setup, shard billing upgrade <plan>), which signs a person in with a CLI session.

Pinning

With SHARDFLUX_WORKSPACE_KEY set, the server works on that one workspace:

  • workspace_key becomes optional on every tool and defaults to the pinned key.
  • A different key is refused with code: workspace_pinned (details.pinned_workspace_key).
  • workspace_open opens (or creates) the pinned workspace.

Pin a workspace when an agent should have one computer and nothing else, for example a per-project scratch workspace.

Wake on use

Workspace tools resume a suspended workspace, then run:

  • A suspended workspace is resumed (or the resume or open already running is joined), and the call runs once it is running. A call made during a suspend or resume waits for it to finish. The call never runs twice: the refused attempt did nothing.
  • The wait is bounded by SHARDFLUX_WAKE_TIMEOUT_MS and the call's deadline. Past it the result is code: timeout with the operation_id and last_state of the resume or open, and (0.15.0+) last_reason, deadline_at and queue_position when the operation reports them. That operation continues server side: operation_wait keeps waiting.
  • (0.15.0+) A call refused before it ran because room is being made for it, on the workspace's host (503 host_capacity, details.queue_position) or in the plan's workspaces working at once (429 quota_exceeded), is sent again after each Retry-After until shortly before the call's deadline. A refusal that lasts is the error with retry_after_seconds and a hint; a deadline reached while waiting is code: timeout with reason, queue_position and retry_after_seconds. Nothing ran.
  • A resume or open that fails returns code: operation_failed (retryable: true for capacity_unavailable; the workspace stays suspended).
  • With SHARDFLUX_WAKE=off the refusal comes back instead: conflict with details.reason: workspace_not_running, or workspace_not_running from the cell gateway.
  • (0.4.0+) The wake is one request: the API holds the resume until the workspace runs and answers with this server's tool token, so the tool runs at once. workspace_resume with wait: true sends the same request. The wake's timing is one request(held) phase.
  • (0.4.0+) read_file, list_files and search_files of a suspended workspace are answered from its saved disk without waking it: the files as they were at the suspend.
  • (0.4.0+) Every other workspace tool call first sends a wake hint without waiting for it, so a workspace its host has parked while idle starts waking, and a suspended one starts resuming, while the call is prepared.

Deadlines and cancellation

  • Every call has a deadline: timeout_ms, clamped to SHARDFLUX_MCP_TOOL_TIMEOUT_MS. Waits time out just before it with code: timeout and the operation_id; the operation continues server side. Any request still in flight at the deadline is aborted.
  • A queued open, resume or fork (capacity_pending) has a deadline 15 minutes after it was created, moved later while new capacity is starting for it (start deadlines). A wait that ends first returns code: timeout, and its message names the deadline; the start keeps its place, and operation_wait keeps waiting. Past the deadline, the start fails: operation_failed with details.error_code: capacity_unavailable and retryable: true; nothing was started.
  • Progress (0.15.0+). A request with _meta.progressToken gets notifications/progress while its call waits: on each change and at least every 10 seconds, with a message such as Queued for capacity (position 3); a new host is starting, ready by 21:40Z (an open, resume, fork, wake or operation_wait of a queued start), Waiting for room on the workspace's host (position 2) or Waiting for a free working slot: ... (a tool call waiting to be admitted), or the lifecycle phase. progress counts up; there is no total. A request without a token gets none. Clients that reset their request timeout on progress keep long waits alive this way.
  • MCP notifications/cancelled aborts the work behind the call: waits, requests to the API and the cell gateway, and backoff sleeps. No response is sent and the server stays up. A lifecycle operation that was already started is not canceled.

Errors

Errors are tool results, never protocol failures: isError: true and structuredContent.error = {code, message, status, request_id, retryable, operation_id, details, source}, plus reason (the refusal's details.reason) and, (0.4.0+) for the file-first refusals and host_feature_unavailable, a hint saying what to do instead. The only protocol error is an unknown tool name (InvalidParams).

(0.4.0+) An unexpected failure also carries structuredContent.feedback: a suggestion to preview send_feedback and obtain explicit approval before sending, with category bug, the request id and the error code. The expected flow has none: invalid_arguments, workspace_pinned, unauthenticated, validation_failed, timeout, and refusals whose error names the next step (a stale revision, an edit that does not match, a mode the workspace lacks, a feature the workspace does not offer).

code Meaning
An API or cell gateway code The API or the workspace refused the call. source is api or cell.
invalid_arguments The arguments do not match the tool's schema (issues lists the problems), or a local path of template_build is outside the working directory. Nothing was sent.
workspace_pinned A different key than the pinned one.
not_found No workspace with that key in the project.
timeout The call's deadline or the wake timeout passed. operation_id and last_state name the operation, which continues; (0.15.0+) last_reason, deadline_at and queue_position when it reports them. retryable is true.
operation_failed The operation ended failed or canceled. details.error_code (and details.reason) say why; retryable is the operation error's own flag.
upload_failed The storage refused a template_build upload (details.sha256, details.storage_code).
network_error The API or the cell gateway could not be reached (retryable: true).
protocol_error A response was not the documented shape.
internal_error An unexpected failure in the server (also logged).

A start refused because an allowance is used up is allowance_exhausted (402) with reason allowance_used (upgrade, or turn on overage), overage_paused (a plan payment is past due) or spend_cap_reached (raise the spend cap or upgrade), and details.spend_cap. An owner or billing member acts on it in the console; retrying does not help. See 402 allowance_exhausted.

A feature the plan does not include is entitlement_required (402) with reason not_included, for example the GPU (GPU needs the Startup or Scale plan.). (0.18.0+) Its hint says an owner or billing member upgrades, naming the plans the refusal lists; retrying does not help.

Timing

A call that opens a workspace or waits says where the time went, compacted for model context:

JSON
{
  "timing": {
    "action": "resume",
    "outcome": "succeeded",
    "operation_id": "01a0ead6-bd61-737a-ae88-66e2d01a6e25",
    "total_ms": 413,
    "phases": ["request 218 ms", "queued 195 ms"],
    "server": { "queued_ms": 51, "run_ms": 290, "total_ms": 341, "resume_path": "local_cache" },
    "outside_server_ms": 72,
    "retries": 0
  }
}
  • workspace_open and operation_wait always carry it; workspace_suspend, workspace_resume and workspace_fork carry it with wait: true; workspace tools carry it when they had to wake the workspace (action: "wake").
  • Phases are in order, as phase(reason) ms. request(held) means the API held the open until the workspace was ready.
  • server is the operation's own queued, run and total time plus the start or resume path; outside_server_ms is everything else (network, polling, reading the workspace, the tool token).
  • A failed or timed-out call carries it too, next to error.

Logging

Logs are JSON lines on stderr (stdout is the protocol), filtered by SHARDFLUX_MCP_LOG_LEVEL. Each line has time, level, service: "shardflux-mcp" and message, plus fields such as tool, outcome, ms and request_id. The first line (ready) records the version, API URL, pinned key, default template, agent label and timeouts. The API key is never logged, and anything shaped like a key is redacted. The server shuts down when the client closes stdin, or on SIGINT or SIGTERM.

Updates

(0.4.0+) At startup, after the configuration is validated, the server checks whether @shardflux/mcp at its version is current: the latest release from npm (0.15.0+; SHARDFLUX_NPM_REGISTRY names another registry) and the oldest supported one from the API's GET /v1/client-versions. Both requests (3 s timeout) run in the background: the MCP handshake and tool calls never wait for them, and any failure is ignored. When the server is outdated, or below the oldest version the API still supports, it logs one warn line on stderr:

The notice includes status, package, current, latest, minimum_supported, upgrade_command and release_notes_url; its versions come from the update check.

  • An unsupported server says ... is no longer supported by the Shardflux API (minimum <version>). Update: ... ("status":"unsupported"). It keeps running.
  • Otherwise it stays silent (one debug line), also when the API does not answer.
  • The notice is not in the server instructions: they are fixed when the server starts, and the handshake does not wait for the check.
  • SHARDFLUX_NO_UPDATE_CHECK=1 or NO_UPDATE_NOTIFIER=1 turns the check off.
  • The @shardflux/sdk client inside the server runs no check of its own: the update to install is the server's.

Compatibility

Breaking changes to tools and results ship only in minor releases and are marked Breaking in the changelog. Tool results are the API's objects summarized for model context; new fields can appear in any release.

Integration controls (0.6.0+)

workspace_open accepts labels and idle_policy; workspace_list filters labels. New controls: workspace_idle, workspace_keepalive, workspace_set_idle_policy (default clears inheritance), workspace_set_labels, workspace_exec_start with stdin_open and (0.7.0+) timeout_ms (read it with exec_read, stop it with exec_cancel), and workspace_exec_input with offset and optional close. The last two require exec permission and processful mode; pipe frames are at most 64 KiB. Use each acknowledged byte offset, including partial writes.

Node 26 uses the SDK's private HTTP/1.1 pool. Protocol errors include source. Failed workspace IDs can recover through resume.

Prepare an imminent tool call (0.8.0+)

Set SHARDFLUX_PREWAKE=on (default off) to offer workspace_hint. A host that observes model tool-input streaming can invoke it with workspace_key ahead of a VM tool call. It stages a parked workspace without waiting for restore; resume a suspended workspace first. File-first workspaces do not list this tool.

workspace_computer_stream reuses a link of the same kind with more than 60 seconds left. fresh: true mints a new link; stop: true clears it. computer_batch returns a final screenshot or zoom image once. SHARDFLUX_BASE_URL aliases SHARDFLUX_API_URL; the latter wins. Environment HTTP(S)_PROXY and NO_PROXY are honored.

Upgrade in place (0.10.0+)

workspace_upgrade accepts workspace_key and at (now or next_resume). The cold start keeps files, installed package files and home, and ends memory and processes. The operation reports whether the target is scheduled or applied. Workspace summaries expose upgrade_available and upgrade_pending.

Saved site logins (0.26.2+)

On your laptop, site_logins_list({ site?, project_id?, organization_id? }) returns metadata. site_login_add({ site, username?, organization_id? }) returns waiting with a secure entry URL to give to your user. Their password goes from that page directly to the encrypted store. List logins after they save; values stay outside tool arguments and results. The server uses the CLI's saved session for its API URL, or SHARDFLUX_SESSION_TOKEN. Its secure entry page ships with the package through @shardflux/cli, so no global CLI installation is needed. credential_fill takes an optional account username and the passkey field.

Credential account creation (0.27.2+): after your user selects it, call needs_you_answer with decision: "create_account". The requesting agent receives that choice and creates the account, storing credentials securely. Do not put secret values in the tool arguments.

View this page as Markdown