MCP server

The Dcision MCP server at https://api.dcision.io/mcp — authentication, the nine tools with their inputs and outputs, errors, and setup for Claude Code, Cursor, VS Code, Claude Desktop, Codex, Gemini CLI and curl.

Endpoint    https://api.dcision.io/mcp
Transport   Streamable HTTP (stateless, JSON responses)
Auth        Authorization: Bearer dcs_live_… | dcs_test_…

The Model Context Protocol server lets AI agents and coding assistants use Dcision: list your decisions, read their contract, check and run states, read executions, browse templates and validate decision schemas. It is part of the Dcision API — same keys, same limits, same billing as the REST API.

For a step-by-step setup in Claude Code, with the Dcision skill, see Use Dcision in Claude Code.

Authentication

Send a workspace API key as a Bearer token on every request. The server keeps no session and stores no credential: each request is authenticated on its own, and the tools act on the key's workspace.

  • No key, a malformed key or a revoked key → HTTP 401, with a WWW-Authenticate: Bearer header and a message that says where to create a key.
  • Only API keys are accepted — never a session from the app.
  • Prefer a dcs_test_… key while you experiment: runs are real and count as usage, but destinations deliver with livemode: false.

Limits and billing

Every requestCounts in the read rate-limit window, shared with GET /v1/me, GET /v1/decisions and GET /v1/executions. Reads are not billed.
run_decisionAlso counts in the decisions window, shared with POST /v1/decisions/{slug}. Billed like an API call, with the same quota.
RequestsPOST /mcp only. GET /mcp and DELETE /mcp answer 405: there are no sessions and no server-sent event stream.

Tools

Every tool returns its result as JSON — as text in the result's content, and as structuredContent. Every tool but run_decision is annotated readOnlyHint: true; run_decision is annotated as neither read-only nor idempotent, so clients can ask before they call it.

ToolRead-onlyArgumentsReturns
get_accountYes—The key's workspace, the key, the plan and this period's usage — the body of GET /v1/me.
list_decisionsYes—The workspace's decisions with slug, name, status and active version — the body of GET /v1/decisions.
get_decisionYesslugOne decision's contract — state schema, questions with their options, actions, fallback action and an example state — the body of GET /v1/decisions/{slug}.
check_stateYesslug, state{ "valid": true }, or { "valid": false, "message" } with the reason a run would fail with 422 INVALID_STATE. Checks the active version's state schema and the state's own token limit; nothing runs. A run can still answer 422 when the state plus the longest question exceed the engine's token budget.
run_decisionNo — billedslug, state, optional include_probabilities (boolean)The decision's response, as POST /v1/decisions/{slug} returns it.
list_executionsYesoptional decision (slug), status (success or error), limit (1–100, default 20), cursorRecent executions, never the inputs — the body of GET /v1/executions.
list_templatesYes—{ "data": [...] } with each template's id, name, description, category and patterns.
get_templateYesidThe template's summary plus its complete decision schema in schema and a sample_state.
validate_schemaYesschema (object){ "valid": true, "schema" } with the normalized schema — other added, defaults filled in — or { "valid": false, "issues": [{ "path", "message" }] }. Same rules as the editor and the API.

Each tool publishes its exact input schema in tools/list: read it there when you build your own client.

Run decisions

The usual flow, which the Dcision skill teaches agents:

  1. list_decisions — pick a decision whose status is deployed.
  2. get_decision — read state_schema and start from example_state.
  3. check_state — fix the state until it passes; it costs nothing.
  4. run_decision — run it once, then act on action.

run_decision sends the state as the API does: an object, a string or an array, depending on the decision's state kind. It has no idempotency key: every call that reaches the engine runs and is billed. If a call fails on the network, look for the run with list_executions before trying again. For retries that are safe by construction, call the REST API with an Idempotency-Key.

Write decision schemas

Creating, editing and deploying decisions happens in the app: API keys can't change decisions. An agent can still do most of the work — start from get_template, write the schema, run validate_schema until it has no issues, and give it to you to paste in the decision's editor, test in the Playground and deploy.

Errors

