Skip to main content

MCP

Plan requirement

Connecting a client to Cracken over the remote MCP server — the same surface as the External API — requires the Pro plan and above on Cracken Cloud; a key on a lower plan is rejected at authentication. Self-hosted deployments include it on every tier. Giving the agent external MCP servers during an operation is part of every plan.

The Model Context Protocol (MCP) connects Cracken with other AI tooling in two directions:

  • Your client → Cracken. Point an MCP-capable client (Claude, Cursor, and others) at Cracken to create and inspect operations and resolve approvals as tools, authenticated with your Cracken API key. See Connect a client to Cracken.
  • Cracken's agent → external servers. During an operation, the agent starts or connects MCP servers on a Tentacle to gain domain-specific tools and data sources beyond Cracken's built-in Vessels and tools. See Give the agent external MCP servers.

The two are independent — you can use either, both, or neither.

Connect a client to Cracken

Connect your AI client to Cracken over the Model Context Protocol, using your Cracken API key as a bearer token. Create a key in Settings → API keys (tenant owners only — the settings entry is hidden for other roles), then pick your client:

claude mcp add --transport http cracken \
https://api.app.cracken.ai/mcp \
--header "Authorization: Bearer crk_live_<key_uuid>.<secret>"
Self-hosted Cracken

On a self-hosted instance, replace https://api.app.cracken.ai with your own Cracken API URL. The path stays /mcp.

Tools

ToolArgumentsReturnsRequires
list_realmsnonearray of realms the key can accessoperations:read
list_playbooksrealm_uuid (required)array of playbooks in the realm (pin one when creating an operation)operations:read
list_modelsnonearray of LLM models available in this deploymentoperations:read
list_operationsrealm_uuid (required), limit (1–100, default 100), offset (default 0), include_archived (default false)array of operationsoperations:read
create_operationrealm_uuid, task (required); naming_task, autonomous, playbook_uuid, playbook_path, parent_uuid, root_operation_id, context, fork_from_operation_id, operational_goal, operational_goal_enabled, planning_enabled, final_output_contract, model_id, llm_config, loadout (optional). naming_task is secret-scanned and only names the operation — it does not change the executed task. playbook_uuid and playbook_path are mutually exclusive; send explicit null for root_operation_id with parent_uuid to create a top-level grouped child.the created operationoperations:create; forks also need operations:read; non-manual autonomy also needs operations:autonomy
get_operationoperation_uuid (required), include_archived (default false)one operationoperations:read
get_current_approval_requestoperation_uuid (required){"approval_request": {...} | null}operations:read
get_pending_gatesoperation_uuid (required){"gates": [...]} containing the current user-blocking gatesoperations:read
update_operation_controlsoperation_uuid (required); any of name, autonomous, semi_auto_policy (+ clear_semi_auto_policy), operational_goal (+ clear_operational_goal), operational_goal_enabled, planning_enabled; cascade (default false) applies autonomous, semi_auto_policy, operational_goal_enabled, and planning_enabled to descendant sub-operations; name, operational_goal, and clear_operational_goal remain root-onlythe updated operationoperations:autonomy + operations:read
set_operation_lifecycleoperation_uuid and paused (required); cascade (default false) to also apply to eligible descendant sub-operationsthe updated operationoperations:autonomy + operations:read
send_operation_messageoperation_uuid, text (required). Attaches the instruction and restarts the operation; one waiting on a blocking sub-operation applies it once that sub-operation finishes. Archived operations, operations frozen and owned by another operation, and operations whose final output contract has already produced its result reject the call.{"operation_uuid", "realm_uuid", "cell_uuid"}operations:reply
set_operation_archivedoperation_uuid (required), archived (default true). Archiving stops the subtree; restoring does not resume it.affected operation UUIDsoperations:archive
approve_approval_requestoperation_uuid, approval_request_id (both required), feedback, approve_always (optional){"status": "accepted", operation_uuid, approval_request_id}operations:approve; approve_always: true also requires operations:autonomy and Autonomous Operations
deny_approval_requestoperation_uuid, approval_request_id (both required), feedback (optional){"status": "denied", operation_uuid, approval_request_id}operations:approve
rerun_actionoperation_uuid, action_cell_uuid (required){"status": "accepted", operation_uuid, action_cell_uuid}operations:approve
submit_form_gateoperation_uuid, gate_id, response (required)gate decisionoperations:answer-ask; credential persistence also requires integration:write
deny_form_gateoperation_uuid, gate_id (required)gate decisionoperations:answer-ask
approve_config_gateoperation_uuid, gate_id (required)gate decisionoperations:approve + realm:update
reject_config_gateoperation_uuid, gate_id (required), reason (optional)gate decisionoperations:approve
allow_output_files_gateoperation_uuid, gate_id (required)gate decisionoperations:approve
respond_monitor_gateoperation_uuid, gate_id (required), payload, summary (optional){"status", "operation_uuid", "gate_id"}operations:reply
cancel_monitor_gateoperation_uuid, gate_id (required){"monitor_uuid", "status", "expires_at"}operations:reply; current blocking monitor only
background_monitor_gateoperation_uuid, gate_id (required){"monitor_uuid", "status", "expires_at"}operations:reply; current blocking monitor only
extend_monitor_gateoperation_uuid, gate_id (required), extend_seconds (optional; default 3,600, range 1–2,592,000){"monitor_uuid", "status", "expires_at"}operations:reply; current blocking monitor only; expiry is capped 30 days after the monitor was armed
approve_sub_operation_gateoperation_uuid, gate_id (required)gate decisionoperations:approve
reject_sub_operation_gateoperation_uuid, gate_id (required)gate decisionoperations:approve

