Skip to content

Integration guide

Crank exposes the same tool registry through several transports. Pick the one your runtime supports; the tools, parameters, and structured envelopes are identical across all of them.

One source of truth

Every tool is defined once as a @mcp.tool on the FastMCP server. The crank_mcp.schema_export module introspects that live registry and emits per-framework definitions, so no integration hand-maintains its own copy:

Target Exporter Artifact
OpenAI function calling to_openai openai.json
Gemini functionDeclarations to_gemini gemini.json
OpenAPI 3.1 document build_openapi_document reference/openapi.json
LangChain StructuredTool to_langchain langchain.json

Regenerate the JSON artifacts at any time:

source .venv/bin/activate
python scripts/export-tool-schemas.py            # writes build/tool-schemas/*.json

The Markdown tool reference is generated from the same snapshot by docs/gen_tool_reference.py. Never hand-edit generated output; change the tool docstring and regenerate.

The hosted server speaks the MCP streamable-HTTP transport: a single endpoint that takes JSON-RPC over POST and streams the event channel over GET.

https://mcp.crank.ing/mcp
  • CORS is open by default, so browser-based agents (OpenAI Responses, web LangChain) can call it cross-origin.
  • The transport returns an mcp-session-id header; echo it back on subsequent requests to resume a session.
  • HSTS and standard hardening headers are set on every response.

This is the right choice for most agents, including remote MCP connectors.

Transport 2: stdio (local, for desktop and local-model hosts)

Status: Coming soon

Hosts that launch MCP servers as a subprocess -- Claude Desktop, Cursor, Windsurf, Codex CLI, Gemini CLI, LM Studio, and MCPHost with Ollama, llama.cpp or MLX models -- run the Crank stdio bridge. One command, no server to host:

npx -y @crank-ing/mcp      # TypeScript
uvx crank-mcp          # Python twin, same flags

@crank-ing/mcp and crank-mcp ship with the SDKs and are not yet published to npm or PyPI. Until then, run the bridge from a checkout of the repository: packages/crank-mcp-stdio (npm install && npm run build, then node dist/cli.js).

The bridge is a thin local proxy. It forwards tools/list and tools/call to https://mcp.crank.ing/mcp/agent-v1, or to the anonymous /mcp surface while you are not paired, and adds four things on your machine:

  • A small tool set by default. --profile=lite (the default) serves the 14 lite tools described below. --profile=full serves everything your pairing allows. --toolsets=market_data,spot,portfolio sends X-Crank-Toolsets to narrow the list further.
  • Pairing, with the token in your OS keychain. While unpaired, the bridge serves read-only tools only and starts the pairing flow in the background. Your model can call the crank_pair tool to get the short code and the crank.ing URL to show you. You approve in your browser, and the bridge switches to agent-v1 and refreshes the tool list. The token is stored in the macOS Keychain or the Linux Secret Service (a 0600 file is the fallback), in the same place npx create-crank-agent pair uses. It is never printed and never returned by a tool. crank-mcp pair pairs from a terminal instead.
  • Signing stays in your wallet. A value-bearing tool returns an unsigned transaction. The bridge never signs with a key of its own, because it holds none. It hands the transaction to a local signer hook: --signer=wallet-adapter (the default) opens crank.ing/approve/<id>, where you review the trade and the technology service fee and sign with your own browser wallet. --signer=ledger signs on a Ledger device, --signer=turnkey uses a Turnkey session signer under your Turnkey policy, and --signer=module:<path> loads your own signer module. There is no keypair or private-key option, and the bridge refuses to start if its configuration contains wallet key material.
  • A local policy pre-check. Before forwarding a swap, the bridge reads the wallet's policy (wallet_status, get_trading_limits) and refuses locally when the call would obviously be refused anyway: a paused or killed wallet, or a trade paid in USDC that is larger than a per-trade or daily cap. Crank's server still runs the full policy check on every call.

Add flags to args, for example ["-y", "@crank-ing/mcp", "--toolsets=spot,portfolio"]. Use --dev to point at the dev endpoints. Do not put a key, seed phrase or pairing token in any of these files.

Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "crank": {
      "command": "npx",
      "args": ["-y", "@crank-ing/mcp"]
    }
  }
}

With the Python twin, use "command": "uvx" and "args": ["crank-mcp"].

Cursor

~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one project). The entry is the same as for Claude Desktop:

{
  "mcpServers": {
    "crank": {
      "command": "npx",
      "args": ["-y", "@crank-ing/mcp"]
    }
  }
}

Windsurf

~/.codeium/windsurf/mcp_config.json, with the same mcpServers entry as Claude Desktop.

Codex CLI

~/.codex/config.toml:

[mcp_servers.crank]
command = "npx"
args = ["-y", "@crank-ing/mcp"]

Gemini CLI

Merge into the mcpServers key of ~/.gemini/settings.json:

{
  "mcpServers": {
    "crank": {
      "command": "npx",
      "args": ["-y", "@crank-ing/mcp"]
    }
  }
}

LM Studio

In LM Studio, open the Program tab, choose Install, then Edit mcp.json (~/.lmstudio/mcp.json), and add the same mcpServers entry as Claude Desktop.

