Agent Bootstrap Protocol
A copy-paste-ready recipe for connecting an AI agent to a running ClaudusBridge instance from scratch. This page is the procedural complement to Your First Conversation — that one walks through what you'll see; this one gives you the exact wire-level commands an agent (Codex, another Claude Code session, Cursor, Windsurf, or a custom MCP client) needs to execute.
If you're a human user setting up your IDE for the first time, follow Connecting Your AI Client instead — that page covers the IDE-config side. This page is for the agent itself.
Audience and prerequisites
- You are an AI agent (or a script acting on behalf of one) that needs to talk to ClaudusBridge over MCP.
- Unreal Editor with the ClaudusBridge plugin is already running on the user's machine.
- You have network access to
http://localhost:3000(the editor's MCP HTTP server). The default port is 3000; the user may have changed it via Project Settings → Plugins → ClaudusBridge. - You can make HTTP POST requests with a JSON body. The MCP transport is Streamable HTTP per the MCP spec 2025-03-26.
The full procedure (overview)
┌─ Step 1 ─────────────────────────────────────────────────────────┐
│ GET /health │
│ → confirm server is alive and read live version + tool count │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌─ Step 2 ─────────────────────────────────────────────────────────┐
│ POST /mcp │
│ method: initialize │
│ → receive serverInfo, instructions (~16 KB), neuralCortex.regions │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌─ Step 3 ─────────────────────────────────────────────────────────┐
│ POST /mcp │
│ method: notifications/initialized │
│ → server returns HTTP 202 Accepted, empty body │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌─ Step 4 ─────────────────────────────────────────────────────────┐
│ POST /mcp │
│ method: tools/call name: claudus_cognitive_state │
│ → read provider.mode ("claudus" or "handshake" or "anthropic")│
└──────────────────────────────────────────────────────────────────┘
│
┌─────────────┴─────────────┐
│ │
▼ ▼
mode == "claudus" mode == "handshake"
(provider attached) (no provider yet)
│ │
│ ▼
│ ┌─ Recovery sub-procedure ────────┐
│ │ Read dispatch.json for port │
│ │ Check runtime PID is alive │
│ │ If not: spawn launch script │
│ │ Re-read dispatch.json │
│ │ POST tools/call agent_login │
│ │ with base_url=http://127.0.0.1:│
│ │ <port>/v1/messages │
│ └─────────────────────────────────┘
│ │
└─────────────┬─────────────┘
▼
┌─ Step 5 ─────────────────────────────────────────────────────────┐
│ Subscribe to events you care about │
│ POST /mcp tools/call subscribe_events │
│ session: "<your-agent-name>" │
│ event_types: ["agent_message", "blueprint_compiled", ...] │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌─ Step 6 ─────────────────────────────────────────────────────────┐
│ Work loop (poll + react + post evidence) │
└──────────────────────────────────────────────────────────────────┘
Step 1: Health check
curl -s http://localhost:3000/health
Expected response:
{
"status": "ok",
"server": "ClaudusBridge",
"version": "0.6.3",
"port": 3000,
"mcp_initialized": false,
"tools_count": 567,
"tools_list_count": 567,
"registered_tools_count": 566
}
If you get a connection refused, the editor isn't running, or the MCP server is on a different port. The default is 3000; if it's changed, the user has the new port in Project Settings → Plugins → ClaudusBridge → MCP Server Port.
mcp_initialized: false is fine on a fresh editor — it flips to true after at least one client completes the handshake. Either way you can proceed.
Step 2: MCP initialize
curl -s -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": {
"name": "your-agent-name",
"version": "1.0.0"
}
}
}'
The response contains serverInfo, protocolVersion, the full capabilities.tools block, a 16 KB instructions field, and a neuralCortex object with the 12 region names. Read the instructions once — it's the canonical operating manual for the active session and contains the action protocol, EYES MANDATORY rule, memory + checkpoint patterns, and the multi-agent shared-transcript model.
Pick a clientInfo.name that uniquely identifies your agent (e.g. codex-cli, claude-code-primary, cursor-pair, windsurf-build-bot). The same string should also be used as the session parameter in subscribe_events / poll_editor_events / publish_agent_event so logs, dashboards, and event queues all line up under one name.
Step 3: Complete the handshake
curl -s -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}'
Server returns HTTP 202 Accepted with empty body. Some strict MCP clients (Codex CLI / rmcp) treat anything else as a transport error, so don't expect JSON back here.
After this step, mcp_initialized: true on /health.
Step 4: Check the provider state
Every other interaction routes through the active provider model (Claude / ChatGPT / Gemini, attached through the local Claudus runtime). Confirm one is actually attached before you send a chat:
curl -s -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "claudus_cognitive_state",
"arguments": {}
}
}'
Parse the response's result.content[0].text as JSON. The data.provider block tells you everything:
{
"data": {
"provider": {
"mode": "claudus",
"model": "claude-opus-4-7[1m]",
"model_display": "Claude Opus 4.7 1M context (claude-opus-4-7[1m])",
"has_inference_provider": true,
"connected_agent": "claudus-auto-bootstrap"
},
"access": {
"mode": "Full Access",
"full_access_enabled": true
}
}
}
If provider.mode == "claudus" or "anthropic", you're attached and can skip to Step 5.
If provider.mode == "handshake", the plugin couldn't attach a provider on its own. Run the recovery sub-procedure below.
Recovery sub-procedure: provider not attached
This happens when:
- The user just launched the editor and the local Node provider runtime hasn't started yet.
- The runtime was killed or crashed and the editor cached a stale port.
- The user is connecting for the very first time and the auto-bootstrap couldn't find a valid
provider-selection.json.
R-1. Read the dispatch sentinel
The local provider runtime writes a tiny JSON sentinel at:
$LOCALAPPDATA/ClaudusBridge/ProviderRuntime/dispatch.json
(On Windows. On macOS / Linux it's under ~/Library/Application Support/ClaudusBridge/ProviderRuntime/ / ~/.local/share/ClaudusBridge/ProviderRuntime/.) Read it:
# Windows PowerShell
Get-Content "$env:LOCALAPPDATA\ClaudusBridge\ProviderRuntime\dispatch.json" -Raw
# macOS / Linux
cat ~/Library/Application\ Support/ClaudusBridge/ProviderRuntime/dispatch.json
Expected shape:
{
"port": 65164,
"upstreamPort": 65163,
"pid": 27616,
"runtime": "claudus-provider-runtime",
"routeLayer": "claudus-public-model-router-v2",
"startedAt": "2026-05-18T18:29:33.389Z",
"updatedAt": "2026-05-18T18:29:34.120Z",
"installRoot": "..."
}
If the file doesn't exist, the runtime has never been started on this machine — skip to R-3 (spawn fresh runtime).
R-2. Confirm the runtime is still alive
The sentinel may be stale. Confirm the pid is a live process:
# Windows
Get-Process -Id <pid> -ErrorAction SilentlyContinue
# macOS / Linux
ps -p <pid>
If the process is gone, the sentinel is stale and the runtime needs to be respawned — go to R-3.
If the process is alive, jump to R-4.
R-3. Spawn a fresh runtime
The plugin ships a launcher script bundled with itself:
# Windows PowerShell — adjust path to the plugin's Resources folder
$script = "<ProjectDir>\Plugins\ClaudusBridge\Resources\ClaudusProviderRuntime\launch-claudus-provider-runtime.ps1"
Start-Process powershell.exe `
-ArgumentList "-NoLogo","-NoProfile","-ExecutionPolicy","Bypass","-File","`"$script`"" `
-PassThru -WindowStyle Hidden
Wait ~5 seconds, then re-read dispatch.json. You should now see a fresh pid and a new port.
Alternatively, the user can run /runtime start in the Unreal Output Log (slash command), or click the "Start runtime" quick action in the Claudus dashboard. The script's job is the same either way.
R-4. Call agent_login with the live port
Build the URL from the sentinel's port and call agent_login:
curl -s -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "agent_login",
"arguments": {
"provider_mode": "claudus",
"base_url": "http://127.0.0.1:65164/v1/messages",
"model": "claude-opus-4-7[1m]",
"agent_name": "your-agent-name"
}
}
}'
Substitute the real port from the sentinel into base_url. The model field can be any of the routes from the model catalog below.
Success response:
{
"data": {
"logged_in": true,
"mode": "claudus",
"provider_display": "Claude",
"model_display": "Claude Opus 4.7 1M context (claude-opus-4-7[1m])",
"base_url": "http://127.0.0.1:65164/v1/messages",
"verify_latency_ms": 2161.4
}
}
If you get verify_error: Network error (no response from ...), the port in base_url doesn't match a live runtime. Re-read dispatch.json (it may have been updated by a swap) and retry. Starting in 0.6.3, the plugin's self-healing pipeline automatically stat()s dispatch.json before every chat request and swaps to the live port silently — so once you've called agent_login with the right URL, subsequent chats survive runtime restarts without your intervention.
Step 5: Subscribe to events
Multiple agents share the same editor. Each agent gets its own isolated event queue keyed by a session string. Subscribe to the event types you actually care about:
curl -s -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "subscribe_events",
"arguments": {
"session": "your-agent-name",
"event_types": ["agent_message", "blueprint_compiled", "asset_saved", "actor_spawned", "pie_started", "pie_stopped"]
}
}
}'
Pass event_types: ["all"] for everything. Subscriptions filter at insert time — pick what you actually need or your queue will fill up with irrelevant events.
Use the same string for clientInfo.name (Step 2), session here, and from_session in publish_agent_event calls. That way the dashboard and the logs all show your activity under one name.
Step 6: The work loop
You're connected. From here on, two patterns cover almost every agent role:
Pattern A — Reasoning agent (provider role)
You're the model attached as the active Claudus provider (Step 4 made you the lead, or the user attached you via the dashboard's /login). Your job is to receive natural-language input, plan, and emit [Claudus Action Request] blocks for real work to be done by other agents.
# Receive user input via ask_claudus, or read the chat log directly:
curl -s -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc":"2.0","id":5,"method":"tools/call",
"params":{"name":"get_claudus_chat_log","arguments":{"limit":20}}
}'
Reply with chat content that includes [Claudus Action Request] blocks for native MCP tools you want executed:
[Claudus Action Request]
target: claudus
capability: mcp
tool: find_assets
path: /Game/Materials
max_results: 50
Claudus Native Tool Executor auto-runs allowlisted read-only tools in Limited Access mode and all native tools in Full Access mode. Results come back to the chat log as action-result entries you'll see on the next poll.
Pattern B — Execution agent (Codex / Claude Code / Cursor / Windsurf role)
You're an external agent whose job is to claim provider-emitted action requests that need real OS / filesystem / shell / browser / build / out-of-root work and execute them with your own native tools, then post evidence back.
The main loop:
# 1. Poll your event queue for new agent_message + action signals
curl -s -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc":"2.0","id":6,"method":"tools/call",
"params":{
"name":"poll_editor_events",
"arguments":{"session":"your-agent-name","limit":50}
}
}'
# 2. Fetch pending action requests aimed at you (claim=true means
# "lock them so other agents won't pick them up")
curl -s -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc":"2.0","id":7,"method":"tools/call",
"params":{
"name":"claudus_get_action_requests",
"arguments":{"claim":true,"target":"codex"}
}
}'
target: "codex" filters to action requests whose target string is codex (or whatever your agent identity is). Pass target: "all" if you want to see every pending action regardless of target.
For each claimed action:
# 3. Mirror your start into the dashboard so the human sees what's happening
curl -s -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc":"2.0","id":8,"method":"tools/call",
"params":{
"name":"claudus_agent_note",
"arguments":{
"from": "your-agent-name",
"text": "Starting full build, ~3 min estimate."
}
}
}'
# 4. Do the actual work with YOUR OWN native tools
# (Read, Write, Bash, browser, source-control, …)
# 5. Post the result back to Claudus as evidence
curl -s -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc":"2.0","id":9,"method":"tools/call",
"params":{
"name":"claudus_provide_action_result",
"arguments":{
"action_id": "<id-from-step-2>",
"result": "Compact text summary of what happened",
"success": true,
"agent_name": "your-agent-name",
"continue_provider": true,
"result_path": "C:/path/to/large/evidence.json"
}
}
}'
The provider's continuation fires automatically after each claudus_provide_action_result (or batched if multiple results land inside ~500 ms). You don't need to ping the provider — the chat log already shows it the evidence; it will respond on its next turn.
Loop back to step 1.
Multi-agent coordination
For agent-to-agent messaging (outside the action queue), use the agent_message event channel:
# Publish a message
curl -s -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc":"2.0","id":10,"method":"tools/call",
"params":{
"name":"publish_agent_event",
"arguments":{
"from_session": "your-agent-name",
"target_session": "primary",
"channel": "task.progress",
"payload": {
"step": "compile",
"status": "running",
"estimate_s": 120
}
}
}
}'
# Omit target_session for broadcast (excludes the sender)
See Multi-Agent Coordination for the canonical channel namespaces (watcher.observation, verification.needed/confirmed/rejected, task.progress/complete, alert.error/warning, handoff.request/accept, delegate.<domain>, review.feedback, feedback.<kind>).
Read the auto-generated docs first
Before doing real work, read the curated documentation pack the plugin generates specifically for agents:
curl -s -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc":"2.0","id":11,"method":"tools/call",
"params":{
"name":"claudus_get_documentation_pack",
"arguments":{"topic":"all"}
}
}'
The pack covers the action protocol, the Neural Cortex workflow, the EYES MANDATORY rule, memory + checkpoint patterns, and the provider-identity-hygiene rules. Topics: all, gallery, native_tools, multi_agent_workflow, project_context, native_unreal_editing, agents, codex_agent_runtime, skills. See Installing Companion AI Agents for the full topic table.
If you want a project-baseline read at the same time:
curl -s -X POST http://localhost:3000/mcp -H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":12,"method":"tools/call",
"params":{"name":"claudus_get_project_intelligence","arguments":{}}}'
curl -s -X POST http://localhost:3000/mcp -H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":13,"method":"tools/call",
"params":{"name":"claudus_recall_observations","arguments":{"since_hours":168,"limit":50}}}'
Two cheap reads, a few hundred tokens total. The agent walks in knowing the project's asset baseline + the recent activity journal without re-scanning anything.
Model catalog
When you call agent_login with provider_mode: "claudus", pass any of these as model:
Claude (via Claude.ai OAuth account route):
claude-opus-4-7[1m]— Opus 4.7, 1M context windowclaude-opus-4-7— Opus 4.7, standard contextclaude-opus-4-6[1m],claude-opus-4-6claude-sonnet-4-6[1m],claude-sonnet-4-6claude-haiku-4-5
ChatGPT (via Codex OAuth account route):
claudus-gpt-5.5,claudus-gpt-5.4,claudus-gpt-5.4-mini,claudus-gpt-5.3-codex
Gemini (via Gemini Code Assist):
claudus-gemini-3-pro-preview,claudus-gemini-3.1-pro-previewclaudus-gemini-2.5-proclaudus-gemini-3-flash-preview,claudus-gemini-2.5-flash
The Output Log slash commands accept short aliases (opus m, opus, sonnet m, sonnet, haiku, mini, codex, flash). agent_login accepts the canonical model id; if you want the shorter form, use /provider + /model from the Output Log or the dashboard instead.
Reference: complete bash one-liner
For agents that prefer a single shell-friendly recipe:
PORT=3000
# 1 + 2 + 3. Health, initialize, complete handshake
curl -fsS http://localhost:$PORT/health > /dev/null
curl -fsS -X POST http://localhost:$PORT/mcp \
-H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"my-agent","version":"1"}}}' > /dev/null
curl -fsS -X POST http://localhost:$PORT/mcp \
-H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"notifications/initialized"}' > /dev/null
# 4. Probe provider state
STATE=$(curl -fsS -X POST http://localhost:$PORT/mcp \
-H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"claudus_cognitive_state","arguments":{}}}')
# 5. Read the docs pack for context
curl -fsS -X POST http://localhost:$PORT/mcp \
-H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"claudus_get_documentation_pack","arguments":{"topic":"all"}}}'
# 6. Subscribe to your work queue
curl -fsS -X POST http://localhost:$PORT/mcp \
-H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"subscribe_events","arguments":{"session":"my-agent","event_types":["agent_message"]}}}'
# 7. Enter the work loop (poll → claim → execute with native tools → provide result → repeat)
cb.py (auto-generated under <ProjectDir>/Saved/ClaudusBridge/cb.py) collapses most of this into single-line subcommands — cb call <tool> '<args-json>', cb poll <session>, cb pub <channel> '<payload>', etc. Once the editor is reachable, the cb helper is the preferred interface — see The cb Helper CLI.
Where to go next
- Your First Conversation — Live transcript of the procedure above with real outputs and the failure-recovery patterns that emerge
- Native Editor Conversation — The dashboard tab + every Output Log slash command if you (or the user) prefer human-facing controls
- Installing Companion AI Agents — Skip writing the bootstrap by hand: generate a ready-to-install package for Claude Code / Cursor / Windsurf / Gemini CLI with
claudus_get_companion_package - Multi-Agent Coordination — Per-session events,
agent_messagechannels, the canonical channel namespaces - Generated Files Reference — Everything the plugin writes under
Saved/ClaudusBridge/and when