reasonix-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@reasonix-mcpspawn an agent to investigate the flaky tests and propose a fix"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
reasonix-mcp — spawn and steer Reasonix agents from any MCP client
An MCP server that bridges any MCP host (Claude Code, Codex, …) to live,
interactive Reasonix agents. Your MCP client is the front-end; this project
adds the server it talks to, plus a detached daemon that owns the agents.
Each spawned agent runs reasonix acp
(Agent Client Protocol v1, NDJSON
JSON-RPC over stdio) in a subprocess, rooted in your project, under your own
Reasonix config and provider credentials.
How it works
MCP host (Claude Code, Codex, …) ──(MCP stdio)──▶ launcher.py ──▶ server.py ──(Unix socket JSON-RPC)──▶ agentd ──(ACP stdio)──▶ reasonix acp ──▶ agents
│ spawn/send/watch/poll/list/… ▲ owns the subprocesses
└─ blocking watch + elicitation ──────┘launcher.py is the per-orchestrator MCP supervisor; server.py is a thin
MCP front-end; agentd.py is a detached daemon that
owns the agents. This split is what makes agents survive: close the MCP host
(or kill the MCP server) and the fleet keeps running in the daemon — a new
server reconnects to the same socket and reasonix_list shows everything
still there. agentd is auto-started by the server on first use
(socket: ~/.reasonix-mcp/agentd.sock, log beside it) and stops only when
shut down (killing the daemon kills its agents — they carry PDEATHSIG).
Spawn returns a
session_idimmediately; the agent works in the daemon.Send steers a running agent mid-turn via
_reasonix.io/session/steer; if idle it starts a new turn.Poll returns recent output since last poll: text, turns, plan, events, permission requests, stop reason, and terminal error text when applicable.
Cleanup can stop completed agents after an idle grace period; it is disabled by default. Use
keep_alive=truefor interactive follow-up turns.Resume revives a stopped/crashed session from its persisted transcript.
Stop cancels + closes + kills; the session stays listed and resumable.
Wake-up: keep
reasonix_watchin flight. It returns compact terminal or permission results directly, with no timeout and no follow-up poll by default. Wire notifications are diagnostics only.
Related MCP server: OpenClaw MCP Server
Setup
cd ~/reasonix-mcp
python3 -m venv .venv
.venv/bin/pip install -r requirements.txtRequires reasonix on PATH (verified: v1.17.20) and a configured provider
(reasonix setup).
Register with your MCP client
Project scope (this directory): the included .mcp.json is picked up
automatically when the MCP host runs in ~/reasonix-mcp.
User scope (available in every project) — example with Claude Code:
claude mcp add reasonix --scope user -- \
/home/asmodeus/reasonix-mcp/.venv/bin/python \
/home/asmodeus/reasonix-mcp/src/reasonix_mcp/launcher.pyFor Codex, register the same launcher and raise the per-tool transport timeout
because reasonix_watch is intentionally long-lived:
[mcp_servers.reasonix]
command = "/home/asmodeus/reasonix-mcp/.venv/bin/python"
args = ["/home/asmodeus/reasonix-mcp/src/reasonix_mcp/launcher.py"]
tool_timeout_sec = 86400Codex defaults to a finite per-tool timeout (and existing installations may
use a shorter explicit value such as 300 seconds). A
timed out awaiting tools/call error at that exact interval is the Codex
transport ending the call, not Reasonix timing out or an agent failing. Reload
Codex after changing config.toml; restarting only the Reasonix MCP server
does not reload the host's timeout setting. Never restart MCP or agentd for a
host-side tool timeout—reissue one watch for the complete remaining fleet.
Other MCP hosts register the stdio server through their own mcp add
equivalents—same command and arguments, different client. Then restart the MCP
client and verify the server is listed.
Tools
Tool | Purpose |
| Start an agent in the daemon on |
| Revive a stopped/crashed session from its persisted transcript. |
| List selectable models: |
| Forced steer: queue as mid-turn guidance, or start a new turn if idle. Never dropped. |
| New output / status / completed turns / current |
| What the agent actually did: tool calls with args, files touched (write/read/bash), roles, work duration, last text — powers rebase decisions. (Reasonix does not persist token/cost usage; these are activity metrics.) |
| Primary callback: block indefinitely by default until completion, permission/question, or process death. Returns a compact result; |
| Block until any watched session produces output, finishes a turn, or raises a permission request. |
| All live sessions: id, status, cwd, compact task preview, transcript_path. Set |
| Answer a tool-approval request ( |
| Cancel + close + kill the agent (tombstone: poll keeps reporting |
| Explicitly reload the detached daemon. Source changes already queue a safe automatic reload; |
| Explicitly restart this orchestrator's MCP server through |
Completion and decision delivery
Keep reasonix_watch(session_ids) in flight while agents work. It returns when
a child finishes, exits, or needs a decision, with each compact result in
results[session_id]. By default each result contains only status,
stop reason, one capped message, permission details, plan/current work, errors,
and transcript path. Its timeout is disabled by default and it does
not wake for ordinary text chunks, so no timer loop or follow-up poll is needed.
Omit timeout for normal orchestration. Values such as timeout=240 in the
self-tests are test-runner safety guards, not production defaults.
Use one watch per orchestrator fleet. If another child finishes
while a result is being handled, its terminal state remains pending and the
next watch returns it immediately. A newer overlapping watch supersedes the
older call safely; a stale canceled watch never requires an MCP-server restart.
The displaced call returns superseded=true, and the newest call owns the
fleet. Always include the complete remaining fleet when replacing a watch. If
the MCP host or server restarts during a watch, reconnect, recover the owned
fleet with reasonix_list, and watch it again; undelivered terminal state
remains pending in agentd.
Compact watch consumes queued events so long-running sessions stay bounded.
Use reasonix_watch(..., detail=true) when raw event/turn detail is wanted
immediately. Full accumulated text remains available afterward through
reasonix_poll(include_full=true), and tool history through
reasonix_transcript.
For diagnostics, the server also emits this custom notification on the wire:
{"method": "reasonix/agent_event", "params": {
"session_id": "…", "event": "turn_end", "status": "idle",
"stop_reason": "end_turn", "transcript_path": "…", "note": "…"}}Events:
status(plan/current-work update),turn_end(done/stopped/errored, withstop_reason),permission_request(a tool-approval or an agent question — see below),process_exited.Diagnostic only: JSON-RPC clients silently ignore unknown notifications, and even a standard MCP notification is delivered to the client application, not injected into the model's conversation. Do not build orchestration loops around either
reasonix/agent_eventornotifications/message.
Orchestrator loop:
reasonix_watch(session_ids)→ handle each result → answer a permission or remove a terminal id → watch the remaining ids again.reasonix_waitremains available as a legacy output-sensitive long poll; unlike watch, it requires a follow-upreasonix_poll.
Diagnostic notifications are always emitted. The daemon and MCP server log each emit/relay result so host-side dropping is distinguishable from a server-side omission.
The Reasonix [notifications].enabled setting controls Reasonix CLI/desktop
system notifications; it is separate from this MCP transport.
Errored turns and unexpected process exits include error_text in the push
payload. reasonix_watch returns the same detail directly, so an
orchestrator can decide whether to resume or retry without inspecting the
session JSONL by hand.
Verified at the wire level by
selftest_notifications.py(raw JSON-RPC client — the SDK client validates server notifications against known types and may drop custom ones).
Agent questions
The agent can put a structured multiple-choice question to the orchestrator
mid-task via its built-in ask tool — and YOLO does not bypass it (a
question is a genuine user decision, not a tool approval). Questions ride the
same session/request_permission channel (kind "other"), so they surface
identically:
{"permission_request": {"request_id": 7,
"tool_call": {"title": "Which approach should we take?", "kind": "other",
"toolCallId": "ask-1-q1", "rawInput": {"id":"q1","options":[…],"question":…}},
"options": [{"optionId": "q1:1", "name": "A"}, {"optionId": "q1:2", "name": "B"}, …]}}Clients that advertise MCP elicitation receive a standard
elicitation/create form and the selected option is returned to Reasonix
automatically. If the client declines or cancels that form, Reasonix leaves
the ACP request pending; dismissal is not treated as rejection. Watch and
answer with reasonix_respond_permission(session_id, "q1:1"); the chosen label becomes
the ask tool result and the agent continues. A diagnostic agent_event is
also emitted. Verified live by selftest_question.py.
Spawn defaults
Spawned agents run at effort = max on opencode-go/deepseek-v4-flash
with tool_approval = yolo by default (the user's requested defaults). All
spawn options are per-call overridable, and the defaults themselves are
env-overridable (REASONIX_MCP_DEFAULT_MODEL, REASONIX_MCP_DEFAULT_EFFORT,
REASONIX_MCP_DEFAULT_WORK_MODE, REASONIX_MCP_DEFAULT_TOOL_APPROVAL).
Model selection: pass reasonix_spawn(model="<provider>/<model>", ...) to
pick the agent's model per call — reasonix_models() lists the valid refs and
each model's supported_efforts (effort is per-model: e.g. kimi-k3 accepts
only high/max; an unsupported value fails at spawn). Some gateway models
bake effort into the id (omniroute/codex/gpt-5.6-luna-{low,medium,high,xhigh, max}): they advertise no effort config option, so spawn skips it and
reports skipped_options in the result — pick the variant id instead.
reasonix_send is forced steer: a message is always delivered — queued as
mid-turn guidance while a turn is running, or submitted as a new turn if the
agent is idle (or the turn ended mid-race). Messages are never dropped.
expect (any default) narrows that: expect="steer" raises instead of
accidentally starting a new turn; expect="new_turn" raises if the message
was steered into a running turn.
Option | Values |
| any configured |
|
|
|
|
|
|
Poll is lean (orchestrator-friendly)
A spawned session emits a burst of static setup events
(available_commands_update — 24 slash commands with descriptions — and
config_option_update — the full model catalogue). Unfiltered, that is
~31 KB / ~8k tokens per poll for a 4-byte reply (measured), which kills
parallel orchestration. By default reasonix_poll omits those two types
from events (they are implied by spawn and available via transcript_path);
events_filtered counts what was omitted. To change the filter:
include_events=["tool_call","tool_call_update","plan"]— only these sessionUpdate types (permission requests are always included);Ordinary polls return a small recent event tail (50 by default; set
max_eventsto choose another value).include_eventsopts named types back in, including static setup types when explicitly named.exclude_events=[...]— drop additional types;the orchestrator-relevant set is
tool_call,tool_call_update,plan,permission_request.
Every poll also includes current_work: the active native tool call when one
is running, or the plan step marked in_progress. Agents spawned through this
server receive a small status contract asking them to keep that plan current.
It is injected exactly once per persisted session: follow-up turns do not
repeat it, and resume detects it in session history. Explicit task restrictions
on tools take precedence.
turns in poll results gives completed turns as [{text, stop_reason}] —
clean turn boundaries (full_text alone concatenates turns).
Thought and full_* are opt-in. Reasoning is the bulk of what effort=max
models emit, so reasonix_poll does not return thought / full_thought /
full_text by default — it returns only what changed (text delta, turns,
events, status). They stay accumulated server-side and are available on demand:
include_thought=True→thought(delta) +full_thoughtinclude_full=True→full_text(whole conversation;turnsusually suffices — per-turn text + stop_reason)
Use include_thought when diagnosing a derailed agent. Defaults are
env-overridable: REASONIX_MCP_INCLUDE_THOUGHT=1, REASONIX_MCP_INCLUDE_FULL=1.
Parallel orchestration
spawn 6–8 agents (note session_ids, each spawn reports its sandbox posture)
loop:
event = reasonix_watch(all ids) # no timeout; compact terminal/permission results
handle event.results # no follow-up poll
reasonix_send(sid, msg, expect="steer") when a discovery invalidates a round
drop finished ids from the watch list; reasonix_stop() the rest when done
reasonix_list() whenever you lose track of session_idsCaps & truncation
Poll output is capped so long gaps can't blow up the MCP host's context; the cuts are reported, never silent:
Field | Limit (env override) |
| recent tail (50 by default; explicit cap 200) — |
| last |
compact watch | first/last |
| last |
| last |
events_dropped (queue/size cap) is distinct from events_filtered
(static-type omission). The unpolled in-server event buffer is bounded at 4000
chunk events; critical events (permission, turn end, process exit) are never
dropped.
Sandbox posture
reasonix_spawn reads and returns the effective [sandbox] posture at spawn
time (sandbox, legacy bash, allow_write, network, workspace_root,
config_file) so an orchestrator knows up front whether agents can execute
commands and write outside cwd. Note Reasonix semantics: bash = "off" means
unconfined (execution allowed), while bash = "enforce" jails commands in
bubblewrap when available. The clearer posture names are sandbox = "bwrap"
or sandbox = "none"; with none, allow_write cannot be enforced for bash
and a warning is returned/logged. Changing config while an agent runs does not
change that agent; inspect the spawn response for its effective posture. Under
tool_approval = "ask", gated commands raise a
permission_request in watch/poll — answer with reasonix_respond_permission;
approving blind is not required: the request's tool_call carries the tool
name (title/kind) and rawInput (the JSON arguments).
Ask mode does not pause every shell command: Reasonix requests permission only
for commands its policy classifies as gated. Its explicit ask tool always
creates a user-decision request, including in YOLO mode.
Updating the daemon
agentd watches agentd.py, acp_bridge.py, and common.py. A source change
queues an automatic restart; active turns, pending decisions, and
keep_alive=true sessions are never interrupted. Once agents are safely idle
and their terminal output has been polled, the daemon waits a short grace
period, closes resumable idle processes, and starts a fresh daemon from current
code. No MCP reinstallation is needed.
For explicit control, call reasonix_restart_agentd(). It safely reloads the
shared daemon when no live agents remain. If live agents can be discarded, use
reasonix_restart_agentd(force=true); their persisted transcripts can be
resumed after the fresh daemon starts. The next tool call automatically starts
the new daemon, so no shell command or socket cleanup is needed. The daemon is
shared by MCP clients, so a restart disconnects other clients too; they
reconnect automatically on their next tool call.
Restarting the MCP server
launcher.py watches the package's Python sources and replaces its MCP server
automatically after a change. It proxies stdio, replays the negotiated MCP
handshake into the new child, and leaves shared agentd sessions untouched,
so an already-running orchestrator can continue without being restarted.
Every orchestrator has its own launcher and refreshes independently.
reasonix_restart_mcp_server() remains available for an explicit reload.
Registrations that point directly to server.py must be changed to
launcher.py once; after that, source updates need no MCP reinstall.
Orchestrator isolation
Sessions are scoped to the MCP orchestrator that created them. reasonix_list
and all session operations only expose that orchestrator's sessions. The scope
is stable across MCP server restarts and is derived from the MCP client's name
and workspace. If multiple instances of the same CLI run in the same workspace,
set a distinct stable value in each environment:
REASONIX_MCP_ORCHESTRATOR_ID=project-a-cli-1The daemon is shared, but ownership is enforced by the daemon and persisted
with each session. reasonix_restart_agentd remains a global operation because
restarting the shared daemon affects every orchestrator; it refuses while
another orchestrator has live agents unless force=true.
Agent cleanup
After a terminal turn (including an errored turn), an agent remains available
for the idle grace period (REASONIX_MCP_IDLE_TIMEOUT, disabled by default, or
idle_timeout per spawn) so the orchestrator can poll its final output or send
a quick follow-up. It is then stopped and remains as an exited, resumable
tombstone. Set keep_alive=true on reasonix_spawn for an agent that needs
ongoing interactive turns; call reasonix_stop when it is no longer needed.
Use idle_timeout=-1 to disable cleanup, 0 for immediate cleanup after a
terminal turn, or a positive number of seconds for a grace period.
Safety
Agents run under your Reasonix permissions and workspace sandbox (writes confined to
cwd+allow_write; bash jailed where the OS sandbox is enabled and available). Withsandbox = "none"/bash = "off", bash is unjailed andallow_writeis not enforceable.Spawn cwd is confined:
reasonix_spawn(cwd=…)is rejected unless the target is the MCP host's project dir (or a subdir) or one of the[sandbox] allow_writedirs — a prompt-injected orchestrator can't spawn agents that write anywhere (the server runs with your full permissions andyolodefault). Escape hatch:REASONIX_MCP_ALLOW_ANY_CWD=1.Agents die with the server: PDEATHSIG guarantees a killed MCP server can never orphan
reasonix acpprocesses.tool_approvalper spawn:yolo(default; approve except protected decisions),auto(follow configured permission rules), orask(relay every approval throughreasonix_respond_permission).reasonix_spawnreturns the effective sandbox posture — check it before assigning tasks that require running commands.cwddefaults to the MCP host's project root; pass an explicitcwdto scope an agent elsewhere.
Long-running agents
A spawned agent may legitimately run for hours — long thinking, tool loops, implementing across many files. The bridge is built for that:
Nothing blocks.
reasonix_spawn/reasonix_send/reasonix_pollreturn immediately; the agent works in its own subprocess. The MCP host stays fully responsive while the agent grinds.No default timeout. A turn runs until it finishes or you call
reasonix_stop(cancels the turn, closes the session, kills the process).You can come back anytime.
reasonix_pollreportsstatus: "running"with everything new since your last poll — leave it for an hour, then check again.reasonix_sendsteers even mid-turn.Memory is bounded. Unpolled chunk events are capped in the server; poll results cap
text/thought/full_textand the structuredeventslist (tails kept,*_truncated/events_droppedflags report the cut) so a long gap can't blow up the MCP host's context.
One constraint, now mostly lifted: agents live in the daemon, not the MCP
server — the MCP host can close and come back and the fleet is still running
(reasonix_list). The daemon itself is the survival boundary: kill it and its
agents die (PDEATHSIG); a crashed session's work survives on disk and can be
revived with reasonix_resume.
Testing
.venv/bin/python tests/selftest.py # spawn → poll → steer → stop (real provider)
.venv/bin/python tests/selftest_daemon.py # survival across server kill + resume + 6-way concurrency (real provider)
.venv/bin/python tests/selftest_permission.py # ask-mode permission round-trip (real provider)
.venv/bin/python tests/selftest_question.py # agent asks a question via `ask` (real provider)
.venv/bin/python tests/selftest_transcript.py # transcript + plan fields (real provider)
.venv/bin/python tests/selftest_orchestrator.py # list/wait/filtering/posture (no model calls)
.venv/bin/python tests/selftest_notifications.py # diagnostic event frames (no model calls)
.venv/bin/python tests/selftest_elicitation.py # ACP decision → MCP elicitation bridge (no model calls)
.venv/bin/python tests/selftest_watch.py # watch overlap/cancellation safety (no model calls)
.venv/bin/python tests/selftest_mcp_restart.py # manual + source-change hot reload (no model calls)
.venv/bin/python tests/selftest_auto_reload.py # agentd source watcher + self-replace (no model calls)
.venv/bin/python tests/selftest_prompt_injection.py # one status contract per session (no model calls)
.venv/bin/python tests/selftest_chaos.py # cwd allowlist + dual notify + PDEATHSIG (no model calls)
.venv/bin/python tests/selftest_allow_write.py # cross-cwd write via allow_write (real provider)The selftest runs fully isolated: it copies config.toml + .env into a
scratch REASONIX_HOME under /tmp (removed on exit), so it never touches
your live ~/.reasonix sessions and spawns the native Reasonix Go binary
directly (never the npm node shim) in its own process group that it kills on
cleanup.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceEnables MCP-compatible clients to interact with deployed Agent5ive agents as tools. Allows users to query agent purposes and send messages to leverage Agent5ive capabilities through natural language.73MIT
- Flicense-quality-maintenanceEnables delegation of immediate conversational messages and long-running background tasks to OpenClaw agents. It allows users to spawn research or monitoring tasks, check execution status, and manage active agent sessions within MCP-compatible clients.
- FlicenseAqualityFmaintenanceMCP server that exposes 300+ AI agents as tools via a single API key. Supports listing agents, invoking any agent with chat-completion style messages, checking agent health, and retrieving platform statistics.53
- Alicense-qualityBmaintenanceBridges MCP-compatible AI clients to over 100 Hermes Agent skills for web browsing, file management, code execution, GitHub operations, and more.1MIT
Related MCP Connectors
Agent-native collaboration network: orchestrate a team of long-running agents from any MCP client.
Hosted AgentLux MCP server for marketplace, identity, creator, services, and social flows.
OCR, transcription, file extraction, and image generation for AI agents via MCP.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/AsmodeusX/reasonix-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server