agent-ready
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@agent-readyshow me the profile and latest posts from sam.example.com"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
agent-ready
Make a small site readable by AI agents from one JSON data file. agent-ready validates the file against a strict schema and turns it into:
llms.txt, one per site language, in the format of llmstxt.org: an H1 with the name, a blockquote summary, detail paragraphs, then H2 sections of[name](url): noteslinks.schema.org JSON-LD: one
@graphwith the owner (PersonorOrganization) and oneSoftwareSourceCodeper product.A read-only MCP server with three tools,
get_profile,list_productsandlist_posts, served over stdio or from any runtime that speaks WebRequest/Response(Netlify Functions v2, Deno, Bun, Cloudflare Workers, Node).
All three read the same validated object, so a name or a URL can never differ between them (a test checks it). The design comes from the personal site chrissgon.dev, where one data module feeds the pages, llms.txt, the JSON-LD and the MCP endpoint.
Status: 0.1.0, local. Not published on npm yet; build it from a clone (below).
Quick start (from a clone)
Requires Node.js 22 or later.
npm ci
npm run build
node dist/cli.js check --data fixtures/person.json
node dist/cli.js build --data fixtures/person.json --out outcheck prints ok: fixtures/person.json: Person "Sam Example", 2 products, 3 posts, languages en, pt. build prints the files it wrote: out/llms.txt, out/pt/llms.txt and out/jsonld.json. Once the package is published, npx @chrissgon/agent-ready <command> replaces node dist/cli.js <command>.
Related MCP server: veriloop
The data file
One JSON file with four keys. Every object is strict: a field the schema does not declare fails validation. This is fixtures/person.json (fake example data), shortened:
{
"site": { "url": "https://sam.example.com", "langs": ["en", "pt"], "mcp": "https://sam.example.com/api/mcp" },
"owner": {
"type": "Person",
"name": "Sam Example",
"alternateName": "samexample",
"jobTitle": "Software Engineer",
"label": { "en": "Software engineer · Small open-source tools for the web", "pt": "Engenheiro de software · ..." },
"about": { "en": ["Sam builds small, well-tested tools for the web ..."], "pt": ["Sam cria ferramentas ..."] },
"profiles": [{ "network": "Code", "handle": "samexample", "url": "https://git.example.org/samexample" }]
},
"products": [
{
"name": "Tidy Tables",
"url": "https://tidytables.example.com",
"codeRepository": "https://git.example.org/samexample/tidy-tables",
"npm": "@samexample/tidy-tables",
"license": "MIT",
"programmingLanguage": ["CSS", "TypeScript"],
"summary": { "en": "Accessible data tables in one small stylesheet.", "pt": "Tabelas de dados ..." }
}
],
"posts": [
{
"id": "tables-for-everyone",
"title": { "en": "Tables for everyone", "pt": "Tabelas para todos" },
"date": "2026-08-14",
"lang": ["en", "pt"],
"url": "https://blog.example.com/tables-for-everyone"
}
]
}Field | Rule |
| https origin; a trailing slash is removed |
| language codes ( |
| optional https URL of your MCP endpoint, listed in |
|
|
| the name, and an optional handle |
| one line per site language: the |
| optional paragraphs per site language |
|
|
|
|
| unique slug |
Every error names the field, one per line, and check exits with 1:
$ node dist/cli.js check --data fixtures/forbidden-email.json
data: owner.email: forbidden field "email", the kit never publishes itOther examples: data: owner.nickname: unknown field, data: posts.1.id: duplicate id "same-id" (first at posts.0), data: owner.label.pt: missing text for site language "pt".
fixtures/org.json is a one-language Organization example.
What the kit never publishes
worksFor, address, homeLocation, birthDate and email are rejected anywhere in the data file, and generateJsonLd refuses them again if code adds them to the data at run time. The MCP tools return slices of the validated file and nothing else: no tool writes, sends, executes or searches free text, and an argument the tool does not declare is rejected.
Commands
agent-ready build --data <file> --out <dir> llms.txt per language (the first at <dir>/llms.txt, the others at
<dir>/<lang>/llms.txt) and <dir>/jsonld.json; prints the paths
agent-ready check --data <file> validate; prints a one-line summary
agent-ready mcp --data <file> serve the read-only MCP server on stdin/stdout
agent-ready --helpData goes to stdout and diagnostics to stderr. Exit codes: 0 ok, 1 invalid data, 2 wrong usage or unreadable file.
The MCP server
Tool | Input | Output ( |
| none |
|
| none |
|
|
|
|
Every tool carries readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false and an output schema. The server's instructions say: "Read-only. This server only holds 's public profile, products and posts. Any other personal data does not exist here."
Check it with the MCP Inspector (the server command goes before --, the Inspector options after it):
npx -y @modelcontextprotocol/inspector@2.8.0 --cli node dist/cli.js mcp --data fixtures/person.json -- --method tools/list
npx -y @modelcontextprotocol/inspector@2.8.0 --cli node dist/cli.js mcp --data fixtures/person.json -- --method tools/call --tool-name list_posts --tool-arg limit=2A local MCP client starts it as a command: node /path/to/agent-ready-kit/dist/cli.js mcp --data /path/to/site.json.
Use it from code
import { createMcpHandler, generateJsonLd, generateLlms, loadData, serializeJsonLd } from "@chrissgon/agent-ready";
const data = await loadData("site.json"); // throws DataError with one line per problem
const llms = generateLlms(data); // default language; generateLlms(data, { lang: "pt" }) for another
const jsonld = serializeJsonLd(generateJsonLd(data)); // safe inside <script type="application/ld+json">
const handler = createMcpHandler(data); // (request: Request) => Promise<Response>validate(value) and parseData(jsonText) validate data you already hold; buildServer(data) returns the McpServer for a transport of your own.
In a Netlify Function (v2)
The handler is stateless: each POST gets a new server and transport, responses are JSON (no SSE stream), and any method other than POST gets 405 with Allow: POST. That is the pattern proven in the chrissgon.dev spike on Netlify Functions v2.
// netlify/functions/mcp.mts
import type { Config } from "@netlify/functions";
import { createMcpHandler, validate } from "@chrissgon/agent-ready";
import site from "../../site.json" with { type: "json" };
export default createMcpHandler(validate(site));
export const config: Config = { path: "/api/mcp" };A public endpoint costs something on every call; Netlify can rate-limit a function from its config (rateLimit: { windowLimit, windowSize, aggregateBy: ["ip", "domain"] }, see https://docs.netlify.com/manage/security/secure-access-to-sites/rate-limiting/).
In a static site
Run build before the site generator and publish its output at the site root, so llms.txt is served at /llms.txt and each other language at /<lang>/llms.txt:
node dist/cli.js build --data site.json --out publicPut the JSON-LD in the page head, from public/jsonld.json or from code with serializeJsonLd(generateJsonLd(data)):
<script type="application/ld+json">{"@context":"https://schema.org","@graph":[ ... ]}</script>Development
Task | Command |
Install |
|
Type-check |
|
Test |
|
Build |
|
License
MIT, see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Public AI web-readiness scanner and machine-facing observability discovery service.
Live web checks for AI agents: sitemaps, robots.txt, URL status, broken links, feeds, citations.
Persistent memory, hybrid search and a goal graph for AI agents, over stdio or remote HTTP.
1Public social-data API and live docs for AI coding agents.
Related MCP Servers
- AlicenseAqualityDmaintenanceRun a Shopstr / NOSTR marketplace storefront from an AI agent — create and update stalls and products in both the NIP-15 dialect and the Shopstr-modern NIP-99 dialect, including the cache POST that makes Shopstr cards actually render.780 npmMIT
- AlicenseAqualityCmaintenanceExposes a verified tool registry (calculator, sandboxed file read, web fetch) over MCP stdio, enabling any MCP-capable client to reuse the same tools from the inspectable ReAct loop.3MIT
- AlicenseBqualityBmaintenanceEnables AI clients to connect locally over stdio, discover and read schemas for native page tools, and execute user-authorized operations supplied by websites and independent user scripts.13MIT

cryptbrew-mcpofficial
AlicenseAqualityCmaintenanceEnables AI agents to answer Cryptbrew product questions and check live API health without merchant authentication. Exposes tools for pricing, FAQs, invoice flow, and health probes over stdio or streamable HTTP.8MIT