MCP server
The MCP server gives any MCP-capable agent Bezial as a set of tools with zero glue. It exposes the same verb set as the library and HTTP API, each tool a thin adapter over the one engine - never a reimplementation. It is a hand-rolled JSON-RPC 2.0 server over the MCP stdio transport, with no MCP-SDK dependency, keeping the dependency tree clean.
Running the server
Section titled “Running the server”The server runs as a subprocess of one agent and speaks newline-delimited JSON-RPC 2.0 over stdin/stdout (logs go to stderr). It is configured from the environment:
| Variable | Default | Purpose |
|---|---|---|
BEZIAL_MCP_TOKEN |
required | The server’s credential - a bzk_ API key or a bzs_ signed principal. |
BEZIAL_ROOT |
./.bezial-data |
Object store + change logs root. |
BEZIAL_PERMISSIONS |
acl |
The ACL model is enforced by default; set allow-all to disable enforcement (trusted single-tenant). |
BEZIAL_KEYS |
<root>/api-keys.json |
API-key records (hashed). |
BEZIAL_MCP_SPACE |
default |
The space used when a tool call omits space. |
BEZIAL_SIGNING_SECRET |
- | If set, also accept bzs_ signed-principal tokens. |
One process, one principal
Section titled “One process, one principal”The token resolves to one fixed principal at startup, for the lifetime of the process.
A tool argument can never assert a different identity - there is no auth bypass.
So an agent’s MCP server acts as exactly the caller it was launched as, and every tool call is authorized against that principal: reads are ACL-gated, list and audit are permission-filtered, and recall and the views are filtered per fact - zero cross-space and cross-author leak, exactly as on every other surface.
The tools
Section titled “The tools”Every tool takes an optional space (defaulting to BEZIAL_MCP_SPACE).
| Tool | Required args | Verb |
|---|---|---|
bezial_add |
text |
add |
bezial_write |
path, content |
write |
bezial_read |
path (version?) |
read |
bezial_list |
- (prefix?) |
list |
bezial_history |
path |
history |
bezial_restore |
path, version |
restore a document version |
bezial_recall |
query (asOf?, scope?, synthesize?, limit?, includeArchived?) |
recall |
bezial_file_map |
- (asOf?, scope?) |
file-map view |
bezial_fact_graph |
- (asOf?, scope?) |
fact-graph view |
bezial_grant |
path, granteeId |
grant |
bezial_revoke |
path, granteeId |
revoke |
bezial_set_visibility |
path, visibility (private|space) |
setVisibility |
bezial_acl |
path |
acl |
bezial_audit |
- (path?, principalId?, since?) |
audit |
bezial_pin |
factId |
pin |
bezial_unpin |
factId |
unpin |
bezial_forget |
factId, reason |
forget |
bezial_restore_fact |
factId |
restore a forgotten fact |
The factId for the forgetting tools is the id field from a bezial_recall result.
Error handling
Section titled “Error handling”A denied, not-found, or bad-argument tool call returns an MCP isError result carrying the reason - a normal tool result, not a protocol error - so the agent can read the message and react rather than crashing.
Successful results return the engine’s response as formatted JSON text.
Why a Bezial-native MCP server
Section titled “Why a Bezial-native MCP server”Graphiti ships its own MCP server, but it is Python and graph-DB-specific. Bezial is general-purpose and file-is-truth, so a thin adapter over the Bezial engine is the right fit: it keeps the surface general-purpose and guarantees the MCP path shares the one write path, one permission model, and one recall with every other surface.