Skip to content

MCP server

OAuth 2.1 protection, the full StackShip tool catalog, write scopes, idempotency, and agent attribution.

Updated View as Markdown

The StackShip MCP resource is:

https://mcp.stackship.run/mcp

It uses Streamable HTTP and publishes protected-resource metadata at:

https://mcp.stackship.run/.well-known/oauth-protected-resource
https://mcp.stackship.run/.well-known/oauth-protected-resource/mcp

Both documents identify https://api.stackship.run/api/auth as the authorization server and advertise the mcp:tools and mcp:write scopes. Clients use OAuth 2.1 with PKCE and send the access token only in the Authorization header.

Validation

Every MCP request verifies:

  • the configured API issuer;
  • the JWT signature against the API JWKS;
  • expiry and other temporal claims;
  • the MCP resource audience;
  • the mcp:tools scope; and
  • one exact org_ organization claim.

Validation fails closed. A token intended for the dashboard, OpenTofu cloud protocol, or another resource cannot be reused at MCP. Missing and invalid credentials return an OAuth bearer challenge that points to the protected resource metadata and advertises the required mcp:tools scope. An invalid bearer challenge also includes error="invalid_token" so OAuth clients can distinguish rejected credentials from an initial authorization challenge. Both cases return HTTP 401. A valid token that lacks mcp:tools instead returns HTTP 403 with error="insufficient_scope" and scope="mcp:tools" in WWW-Authenticate, as required by RFC 6750.

Scopes

mcp:tools grants the read catalog. Mutating tools additionally require mcp:write; the server publishes them only to write-scoped tokens, and the API independently refuses an MCP mutation without mcp:write using the MCP_SCOPE_INSUFFICIENT error code.

Dynamically registered clients receive mcp:tools by default and must explicitly request mcp:write. Scopes cap what a token may attempt; the caller’s organization role still decides what is permitted. Every tool call re-reads the caller’s live membership, so a permission the role lacks returns 403 FORBIDDEN regardless of scope.

Execution model

MCP tools contain no business logic. Each tool is a thin adapter over exactly one frozen v1 REST operation: the MCP Worker forwards the caller’s own access token to api.stackship.run, and the API re-verifies the token — signature-authentic through its hashed token record, unexpired, unrevoked, MCP-audience-bound, and organization-claimed — before resolving the same tenant, permission, idempotency, and audit path the dashboard uses.

The API confines MCP-audience bearer sessions to the published automation surface. An operation outside the catalog — including every delete — returns 403 MCP_OPERATION_NOT_SUPPORTED before any route logic runs. Operations that require step-up reauthentication (apply recovery, raw state and sensitive artifact downloads) are structurally unreachable because an MCP session never carries step-up evidence.

Read tools

Tool Purpose
stackship_status Service status plus the authenticated subject, organization, and scopes
stackship_list_projects, stackship_get_project Project inventory
stackship_list_workspaces, stackship_get_workspace Workspace inventory, regions, OpenTofu versions, cloud names
stackship_get_workspace_source GitHub repository, branch, working directory, and trigger paths
stackship_list_runs Cursor-paginated organization run feed
stackship_list_workspace_runs, stackship_get_run Workspace runs and full run state
stackship_get_run_review Review evidence, available actions, and the exact approval binding
stackship_get_run_logs Sanitized plan, policy, or apply log chunks (tail or forward polling, 256 KiB cap)
stackship_get_run_plan_changes Non-sensitive plan change summary (512 KiB cap)
stackship_get_run_policy Policy evaluation outcome and per-attachment decisions
stackship_list_workspace_state_versions Immutable state history metadata, cursor-paginated
stackship_list_workspace_variables Variable metadata; sensitive values are never returned
stackship_list_workspace_access_assignments Cross-workspace state access assignments
stackship_list_audit_events Newest sanitized audit events, cursor-paginated
stackship_list_policy_sets, stackship_list_policy_set_versions, stackship_list_workspace_policy_attachments Policy inventory
stackship_get_github_installation, stackship_list_github_repositories GitHub App status and visible repositories
stackship_list_registry_modules, stackship_get_registry_module, stackship_list_registry_module_versions, stackship_get_registry_module_version, stackship_list_registry_module_ingestions Private module registry inventory
stackship_list_workspace_credential_profiles, stackship_list_credential_profile_versions, stackship_get_credential_profile_trust_template Credential metadata and OIDC trust templates; secret material is never readable
stackship_list_opentofu_versions Selectable OpenTofu versions

