MCP Server
The AGLedger MCP server connects any MCP-compatible agent runtime (Claude Desktop, Cursor, Windsurf, ChatGPT MCP, Gemini) to your AGLedger Server. It is a thin pass-through: the agent calls a small set of MCP tools, and those tools relay HTTP calls to the API and forward the responses verbatim. Nothing about the record lifecycle lives in the server — it carries the agent's calls and the API's guidance back and forth.
Use this guide when you want an agent to notarize through MCP rather than calling the HTTP API directly, or rather than embedding the SDK. For endpoint and field-level detail, the API reference is canonical — this page covers only the MCP setup and the tool surface.
The package is @agledger/mcp-server, pinned here at v2.4.8. It requires Node.js 24 or newer and speaks MCP over stdio.
1. Install the server
npm install -g @agledger/[email protected]
This installs the agledger-mcp binary. Confirm it runs and points at the version you expect:
agledger-mcp --help
AGLedger MCP Server v2.4.8
Usage: agledger-mcp --api-key <key> [--api-url <url>]
Options:
--api-key, -k AGLedger API key (or AGLEDGER_API_KEY env var)
--api-url, -u AGLedger API base URL (or AGLEDGER_API_URL env var)
--help, -h Show this help message
Tools:
agledger_discover Returns API health, your identity, and available scopes
agledger_api Make any AGLedger API call — the API guides you via nextSteps
agledger_verify Verify an audit export offline (hash chain + Ed25519)
The server needs two things: an API key and the base URL of your Server. Both can come from flags or environment variables — AGLEDGER_API_KEY and AGLEDGER_API_URL. The key is a Bearer credential the server attaches to every call; mint one as described in Authentication. If --api-url is omitted the server falls back to a placeholder (https://agledger.example.com), so always set it to your own Server.
2. Wire it into your MCP client
Add the server to your client's MCP configuration. For Claude Desktop this is claude_desktop_config.json; other clients use the same mcpServers shape.
{
"mcpServers": {
"agledger": {
"command": "agledger-mcp",
"args": ["--api-url", "https://agledger.your-company.internal"],
"env": {
"AGLEDGER_API_KEY": "agl_agt_…"
}
}
}
}
Keep the API key in the env block, not in args — process arguments are visible in process listings, environment variables are not. Restart the client so it spawns the server. On connect the client lists three tools (agledger_discover, agledger_api, agledger_verify) and one resource (agledger://openapi).
3. The tools
The server exposes exactly three tools. The agent calls agledger_discover once to orient, drives the record lifecycle through agledger_api, and verifies an export with agledger_verify.
agledger_discover
No arguments. Returns your Server's health, the calling identity (GET /v1/auth/me), the available scope profiles, and a four-step quickstart. The agent calls this first — the response tells it who it is, what scopes it holds, and what to do next. It is read-only and makes no changes.
agledger_api
The workhorse. Makes any AGLedger API call and forwards the response unmodified. Three arguments:
| Argument | Type | Notes |
|---|---|---|
| method | GET / POST / PUT / PATCH / DELETE | required |
| path | string | must start with /; all routes use the /v1/ prefix |
| params | JSON-encoded string (or native object) | optional. For GET/DELETE it becomes query parameters; for POST/PUT/PATCH it becomes the JSON body |
The agent notarizes through this one tool. The tool's own description hands the agent the lifecycle, and every API response carries nextSteps and (on errors) a suggestion field, so the agent self-guides:
GET /v1/schemas— list the available record types (contract types).GET /v1/schemas/{type}— read the required fields and examples for the type.POST /v1/records— notarize a record. For a notarize-only type this terminalizes the record atRECORDEDin that one signed call.POST /v1/records/{id}/completions— submit a Completion (the performer's evidence) when the work is done, for types that run the gated lifecycle.
A bad path returns a structured PATH_INVALID error; malformed params returns INVALID_JSON; a slow Server returns TIMEOUT; a connectivity failure returns NETWORK_ERROR. API-origin errors (a 403 for a missing scope, a 422 for a schema violation) are forwarded byte-for-byte — the API owns that guidance, and the agent reads the suggestion field to recover.
agledger_verify
Verifies a record audit export entirely offline. The agent first pulls the export through agledger_api (method=GET, path=/v1/records/{id}/audit-export), then passes the response body as the export argument.
| Argument | Type | Notes |
|---|---|---|
| export | JSON-encoded string (or native object) | required. The body from GET /v1/records/{id}/audit-export |
| publicKeys | JSON-encoded string (or native object) | optional. Map of signingKeyId → SPKI-DER base64 public key, merged over any keys embedded in the export |
| requireKeyId | string | optional. Reject any entry not signed by this key, even if otherwise valid |
The verifier decodes each entry's tagged COSE_Sign1 envelope (RFC 9052, EdDSA) over its in-toto v1 Statement payload, recomputes the SHA-256 over the envelope bytes, walks the hash chain, cross-checks the protected-header chain claim against the row columns, and verifies every Ed25519 signature. It makes no network calls — trust is rooted in the signing keys embedded in the export (or supplied via publicKeys). On a clean export it returns valid: true with a signatureCoverage breakdown; on a tampered or broken export it returns valid: false with brokenAt, which pinpoints the first failing entry and the reason (one of payload_hash_mismatch, chain_break, cose_decode_failed, cose_header_mismatch, signature_invalid, unknown_key, position_gap, malformed_entry, unsupported_algorithm).
Do not read valid: true alone as "every entry was cryptographically signed" — surface signatureCoverage ({ signed, unsigned, skipped, total }) so an unsigned-but-chain-intact entry is not mistaken for a signed one.
The agledger://openapi resource
Alongside the tools, the server exposes the live OpenAPI spec as an MCP resource. Clients surface it in their resource picker, so the agent (or operator) can pull the full route catalog into context without constructing a call. The resource proxies GET /openapi.json at read time — it is always current with the running Server, never a stale local copy.
Verify it worked
After wiring the config, have the agent call agledger_discover. A healthy connection returns your identity and scopes; the identity block mirrors GET /v1/auth/me and should show your role and authType. If health carries an error instead, the server reached your runtime but could not reach the API — check --api-url and that the key is valid.
Failure modes
| Symptom | Cause | Fix |
|---|---|---|
| Server exits immediately on start | No API key supplied | Set AGLEDGER_API_KEY in the client's env block, or pass --api-key |
| agledger_discover returns health.error | API URL wrong or Server unreachable | Confirm --api-url resolves from where the client runs; try GET /health directly |
| agledger_api returns NETWORK_ERROR | DNS or transport failure to the API | Check the URL; the suggestion points you at GET /health |
| agledger_api returns TIMEOUT | Server slow to respond (default 30s) | Retry; the request is forwarded as-is, so retries are safe for idempotent calls |
| agledger_api returns a 403 body | Key lacks the scope for the call | Mint a key with the right scope profile (see Authentication) |
| agledger_api returns INVALID_JSON | params was not a JSON object | Pass params as a JSON-encoded object string, e.g. {"type":"ACH-PROC-v1"} |
| agledger_verify returns INVALID_EXPORT | Input was not an audit export | Fetch it first with GET /v1/records/{id}/audit-export, then pass the response body |
| agledger_verify returns unsupported_algorithm | Pre-2.0 export format | Re-export the chain from a v0.23.0+ Server |
Air-gapped operation
The MCP server has no runtime dependency on the AGLedger website, Docker Hub, or npm once it is installed. Every flow above works against a Server on your own network with no outbound internet.
Install without npm at runtime. On a connected staging host, fetch the package tarball once and carry it across the boundary:
npm pack @agledger/[email protected]
This produces agledger-mcp-server-2.4.8.tgz. Transfer it into the air-gapped environment and install from the file — no registry contact:
npm install -g ./agledger-mcp-server-2.4.8.tgz
Point it at your internal Server. Set --api-url (or AGLEDGER_API_URL) to your in-network Server. All three tools then operate without leaving the network: agledger_discover and agledger_api call only that Server, and agledger_verify is offline by construction.
Verification needs no Server at all. Because agledger_verify makes no network calls and roots trust in the keys embedded in the export, an auditor can verify a chain on a fully disconnected machine. Carry the audit-export JSON across the boundary, supply the expected signing keys via publicKeys (and requireKeyId to pin a key), and the verdict is self-contained. The same offline verification is also available as a standalone step — see Verify offline.
Tool surface (agledger_discover, agledger_api, agledger_verify), the agledger://openapi resource, the CLI flags, and the offline-verifier failure classes are drawn from @agledger/mcp-server v2.4.8. Endpoint and schema detail is canonical in the API reference; confirm response shapes against your own Server.