CLAUDE.md@crates/orbit-mcp · git:20260829.e25929a · 2026-08-29 · sha256 8946ff37e71bf94d
CLAUDE.md@crates/orbit-mcp git:20260829.e25929aA
Immutable. This exact content is served forever at /api/v1/blob/8946ff37e71bf94d.
# orbit-mcp Project instructions for the Model Context Protocol crate. ## One job Speak MCP. This crate owns stdio framing, advertised-name translation, structured responses, per-call trace creation, canonical tool discovery, server identity presentation, the TCP listener, the direct SSH stdio proxy, and the federated mux. It is a protocol crate, not a runtime. Everything a protocol should not decide stays behind the [`McpHost`](src/lib.rs) trait: workspace resolution, domain validation, auditing, and authorization. The kernel hands the host a canonicalized call plus one trusted `ToolSessionContext` and returns what it gets back. If you find yourself writing a rule about *whether* a call is allowed, it belongs in `orbit-core`. ## Dependency boundary is a test [`tests/dep_boundary.rs`](tests/dep_boundary.rs) asserts the exact set of internal dependencies (`orbit-common`, `orbit-registry`, `orbit-tools`, `orbit-types`) by parsing this crate's manifest. Adding an edge to a command, runtime, or Web crate fails that test on purpose — the fix is a host method, not a wider manifest. `rmcp` appears in this crate and nowhere else in the workspace. Keep it that way: translate `rmcp` types at the adapter edge rather than re-exporting them, so a protocol-library upgrade stays a change in one crate. ## Internal layout - [`adapter/`](src/adapter) — the MCP server itself: [`dispatch`](src/adapter/dispatch.rs) routes a call, [`name_map`](src/adapter/name_map.rs) translates canonical Orbit tool names to the advertised character set and detects collisions, [`schema`](src/adapter/schema.rs) composes JSON Schema, and [`structured`](src/adapter/structured.rs) shapes responses. - [`remote/`](src/remote) — server identity, canonical discovery, and the byte-transparent SSH proxy for a caller that has already chosen one host. - [`federated/`](src/federated) — the mux: `config` (operator destinations), `descriptor` (live workspace descriptors), `probe` (in-process and SSH destinations), `capability`, and `host` (`FederatedMcpHost`). - [`listener.rs`](src/listener.rs) — the TCP transport and its exposure gate. - [`error.rs`](src/error.rs) — error shaping toward MCP clients. Tests use sibling `tests/` directories ([`test_layout.md`](../../docs/design-patterns/test_layout.md)); crate-root [`tests/`](tests) holds the dependency-boundary assertion and the wire round-trip that drives a real client over an in-memory duplex. ## Crate-specific invariants - **Advertised names are shipped contract.** Sanitization exists because Cursor accepts `[a-zA-Z0-9_]` and VS Code accepts `[a-z0-9_-]`; the mapping keeps Orbit's names inside that intersection *without renaming any canonical identifier*. A collision after sanitization is a hard error, never a silent rename. - **The federated mux is the one place Orbit is also an MCP client.** Remote membership comes only from the operator's destinations file; the accepting machine is an implicit local destination, never an SSH row. It is not a fleet registry and answers are not cached between calls. - **Routing is fail-closed.** A federated call carries a host-qualified selector the caller copied from federated `orbit.workspace.list`. A local selector is delivered in-process without SSH; anything else is refused as `unknown_selector` rather than guessed at. - **The accepting machine resolves local state.** Whatever the transport — stdio, TCP, SSH proxy, or a routed federated call — the machine that accepts the call resolves its own workspaces and dispatches through Core.