io.github.Gareth1953/agent-services-mcp
MCP server: x402-paid & free tools for AI agents — provenance, quality scoring, action audit.
Open source Open in the app JSON README (API)
About
MCP server: x402-paid & free tools for AI agents — provenance, quality scoring, action audit.
Details
- Kind
- MCP servers
- Topic
- Finance & crypto
- Publisher
- gareth1953
- Origin
- official
- Category
- ferramentas
- Transport
- local
- Version
- 0.2.1
- Last push
- 2026-06-22T05:35:39Z
- Repository state
- ativo
- Language
- JavaScript
- License
- MIT
- Added
- 2026-08-29 03:01:55
- Updated
- 2026-08-29 03:01:55
- Origin id
io.github.Gareth1953/agent-services-mcp
README
# agent-services-mcp
A single **thin MCP (Model Context Protocol) server** that exposes three existing
services as discoverable tools, so AI agents and MCP-compatible clients can find
and use them through one connection:
- **[provenance-receipts](https://github.com/Gareth1953/provenance-receipts)** — certifies content **origin**;
returns an Ed25519-signed receipt.
- **[quality-gate](https://github.com/Gareth1953/quality-gate)** — scores content **quality** against a
published rubric; returns an Ed25519-signed score receipt.
- **agent-action-audit** — signs a **tamper-evident audit receipt** for an action an
agent took (agent accountability); returns an Ed25519-signed audit receipt.
> **It is a thin wrapper.** Every tool forwards an HTTP call to the underlying
> Worker and returns its response verbatim. It does **not** reimplement signing,
> scoring, or payment logic — those live in the underlying services. The honesty
> about what each service proves carries through to the tool descriptions.
## Quickstart — your first (free) call in ~2 minutes
```bash
npm install && npm run build
node examples/free-call.mjs # connects to the LIVE services and calls a free tool
```
`examples/free-call.mjs` runs an MCP client against this server (pointed at the live
deployments) and calls `get_quality_rubric` and `verify_audit` — both **free**, no
wallet needed. To wire the server into an MCP client (Claude Desktop / Claude Code
style), see **Connecting an MCP client** below.
**Free vs paid at a glance:** `verify_provenance`, `verify_quality`, `verify_audit`,
and `get_quality_rubric` are **free**. `certify_provenance`, `score_quality`, and
`audit_action` are **paid** (an x402 USDC micropayment on Base) — see **Calling paid
tools** for the two-step payment flow and a working example.
## What the wrapped services prove (and do not)
- **Provenance:** proves the content is unmodified (SHA-256 hash) and the receipt
was issued by the service's key. The `generator_metadata` is **caller-attested**
— it proves you *claimed* it, not that a specific model ran. Not AI-detection,
not a truth guarantee.
- **Quality:** a reproducible score **against the published rubric** (clarity,
completeness, internal consistency, obvious-error freedom). **Not** absolute
truth, **not** an external standard, **not** a fact-check. Read the rubric via
the `get_quality_rubric` tool.
- **Audit:** proves the action **record** is genuine (issued by the service's key)
and **unaltered since issue** (tamper-evident). The `action`, `actor_metadata`,
and `context` are **caller-attested** — it proves you *claimed* this record, not
that the agent's claim is true. An accountability/audit tool, **not** a
lie-detector.
## Tools
| Tool | Forwards to | Paid? | Input |
| -------------------- | ---------------------------------------- | ---------- | ----- |
| `certify_provenance` | provenance-receipts `POST /v1/certify` | yes (x402) | `content` (string), `generator_metadata` (object, optional) |
| `verify_provenance` | provenance-receipts `POST /v1/verify` | no | `content` (string), `receipt` (object) |
| `score_quality` | quality-gate `POST /v1/score` | yes (x402) | `content` (string), `rubric_version` (string, optional), `target_score` (number 0–100, optional) |
| `verify_quality` | quality-gate `POST /v1/verify` | no | `content` (string), `receipt` (object) |
| `get_quality_rubric` | quality-gate `GET /v1/rubric` | no | none |
| `audit_action` | agent-action-audit `POST /v1/audit` | yes (x402) | `action` (string), `actor_metadata` (object), `context` (object, optional) |
| `verify_audit` | agent-action-audit `POST /v1/verify` | no | `action` (string), `actor_metadata` (object), `context` (object, optional), `receipt` (object) |
Full descriptions and Zod input/output schemas: [`src/tools.ts`](src/tools.ts).
Each tool returns the service's raw JSON (or markdown, for the rubric) as text; the
`verify_*` and `score_quality` tools **also** declare an `outputSchema` and return
parsed **`structuredContent`** you can read directly (e.g. `result.structuredContent.valid`).
A non-2xx response (including a `402 Payment Required`) is surfaced with
`isError: true` and the body preserved — for a `402` the wrapper prepends a short,
actionable note on how to pay. The three **paid** tools also accept an optional
**`x_payment`** input (the x402 X-PAYMENT token) to settle payment through the
wrapper — see **Calling paid tools**.
## Configuration
The three service URLs are environment-configurable (no secrets — just base URLs):
| Env var | Live (deployed) | Local dev fallback |
| ------------------ | -------------------------------------------------------- | ------------------------- |
| `PROVENANCE_URL` | `https://provenance-receipts.gpmiddleton71.workers.dev` | `http://localhost:8787` |
| `QUALITY_GATE_URL` | `https://quality-gate.gpmiddleton71.workers.dev` | `http://localhost:8788` |
| `AUDIT_URL` | `https://agent-action-audit.gpmiddleton71.workers.dev` | `http://localhost:8789` |
`.env.example` and the client config below point at the **live** deployments. If
the vars are unset, the server falls back to localhost for local `wrangler dev`
(the Workers default to `:8787`, so run quality-gate on `:8788` and
agent-action-audit on `:8789` to avoid clashes).
> Against the live services, the **paid** tools (`certify_provenance`,
> `score_quality`, `audit_action`) require x402 — this wrapper forwards the request
> and holds no wallet, so without an `X-PAYMENT` they return a `402` (the payment
> requirements) surfaced as `isError`. The free tools work as normal.
## Calling paid tools (x402)
The three paid tools require an x402 micropayment (USDC on Base mainnet). The wrapper
**holds no wallet** — it never spends on your behalf — so paying is a two-step flow:
1. **Call the tool with no `x_payment`.** You get back a `402` whose body is the x402
payment **requirements** (network, asset, amount, `payTo`). The wrapper prepends a
one-line note explaining what to do next.
2. **Build an x402 `X-PAYMENT` token** from those requirements with an x402 client +
a funded wallet, then **call the tool again with that token in the `x_payment`
input.** The wrapper forwards it as the `X-PAYMENT` header; the underlying service
verifies, settles, and returns the signed receipt.
Easiest path to a *working* paid call — let an x402 client settle for you against the
underlying service directly:
```bash
npm install x402-fetch
BUYER_PRIVATE_KEY=0x... node examples/paid-call.mjs
```
`examples/paid-call.mjs` uses `x402-fetch` + a **throwaway** Base-mainnet wallet
(holding a little real USDC) to pay for and call `audit_action`. ~$0.01 USDC moves
buyer → the service's `payTo`, gasless (the facilitator pays gas). **Real money — use
a disposable key with a few cents only.** The same applies to `certify_provenance`
and `score_quality`.
## Quickstart (local)
```bash
# 1. Build the MCP server
npm install
npm run build # -> dist/index.js
# 2. In separate terminals, run the three services (free; payments off)
# (provenance-receipts) npm run dev # http://localhost:8787
# (quality-gate) npx wrangler dev --port 8788 # http://localhost:8788
# (agent-action-audit) npx wrangler dev --port 8789 # http://localhost:8789
# 3a. Smoke-test the free tool paths through an MCP stdio client
node scripts/test-client.mjs
# 3b. (optional, costs ~$0.012) prove the paid score_quality path end-to-end
node scripts/test-score.mjs
# 3c. Smoke-test the wrapper against the LIVE deployed services (free — the
# paid tools return a forwarded 402; no payment, no scoring call)
node scripts/test-live.mjs
```
`scripts/test-client.mjs` exercises the free tools locally; `scripts/test-score.mjs`
makes one real Anthropic scoring call through `score_quality`;
`scripts/test-live.mjs` points the wrapper at the deployed workers.dev URLs and
asserts the free tools work and the paid tools forward the x402 `402`.
## Connecting an MCP client (stdio)
This server speaks MCP over **stdio** (stdin/stdout). Any MCP client launches it
as a subprocess. Example for a Claude Desktop / Claude Code style
`mcpServers` config:
```json
{
"mcpServers": {
"agent-services": {
"command": "node",
"args": ["C:\\Users\\Gareth\\agent-services-mcp\\dist\\index.js"],
"env": {
"PROVENANCE_URL": "https://provenance-receipts.gpmiddleton71.workers.dev",
"QUALITY_GATE_URL": "https://quality-gate.gpmiddleton71.workers.dev",
"AUDIT_URL": "https://agent-action-audit.gpmiddleton71.workers.dev"
}
}
}
}
```
- Run `npm run build` first so `dist/index.js` exists.
- The client connects, calls `tools/list` (it will see the 7 tools above), and
invokes them via `tools/call`.
- The underlying services must be reachable at the configured URLs when a tool is
called.
- Logs go to **stderr**; stdout is reserved for the MCP protocol.
Programmatically, connect with the SDK's `Client` + `StdioClientTransport`
(`command: "node"`, `args: ["dist/index.js"]`) — see `scripts/test-client.mjs`.
## x402 payments (forwarded, not handled here)
The paid endpoints (`/v1/certify`, `/v1/score`, `/v1/audit`) are gated by
[x402](https://github.com/coinbase/x402) on the underlying services. This wrapper
**forwards** requests and does not hold a wallet. If a service has payments
enabled and no valid `X-PAYMENT` is supplied, it returns `402` with the payment
requirements — the wrapper surfaces that as `isError` with the requirements body
intact. Settling a payment (signing an x402 authorization) is the client's
responsibility against the underlying service. See each service's `README.md` /
`docs/API.md` for the x402 details. **Base Sepolia testnet only — no mainnet.**
## Verifying receipts independently
The receipts returned by `certify_provenance`, `score_quality`, and `audit_action`
are Ed25519-signed and verifiable **without trusting any of these services** —
re-hash the content/record and check the signature against the service's public
key. Each service ships a runnable independent verifier and recipe: see
[provenance-receipts/docs/VERIFYING.md](https://github.com/Gareth1953/provenance-receipts/blob/main/docs/VERIFYING.md),
[quality-gate/docs/VERIFYING.md](https://github.com/Gareth1953/quality-gate/blob/main/docs/VERIFYING.md),
and agent-action-audit's `docs/VERIFYING.md`.
## Build status
- [x] **Step 1 — skeleton + tool definitions** (`src/tools.ts`)
- [x] **Step 2 — tool handlers (HTTP forwarding) + local smoke test**
- [x] **Step 3 — README: what it is, the tools, and how an MCP client connects**
- [x] **Live — pointed at the deployed services** (`*.gpmiddleton71.workers.dev`)
and verified end-to-end via `scripts/test-live.mjs`: free tools work; paid
tools forward the x402 `402`.
All seven tool paths verified against the live deployments (including one paid
`score_quality` call end-to-end through the wrapper); the paid tools
(`certify_provenance`, `score_quality`, `audit_action`) forward the x402 `402`.
## Stack
- Official MCP SDK: [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcontextprotocol/sdk)
v1.29.0 (TypeScript), stdio transport, [`zod`](https://www.npmjs.com/package/zod)
input schemas.
- Node ESM + TypeScript (`tsc` → `dist/`).
## Project layout
```
agent-services-mcp/
├── src/
│ ├── index.ts # MCP server: registers tools, forwards HTTP, stdio transport
│ └── tools.ts # the 7 tool definitions (names, descriptions, Zod schemas)
├── scripts/
│ ├── test-client.mjs # MCP stdio client — free tool smoke test (local)
│ ├── test-score.mjs # MCP stdio client — one paid score_quality e2e check
│ └── test-live.mjs # MCP stdio client — against the live deployed services
├── package.json
├── tsconfig.json
├── .gitignore
└── .env.example # PROVENANCE_URL, QUALITY_GATE_URL, AUDIT_URL
```