feat(soul): MCP tool-bridge — suspend agentic loop for client-executed tools #5
Closed
tim.lingo
wants to merge 0 commits from
feat/mcp-tool-bridge into main
pull from: feat/mcp-tool-bridge
merge into: :main
:main
:feat/cgi-identity-accessors
:fix/restore-soul-identity-producer
:rebase/openai-tools-onto-main
:rebase/gate-state-key-reads-onto-main
:rebase/structural-audit-onto-main
:feat/self-seeded-context
:integrate/semantic-plus-writethrough
:feat/semantic-leg-dropout
:feat/semantic-substrate
:feat/gold-set-heldout
:feat/evidence-weighted-merge
:feat/structural-audit
:feat/claim24-unfloored-semantic
:feat/executive-filter-recall
:feat/bm25-lexical-leg
:feat/semantic-seeded-assoc
:feat/associative-recall-leg
:feat/hybrid-semantic-recall
:chore/retrieval-measurement-contract
:feat/retrieval-eval-harness
:feat/soul-write-through
:feat/recall-through-activation
:chore/regen-soul-amalgam-20260807
:feat/gate-state-key-reads
:fix/129-on-openai-tools
:fix/129-history-amplification
:fix/liveness-engine-91
:feat/soul-openai-tools-v2
:fix/resume-server-tool-replay
:fix/soul-history-provenance-20260805
:feat/soul-plain-chat-generation-20260805
:feat/soul-native-web-search-20260804
:ci/pin-vendored-runtime
:reconcile/soul-union-main
:fix/bound-session-payload-main
:fix/receipts-wrapper-forget
:fix/receipts-agent-tools
:reconcile/neuron-wip-to-main
:fix/bound-session-payload
:hotfix/trackb-threat-to-others
:reconcile/hotfix-to-main-launch
:hotfix/elc-source-typos
:fix/safety-contact-truncation
:fix/genesis-boot-crash
:fix/immutable-on-hotfix
:feat/bounded-persona-floor
:ci/rdynamic-http-handler
:ci/harden-gate-boot
:feat/agent-phase1-soul
:salvage/elh-state-20260704
:feat/soul-model-self-report
:feat/openai-format-providers
:feat/plan-mode-endpoint
:fix/operator-identity-home-resolution
:fix/wrapper-backlog-endpoints
:fix/list-typed-slice-offset
:feat/connectors-call-route
:fix/chat-vision-attachments
:fix/prevent-engram-corruption
:fix/emergency-regressions
:fix/session-continuity-hook
:fix/context-dedup-shared-ids
:fix/engram-float-parser
:improve/recall-context-format
:improve/recall-context-dedup
:improve/recall-cross-session-continuity
:improve/recall-emotional-recall
:improve/recall-activation-seed
:improve/recall-recall-completeness
:improve/recall-temporal-precision
:improve/recall-engram-scoring
:improve/recall-recall-reliability
:improve/recall-session-start-recall
:improve/reliability-engram-write
:improve/reliability-state-management
:improve/soul-memory-formation
:improve/safety-crisis-detection
:improve/reliability-route-error-recovery
:improve/reliability-llm-retry
:improve/reliability-session-boundary
:improve/reliability-safety-resilience
:improve/reliability-engram-connection
:improve/soul-routes-api
:improve/reliability-cross-session-affective
:propose/agent-workspace-root-read
:improve/reliability-conv-history
:improve/soul-strip
:improve/soul-chat-pipeline
:docs/conversation-retrieval-design
:propose/no-fake-tools-in-chat-mode
:fix/ci-soul-build-single-file
:fix/canonical-self-bridge
:feat/agent-tool-workspace-scope
:fix/agentic-tools-duplicate-web-search
:green/agentic-fixes
:feat/connectors-soul
:feat/layer-safety
:feat/layer-imprint
:feat/layer-stewardship
:test/layer-composition
:test/layer-safety
:test/layer-stewardship
:test/layer-imprint
:feat/memory-delete-update
:feat/native-web-search
No Reviewers
Labels
Clear labels
BETA-CRITICAL
blocks-public-beta
HELD
ORTHOGONAL
P0
POST-BETA
security
On the beta critical path — must resolve before ship
Must be fixed before any public beta
Blocked pending an external decision (counsel / dual sign-off)
Parallel workstream (testing/hardening) — safe to assign off critical path
Drop-everything severity
Important but not blocking the beta ship
Security vulnerability
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: neuron-technologies/neuron#5
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "feat/mcp-tool-bridge"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
"Option B" MCP tool-bridge on the soul side. The agentic chat loop
(
handle_chat_agentic) used to return the literal string"unknown tool: <name>"for any tool it could not run in-process. It now suspends and asks the client
(the Kotlin desktop app) to execute the tool — this is what lets Neuron run MCP
connectors/plugins, matching Claude's Connectors.
Built-in tools (
read_file,write_file,web_get,search_memory,run_command)and Anthropic's native server-side
web_searchare unchanged. There was nopre-existing tool-approval /
tool_pendinground-trip in the soul, so this PRdefines the contract below as a new, minimal
tool_resultendpoint.Client contract (for the Kotlin MCP-client lane)
1. Soul → client: pending signal
When the model calls a tool the soul cannot run in-process, the agentic loop
suspends and
/api/chat(agentic) returns, with HTTP 200:The client detects
tool_pending == true, executes the named MCP tool withtool_input, and captures the output as a string.2. Client → soul: result, to resume
Body:
session_idcomes from the URL path (thesession_idfield of the envelope).call_idshould echo the envelope'scall_id. If omitted/mismatched, the soulfalls back to the
tool_use_idit suspended on, so a partial client still resumes.contentis the tool's textual result (truncated to 6000 chars upstream, likelocal tool results).
3. Soul resumes
The soul appends the result as a
tool_resultblock bound to the originaltool_use_id, re-enters the agentic loop, and returns the same envelope shape:tool_pendingenvelope if the continuation hits a further MCP tool.The bridge is fully chainable across multiple MCP calls in one turn.
The saved continuation is one-shot: it is cleared on resume, so a
session_idcannot be replayed.
Implementation notes
chat.el:is_builtin_tool,next_bridge_id, refactor of the agentic loop into aresumable
agentic_loop(session_id, model, safe_sys, tools_json, messages, h, tools_log),plus
bridge_save,agentic_resume,handle_tool_result. The suspended turn's fullmessage history (including the assistant turn that requested the tool) is persisted in
soul state under
mcp_bridge:<session_id>.routes.el: routesPOST /api/sessions/{id}/tool_resulttohandle_tool_result.handle_chat_agentic) used by thedesktop app. The DHARMA-room agentic loop (
handle_dharma_room_turn_agentic) is leftunchanged for now; it still runs only built-ins.
Verification
~/el-sdk/elc --target=c <file>exits 0 with no stderr forchat.el,routes.el, and the fullsoul.elimport graph.only and needs Will's build to ship and test end-to-end.
🤖 Generated with Claude Code
When handle_chat_agentic hits a tool the soul cannot run in-process (an MCP connector/plugin surfaced by the Kotlin desktop app), instead of returning "unknown tool" it now suspends the agentic loop and returns a tool_pending envelope so the CLIENT executes the tool and posts the result back. Built-in tools (read_file/write_file/web_get/search_memory/run_command) and Anthropic's native web_search are unchanged. Client contract: - Soul returns (HTTP 200) on an unknown tool: { "tool_pending": true, "session_id": "br-...", "call_id": "<tool_use_id>", "tool_name": "...", "tool_input": { ... }, "model": "...", "agentic": true, "tools_used": [...] } - Client runs the MCP tool, then POSTs to /api/sessions/{session_id}/tool_result with body: { "call_id": "<the call_id from the envelope>", "content": "<MCP tool output as a string>" } - Soul resumes the loop and returns the same envelope shape: either a final { "reply": ..., "tools_used": [...] } or another tool_pending if the continuation needs a further MCP tool (fully chainable). Saved continuation is one-shot (cleared on resume). elc-verified (--target=c, exit 0, no stderr) on chat.el, routes.el, and the full soul.el import graph. Needs Will's build to ship. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>testto feat(soul): MCP tool-bridge — suspend agentic loop for client-executed toolsHandoff (auto) — prereq #16.
⚠ OVERLAPS #9 by ~80%: identical changes to awareness.el (+402 -9), mcp-wrapper/src/main.el (+831), neuron-api.el (+173), mcp-proxy, and the same docs. #5 and #9 are the same underlying work in two giant diffs — they will conflict. RECONCILE with #9 before merging either (see #9; likely #9 is canonical).
WHAT real: awareness.el +402, chat.el +184, mcp-wrapper +831, neuron-api.el +173, soul.el +94 -25, routes.el +25.
REAL SOURCE: ~2,181 lines (not 70k — the rest was generated dist/*.c).
RISK: higher — touches soul.el + awareness.el (cognitive core).
ORDER: last, as part of the #5/#9 reconciliation.
Pull request closed