For AI agents
This site answers AI agents. An MCP server at https://ai.pournasserian.com/mcp and a search API serve one index of every page, rebuilt each time the site deploys, so ChatGPT, Claude and any other client of the Model Context Protocol (MCP) can search and read it. The server is mcp-my-site, the open-source tool I built, and this site is its first user; this page is about how this site runs it.
Connect
Any MCP client that speaks the Streamable HTTP transport can connect to https://ai.pournasserian.com/mcp. No key is needed.
Claude Code
claude mcp add --transport http pournasserian https://ai.pournasserian.com/mcp
Claude.ai and Claude Desktop. Add https://ai.pournasserian.com/mcp as a custom connector in Settings.
Visual Studio Code (.vscode/mcp.json)
{
"servers": {
"pournasserian": {
"type": "http",
"url": "https://ai.pournasserian.com/mcp"
}
}
}
Cursor (.cursor/mcp.json)
{ "mcpServers": { "pournasserian": { "url": "https://ai.pournasserian.com/mcp" } } }
In the browser. The playground is a small MCP client in the page, so you can try the server without installing anything.
curl, to see the raw protocol:
curl -s https://ai.pournasserian.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search","arguments":{"query":"mcp","limit":3}}}'
The server has two tools, both read-only. search takes a question or keywords and returns the pages that match best, one hit per page, each with an id, its title, its address, a snippet and the section it was found in. fetch takes that id and returns the whole page as Markdown, with its title, description, language and last-modified date. The server also gives the model instructions written from the site itself: what the site is, when its pages were indexed, when to use the tools, and an outline of its sections.
Every door
The MCP server is one way in. Here is everything a machine can read on this site, and what each is for.
| Address | What it holds | Who it is for |
|---|---|---|
/llms.txt | A map of the site: every page, article and idea by title and meta description, each linked to its Markdown copy | Language-model crawlers |
/llms-full.txt | Every Markdown copy in one file, in the order of llms.txt | Language-model crawlers |
A page’s address with .md added (Home’s is /index.md) | The page’s Markdown copy, in its own words, named in the page’s head by rel="alternate" | Agents |
A page’s own address, asked for with Accept: text/markdown | The same Markdown copy, for an agent that asks for Markdown without knowing the .md address | Agents |
/rss.xml and /ideas.xml | The feeds of the articles and the ideas, newest first, each item carrying the whole post | Feed readers |
/sitemap.xml | Every page, with the date it last changed | Search engines |
| Structured data (JSON-LD) in the pages | Who the site is about, and what a page is: a profile, a case study, a project or a post | Search engines |
/robots.txt | Every crawler allowed, and Cloudflare’s Content-Signal line: search, AI answers that cite the site and AI training are all welcome | Crawlers |
/.well-known/ai-catalog.json | The AI Catalog, with the card of the MCP server; the server is also listed in the official MCP registry | Agents looking for the site’s MCP server |
https://ai.pournasserian.com/mcp | The MCP server, with its search and fetch tools | MCP clients |
https://ai.pournasserian.com/api/search?q= | The search API, as JSON, described by an OpenAPI document at /openapi/v1.json and an interactive reference at /docs | Developers, and the site’s own search box |
/search | The site’s own search box, which calls that API | People |
The Markdown copies, the feeds and llms.txt are built from the same files as the pages, so they hold the pages’ own words.
How the index is built
The index is rebuilt every time the site deploys. A push to master deploys the site as a Cloudflare Worker. GitHub Actions then checks out the pinned mcp-my-site release, crawls the live site, and embeds only the chunks that changed, through OpenRouter, with the embedding cache kept between runs. The index goes to Azure Blob Storage, the manifest last, so a reader never sees a half-written index. The server, on Azure Container Apps, polls the manifest and swaps the new index in without a restart.
When a new release is pinned, the server is rolled out before the index is uploaded, because an older server cannot read a newer index format, while a newer server reads the previous one.
A broken crawl never replaces a working index. The indexer refuses a crawl that found too few pages, lost more than half of them, or failed on too many, and nothing is uploaded; a server that cannot load a new index keeps serving the one it has. The server’s embedding key and the certificate between Cloudflare and the server are held in Azure Key Vault.
How a question is answered
Every request reaches the server through Cloudflare. The server reads the visitor’s address from the CF-Connecting-IP header for its rate limit, and believes it only when the connection comes from Cloudflare’s own ranges. The question is embedded through OpenRouter; keyword and vector search then run over the index and are fused per query, with one hit per page. When the embedding provider is unavailable, the search falls back to keywords alone and says so in its answer. The MCP tools and the search API share the same search code, so an agent and the site’s search box are answered by the same search.
Cost and privacy
Embedding a small site costs a fraction of a cent, each rebuild re-embeds only the chunks whose text changed, and a question embeds a few tokens. The server’s cost is its hosting plan.
What you search for is not logged. No log line or trace carries the text of a search unless the setting that turns it on is set, and this site leaves it off. The server’s telemetry goes to Application Insights: searches by channel, how long they took and whether they fell back to keywords, never the text.
The MCP endpoint is open, with no key, and read-only: the tools cannot change anything, and they serve only what was public on the site anyway. Each visitor can make 60 requests a minute, shared between the MCP endpoint and the search API.
What it is not
There is no chat yet: it is planned for the next version of mcp-my-site. Search runs on submit, with no search-as-you-type. Only HTML pages are indexed, and the server covers this site alone.
Stack
mcp-my-site · Cloudflare Workers · GitHub Actions · Azure Container Apps · Azure Blob Storage · Azure Key Vault · Application Insights · OpenRouter