attestive-mcp-example
A thin MCP server wrapper that automatically audits all tool calls via Attestive's AuditClient, logging decisions and enabling verification of the hash chain. It provides an example server with audited tools and demonstrates end-to-end recording and verification through the MCP protocol.
README
attestive-mcp-example
A thin wrapper that hooks Attestive's AuditClient.record()
into an MCP server's tool-call lifecycle — the natural interception point on the
server side of MCP, the same way
attestive-agent-sdk-example's
PostToolUse hook is the natural interception point on the client side. One
line — auditMcpServer(server, auditClient) — and every tool registered on
that server from then on gets its calls recorded automatically, no matter
which MCP host (Claude Desktop, Claude Code, or anything else speaking MCP)
ends up calling it.
Extracted from Attestive's main repo (git subtree split) so it's readable
and runnable on its own. The canonical, currently-maintained version of
AuditClient lives at github.com/magves56/Attestive;
see "Standalone vs. canonical source" below for what that means here.
attestive-audit.ts— the reusable wrapper.withAudit()wraps one tool callback;auditMcpServer()wrapsserver.registerToolso every future registration getswithAudit()applied automatically. This is the file to read if you're integrating this into your own server — everything else here is example scaffolding.demo-server.ts— a real MCP server with two tools a support agent might call (check_order_status, a read-only lookup;issue_refund, an actual decision with a real approve/deny outcome), both audited via one call toauditMcpServer(). Runs on stdio, exactly like any MCP server a real host spawns.run-example.ts— the real thing: spawnsdemo-server.tsas an actual subprocess, connects a real MCPClientoverStdioClientTransport, calls both tools through the real MCP protocol, then exports and verifies the resulting chain with the actual publishedattestive-verifypackage.smoke-test.ts— exerciseswithAudit()directly against fake tool callbacks (both MCP callback shapes, plus a callback that throws), no MCP server or subprocess involved. Useful for iterating on the wrapper itself.attestive-client.ts— a self-contained copy ofAuditClientand the hash-chain/framework-citation logic it depends on, so this repo runs on its own with nothing butnpm install. See its own header comment, and "Standalone vs. canonical source" below.
Steps: npm install → first verified logged decision
npm install
npm run smoke-test # proves the wrapping logic works in isolation
npm run start # the real thing -- spawns a real MCP server, calls real tools, verifies the chain
Neither command needs any credentials — MCP tool-calling doesn't require an
LLM in the loop to demonstrate, unlike the Claude Agent SDK example, which
needs ANTHROPIC_API_KEY or a Claude Code login to run the live agent path.
That's a real difference worth knowing if you're choosing which example to
try first: this one you can fully verify end to end with nothing but Node
installed.
Honest timing
Measured against this repo, standalone, on a clean install:
| Step | Time |
|---|---|
npm install (97 packages, cold) |
~9s |
npm run smoke-test |
instant; proves withAudit() → record() → exportEvidence() → verifyChain(), including a simulated thrown error |
npx tsc --noEmit against the installed SDK's real .d.ts |
clean, no errors |
npm run start — spawn a real subprocess, connect a real MCP Client, call two real tools through the real protocol, export, verify |
~2.4s wall clock, all in |
Total, start to a verified logged decision: under 15 seconds, no external accounts needed.
What "real running MCP server" means here
run-example.ts doesn't mock anything: demo-server.ts is spawned as a
genuine child process (node demo-server.ts, via the SDK's own
StdioClientTransport, which is exactly how Claude Desktop and Claude Code
launch MCP servers), and every tool call crosses a real stdio pipe as real
JSON-RPC messages, dispatched by the real @modelcontextprotocol/sdk
McpServer. The one piece of demo-only plumbing is _export_chain, a third
tool registered before auditMcpServer() runs (so it isn't itself
audited — exporting a chain isn't a decision) purely so run-example.ts has
a way to read back what the subprocess recorded in its own memory, the same
way a real integrator's own tooling would need to reach into wherever they
point ChainStore.
Coverage and limits, stated plainly
- Only the current, recommended
registerTool()API is wrapped byauditMcpServer(). The deprecated.tool()overloads are not intercepted automatically — migrate toregisterTool()first (the MCP SDK already recommends this regardless of auditing), or callwithAudit()directly around a.tool()callback if you can't migrate yet:server.tool("name", schema, withAudit("name", auditClient, handler)). - The default
agentIdis the MCP transport'ssessionIdif one is available (Streamable HTTP provides this), falling back to"mcp-server"otherwise. Stdio transports are typically one server process per session already, so one chain per process is a reasonable default there — but for a multi-tenant server wheresessionIdalone isn't the right audit boundary, passagentId: (extra) => yourOwnId(extra)toauditMcpServer(). - The default
decisionTypeis"automated_decision"— the same value the Claude Agent SDK example uses, whichsuggestControlsForDecisionType()maps to human-oversight and record-keeping citations. PassdecisionTypetoauditMcpServer()(or per-tool towithAudit()) if a more specific type fits your tools better. - An audit-logging failure (the backing
ChainStorethrows) is caught and logged to stderr, never allowed to change what the MCP client actually receives back from the tool call — verified insmoke-test.ts's thrown-error case.
Standalone vs. canonical source
attestive-client.ts in this repo is a deliberate copy of AuditClient, not
an import of it — AuditClient isn't published as an installable package
yet (unlike attestive-verify, which this example genuinely depends on via
npm install), and the monorepo paths it lives at only resolve inside that
monorepo's own layout. If you're evaluating Attestive, treat
github.com/magves56/Attestive's
src/client.ts as the source of truth; this copy exists purely so this repo
runs on its own. The monorepo guards the two from silently drifting apart
with a cross-check test that isn't (and can't be) included here — see
attestive-client.ts's own header comment.
Swapping in the real backend
This example uses InMemoryChainStore — the point is proving the MCP
integration works, not standing up a database. For a real deployment, swap
in a persistent ChainStore implementation (see attestive-client.ts's
ChainStore interface, and src/store/supabase-chain-store.ts in the main
Attestive repo for how the hosted product backs it with Postgres), and pass
a real organizationId/apiKey to AuditClient instead of the
"local-demo" placeholder used here.
License
MIT — see LICENSE.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。