MCPHost with Ollama

examples/local-ollama/mcphost-config.stdio.json:

{
  "mcpServers": {
    "crank": {
      "type": "local",
      "command": ["npx", "-y", "@crank-ing/mcp"]
    }
  }
}
mcphost --config mcphost-config.stdio.json --model "ollama:qwen2.5:7b"

The same snippets are in packages/crank-mcp-stdio/hosts/. The package's test suite launches each one and checks that it serves the lite tool set.

Self-hosting the full server

Running the FastMCP server itself (python -m crank_mcp.server, stdio by default, or MCP_TRANSPORT=http MCP_PORT=8900 python -m crank_mcp.server) needs the Crank backend alongside it. That is a path for Crank contributors, not for customers. Use the bridge above instead.

Transport 3: OpenAPI / REST

If your runtime cannot speak MCP, consume the OpenAPI 3.1 document. Each tool is a POST /tools/{tool_name} operation whose request body is the tool's parameter schema and whose response is the structured envelope.

Tool surfaces and per-harness presets

Smaller tool lists mean smaller prompts and more reliable tool selection. The hosted server offers several surfaces over the same registry:

Path Who it is for Auth
/mcp Full public catalog caller_id; x402 on value-bearing actions
/mcp/agent-v1 Autonomous agents: the full execution surface Paired plugin token (Authorization: Bearer)
/mcp/agent-lite Small / on-device models: a fixed set of 14 tools Same paired plugin token as agent-v1

The lite profile

/mcp/agent-lite serves a frozen set of tools, enough to quote, check, propose and track a spot trade, plus the two wallet brakes:

get_quotes, token_info, asset_classification, get_market_briefing, get_balances, portfolio_snapshot, get_trading_limits, wallet_status, jupiter_swap, create_execution_intent, get_intent_status, pause_wallet, kill_wallet, search_tools.

  • Descriptions are one line (160 characters at most). Schemas carry no examples, title or output schema, and closed value sets are enums (get_market_briefing.detail, detail_level; jupiter_swap.submit_mode). The full docstrings stay in the tool reference.
  • jupiter_swap on lite is for building the transaction: omit signed_transaction and you get an UNSIGNED transaction for the user's own wallet to sign. Crank never holds keys.
  • A call to any tool outside the set is refused before authentication is checked. search_tools still searches the whole catalog, so a model can tell the user which wider tool they need on agent-v1.
  • Already connected to agent-v1? Send X-Crank-Profile: lite on each request to get the same narrowed, compact surface on that URL. If the header is missing, you get the full agent-v1 surface, under the same token and scopes.

Presets by harness

Harness Surface Narrowing
Claude Code / Claude Agent SDK /mcp or /mcp/agent-v1 (full) Keep the full list; let the model call search_tools to discover tools
Cursor / Codex /mcp/agent-v1 X-Crank-Toolsets: spot,portfolio
Claude Desktop, Cursor, Windsurf, Codex CLI, Gemini CLI, LM Studio (stdio) npx -y @crank-ing/mcp (proxies agent-v1) Lite by default; --toolsets= or --profile=full
Apple Foundation Models, 3-8B local models (Ollama / MLX), LoRA fine-tunes /mcp/agent-lite, or @crank-ing/mcp over stdio via MCPHost / LM Studio None needed: the set is fixed

X-Crank-Toolsets takes a comma-separated list of toolset names (market_data, spot, perps, lending_staking, portfolio, strategies, intelligence, rewards_growth, wallet_admin, support). It only shortens tools/list; it is never an access control.

Prompt caching for customer harnesses

Tool schemas are the largest fixed part of every request. To keep them cached:

  • Crank serves tools/list in a stable order. On lite, the order is the frozen list above; on every other surface, it is registry order. Do not re-sort or filter tools per request on the client side.
  • Put the tool block first and place your cache breakpoint straight after it (for Claude, cache_control on the last tool definition), before the system prompt and the conversation.
  • Fetch tools/list once per session and reuse it. A changed tool list invalidates the cache.
  • Each surface's tools/list size is measured in CI (cl100k tokens as a proxy). The lite surface has a hard ceiling of 4,000 tokens.

Per-framework wiring

Framework How Detailed doc
Claude (API / Agent SDK / Desktop) Remote MCP connector, or stdio via @crank-ing/mcp Code examples
OpenAI (function calling / GPT Actions) Feed openai.json; dispatch tool calls docs/integrations/openai.md
Gemini Feed gemini.json functionDeclarations; dispatch docs/integrations/gemini.md
LangChain / CrewAI Native MCP tool loader, or langchain.json Code examples
Crank SDKs (Python / TypeScript) crank-sdk, @crank-ing/sdk -- Status: Coming soon docs/integrations/sdk.md
OpenClaw autonomous managers Provisioning API docs/integrations/openclaw.md

Environments

Network Use
devnet Default sandbox. Build and test here.
mainnet Production. Switch only when your flow is proven.

The tool surface is identical across networks. Free read tools work without any payment setup on either network; value-bearing actions require the x402 flow described in Authentication & x402.