Write tools

All write tools require mcp:write plus the same product permission the dashboard requires for the equivalent action.

Tool Purpose
stackship_create_project Create a project
stackship_create_workspace Create a workspace
stackship_update_workspace Replace execution settings; optional rename
stackship_update_workspace_source Bind or rebind the GitHub source
stackship_create_run Propose a managed run
stackship_approve_run Approve a gated plan with the exact review binding
stackship_reject_run Reject a gated plan with the binding and a reason
stackship_cancel_run Signal a non-terminal run to cancel
stackship_create_workspace_variable, stackship_update_workspace_variable Variable writes; sensitive values stay write-only
stackship_create_policy_set Create a policy set (source publication stays outside MCP)
stackship_create_policy_attachment, stackship_create_workspace_policy_attachment Attach built policy versions
stackship_create_run_policy_override Justified, expiring soft-mandatory override
stackship_create_registry_module, stackship_sync_registry_module, stackship_update_registry_module_source Registry module lifecycle
stackship_deprecate_registry_module_version, stackship_restore_registry_module_version Reversible version deprecation

Approvals are never bypassed

Run approval and rejection carry the same exact plan, dependency, predecessor-state, and policy-result binding the dashboard submits. Agents must read stackship_get_run_review first and echo the binding verbatim; a since-changed plan is rejected with 409 APPROVAL_STALE instead of authorizing different changes. A closed policy gate advertises rejection but never approval. Soft-mandatory policy overrides require the dedicated policy:override_soft permission and record a justification and expiry.

Idempotency and attribution

Every mutation sends an Idempotency-Key. Tools accept an optional idempotency_key argument for exact retries and generate a fresh key when it is omitted. Replay, conflict, and in-progress semantics are identical to the v1 REST API.

Every MCP mutation is attributed to the human principal who authorized the OAuth client — the audit actor is that user, never a synthetic agent — and the audit event’s details carry an automation label with kind: "mcp" and the acting OAuth client_id, so agent-performed changes are distinguishable in the audit feed.

Not available through MCP

The automation surface deliberately excludes destructive and secret-bearing operations:

  • deletes of any resource (variables, modules, policy attachments, access assignments) and service-account token revocation;
  • apply recovery and every step-up-gated operation;
  • raw state, sensitive artifact, and emergency-state downloads;
  • credential profile creation, secret version writes, verification, archive, and revoke (credential metadata stays readable);
  • service-account and token minting;
  • access-assignment grants;
  • policy source upload and version registration from artifacts;
  • the GitHub App installation browser flow; and
  • platform admin controls.

These operations must not be inferred from the dashboard or v1 API; the API refuses them for MCP-audience credentials.

Token lifetime and revocation

An MCP access token is a signed JWT bound to the organization selected during authorization. It expires after one hour. If a client requests offline_access, the authorization server also issues a hashed, opaque refresh token that expires after 30 days and rotates on use.

The MCP Worker validates signatures and claims locally, so a revoked JWT can briefly keep satisfying the Worker’s own check; the API behind it, however, resolves every tool call against the hashed token record, so a revoked or deleted grant stops executing tools immediately. Changing the bound organization requires a new authorization.

Data handling

Tool output is the sanitized v1 response body: log streams are terminal-sanitized, sensitive variable values are never present, and secret material has no read operation. Operational analytics receive only the MCP request event and opaque identity values. Authorization headers and access-token plaintext are not logged, and API errors surface to the agent as bounded {code, status, request_id} documents.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close