Both cascade tools exclude archived and frozen descendants. Control cascades apply only autonomous, semi_auto_policy, operational_goal_enabled, and planning_enabled to descendants; name and operational-goal text changes remain root-only. Those descendant settings are still applied to terminal operations; only the follow-on execution transition caused by increasing autonomy skips them. An autonomy increase is MANUAL to SEMI_AUTO, MANUAL to AUTO, or SEMI_AUTO to AUTO. Lifecycle pause skips terminal descendants, while resume targets only non-terminal descendants that are paused or parked. A resume target blocked by an active ordinary monitor is skipped without stopping later descendants, so a cascade can be partial. Tool results contain only the updated root operation; call get_operation or list_operations again to observe descendant results.

An operation object is {uuid, name, realm_uuid, parent_uuid, playbook_uuid, playbook_version_uuid, playbook_sub_path, playbook_name, status, paused, activity_state, actionability, pending_gate_uuid, lifecycle_control_revision, status_projection_revision, autonomous, semi_auto_policy, operational_goal, operational_goal_enabled, planning_enabled, created_at, updated_at, archived_at, trigger}, where status is one of PENDING, THINKING, GENERATING, WAITING_FOR_APPROVAL, EXECUTING, SUSPENDED, COMPLETED, FAILED, CANCELLED. PENDING is reported while an operation is parked waiting on a blocking child operation. NO_USER_GATE actionability means there is no pending user-resolvable gate; use activity_state, not actionability, to determine whether the agent is actively progressing, paused, or waiting.

status_projection_revision orders the status projection, not every field on the object. A lower revision is stale. At an equal revision, discard a replayed status event, but merge an authoritative MCP or REST snapshot because non-projection fields may have advanced while the projection stayed unchanged. A higher revision does not imply that another field changed. lifecycle_control_revision independently orders lifecycle control; compare lifecycle fields with that revision instead.

pending_gate_uuid is the UUID of the ledger record holding the user gate the operation is blocked on — the same value gate discovery returns as gate_id for action, form, config, output-files, and sub-operation gates; it is null when there is no such record gate, including monitor waits.

