# @h33/mcp

H33 attestation layer for MCP servers. Every tool call attested, every response verifiable.

Wraps any [Model Context Protocol](https://modelcontextprotocol.io) server so that every tool call, resource read, and optionally prompt completion produces a cryptographic receipt -- post-quantum signed, DAG-chained, and independently verifiable.

## Installation

```bash
npm install @h33/mcp @h33/agent @modelcontextprotocol/sdk
```

Set your API key:

```bash
export H33_API_KEY="your-key-here"
```

## Quick Start

Three lines to attest every tool call:

```typescript
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
attested.setRequestHandler('tools/call', async (request) => {
  const result = await handleToolCall(request);
  return result; // _h33_receipt automatically attached
});
```

## API Reference

### `attestMCPServer(server, config)`

Wraps an MCP Server with automatic attestation. Returns the same server instance with intercepted handlers.

**Config:**

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `agent` | `H33AgentConfig` | required | Agent identity and configuration |
| `attestTools` | `boolean` | `true` | Attest `tools/call` requests |
| `attestResources` | `boolean` | `true` | Attest `resources/read` requests |
| `attestPrompts` | `boolean` | `false` | Attest `prompts/get` requests |

### `getAgent(server)`

Retrieve the underlying `H33Agent` from a wrapped server for advanced operations (policy checks, delegation, replay).

```typescript
const agent = getAgent(attested);
if (agent) {
  const proof = await agent.verify(receipt);
}
```

### `createAttestedTool(agent, def)`

Create an individual attested tool when you want per-tool control instead of wrapping the entire server.

```typescript
import { H33Agent } from '@h33/agent';
import { createAttestedTool } from '@h33/mcp';

const agent = new H33Agent({ /* ... */ });
await agent.start();

const tool = createAttestedTool(agent, {
  name: 'search_database',
  description: 'Search the claims database',
  inputSchema: { type: 'object', properties: { query: { type: 'string' } } },
  handler: async (args) => await db.search(args.query),
});

const { result, receipt } = await tool.handler({ query: 'open claims' });
```

### `h33Middleware(agent)`

Express/Hono-compatible middleware that attests every HTTP request/response pair. Receipt ID and verification URL are set as response headers.

```typescript
import express from 'express';
import { H33Agent } from '@h33/agent';
import { h33Middleware } from '@h33/mcp';

const agent = new H33Agent({ /* ... */ });
await agent.start();

const app = express();
app.use('/tools', h33Middleware(agent));
// X-H33-Receipt and X-H33-Verify headers on every response
```

## How Verification Works

Every attested action produces a receipt containing:

- **receipt_id** -- unique identifier for this attestation node
- **node_hash** -- SHA-256 hash chaining this node to its parent in the session DAG
- **verification_url** -- public URL for independent verification
- **replay_ref** -- reference for deterministic session replay

Verify any receipt publicly (no API key needed):

```
GET https://api.h33.ai/api/v1/agents/proofs/{receipt_id}
```

Or via CLI:

```bash
hats verify --node {receipt_id}
```

## Receipt Attachment

Receipts are attached non-intrusively to tool call results as `_h33_receipt`:

```json
{
  "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": "..."
  }
}
```

For HTTP middleware, receipts appear as response headers instead.

## What Gets Attested

| 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) |

## Architecture

```
MCP Client --> Attested Server --> Your Handler
                    |
                    +--> H33Agent.callTool()
                    |        |
                    |        +--> SHA-256 hash input
                    |        +--> SHA-256 hash output
                    |        +--> PQ-sign + DAG-chain
                    |        +--> Return receipt
                    |
                    +--> Attach _h33_receipt to result
```

## License

MIT
