1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//! MCP (Model Context Protocol) server library — transport-agnostic
//! dispatch for exposing CAR capabilities to MCP-aware clients.
//!
//! Two transports use this crate today:
//!
//! - **stdio** — `car-mcp-server` binary, one client per process.
//! Suitable for Claude Desktop / Cursor / Claude Code's
//! `--mcp-config` and any other client that follows the MCP spec's
//! stdio framing. See [`transport::stdio_loop`].
//! - **HTTP-streamable** — `car-server` daemon endpoint, many
//! concurrent clients sharing the same `Runtime` / policy chain /
//! eventlog. Implemented in `car_server_core::mcp` against the same
//! [`Server::handle`] entry point: `POST /mcp` for one JSON-RPC
//! request/response, `GET /mcp` for the SSE stream, `GET
//! /mcp/health` for liveness. Bind address is `--mcp-bind` /
//! `CAR_MCP_BIND`; pass `disabled` to skip the listener.
//!
//! Both share the same `Server::handle(Request) -> Option<Response>`
//! pure function, so transports stay separable from protocol logic.
//!
//! The *tool set*, however, is per-[`Server`], not per-process. A
//! transport may register tools it alone can serve via
//! [`Server::register_tool`]: the daemon holds a live `Runtime`, so it
//! can carry tools the stdio binary has no way to run and must not
//! advertise. With nothing registered, a server advertises exactly the
//! built-in schemas, unchanged.
//!
//! The daemon uses that seam for exactly one thing today:
//! `assistant_start` / `assistant_poll` / `assistant_cancel`
//! (`car_server_core::mcp_assistant`, car#972 §6), which drive the agent
//! behind `car do` through a run handle. They are absent from stdio because
//! `car-mcp-server` is this crate plus telemetry — no `Runtime`, no inference
//! engine — so a stdio client gets `-32601` for a tool that never existed
//! there rather than a tool that exists and cannot work.
//!
//! ## Why a library crate
//!
//! Originally this lived in `car-mcp-server`'s `main.rs` as a
//! self-contained binary. v0.8 + the external-agent work made it
//! clear MCP needs to be a first-class daemon surface so every
//! external client (Claude Code, Codex, Gemini, custom GPTs) gets
//! CAR's tools through the same governance layer. Extracting the
//! dispatch logic into a library lets the daemon embed it without
//! shelling out to a subprocess. See
//! `docs/proposals/external-agent-detection.md`. The daemon endpoint
//! landed in 0542d10f; `docs/websocket-protocol.md` and
//! `docs/cookbook/07-mcp-server.md` document the live surface.
pub use ;
pub use ;
/// Where [`Server::with_store`] should point by default: the same note store
/// the assistant behind `car do` reads and writes.
///
/// Sharing one file is the point. A separate MCP-only store would leave
/// `memory_query` from an editor unable to see anything the user remembered
/// through `car do`, which is half of what car#972 §1 reports as broken.
///
/// Relocating it needs no new knob: the path resolves under `CAR_HOME`, so an
/// editor plugin that wants an isolated memory sets that one variable and
/// every other daemon state path moves with it.
/// MCP protocol version this server speaks.
pub const PROTOCOL_VERSION: &str = "2024-11-05";
/// Every protocol revision this server will answer `initialize` with.
///
/// Exactly one entry today, so negotiation is a no-op in practice: every
/// client is answered `2024-11-05` either because it asked for that, or
/// because nothing else is on the list. The list exists so a future bump is
/// an append plus a move of [`PROTOCOL_VERSION`] to the new revision — at
/// which point a client still asking for `2024-11-05` keeps getting it back
/// instead of being handed a revision it never asked for and may refuse.
/// That inversion is what car#972 §3 identifies as the real blocker to the
/// bump; the negotiation in `Server::handle` is what removes it.
pub const SUPPORTED_VERSIONS: & = &;
/// Server identifier reported in `initialize` responses.
pub const SERVER_NAME: &str = "car-mcp";
/// JSON-RPC error codes per the spec.