- Published on
I Gave My Blog an MCP Server. Here Is the Whole Build.
- Authors

- Name
- Patrick Burger
A rendered article on this site costs an agent 21,847 tokens. The same prose as Markdown costs 491.
Websites now have two kinds of readers. One uses a browser. The other is an agent that fetches a URL into a context window and pays by the token.
The rendered page fails the second reader in three ways. It costs more — HTML tokenizes at roughly 3.5 characters per token, Markdown gets 5.5, and tags fragment into tokens that carry no meaning. Compression does not help: tokenization runs after decompression, so markup gets billed no matter how well it transferred. It carries no signal — an agent cannot tell the article from the chrome, so navigation and sidebars get billed before they are discarded. And it strips attribution: a citing agent needs title, date and canonical URL, and if that is a second fetch you halve the citations you get.
What already ships
The layer with real consumers came first, and it is not llms.txt.
Every article has a Markdown variant at its own URL, with an attribution header on top: title, summary, date, canonical. One fetch gets an agent clean prose plus the data it needs to cite. The knowledge base ships as JSON on the same principle.
llms.txt exists too. I keep it, but I know what it is. Ahrefs analyzed a month of logs across 137,000 domains: 97% of llms.txt files received zero requests from anything. No major platform has committed to reading them. Mine serves the developer wiring an agent up, as a man page. Worth having. Not an agent-facing surface, and I stopped pretending it was.
Where HTTP stops
Page-readable is not queryable. There was no way to ask what this site means by agent gateway and get that one entry back with its sources. That is what the MCP server closes.
Two of the six tools earn the deployment: get_definition and search_faqs. The other four restate what HTTP already serves, and an agent that can fetch a URL does not need a tool call to read a blog. I shipped them anyway because the tool surface is the interface contract — it declares what questions this content answers. Dead is still the right word for four of them: a client that lists tools on every run pays for every schema each time, and tool selection degrades as the set grows. Harmless at six. Not free in general.
The build
A static export cannot host an API route. No /api/mcp, not ever. So the server lives in a second deployment behind the same hostname, reached through a proxy-level rewrite evaluated before any function runs. The static edge stays static. The server reads the blog's own published artifacts back over HTTPS: single source of truth, no copy, publishing an article does not require a server deploy.
Two placement decisions matter. The content cache is a correctness requirement, not an optimisation — the search index plus article bodies approach a megabyte of JSON, and refetching that per request turns a fixed asset into a per-request cost. And the rate limit lives in the platform firewall, not the route handler: a 429 returned from your own function has already cost you the invocation it was meant to protect.
No embeddings. All content comes to about 120,000 tokens, it fits in a modern context window, and substring scoring handles retrieval at this scale. No auth. The content is public, and OAuth on a read-only server over public data is security theatre with a token refresh bug in it.
The wiring stays unpublished. OpenAI's Agents SDK now redacts sensitive tool outputs, tool arguments in error messages, and credentials from traces and persisted state by default — it treats recorded agent state as a leak surface. I treat published deployment detail the same way.
Why MCP at all
Adoption. llms.txt lost because it was a convention: no client committed to reading it, so reading it bought nobody anything. MCP won because it was a protocol with clients — every major platform shipped support, so a server bought reach on day one. REST took the web the same way.
Conventions need someone else to change. Protocols already changed them.
Try it
Point a client at it:
{
"mcpServers": {
"brgr-one": { "url": "https://www.brgr.one/api/mcp" }
}
}
No key. POST-only, so a browser gets 405 — that is the protocol, not a fault.
Check your logs. What share of your traffic is agents, and what are they paying in tokens to read you?