When actionability is USER_BLOCKED, call get_pending_gates and inspect each item in gates. The type discriminator selects the resolution tool: action uses the existing approval-request tools, form uses submit/deny, config uses approve/reject, output_files uses allow, monitor uses respond/cancel/background/extend, and sub_operation uses approve/reject. Discovery returns zero or one action, form, config, output-files, or sub-operation gate, but it can return several blocking monitors. Output-files gates intentionally have no deny tool. Form discovery strips secret defaults, and monitor discovery omits private trigger configuration, conditions, and tokens.

Sub-operation gates include task, execution_mode, created_at, and updated_at. Form, configuration, output-files, and sub-operation decisions, plus respond_monitor_gate, return {"status", "operation_uuid", "gate_id"}. Cancel, background, and extend monitor controls return {"monitor_uuid", "status", "expires_at"} instead.

// tools/call
{"name": "get_pending_gates", "arguments": {"operation_uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6"}}
// response
{
"gates": [
{
"gate_id": "b1e6c2a0-5717-4562-b3fc-2c963f66af11",
"operation_uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"realm_uuid": "3fa85f64-5717-4562-b3fc-2c963f66a000",
"type": "form",
"status": "pending",
"title": "Choose a target",
"description": "Select the host to assess.",
"form_schema": {"type": "object", "properties": {"host": {"type": "string"}}},
"default_values": null,
"secret_fields": null,
"created_at": "2026-07-02T10:15:00Z",
"updated_at": "2026-07-02T10:15:00Z"
}
]
}

All gate variants include gate_id, operation_uuid, realm_uuid, type, and status. Action, form, configuration, output-files, and sub-operation gates also include created_at and updated_at. Form gates add title, description, form_schema, redacted default_values, and secret_fields; configuration gates add config_type, proposed_settings, explanation, and changes_summary; output-files gates add name, summary, body, items, and reason; sub-operation gates add task and execution_mode; monitor gates add name, source_kind, armed_at, and expires_at.

Action and output-files body values, including the body returned by get_current_approval_request, are sanitized for tenant-sensitive values and sensitive JSON keys. Redacted values are replaced with ***REDACTED***, so the returned body is not guaranteed to match its source text byte for byte.

Example: reading and resolving a pending approval

// tools/call
{"name": "get_current_approval_request", "arguments": {"operation_uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6"}}
// response
{
"approval_request": {
"approval_request_id": "b1e6c2a0-5717-4562-b3fc-2c963f66af11",
"operation_uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"realm_uuid": "3fa85f64-5717-4562-b3fc-2c963f66a000",
"type": "action",
"status": "pending",
"tool": "run_bash",
"execution_layer": "TENTACLE",
"vessel_type": null,
"name": "Run shell command",
"summary": "Scan the target's open ports",
"body": "nmap -p 3000 <target>",
"reason": "Shell command requires approval",
"created_at": "2026-07-02T10:15:00Z",
"updated_at": "2026-07-02T10:15:00Z"
}
}
// tools/call
{
"name": "approve_approval_request",
"arguments": {
"operation_uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"approval_request_id": "b1e6c2a0-5717-4562-b3fc-2c963f66af11",
"feedback": "Looks scoped correctly"
}
}
// response
{
"status": "accepted",
"operation_uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"approval_request_id": "b1e6c2a0-5717-4562-b3fc-2c963f66af11"
}

When get_current_approval_request returns {"approval_request": null}, there is nothing pending — poll again once the operation has moved past its current step.

Auth

Every request carries Authorization: Bearer <api-key>, where the key has the shape crk_live_<key_uuid>.<secret>. A key is scoped to a fixed set of realms at creation time — a realm_uuid or an operation outside that set is rejected, not filtered.

CapabilityGrants
operations:readlist_realms, list_playbooks, list_models, list_operations, get_operation, get_current_approval_request, get_pending_gates
operations:createcreate_operation
operations:autonomyupdate_operation_controls (rename, autonomy, semi-auto policy, goal and planning controls) and set_operation_lifecycle (pause/resume)
operations:archiveset_operation_archived
operations:approveaction and delegated sub-operation decisions, action reruns, config rejection, and output-files allow
realm:updateconfiguration approval, together with operations:approve
operations:answer-asksubmit_form_gate, deny_form_gate
integration:writePersist credentials submitted through submit_form_gate; credential forms require both capabilities.
operations:replysend_operation_message, respond_monitor_gate, cancel_monitor_gate, background_monitor_gate, extend_monitor_gate

