- AI & Agents
- MCP Server
MCP Server
Ironflow includes a built-in Model Context Protocol (MCP) server. This lets AI assistants operate your Ironflow server directly from the IDE — list runs, inspect step outputs, emit events, query projections, and more.
Claude Code
Section titled “Claude Code”Add to your project’s .mcp.json:
{ "mcpServers": { "ironflow": { "command": "ironflow", "args": ["mcp", "--allow-writes"] } }}Cursor
Section titled “Cursor”Add to your MCP settings (Settings → MCP):
{ "ironflow": { "command": "ironflow", "args": ["mcp", "--allow-writes"] }}Custom Server URL
Section titled “Custom Server URL”If the Ironflow server is running on a different port or host:
{ "mcpServers": { "ironflow": { "command": "ironflow", "args": ["mcp", "--allow-writes", "--server-url", "http://localhost:9000"] } }}Authentication
Section titled “Authentication”For servers with auth enabled, pass an API key:
{ "mcpServers": { "ironflow": { "command": "ironflow", "args": ["mcp", "--allow-writes", "--api-key", "ifkey_your_api_key"] } }}Or set the IRONFLOW_API_KEY environment variable.
Read-Only vs Read-Write Mode
Section titled “Read-Only vs Read-Write Mode”By default, the MCP server starts in read-only mode — only observation tools are available. Add --allow-writes to enable tools that modify state (emitting events, invoking functions, writing to KV store, etc.). Pairing --allow-writes with --evidence-file also registers ironflow_await_reload, a cooperative gate that blocks until the dev server re-registers your functions past the version your last test event hit — call it after editing function code and before emitting a verification event. A plain --allow-writes session (no evidence file) does not expose it.
Available Tools
Section titled “Available Tools”Read Tools (always available)
Section titled “Read Tools (always available)”| Tool | Description |
|---|---|
ironflow_server_info | Server health and version |
ironflow_overview | Dashboard stats: function count, active runs, workers, recent events |
ironflow_list_functions | All registered functions, with limit/offset paging |
ironflow_get_function | Function details: triggers, concurrency, config |
ironflow_list_runs | Recent workflow runs with status, with limit/offset paging |
ironflow_get_run | Detailed run info including step outputs |
ironflow_get_run_steps | Step-by-step execution details |
ironflow_list_events | Events, with filters (names, since, until, source, search) and keyset paging |
ironflow_list_projections | All projections (read models), with limit/offset paging |
ironflow_projection_status | Specific projection state |
ironflow_list_entity_streams | All entity streams, with limit/offset paging |
ironflow_read_entity_stream | Entity event history |
ironflow_list_projects | Projects (organizational boundaries) |
ironflow_list_environments | Environments (deployment targets) |
ironflow_list_workers | Connected pull-mode workers |
ironflow_kv_list_buckets | KV store buckets |
ironflow_kv_list_keys | Keys in a KV bucket |
ironflow_kv_get | Get a KV value |
ironflow_list_secrets | Available secret names |
ironflow_sql_query | Read-only SQL queries |
ironflow_rebuild_projection_status | Progress of a rebuild job: events processed, total, ETA |
ironflow_outbox_dlq_list | Outbox dead-letter entries — delivery failures (env required) |
ironflow_circuit_breaker_list | Circuit breakers and their state (closed / open / half-open) |
The last three are operator diagnosis verbs. They sit in the read-only set on purpose: an agent without write access can still determine that dispatch is blocked by an open breaker, or that events are stuck in the outbox. Repairing either needs the corresponding write tool below.
Write Tools (requires --allow-writes)
Section titled “Write Tools (requires --allow-writes)”| Tool | Description |
|---|---|
ironflow_emit_event | Emit an event (triggers matching functions) |
ironflow_invoke_function | Directly invoke a function |
ironflow_cancel_run | Cancel a running workflow |
ironflow_append_entity_event | Append an event to an entity stream |
ironflow_kv_put | Store a value in a KV bucket |
ironflow_secret_set | Set a secret value |
ironflow_resume_run | Resume a paused or failed run — also the retry verb |
ironflow_rebuild_projection | Start a projection rebuild. Destructive — deletes the read model and replays it; the projection serves nothing until it finishes |
ironflow_outbox_dlq_requeue | Requeue dead-letter rows — every row sharing the event_id, not one (env required) |
ironflow_outbox_dlq_discard | Discard dead-letter rows permanently — every row sharing the event_id. Irreversible (env required) |
ironflow_circuit_breaker_reset | Reset a breaker to closed, unblocking dispatch |
Resume, rebuild, requeue and reset are platform remediation: they operate the
runtime itself rather than your application. ironflow_emit_event and
ironflow_invoke_function can only trigger remediation your own code implements.
Example Workflows
Section titled “Example Workflows”Building an App with AI
Section titled “Building an App with AI”With the MCP server configured, you can ask your AI assistant to:
- “What functions are registered?” → calls
ironflow_list_functions - “Emit an order.placed event” → calls
ironflow_emit_event - “Show me what happened in that run” → calls
ironflow_get_run+ironflow_get_run_steps - “What’s the current state of the order-stats projection?” → calls
ironflow_projection_status - “Query the database for failed runs in the last hour” → calls
ironflow_sql_query
Debugging a Failed Run
Section titled “Debugging a Failed Run”You: "List recent failed runs"AI: → ironflow_list_runs (filters for failed status) "Run run_abc123 failed at step 'charge-payment'"
You: "Show me what happened step by step"AI: → ironflow_get_run_steps(run_id: "run_abc123") "Step 1 (validate-order) succeeded with output {...} Step 2 (charge-payment) failed: 'Payment gateway timeout'"
You: "What event triggered this?"AI: → ironflow_list_events "Event order.placed with data {orderId: 'ord-456', total: 99.99}"CLI Reference
Section titled “CLI Reference”ironflow mcp # Read-only modeironflow mcp --allow-writes # Enable write operationsironflow mcp --server-url http://host:port # Custom server URLironflow mcp --api-key ifkey_xxx # API key authenticationIRONFLOW_MCP_BEARER_TOKEN=... ironflow mcp --transport=streamable-http --port=0 # Authenticated loopback HTTP| Flag | Default | Description |
|---|---|---|
--allow-writes | false | Enable write operations |
--server-url | http://localhost:9123 | Ironflow server URL |
--api-key | "" | API key (or set IRONFLOW_API_KEY) |
--transport | stdio | stdio or authenticated streamable-http |
--host | 127.0.0.1 | Loopback HTTP bind host |
--port | 0 | HTTP port (0 chooses an ephemeral port) |
--port-file | "" | Write the bound port as mode-0600 JSON |
--evidence-file | "" | Append a JSONL trail of every tool call and result to this file |
--static-only | false | Exclude SDK-registered application tools |
Pair with AI Skills
Section titled “Pair with AI Skills”The MCP server provides runtime tools (the agent’s “hands”), while AI Skills provide structured knowledge and workflows (the agent’s “brain”). The ops skill automatically uses MCP tools when available and falls back to CLI when not. For the best AI experience, use both.
Dynamic Agent Tools
Section titled “Dynamic Agent Tools”Unless --static-only is set, the MCP server automatically discovers and registers dynamic agent tools at startup. These are tools registered by SDK clients via the AgentToolsService/RegisterTool RPC on the running ironflow serve process.
- The MCP CLI calls
ListToolsat startup to fetch SDK-registered tools - Each returned tool is registered as a dynamic MCP tool
- Invocations are forwarded to the Ironflow server via
InvokeTool - This is best-effort — if the server is unreachable, static tools still work
- Restart the MCP CLI to pick up newly registered agent tools (no live
tools/list_changedpush in v1)
This means your effective MCP tool count may be higher than the static tool set listed in the tables above. (The tables list 34; ironflow_await_reload is the 35th and is described above rather than tabled, since it needs --evidence-file as well.)