For developers
Plug your agents into the same graph as your plans
Project Orchestrator exposes everything the app does as MCP tools, a REST API and two WebSocket streams. A Rust server keeps code, plans, decisions and notes in a Neo4j graph and in Meilisearch.
- MCP tools
- 31
- MCP tools
- actions across them
- 402
- actions across them
- languages parsed
- 17
- languages parsed
- WebSocket streams
- 3
- WebSocket streams
Looking for the product itself? Go back to the home page.
project(action: "sync", slug: "my-app")
code(
action: "analyze_impact",
target: "src/session.rs",
project_slug: "my-app"
)
plan(action: "run", plan_id: "<uuid>")Connect
Plug PO into an MCP client
The desktop app or the server must be running. Then one command registers PO in Claude Code, or you add the entry by hand for any other MCP client.
Install and start the server
The server needs Neo4j and Meilisearch. NATS is optional. The repository ships a docker-compose.yml for all three.
orchestrator serve
# needs Neo4j and Meilisearch: docker compose up -dbrew install this-rs/tap/project-orchestratororchestrator serve --port 8080Register PO in Claude Code
This writes the MCP entry in stdio mode, with this server URL and its auth secret, and pre-approves the tools.
orchestrator setup-claude
orchestrator setup-claude --port 8080setup-claude also adds mcp__project-orchestrator__* to the allowed tools of ~/.claude/settings.json, so Claude Code does not ask before every call.
Check that it works
In Claude Code, run /mcp: project-orchestrator should be listed. Then ask for the list of projects: Claude calls project(action: "list").
Claude Code
# in Claude Code/mcp# then ask: "List all registered projects"# Claude calls: project(action: "list")Any MCP client, stdio
mcp_server is a thin proxy: it speaks MCP on stdio and forwards each call to the REST API. It never connects to Neo4j itself. Set PO_AUTH_TOKEN, or PO_JWT_SECRET to let it generate a token at startup.
~/.claude/mcp.json
{ "mcpServers": { "project-orchestrator": { "command": "/path/to/mcp_server", "env": { "PO_SERVER_URL": "http://127.0.0.1:8080", "PO_AUTH_TOKEN": "<jwt-session-token>" } } }}Remote clients, Streamable HTTP
The server also answers MCP at POST /mcp, behind the same authentication as the REST API. A session id is returned in the Mcp-Session-Id header and must be echoed on each request.
Claude Code
claude mcp add --transport http project-orchestrator http://127.0.0.1:8080/mcp \ --header "Authorization: Bearer <token>"HTTP
POST /mcpAuthorization: Bearer <token>Content-Type: application/json{"jsonrpc":"2.0","id":1,"method":"tools/list"}MCP tools
31 tools, one call shape
Every tool takes an action parameter and dispatches to one operation. Search by tool, action or parameter, then copy the exact call.
31 tools
plan
Plans with dependency graph, waves, critical path, and the autonomous runner.
Planning and delivery 27 actions
Example call
plan( action: "create", title: "Migrate session store to Redis", priority: 8)Actions
+21 more
Parameters
plan_idproject_idtitledescriptionpriorityconstraintsstatussearchlimitoffsetsort_bysort_orderpriority_minpriority_maxcwdproject_slugtrigger_idtrigger_typeconfigcooldown_secsrun_idrun_idstask_idparent_session_idcustom_sections
Argument values such as <uuid> are placeholders. The action and parameter names are read from the server source.
Architecture
One Rust server, three stores, any client
Clients never touch the databases. They talk to the server, which parses code, serves the API and streams events.
MCP clients
Claude Code, Cursor or any MCP client. They talk MCP to mcp_server over stdio, or to POST /mcp over HTTP.
Desktop app
The Tauri 2 app embeds the interface and starts the server. It manages the Neo4j and Meilisearch containers through Docker.
WebSocket clients
Anything that opens /ws/chat/{session_id}, /ws/events or /ws/run/{run_id}.
mcp_server
Binary mcp_server: MCP on stdio in, REST calls out. Holds no state.
orchestrator
The orchestrator binary (axum). REST API, chat manager, plan runner, tree-sitter parser, event bus.
Neo4j
The graph: code, plans, tasks, decisions, notes, skills, protocols, chat sessions.
Meilisearch
Full-text search over code, notes, decisions and chat messages.
NATSoptional
Syncs events and relays chat between several server instances. Without it, the server runs local-only.
Claude
The chat manager drives Claude through the nexus-claude SDK.
How they talk
- MCP clients / mcp_serverstdio
- MCP clients / orchestratorHTTP /mcp
- mcp_server / orchestratorREST
- Desktop app / orchestratorREST + WebSocket
- WebSocket clients / orchestratorWebSocket
- orchestrator / Neo4jbolt
- orchestrator / MeilisearchHTTP
- orchestrator / NATSNATS
- orchestrator / ClaudeSDK
Code parsing
17 languages, parsed with tree-sitter
Each file is parsed into functions, structs, traits, enums, imports, impl blocks and call edges, then stored in the graph.
17 languages
Rust
Extensions: .rs
tree-sitter-rust
TypeScript / JavaScript
Extensions: .ts .tsx .js .jsx .mjs .cjs
tree-sitter-typescript
Python
Extensions: .py .pyi
tree-sitter-python
Go
Extensions: .go
tree-sitter-go
Java
Extensions: .java
tree-sitter-java
C
Extensions: .c .h
tree-sitter-c
C++
Extensions: .cpp .cc .cxx .hpp .hxx .hh
tree-sitter-cpp
Ruby
Extensions: .rb .rake .gemspec
tree-sitter-ruby
PHP
Extensions: .php .phtml .php5 .php7
tree-sitter-php
Kotlin
Extensions: .kt .kts
tree-sitter-kotlin-ng
Swift
Extensions: .swift
tree-sitter-swift
Bash
Extensions: .sh .bash .zsh
tree-sitter-bash
C#
Extensions: .cs
tree-sitter-c-sharp
Scala
Extensions: .scala .sc
tree-sitter-scala
Zig
Extensions: .zig
tree-sitter-zig
HCL (Terraform)
Extensions: .tf .tfvars
tree-sitter-hcl
Dart
Extensions: .dart
tree-sitter-dart
Per file: functions, structs, traits, enums, imports, impl blocks, function calls with a confidence score.
JavaScript files (.js, .jsx, .mjs, .cjs) are read with the TypeScript grammar.
API and events
REST for state, WebSockets for change
Plans, code, notes and the rest are plain JSON over HTTP. Changes are pushed on WebSockets.
Main REST endpoints
Most routes sit behind the auth middleware. When no auth section is configured, the API is open.
| GET | /health | Liveness |
| GET | /api/version | Server version |
| GET | /api/projects | List projects (POST creates) |
| POST | /api/projects/{slug}/sync | Parse a project into the graph |
| GET | /api/plans/{plan_id}/waves | Parallel waves of a plan |
| POST | /api/plans/{plan_id}/run | Start the runner on a plan |
| GET | /api/code/search | Search code |
| GET | /api/code/impact | Impact analysis |
| GET | /api/notes/search | Search notes |
| GET | /api/decisions/search | Search decisions |
| POST | /api/reason | Reasoning over the graph |
| POST | /mcp | MCP over Streamable HTTP |
WebSocket streams
/ws/events
Every create, update, delete, link, unlink and status change, as one JSON event. Filter with the entity_types, project_id and layers query parameters.
/ws/chat/{session_id}
Conversation with Claude. Send user_message, interrupt, permission_response and input_response; receive the chat events, replayed from last_event after a reconnect.
/ws/run/{run_id}
One stream for a plan run: runner events (task started, wave started...) plus the chat events of every child session.
Browsers authenticate with a cookie, or with a one-time ticket from POST /auth/ws-ticket passed as the ticket parameter.
A /ws/events message
/ws/events?entity_types=plan,task&project_id=<uuid>
{ "entity_type": "task", "action": "status_changed", "entity_id": "<uuid>", "payload": { "old_status": "pending", "new_status": "in_progress" }, "timestamp": "2026-10-05T10:00:00Z", "project_id": "<uuid>"}Extend
Three ways to make PO yours
All three are available through the same MCP tools.
Protocols
Define a finite state machine with states and transitions, start a run, and let agents move it forward with the protocol tool.
Skills
Skills are clusters of notes and code that emerge from use; the skill tool activates, exports and imports them across projects and instances.
MCP federation
mcp_federation connects external MCP servers over stdio, sse or streamable_http, so their tools are reachable through PO.