# AHTML

> Write your page once — AHTML emits MCP, OpenAPI, JSON-LD & llms.txt for AI agents from your existing Next.js, Vite or SvelteKit app. Zero migration. MIT.

- **Type:** MCP server
- **Install:** `agentstack add mcp-dibbayajyotiroy-ahtml`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [DibbayajyotiRoy](https://agentstack.voostack.com/s/dibbayajyotiroy)
- **Installs:** 0
- **Category:** [Developer Tools](https://agentstack.voostack.com/c/developer-tools)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [DibbayajyotiRoy](https://github.com/DibbayajyotiRoy)
- **Source:** https://github.com/DibbayajyotiRoy/AHTML
- **Website:** https://ahtmljs.vercel.app

## Install

```sh
agentstack add mcp-dibbayajyotiroy-ahtml
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# AHTML

> The contract layer of the agent web. One config in, every agent-readable
> protocol out — MCP, OpenAPI 3.1, JSON-LD, llms.txt, RSL, Markdown, and a
> token-optimal snapshot — plus signed provenance, verified-agent auth, and
> priced actions.

[](https://www.npmjs.com/package/@ahtmljs/next)
[](https://www.npmjs.com/package/@ahtmljs/schema)
[](https://www.npmjs.com/package/@ahtmljs/cli)
[](LICENSE)
[](https://modelcontextprotocol.io)
[](https://spec.openapis.org/oas/v3.1.0)
[](https://json-schema.org/draft/2020-12)
[](https://docs.npmjs.com/generating-provenance-statements)
[](TESTING.md)

```bash
npm install @ahtmljs/next @ahtmljs/schema
```

```ts
// app/ahtml/[[...path]]/route.ts
import { createAHTMLRoute } from '@ahtmljs/next/handler';
import { snapshot } from '@ahtmljs/schema';

export const { GET, HEAD } = createAHTMLRoute(async (segments, req) => {
  if (segments[0] !== 'products') return null;
  const p = await db.product.findUnique({ where: { slug: segments[1] } });
  return snapshot(req.url, 'product_detail')
    .ttl(60)
    .add({ id: `product:${p.slug}`, type: 'product', name: p.name,
           price: { amount: p.price, currency: 'USD' },
           stock: { status: p.qty > 0 ? 'in_stock' : 'out_of_stock' } })
    .action({ id: 'purchase', target: `product:${p.slug}`, category: 'transact',
              execute_url: '/api/checkout', auth: 'required',
              cost: { amount: p.price, currency: 'USD', category: 'purchase',
                      rails: ['x402'] },       // priced action (v0.9.5)
              reversible: { reversible: true, window: 'P30D' },
              side_effects: ['charge_card', 'decrement_stock'],
              confirmation: 'required' })
    .build();
});
```

Your Next.js app now serves MCP tools at `/ahtml/mcp.json`, OpenAPI at
`/ahtml/openapi.json`, JSON-LD inline in HTML, a discovery manifest at
`/.well-known/ahtml.json`, an llms.txt shim, RSL at `/rsl.txt`, a Markdown
view over content negotiation, and a token-optimal agent snapshot at
`/ahtml/` — all from the same source.

---

## What is AHTML

The web that browsers see and the web that agents see are diverging. Browsers
render pixels. Agents pay for tokens. A modern product page can ship 300 KB of
nav, footer, tracking, and ad chrome — and an autonomous shopping agent pays
for every byte. AHTML lets your site publish a **typed semantic snapshot**
alongside its HTML: entities with stable IDs, actions with explicit cost /
reversibility / auth / side-effects, freshness metadata, site-wide policy,
cryptographic provenance via detached JWS (v0.8), and — as of v0.9.5 —
**verified-agent authentication** (RFC 9421 signed requests) and **priced
actions** (x402 machine payments + RSL 1.0 licensing).

The plugin auto-generates **MCP tool manifests**, **OpenAPI 3.1 documents**,
**JSON-LD fragments**, the **llms.txt** discovery convention, an **RSL 1.0**
license file, and a **Markdown** view — all from the same source. Browsers see
the same HTML. AHTML is additive — there is no migration.

And the whole toolchain works on **any URL today**, not just adopters: the
`@ahtmljs/cli` and `@ahtmljs/agent` extract typed objects from ordinary HTML
(schema.org + OpenGraph + microdata + data-attrs) when a site hasn't adopted
AHTML yet.

---

## The nine packages

Nine npm packages under the `@ahtmljs` scope, all published at the same version
and released together. Grouped by what you're building:

**Contract layer**

| Package | What it is | Install when |
|---|---|---|
| [`@ahtmljs/schema`](packages/schema) | Snapshot types, validator, dual-format serializers (canonical JSON + token-optimal compact), Markdown + RSL emitters, diff, builder, JSON Schema, HTTP Message Signatures, x402 helpers, policy presets. Pure ESM + CJS, edge-runtime safe. Houses the emitters for well-known, MCP, OpenAPI, and llms.txt (re-exported by adapters). | You want the contract without a framework adapter — Express, Bun, Deno, Workers, or hand-rolled routes. |

**Make your site agent-readable (site adapters)**

| Package | What it is | Install when |
|---|---|---|
| [`@ahtmljs/next`](packages/next) | Next.js 14+/15 App Router plugin. `createAHTMLRoute`, `createWellKnownRoute`, `createLlmsTxtRoute`, MCP + OpenAPI emitters, JSON-LD injector, policy block, `verifyAgents` config, `withPaymentGuard`. | You ship a Next.js app and want it to *be* an MCP server. |
| [`@ahtmljs/vite`](packages/vite) | Vite plugin. Wires the same handler into SvelteKit, SolidStart, Astro, and vanilla Vite. Byte-identical output to the Next adapter. | You ship a Vite-based app and want the same emitters. |
| [`@ahtmljs/hono`](packages/hono) | Hono adapter — one `mountAHTML(app, config)` call. Runs on Node, Bun, Deno, Cloudflare Workers, and AWS Lambda. Edge-first, no `node:*` in the hot path. | You ship a Hono app or want the same surface on the edge / Workers. |

**Read the agent web (agent-side)**

| Package | What it is | Install when |
|---|---|---|
| [`@ahtmljs/agent`](packages/agent) | Client SDK: typed-error fetcher, ETag-conditional GET, diff replay, request coalescing, retry with jittered backoff, timeout, dry-run, real `gpt-tokenizer` + `@anthropic-ai/tokenizer` cost estimation, streaming reader, `fetchPage()` universal read with HTML fallback, agent request signing. | You are building an AI agent that reads other people's sites. |
| [`@ahtmljs/langchain`](packages/langchain) | LangChain.js document loader. Fetches any AHTML-emitting site and yields `Document`s with chunk boundaries, citation anchors, and metadata preserved. | You are building a RAG pipeline and want to **cite a web page in a RAG answer** without re-scraping HTML. |

**Tooling & infrastructure**

| Package | What it is | Install when |
|---|---|---|
| [`@ahtmljs/cli`](packages/cli) | The AHTML CLI — `analyze`, `score`, `doctor`, `extract`, `benchmark`, `mcp` (stdio MCP proxy), `llms` (site→llms.txt crawler). Works on **any URL**, adopter or not. | You want to audit, score, or turn any site into MCP tools from your terminal or agent. |
| [`@ahtmljs/kv`](packages/kv) | Pluggable KV / cache / rate-limit backends: in-memory, Upstash Redis, Cloudflare KV. Backend-agnostic token-bucket `RateLimiter`. | You need caching or per-agent rate limiting at the edge. |
| [`@ahtmljs/webmcp`](packages/webmcp) | Registers AHTML page actions as native [WebMCP](https://github.com/WICG/webmcp) browser tools (Chrome 149+ origin trial), with AHTML's richer cost/reversibility/confirmation metadata as annotations. Plus a zero-install bookmarklet inspector. | You want browser-embedded AI assistants to call your page's actions safely. |

Common install combos:

```bash
# site owner — make your site agent-readable (Next.js)
npm install @ahtmljs/next @ahtmljs/schema

# same, on the edge / Cloudflare Workers
npm install @ahtmljs/hono @ahtmljs/schema hono

# agent author — read the agent web (with HTML fallback for non-adopters)
npm install @ahtmljs/agent @ahtmljs/schema

# audit / score / proxy any URL — no install
npx @ahtmljs/cli analyze https://example.com
```

---

## Works on any URL today — the CLI

You don't need a site to adopt AHTML to get value. `@ahtmljs/cli` extracts
typed objects from ordinary HTML and turns **any** site into MCP tools:

```bash
npx @ahtmljs/cli analyze  https://example.com   # bytes → tokens → savings %, entity counts, agent-readiness probe
npx @ahtmljs/cli score    https://example.com   # Lighthouse-for-agents: 0–100 score, A–F grade, copy-paste fix
npx @ahtmljs/cli doctor   https://example.com   # audit the AHTML discovery chain + verify signatures
npx @ahtmljs/cli extract  https://example.com   # schema.org + OpenGraph + microdata + data-attrs → snapshot
npx @ahtmljs/cli benchmark https://example.com  # HTML vs JSON-LD vs AHTML compact vs AHTML JSON table
npx @ahtmljs/cli mcp      https://example.com   # stdio MCP proxy — any URL becomes typed MCP tools in Claude/Cursor
npx @ahtmljs/cli llms     https://example.com   # crawl a site → spec-compliant llms.txt
```

`ahtml mcp ` is `claude mcp add`-compatible: it probes
`/.well-known/ahtml.json` and proxies to the real endpoint for adopters, and
auto-extracts from plain HTML for everyone else. Four universal MCP tools —
`fetch_page`, `list_pages`, `search`, and `invoke_action` (adopters).

---

## One config, every protocol

A single `buildSnapshot` function feeds every output below. No parallel
implementations.

| Output | Endpoint | Format | Consumer |
|---|---|---|---|
| Compact snapshot | `/ahtml/` | `application/ahtml+text` | LLM agents (Claude, GPT, Gemini) — default |
| Canonical JSON | `/ahtml/?fmt=json` | `application/ahtml+json` | Programmatic clients, signing |
| Markdown view | `/ahtml/` + `Accept: text/markdown` | `text/markdown` | curl / LLM clients (v0.9.4) |
| Streaming snapshot | `/ahtml/?stream=1` | `application/ahtml+json-seq` (NDJSON) | Long pages, progressive ingestion |
| Incremental diff | `/ahtml/?since=` | `application/ahtml-diff+json` | Crawlers, cache layers |
| MCP manifest | `/ahtml/mcp.json` | MCP 2025-11-25 | Cursor, ChatGPT, Claude Desktop, Copilot |
| OpenAPI spec | `/ahtml/openapi.json` | OpenAPI 3.1 + `x-ahtml-*` | REST clients, codegen, agent runtimes |
| Discovery manifest | `/.well-known/ahtml.json` | JSON | Any AHTML-aware agent |
| llms.txt shim | `/llms.txt` | Markdown (+ Content Signals front-matter) | IDE agents (Cursor, Continue, Cline) |
| RSL license | `/rsl.txt` (via `toRsl`) | RSL 1.0 | AI-licensing crawlers (v0.9.5) |
| JSON-LD | inline in HTML | `application/ld+json` | Search engines + schema.org consumers |
| Signed snapshot (v0.8) | header `AHTML-Signature` | Detached JWS over canonical JSON | Trust-sensitive agents |
| Payment required (v0.9.5) | action `execute_url` | `402` + `x-payment-required` (x402/0.2) | Paying agents |

Every wire format is content-negotiated. All of them come from the same
TypeScript object.

---

## Why this exists — concrete numbers, not adjectives

| Concern | Today | With AHTML |
|---|---|---|
| Token cost on a typical product page | 4,269 tokens of HTML | 581 tokens compact (7.3× fewer) |
| Production-bloat Shopify page | 200–500 KB of HTML | ~2 KB snapshot (50–100×) |
| Answer accuracy on 20 fact-extraction questions (real LLM calls) | 91% on HTML | **100% on AHTML JSON** |
| MCP server | Separate process, parallel auth, parallel deploy | Your existing site emits MCP at `/ahtml/mcp.json` |
| schema.org JSON-LD | Describes *what* something is | Plus typed `cost`, `reversible`, `side_effects`, `confirmation` |
| llms.txt | Unstructured markdown — agents still guess | Auto-emitted as shim, plus typed action surface |
| Crawler bandwidth | Full re-fetch every poll | ETag-conditional GET + `?since=` diff endpoint |
| Trust | "I scraped this 12 hours ago, was it tampered with?" | Detached JWS over canonical JSON (v0.8) |
| Agent identity | Any bot can claim to be anyone | RFC 9421 signed requests → `X-AHTML-Agent-Verified` (v0.9.5) |
| Priced actions | Agent can't tell what an action costs or how to pay | Typed `cost.rails: ['x402']` + standards-compliant `402` flow (v0.9.5) |
| Content licensing | Scrapers ignore terms | RSL 1.0 file + Content Signals declarations (v0.9.5) |

The token-only benchmark was measured with the same tokenizers OpenAI and
Anthropic use internally (`gpt-tokenizer`, `@anthropic-ai/tokenizer`) — no
`text.length / 4` guessing. The accuracy benchmark issues real API calls
across `gpt-4o-mini`, `claude-haiku-4.5`, `gemini-2.5-flash`, and
`llama-3.3-70b`. See [`benchmark-results-llm.md`](benchmark-results-llm.md)
and [`examples/llm-benchmark/`](examples/llm-benchmark/) to reproduce
(~$0.10–0.50 in API spend), or run `npx @ahtmljs/cli benchmark ` for a
one-command table on any live page.

For the head-to-head "why AHTML wins" story — token savings **plus** capability
proofs *executed live* (MCP tools emitted, a snapshot signed and verified, an
x402 `402` built, an RFC 9421 agent request verified) — see
[**`WHY-AHTML.md`**](WHY-AHTML.md), regenerated by
[`examples/why-ahtml/`](examples/why-ahtml/) (`npm run benchmark:why`).

---

## Comparison

### vs Firecrawl / ScrapingBee / Jina Reader / r.jina.ai / Spider / Browserbase / Diffbot / Cloudflare auto-markdown

These convert *somebody else's* HTML into LLM-friendly markdown by scraping
it (Cloudflare now does it at the CDN with `Accept: text/markdown`). They are
good tools. AHTML solves the inverse problem: **let the site publish the
agent-readable view itself**, with typed actions, ETag, a signature, and a
price. If you are the site owner, you should not need a third party to scrape
your own pages — and AHTML *also* serves `text/markdown` when a client asks
for it, so it's a superset, not a competitor.

### vs Anthropic MCP SDK / OpenAI MCP SDK / FastMCP / mcp-framework / Smithery

These help you build an MCP server **from scratch**, as a separate process,
with its own auth and deploy story. AHTML makes your **existing Next.js, Vite,
or Hono app** emit MCP — same database, same auth, one deploy. The MCP tool
manifest is generated from the same snapshot that already powers your
agent-facing endpoint. And `ahtml mcp ` turns *any* site — adopter or
not — into MCP tools for your Claude/Cursor session today.

### vs schema.org JSON-LD / llms.txt

| Capability | HTML | llms.txt | schema.org | **AHTML** |
|---|:---:|:---:|:---:|:---:|
| Typed entities | implicit | text only | yes | yes |
| Typed actions | implicit | text only | no | yes |
| Cost / reversibility | no | no | no | yes |
| Side-effect declarations | no | no | no | yes |
| Confirmation requirements | no | no | no | yes |
| Freshness / TTL | no | no | no | yes |
| Conditional fetch (ETag) | partial | no | no | yes |
| Streaming | no | no | no | yes |
| MCP-emittable | no | no | no | yes |
| OpenAPI-emittable | no | no | no | yes |
| Cryptographically signed | no | no | no | yes (v0.8) |
| Verified-agent auth | no | no | no | yes (v0.9.5) |
| Priced actions (x402) | no | no | no | yes (v0.9.5) |

AHTML **ingests** schema.org for a free Level-0 snapshot on most
Shopify/WordPress sites, **emits** llms.txt as a compatibility shim, and
**adds** the typed action surface that both lack.

### vs LangChain CheerioWebBaseLoader / Mozilla Readability / trafilatura / Unstructured.io

Those are HTML cleaners — they strip chrome and return text. AHTML returns
a **structured object** with stable IDs, typed actions, and freshness — so
the LLM does not have to guess what the page is about. The
[`@ahtmljs/langchain`](packages/langchain) loader is a drop-in replacement
for `CheerioWebBaseLoader` when the upstream site emits AHTML.

A longer comparison — including WebMCP, NLWeb, RSL, x402, and Content
Signals — is in [`docs/compare.md`](docs/compare.md).

---

## Install in 3 minutes (Next.js App Router)

**1. Install.**

```bash
npm install @ahtmljs/next @ahtmljs/schema
```

**2. Declare snapshots.**

```ts
// lib/ahtml.ts
import { snapshot } from '@ahtmljs/schema';

export async function buildSnapshot(segments: string[], req: Request) {
  if (segments[0] === 'products' && segments[1]) {
    const p = await db.product.findUnique({ where: { slug: segments[1] } });
    if (!p) return null;
    return snapshot(req.url, 'product_detail')
      .ttl(60)
      .add({
        id: `product:${p.slug}`,
        type: 'product',
        name: p.name,
        price: { amount: p.price, currency: p.currency },
        stock: { status: p.qty > 0 ? 'in_stock' : 'out_of_stock', quantity: p.qty },
      })
      .action({
        id: 'purchase',
        target: `product:${p.slug}`,
        category: 'transact',
        execute_url: '/api/checkout',
        auth: 'required',
        cost: { amount: p.price, currency: p.currency, category: 'purchase' },
        reversible: { reversible: true, window: 'P30D', policy: 'full_refund' },
        side_effects: ['charge_card', 'email_buyer', 'decrement_stock'],
        confirmation: 'required',
      })
      .build();
  }
  ret

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [DibbayajyotiRoy](https://github.com/DibbayajyotiRoy)
- **Source:** [DibbayajyotiRoy/AHTML](https://github.com/DibbayajyotiRoy/AHTML)
- **License:** MIT
- **Homepage:** https://ahtmljs.vercel.app

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-dibbayajyotiroy-ahtml
- Seller: https://agentstack.voostack.com/s/dibbayajyotiroy
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
