MCP adapter
vivary-mcp is an optional, read-only bridge from local MCP clients to Vivary’s
bounded public context producers. It is not part of the baseline install, does not
change the graph, and does not add MCP dependencies to vivary-core.
Read-only is the adapter’s authority ceiling, not a claim that Vivary cannot maintain its workspace. Vivary Core and its CLI workflow can create governed records when an operation has evidence binding and explicit human approval; MCP never grants that approval or silently escalates into a write tool.
vivary-mcp 0.1.3 is published on PyPI. It stays optional and off by default. No
Vivary install starts it for you.
Contract
Section titled “Contract”The adapter pins:
- MCP protocol
2026-07-28 - official Python SDK
mcp==2.0.0andmcp-types==2.0.0 - local standard input/output transport only
- SDK-owned discovery through
server/discover - exactly four tools and no extensions
Tests cover the SDK-owned discovery, metadata, cancellation, schema-validation, and
server-identity paths. Vivary has not passed the pinned external conformance harness.
Doctor therefore reports conformance_status: unproven.
Install boundary
Section titled “Install boundary”Install the optional package explicitly from the public index:
python -m pip install vivary-mcpThat resolution pulls vivary-core and vivary-tropo from their declared floors and
installs the exact reviewed MCP SDK dependency. The normal vivary and
create-vivary installs do not include or start the adapter.
To test a local change instead, install the three distributions together from a checkout so pip does not mix source and registry versions:
python -m pip install ./packages/core ./packages/tropo ./packages/mcpStart the local server
Section titled “Start the local server”Bind each public alias to one canonical workspace root at process startup:
vivary-mcp --workspace docs /absolute/path/to/workspaceRepeat --workspace ALIAS PATH to expose more than one root. An alias may use letters,
numbers, ., _, or -. It must begin with a letter or number and contain at most
64 characters. Startup normalizes each root and requires distinct canonical
directories. It retains an operating-system identity anchor for each root until the
server stops. Ordinary writes inside that directory remain valid, but replacing the
root path makes subsequent calls refuse with workspace_unavailable. Tool calls
cannot supply or change aliases or roots.
For a generated thin-v0.3 workspace, the public producer reads
.vivary/workspace.toml as its type policy. Before git init, Core accepts only the
exact bounded .gitignore block generated by create-vivary; missing, changed,
extended, linked, or arbitrary non-Git policy refuses the request. After the workspace
becomes an exact Git worktree, the existing hardened Git ignore policy is
authoritative. A root tropo.toml may compose with the thin base only when its policy
is privacy-admitted and tighten-only. Invalid, unreadable, linked, or loosening
overlays fail closed; the producer never silently ignores an overlay.
The process speaks newline-delimited MCP JSON-RPC on standard input and standard output. It reserves standard output for protocol messages. Standard error carries bounded, sanitary diagnostics:
vivary-mcp \ --workspace docs /absolute/path/to/workspace \ --observability errors--observability accepts:
off: no diagnosticserrors: refusal, cancellation, and timeout diagnosticsjson: all bounded lifecycle diagnostics
Diagnostics exclude workspace aliases and roots, queries, filters, snippets, and paths. They also exclude identifiers, arguments, environment values, client identity, claims, evidence, exceptions, and stack traces. The adapter writes no telemetry, log file, socket, or network request.
All schemas are closed JSON Schema Draft 2020-12 objects. Unknown fields and values outside the published limits are invalid arguments.
| Tool | Required input | Optional input | Result |
|---|---|---|---|
vivary_find |
workspace, question |
limit, budget |
Bounded context selected for a task or question. |
vivary_query |
workspace, text |
limit, type_filters, path_filters, edge_filters, snippet_chars, explain |
Bounded filtered typed-graph matches. |
vivary_check |
workspace |
paths, strict |
Bounded validation findings without repairs. |
vivary_capsule |
workspace, question |
max_claims |
Privacy-projected public Task Capsule without raw evidence or check execution. |
Every call returns a vivary.mcp-tool-result/v0 envelope with known, unknown, or
refused status. Every envelope names a workspace only by its configured alias. The
adapter returns exact results whole or refuses them. It does not silently truncate an
oversized result.
Bounded work
Section titled “Bounded work”The adapter’s public ceilings are part of its contract, not tuning guidance:
| Boundary | Limit |
|---|---|
| Operator-bound workspaces per process | 16 |
| Workspace alias | 1–64 characters |
| One newline-delimited input frame | 65,536 bytes |
| Question or query text | 4,096 characters |
Returned matches (limit) |
1–20 |
vivary_find budget |
64–4,000; default 1,200 |
| Each query filter list | 16 unique values; type 128, path 512, and edge 256 characters per value |
| Query snippet | 0–1,000 characters; default 160 |
vivary_check paths |
200 unique workspace-relative paths, 512 characters each |
vivary_capsule claims |
0–24; default 24 |
| Active producer work | 1 call, 30-second timeout, 5-second cancellation grace |
| Complete JSON-escaped tool response | 1 MiB |
| One standard-error diagnostic | 4,096 bytes |
An over-limit argument is invalid. Work, privacy, or response overflow returns a typed
unknown/refusal envelope; the adapter never turns a prefix into a complete answer. A
producer that ignores cancellation keeps the sole slot quarantined until its worker
exits, so later calls receive server_busy instead of overlapping it. Downstream
Tropo/Core ceilings still apply, and the tighter limit wins. The constants and schema
live in the adapter source;
limit, timeout, and quarantine regressions
provide the behavior evidence.
Data and authority boundaries
Section titled “Data and authority boundaries”The adapter can:
- inspect only operator-bound local roots
- invoke fixed, bounded internal Git reads used by the public Tropo/Core contracts
- read candidate bytes only after Core’s privacy policy admits their paths
- return bounded public projections
It cannot:
- write, repair, promote memory, execute checks, or persist state
- accept a root, executable, shell command, process, endpoint, or transport from a tool caller
- fetch, index, publish, deploy, approve a gate, or call a provider
- return ignored or sensitive names, raw evidence, commands, absolute machine paths, credentials, or private content
Governed writes stay outside MCP
Section titled “Governed writes stay outside MCP”vivary_capsule returns a complete bounded public capsule object that can bind a
later proposal. It does not return write authority. Save that result object, prepare a
typed Markdown source, preview create-vivary record --capsule <path>, inspect its
capsule-bound plan, and apply only the exact human-approved hash. The CLI verifies the
capsule’s canonical integrity and current workspace fingerprint before it can plan.
The transaction writes one create or update, reruns Doctor, and rolls back on failed
verification. It has no batch or pack mode. See
the command contract.
This separation preserves the normal agent loop: retrieve and propose through bounded context interfaces, then cross a deliberate write gate through the workspace owner. MCP startup and all four MCP calls remain non-materializing.
Cancellation and timeouts reach the active producer and its fixed Git process scope. Only one producer runs at a time. Concurrent calls refuse instead of creating unbounded work.
Passive Doctor report
Section titled “Passive Doctor report”create-vivary doctor --json always includes the optional interop:mcp capability.
Doctor reads installed distribution metadata and entry-point declarations only. It
does not import the adapter, start a process, connect to a server, or use the network.
The capability is not-installed by default. Compatibility requires the active
interpreter to see the vivary-mcp entry point and exact declared mcp==2.0.0
dependency. Doctor reports a different SDK version as incompatible rather than
accepting it speculatively.
Verification
Section titled “Verification”Run the source regressions with the reviewed SDK installed:
python -m pytest packages/mcp/tests/ -qThese tests prove the repository adapter behavior against the pinned SDK. They do not establish external harness conformance or compatibility with a named MCP client. The official-SDK suite also scaffolds a real five-file greenfield workspace, starts the stdio server, discovers and calls the four tools, proves the read phase made no files, then applies one separately approved capsule-bound record and queries it through the same MCP session. It asserts that no template, module pack, or extra record appears.