WhereWhat you get
HTTP + JSON-RPC error401 without a valid API key (with WWW-Authenticate: Bearer), 429 when the read window is used up, 405 for any method but POST, 406 without Accept: application/json, text/event-stream, 400 for a JSON-RPC batch (send one message per request). The body is a JSON-RPC error whose message says what to do. A body that isn't JSON at all gets the API's own 400 INVALID_REQUEST error object.
Tool resultisError: true and { "error": { "code", "message", "details" } } as text, for everything the API would answer with an error — DECISION_NOT_FOUND, DECISION_NOT_DEPLOYED, INVALID_STATE, CREDITS_EXHAUSTED, SPEND_CAP_REACHED, QUOTA_EXCEEDED, RATE_LIMITED on run_decision, engine errors — and also for an unknown tool (NOT_FOUND) or invalid arguments (INVALID_REQUEST, with each issue in details). See Errors.

An agent should read the error's message — it says what to fix — and not retry a 4xx unchanged.

Claude Code

claude mcp add --transport http dcision https://api.dcision.io/mcp \
  --header "Authorization: Bearer $DCISION_API_KEY" \
  --scope user

Drop --scope user to add it to the current project only, or commit a .mcp.json that reads the key from each person's environment:

.mcp.json
{
  "mcpServers": {
    "dcision": {
      "type": "http",
      "url": "https://api.dcision.io/mcp",
      "headers": { "Authorization": "Bearer ${DCISION_API_KEY}" }
    }
  }
}

More in Use Dcision in Claude Code.

Other clients

Any MCP client that supports remote servers over Streamable HTTP with a custom header can connect.

{
  "mcpServers": {
    "dcision": {
      "url": "https://api.dcision.io/mcp",
      "headers": { "Authorization": "Bearer ${env:DCISION_API_KEY}" }
    }
  }
}
  • Cursor — ~/.cursor/mcp.json for every project, or .cursor/mcp.json in a repository.
  • VS Code — .vscode/mcp.json; VS Code asks for the key once and stores it securely.
  • Claude Desktop — Settings → Developer → Edit Config (claude_desktop_config.json). Claude Desktop connects to remote servers through mcp-remote, a community bridge that needs Node.js; the header is passed through an environment variable so the space after Bearer survives on every platform. Restart Claude Desktop after editing.
  • Codex — ~/.codex/config.toml, with DCISION_API_KEY exported where Codex runs.
  • Gemini CLI — ~/.gemini/settings.json or .gemini/settings.json in a project.

ChatGPT and claude.ai

Connectors in ChatGPT and on claude.ai sign in with OAuth, which the Dcision MCP server doesn't offer yet: it only accepts an API key in a header. Use one of the clients above, or the REST API.

Call the server with curl

The server speaks plain JSON-RPC 2.0 over HTTP, and it is stateless — no initialize handshake is needed. Send Content-Type: application/json and Accept: application/json, text/event-stream:

curl -s https://api.dcision.io/mcp \
  -H "Authorization: Bearer $DCISION_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Call a tool with tools/call, its name and its arguments:

curl -s https://api.dcision.io/mcp \
  -H "Authorization: Bearer $DCISION_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": { "name": "get_decision", "arguments": { "slug": "lead-qualification" } }
  }' | jq '.result.structuredContent'

The answer is a JSON-RPC response: result.content[0].text holds the tool's JSON as text and result.structuredContent the same value as an object (abridged):

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [{ "type": "text", "text": "{\"slug\": \"lead-qualification\", \"status\": \"deployed\", \"version\": 3}" }],
    "structuredContent": { "slug": "lead-qualification", "status": "deployed", "version": 3 }
  }
}

This is also how the Dcision skill reaches validate_schema, check_state and the templates when no MCP client is configured.

Security

  • The server acts only on the key's workspace; a key can't reach another workspace's decisions.
  • Tools never return the inputs of past executions, secrets, destination configuration (URLs, headers) or the full schema of a decision — only the contract of its active version. Results of run_decision and list_executions do include the destinations entries of each run, which may carry values mapped from the state (function params, LLM or agent replies): treat them like any decision output.
  • Treat a key used by an agent like any production secret: keep it in the environment, scope it to a test key while experimenting, and revoke it in API Keys if it leaks.

On this page