Requirements

  • A Cracken API key, created in Settings → API keys (available to tenant owners) and scoped to the realms you want to reach.
  • To create operations, grant the key the Create operations capability (operations:create). Forking also requires operations:read; creating in SEMI_AUTO or AUTO also requires operations:autonomy.
  • Grant the key the capability that matches each gate it must resolve: operations:approve for action and delegated sub-operation decisions, configuration rejection, and output decisions; configuration approval also requires realm:update; forms require operations:answer-ask; blocking monitors require operations:reply. Submitting a credential-saving form also requires integration:write. approve_always: true additionally requires operations:autonomy and the Autonomous Operations plan feature because it persists a broad semi-auto-policy rule. A read-only key can discover gates but cannot resolve them.
  • On Cracken Cloud (SaaS): the Pro plan or higher. Self-hosted / on-premises deployments have no plans, so this requirement does not apply.

Give the agent external MCP servers

Give the agent extra tools and data sources during an operation by running MCP servers on a Tentacle. The agent discovers the tools an MCP server exposes and calls them alongside Cracken's built-in tools. Once a server is running, its tools — discovered as mcp__<server_name>__<tool_name> — are inherited by every operation in the realm until the server's Vessel is terminated.

What an MCP server is

An MCP server is a process that implements the Model Context Protocol and exposes tools and data sources. The agent can start a local MCP server on a Tentacle, or connect to a remote MCP server over HTTP, and then invoke its tools during an operation. This extends what the agent can do beyond Cracken's built-in Vessels and tools.

Common uses:

  • Domain-specific tools — connect proprietary or specialized security tools.
  • Custom data sources — give the agent access to internal databases or APIs.
  • Third-party services — let the agent call external services during operations.

How MCP servers work

Saved configurations

A realm can hold saved MCP server configurations. A configuration is a template: it records how to start or connect a server, not a running instance. Any operation in the realm can reference a saved configuration by name when the agent starts a server.

The agent starts servers

The agent runs MCP servers itself during an operation, using one of two tools:

  • start_mcp_server — starts a local server process on a Tentacle (for example npx, uvx, or a path to an executable). It can use a saved configuration by name (config_name) or take a command and args directly.
  • connect_mcp_server — connects to a remote server whose command is an http:// or https:// URL.

Each call takes an optional tentacle_uuid — the connected Tentacle the server runs on or is reached from; when omitted, Cracken selects an available Tentacle for the realm. reasoning is always required, and connect_mcp_server also requires a command. The agent decides when to start or connect a server based on the task and the tools it needs.

Realm-wide availability

Once a server is running in an operation, it becomes available to every operation in the same realm. Cracken inherits running MCP servers across operations in a realm, so a server only needs to be started once per realm. A server's tools stop being inherited when its Vessel is terminated.

Set up a saved configuration

Open Integration Center → MCP Servers in your realm. The tab shows a single MCP server input, an optional Realm selector (shown only when you belong to more than one realm), and an Install or Connect button.

  1. Type the server name in the MCP server field.
  2. If you belong to more than one realm, pick the target realm.
  3. Select Install or Connect.

This starts an operation that sets up the server in the realm; the agent does the actual install or connect. Saved configurations and currently running servers appear below the form in the Connected list and the saved-configuration list.

Agent tools

The agent uses these tools to manage MCP servers. Every call requires a reasoning string and takes an optional tentacle_uuid.

start_mcp_server

Starts a local MCP server process on a Tentacle. Use a saved configuration by name, or pass a command directly.

