H33 attestation layer for Model Context Protocol servers. Wraps any MCP server so that every tool call, resource read, and prompt completion produces a cryptographic receipt — post-quantum signed, DAG-chained, and independently verifiable.
Every tool call attested. Every response verifiable. Zero code changes to your existing MCP handlers.
Wraps an existing MCP Server with automatic attestation. Zero code changes to existing handlers.
Access the underlying H33Agent instance for advanced operations such as verification, policy checks, and replay.
Create an individual tool definition with built-in attestation when you need per-tool control.
Express/Hono middleware that adds X-H33-Receipt headers to every HTTP response.
The package also re-exports H33Agent and H33AgentConfig from @h33/agent for convenience.
Three lines transform a standard MCP server into one where every tool call produces a cryptographic receipt:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { attestMCPServer } from '@h33/mcp';
const server = new Server(
{ name: 'my-server', version: '1.0.0' },
{ capabilities: { tools: {} } },
);
// One line -- every tool call is now attested
const attested = attestMCPServer(server, {
agent: {
name: 'My MCP Server',
canonicalName: 'h33.agent.acme.mcp.myserver.prod.001',
tenantId: 'acme-corp',
},
});
// Register tools as normal -- attestation is automatic
attested.setRequestHandler('tools/call', async (request) => {
const result = await handleToolCall(request);
return result; // _h33_receipt automatically attached
});Set your API key via environment variable. Never hardcode credentials:
export H33_API_KEY="your-key-here"The primary integration point. Wraps an MCP Server instance by intercepting setRequestHandler calls. The returned object is the same server instance — existing code continues to work unchanged. Attestation is applied automatically based on configuration flags.
| Field | Type | Default | Description |
|---|---|---|---|
agent | H33AgentConfig | required | Agent identity and configuration (name, canonicalName, tenantId). |
attestTools | boolean | true | Attest tools/call requests. |
attestResources | boolean | true | Attest resources/read requests. |
attestPrompts | boolean | false | Attest prompts/get requests. Opt-in because prompt responses may be large. |
| MCP Method | Attested by Default | Attestation Type |
|---|---|---|
tools/call | Yes | Tool call (input hash + output hash) |
resources/read | Yes | Action (resource URI hash + response hash) |
prompts/get | No (opt-in) | Action (prompt name hash + response hash) |
When you need per-tool attestation control rather than wrapping the entire server, create individual attested tools. Each invocation hashes the input, executes the handler, hashes the output, and produces a receipt through the provided H33Agent.
import { H33Agent } from '@h33/agent';
import { createAttestedTool } from '@h33/mcp';
const agent = new H33Agent({
name: 'Claims Agent',
canonicalName: 'h33.agent.acme.claims.review.prod.001',
tenantId: 'acme-corp',
});
await agent.start();
const searchTool = createAttestedTool(agent, {
name: 'search_database',
description: 'Search the claims database',
inputSchema: {
type: 'object',
properties: { query: { type: 'string' } },
required: ['query'],
},
handler: async (args) => await db.search(args.query),
});
// Every call returns both the result and a receipt
const { result, receipt } = await searchTool.handler({ query: 'open claims' });
console.log(receipt.verification_url);The tool name is automatically namespaced as h33.tool.mcp.<name>.v1 in the attestation chain.
HTTP middleware that attests every request/response pair. Compatible with Express, Hono, or any framework using the (req, res, next) pattern. Receipt ID and verification URL are set as response headers automatically.
import express from 'express';
import { H33Agent } from '@h33/agent';
import { h33Middleware } from '@h33/mcp';
const agent = new H33Agent({
name: 'API Gateway',
canonicalName: 'h33.agent.acme.gateway.prod.001',
tenantId: 'acme-corp',
});
await agent.start();
const app = express();
app.use('/tools', h33Middleware(agent));
app.post('/tools/search', async (req, res) => {
const results = await db.search(req.body.query);
res.json(results);
// X-H33-Receipt and X-H33-Verify headers set automatically
});import { Hono } from 'hono';
import { H33Agent } from '@h33/agent';
import { h33Middleware } from '@h33/mcp';
const agent = new H33Agent({ /* ... */ });
await agent.start();
const app = new Hono();
app.use('/tools/*', h33Middleware(agent));Retrieves the underlying H33Agent instance from a wrapped server. Returns null if the server has not been wrapped with attestMCPServer. Use this for advanced operations: verifying receipts, checking delegation policy, or replaying sessions.
const agent = getAgent(attested);
if (agent) {
const proof = await agent.verify(receipt);
console.log(proof.valid); // true
}When an MCP client invokes a tool on a wrapped server, the following sequence executes transparently:
The attestation layer never modifies the handler's return value. Receipts are attached as a non-intrusive _h33_receipt property on the result object. If attestation fails for any reason, the original result is returned unmodified — attestation failure never breaks the response.
Receipts are attached to tool call results as a _h33_receipt property. For HTTP middleware, they appear as response headers instead.
{
"content": [{ "type": "text", "text": "..." }],
"_h33_receipt": {
"receipt_id": "abc123...",
"node_hash": "def456...",
"verification_url": "https://api.h33.ai/api/v1/agents/proofs/abc123",
"replay_ref": "..."
}
}When using h33Middleware, attestation data is returned via HTTP response headers rather than in the response body:
| Field | Type | Description |
|---|---|---|
receipt_id | string | Unique identifier for this attestation node. |
node_hash | string | SHA-256 hash chaining this node to its parent in the session DAG. |
verification_url | string | Public URL for independent verification (no API key needed). |
replay_ref | string | Reference for deterministic session replay. |
Every receipt is independently verifiable. Verification requires no API key and can be performed by any party.
GET https://api.h33.ai/api/v1/agents/proofs/{receipt_id}$ hats verify --node {receipt_id}const agent = getAgent(attested);
const proof = await agent.verify(receipt);
console.log(proof.valid); // true
console.log(proof.chain_intact); // trueA complete MCP server with two attested tools, running on stdio transport:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { attestMCPServer } from '@h33/mcp';
const server = new Server(
{ name: 'example-attested-server', version: '1.0.0' },
{ capabilities: { tools: {} } },
);
const attested = attestMCPServer(server, {
agent: {
name: 'Example MCP Server',
canonicalName: 'h33.agent.example.mcp.server.dev.001',
tenantId: 'example-org',
},
});
attested.setRequestHandler('tools/list', async () => ({
tools: [
{
name: 'lookup_claim',
description: 'Look up an insurance claim by ID',
inputSchema: {
type: 'object',
properties: { claim_id: { type: 'string' } },
required: ['claim_id'],
},
},
],
}));
attested.setRequestHandler('tools/call', async (request) => {
const { name, arguments: args } = request.params;
if (name === 'lookup_claim') {
const claim = { id: args.claim_id, status: 'open', amount: 15000 };
return { content: [{ type: 'text', text: JSON.stringify(claim) }] };
}
throw new Error(`Unknown tool: ${name}`);
// _h33_receipt attached automatically to the result
});
const transport = new StdioServerTransport();
await attested.connect(transport);