@getbourdon/mcp-server
v0.6.0
Published
Bourdon L6 MCP server (BUSL-1.1) — the facade over @getbourdon/federation that exposes the federation natively to any MCP-aware agent (Claude Code, Codex, Cursor). Faithful port of core/l6_server.py on @modelcontextprotocol/sdk. WIRE-COMPATIBLE with the P
Readme
@getbourdon/mcp-server
Bourdon L6 — the MCP server facade (BUSL-1.1). The TypeScript mirror of the
Python core/l6_server.py on @modelcontextprotocol/sdk. It exposes
@getbourdon/federation (the L6Store + trust boundary) natively to any MCP-aware
agent (Claude Code, Codex, Cursor) and is wire-compatible with the Python
server in BOTH directions, so mixed-language federation works.
Python (
pip install bourdon) is the oracle. This package asserts its tool payloads against the@getbourdon/conformancemcp_snapshotsfixtures, recovered through the exact same wire path a PythonRemoteL6Clientuses.
The wire contract (the single highest-risk detail)
Every tool handler returns JSON-in-TextContent:
{ content: [{ type: "text", text: JSON.stringify(payload) }] }— not the SDK's default structured content. The Python RemoteL6Client (and
@getbourdon/client) recover the payload with json.loads(item.text) /
JSON.parse(text). Returning structured content instead makes a Python peer's
json.loads(item.text) get None and silently breaks federation. The
mcp_snapshots fixtures snapshot the post-round-trip payload, so the parity
test drives a real MCP client over an in-memory transport, recovers
content[0].text, JSON.parses it, normalizes, and compares to the Python .res.
Tools (15) + resources (3)
Thin delegates to @getbourdon/federation + @getbourdon/recognition. Tool
names, arg names, and defaults are byte-identical to the Python server —
including the access_level default split:
| default public (read/query) | default team (recognition / turn) |
|---|---|
| query_agent_memory, list_recent_work, find_entity, get_cross_agent_summary | prepare_recognition_context, compile_codex_turn, get_deeper_context |
list_agents, export_agents, commit_to_federation, list_notes, and
list_workstreams round out the read/write set. Version history ships as
list_memory_versions and explain_memory_change (reads) plus
rollback_agent_memory — a trusted-only, audit-gated restore of an archived
manifest, byte-for-byte; credential redaction applies at every read surface, so
restored bytes are never emitted unredacted.
compile_codex_turn returns the deferred P7 stub ({_status:"deferred",
schema_version:"codex-turn-brief/v1", reason}) — the turn compiler is
environment-bound and ships in Phase 7. Resources:
agent-library://agents, agent-library://agents/{agent_id}/memory,
agent-library://entities/{name}.
Transports + auth
import { createL6Server, runStdio, runHttpServer } from "@getbourdon/mcp-server";
import { L6Store, FederationRegistry } from "@getbourdon/federation";
const store = new L6Store("/path/to/agent-library");
const registry = new FederationRegistry();
// stdio (the MCP-host default; resolves to OPERATOR — v0.8.0 behavior):
await runStdio(createL6Server(store, { registry }));
// streamable-HTTP (Bearer auth, stateless):
runHttpServer(() => createL6Server(store, { registry }), {
host: "127.0.0.1", // default; a NON-loopback bind without auth REFUSES to start
port: 7500,
registry,
});Security invariants are enforced in code: an empty Bearer can never
authenticate as OPERATOR (the legacy compare needs both a configured legacy token
and a non-empty presented token); a non-loopback bind without auth (or with
--allow-unauthenticated, which is loopback-only) throws BindRefusedError;
identity propagates to the tool handlers via AsyncLocalStorage
(runWithCaller) so a quarantined caller can never escalate.
The bourdon-l6-server bin mirrors python -m bourdon.core.l6_server:
--library --transport {stdio,http} --port 7500 --host 127.0.0.1 --federate
--peer --peers-config --no-peers --allow-unauthenticated.
Explicit peer authority
The server starts with zero remote peers and does not read
~/.bourdon/peers.yaml by default. Networking is enabled only by one of these
explicit options:
--federateloads~/.bourdon/peers.yamland fails closed if it is missing or invalid.--peers-config <path>loads only the selected file and fails closed if it is missing or invalid.--peer <url>adds an endpoint directly and may be repeated.--no-peersasserts local-only operation and rejects every option above.
Configuration files use this shape:
peers:
- name: production-peer
url: https://peer.example.com
token_env: BOURDON_PEER_PRODUCTIONtoken_env defaults to BOURDON_PEER_TOKEN and must remain in the
BOURDON_PEER_* namespace. Peer URLs must use HTTPS unless they target a
loopback host; embedded credentials, queries, and fragments are rejected.
Migration note: installations that previously relied on automatic loading of
~/.bourdon/peers.yaml must now pass --federate explicitly.
License
BUSL-1.1 — see LICENSE + LICENSE_FAQ.md.