Example — why the agent starts one: mid-operation the agent needs a capability Cracken's built-in Vessels and tools don't cover — for instance, querying a PostgreSQL database it just found credentials for. Instead of scripting psql calls by hand, it starts the Postgres MCP server on the Tentacle (npx -y @modelcontextprotocol/server-postgres), then uses mcp_call to run that server's schema-inspection and query tools directly. The same pattern applies to any specialized toolset shipped as an MCP server — a cloud provider's CLI wrapper, a SAST scanner, or an internal API — that is more reliable to drive through structured tools than raw shell commands.

Pre-configured:

{
"tentacle_uuid": "11111111-1111-1111-1111-111111111111",
"config_name": "my-server",
"reasoning": "Need specialized tools from my-server"
}

Ad-hoc:

{
"tentacle_uuid": "11111111-1111-1111-1111-111111111111",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-time"],
"env": { "LOG_LEVEL": "info" },
"credential_bindings": {
"TAVILY_API_KEY": {
"service_slug": "tavily",
"field_name": "api_key"
}
},
"reasoning": "Need time-related tools for this task"
}

Put only non-secret variables in env. For secrets, save the service credential in your realm's Integrations first, then reference it from credential_bindings: each entry maps an environment variable name to a service_slug and the field_name to read from that saved credential. Cracken resolves the value from the realm's saved credentials at execution time, so no plaintext secret is stored in the MCP configuration. The agent can also pass protocol_version and a transport override.

Tentacle selection

For Tentacle-backed MCP servers, the agent can pass tentacle_uuid to bind startup to a specific ready Tentacle. When tentacle_uuid is omitted, Cracken selects an available Tentacle for the realm. After the server is running, mcp_call and stop requests continue using the Tentacle that owns that active server. Explicit selections stay pinned to the requested Tentacle and wait until it is ready.

connect_mcp_server

Connects to a remote MCP server. The command must be an http:// or https:// URL.

{
"tentacle_uuid": "11111111-1111-1111-1111-111111111111",
"command": "https://mcp.example.com/mcp",
"headers": { "X-Client": "cracken" },
"reasoning": "Connect to the remote tools server"
}

Put only non-secret values in headers. The agent can also pass protocol_version and a transport override.

mcp_call

Invokes a tool on a running MCP server.

{
"tentacle_uuid": "11111111-1111-1111-1111-111111111111",
"server_name": "my-server",
"tool_name": "query_database",
"arguments": { "query": "SELECT * FROM findings" },
"reasoning": "Querying internal database for existing findings"
}

timeout_seconds is optional.

stop_mcp_server

Stops or disconnects a running MCP server. Identify the server by server_name or by vessel_uuid.

{
"tentacle_uuid": "11111111-1111-1111-1111-111111111111",
"server_name": "my-server",
"reasoning": "No longer need this server"
}

Discovering available tools

Once a server is running, the agent discovers the tools it exposes. These tools sit alongside the agent's built-in capabilities and can be invoked through mcp_call or as dynamic tools named mcp__<server_name>__<tool_name>. The agent selects an MCP tool when it is relevant to the task — the same way it selects built-in Vessels and tools.

Stopping MCP servers

You can stop a server from the Connected list in the MCP Servers tab: find the running server and select Disconnect. Stopping terminates the server instance and removes it from operations in the realm. The saved configuration stays intact and can be used to start a new instance later.

Automatic cleanup

When a server's Vessel is terminated — for example the Tentacle disconnects or the operation completes — Cracken stops inheriting that server and removes it from the affected operations.

Transport

The agent chooses how to reach a server by which tool it uses: start_mcp_server runs a local process on the Tentacle, and connect_mcp_server reaches a remote server over HTTP.

For remote servers, the wire transport defaults to auto. The agent can override it with the transport field:

ValueMeaning
autoLet the connection negotiate the transport. This is the default.
streamable_httpStreamable HTTP, the current MCP HTTP transport.
legacy_sseThe older HTTP+Server-Sent Events transport, for servers that have not adopted Streamable HTTP.
  • Tentacles — where the agent's MCP servers run and how Tentacles connect.
  • Integrations — save the service credentials that credential_bindings reference.
  • Operations — where the agent starts servers and calls their tools, and the operations a client drives over MCP.