conduit-mcp
by IUMvuyo
README.md
# conduit-mcp
[](https://github.com/IUMvuyo/conduit-mcp/actions/workflows/ci.yml)
**A governance-layer MCP server.** An AI agent's writes into a system of record are
**gated**, **four-eyes signed**, and written to a **tamper-evident audit trail**. Reads are
open; writes are not. Zero dependencies, on purpose: there is nothing to trust but this
package and its `lib/`, which is Conduit's own thesis (trust the proof, not the pipe)
applied to the server itself.
It runs out of the box against an in-memory demo backend (a Guidewire-style claims store),
so you can connect a client and try it with no credentials or config.
## What it exposes
Seven tools over the standard MCP stdio transport:
| Tool | What it does |
|---|---|
| `get_record` | Read one record. Open. |
| `search_records` | Search a resource by free text. Open. |
| `propose_change` | Draft a numeric change. Never writes. Returns the gate decision (`auto` / `signoff` / `dual`) and how many distinct human signatures are required. |
| `approve` | Record one human signature on a proposal. Four-eyes enforced. |
| `commit_change` | **Gated.** Writes only if the proposal has the required distinct signatures, otherwise refuses and says what is missing. |
| `get_audit_trail` | The hash-chained audit trail (reads, gate decisions, signatures, commits) with reasoning attached and an integrity check. |
| `set_policy` | Adjust the auto-adjust ceiling and dual-control threshold for the session. |
The point: an agent that calls `propose_change` then `commit_change` on a high-value write
is **stopped**. It must route through human sign-off. Every step is on the record.
## Run
```bash
node server.mjs # speaks MCP JSON-RPC on stdio (demo backend)
npm test # drives the server end to end over both backends (17 checks)
```
## Backends
The governance (gate, four-eyes, audit) is backend-agnostic. Pick the system of record with
`CONDUIT_BACKEND`:
| Backend | Select | Notes |
|---|---|---|
| `demo` (default) | (none) | In-memory Guidewire-style claims store. Zero config. |
| `xero` | `CONDUIT_BACKEND=xero` | The Xero accounting adapter. A committed change reclassifies an amount by posting a balancing `ManualJournal`. Uses a **mock** transport unless `XERO_ACCESS_TOKEN` + `XERO_TENANT_ID` are set, then it posts to the **live** Xero API. |
```bash
CONDUIT_BACKEND=xero node server.mjs
# over Xero, propose_change bankTransaction/BT-5521.reclassified_amount, then approve x2, then commit
```
## Connect a client
**Claude Code**
```bash
claude mcp add conduit -- node /absolute/path/to/mcp-server/server.mjs
```
**Claude Desktop** (`claude_desktop_config.json`)
```json
{
"mcpServers": {
"conduit": { "command": "node", "args": ["/absolute/path/to/mcp-server/server.mjs"] }
}
}
```
**OpenAI Agents SDK** (Python) points at the same stdio server:
```python
from agents.mcp import MCPServerStdio
conduit = MCPServerStdio(params={"command": "node", "args": ["/absolute/path/to/server.mjs"]})
```
Once published to npm you can use `npx conduit-mcp` in place of the absolute path.
## Try it (from any connected client)
1. `get_record` claim `CLM-5510-19` (settlement is `null`)
2. `propose_change` settlement to `612000` (gate: `dual`, needs 2 signatures)
3. `commit_change` -> **refused**, no signatures
4. `approve` as `usr_thabo`, then `approve` as `usr_naledi` (two distinct humans)
5. `commit_change` -> written, returns a `tx`
6. `get_record` again -> settlement is now `612000`
7. `get_audit_trail` -> the whole chain, integrity `ok`
## Design
The write path is the governance ladder from the Conduit project (proven by the test suite (`npm test`, 17 checks): `propose_change` runs the gate; below the
auto-adjust ceiling a change auto-clears, at or above the dual-control threshold it needs
two distinct human signers, otherwise one. `commit_change` verifies signatures before it
writes. The audit chain (`lib/audit.mjs`) is append-only and hash-linked, so altering any
past entry breaks verification.
This server is a working reference. The demo backend is in-memory; a production adapter
(the Xero adapter here, `CONDUIT_BACKEND=xero`) swaps in behind the same tools.
## Publish and list
An MCP server is not "submitted to" a model. Any MCP client connects to it. To get it in
front of Claude and OpenAI users you publish it and list it, then their clients can find it.
**1. Publish to npm** (needs your npm login; a public name claim, so do it deliberately):
```bash
cd mcp-server
npm login
npm view conduit-mcp version # confirm the name is free (E404 = free)
npm publish --access public
```
If `conduit-mcp` is taken, set `"name": "@yourscope/conduit-mcp"` in `package.json` first,
then `npm publish --access public`.
**2. List in the MCP Registry** (registry.modelcontextprotocol.io). The `io.github.iumvuyo/*`
namespace in `server.json` is verified through GitHub, so you publish as the repo owner:
```bash
# get the mcp-publisher CLI from the modelcontextprotocol/registry releases
mcp-publisher login github # OAuth as IUMvuyo, verifies the namespace
mcp-publisher publish # reads server.json, creates the listing
```
Publish to npm first; the registry entry references the npm package.
**3. Clients.** Once listed, Claude Desktop and Claude Code users add it by name; the OpenAI
Agents SDK and ChatGPT developer-mode connectors point at `npx conduit-mcp`. A PR to the
community list at `github.com/modelcontextprotocol/servers` is optional and curated.
**Honest readiness.** The server is real and it now ships two backends: the zero-config demo,
and the Xero accounting adapter that posts a genuine balancing `ManualJournal`. The remaining
gap is live credentials and a real-org shakedown (multi-currency, tracking categories, real
lock dates): the `xero` backend runs on a mock transport until `XERO_ACCESS_TOKEN` +
`XERO_TENANT_ID` are supplied. Publishing now is legitimate as a reference governance server
with a real (mock-by-default) adapter; a "verified against a live org" claim needs those creds
and a design partner first.
MIT licensed. Part of [Conduit](https://conduit-mu-ten.vercel.app).
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues