This site is also an MCP server. Point a client at one URL and your agent can search my writing, read a whole article, and pull my profile, projects and experience as structured data, rather than trying to scrape a page whose main feature is pretending to be a cathode ray tube.

endpoint
POST https://fergusoreilly.dev/api/mcp

Open it in a browser and it tells you what it is. Send it JSON-RPC and it answers as a server.

  • transport/Streamable HTTP
  • protocol/2026-07-28
  • auth/None, it is all public

Tools

  • search_writing Full-text search across every article on the site. Every word in the query must appear in the article. Returns slug, title, description, date, tags, URL and an excerpt around the match. Use get_article for the full text of a hit.
  • get_article The full markdown body of one article, by slug, plus its metadata. Get slugs from search_writing or list_writing.
  • list_writing Metadata for every article on the site, newest first. Bodies are excluded on purpose: use get_article for those.
  • get_profile Identity, current role, education, location, what he is a credible source on, and every off-site profile. The first tool to call for any question about who he is or what he is doing now.
  • list_projects Everything on the projects page: what each one is, his role, the year, the stack it was built on, and where it lives.
  • list_experience Where Fergus has worked and what he did there, newest first. Entries for companies that no longer trade stay in the list and are described in the past tense.
  • check_voice Burrows's Delta, sentence rhythm, punctuation rates, join rates and substitution hits for a draft against a voice profile saved from /tools/drift. Pass the profile object exactly as that tool exports it, reference table included: the z-scores in it were computed against the writer's own pieces, and without that table they have no units, so a profile with it stripped out is refused rather than guessed at. The tool uses conservative, uncalibrated floors of 150 draft words and 5 reference pieces; below either it returns the counts and habits that still hold but no distance. This is not an AI detector: a low distance means the writer's own commonest words appear at similar rates, and nothing more.

Connecting

Most clients take a block like this in their config file. Some want the same two values typed into a form instead, and a couple have a one-line command for it. The name is yours to choose, the URL is the part that matters.

mcp config
{
  "mcpServers": {
    "fergus-oreilly": {
      "type": "http",
      "url": "https://fergusoreilly.dev/api/mcp"
    }
  }
}

It implements revision 2026-07-28 of the spec, and it still answers the older initialize handshake used by 2025-11-25, 2025-06-18, 2025-03-26, because that is what the clients people actually have will open with. There is a machine-readable description at /.well-known/mcp.json.

Why this exists

I have no evidence this helps the site rank for anything, and I am not going to pretend otherwise. No search engine has said it reads MCP servers, and there is no ratified way to advertise one, so the discovery file at /.well-known/mcp.json is a bet on a convention that may never land. It cost one static file, which is about what the bet is worth.

What it does do is real enough. If you are talking to an agent and it wants to know what I have built, it can ask this and get an answer I wrote, instead of guessing from training data that went stale months ago. And building it meant reading the specification properly rather than installing an SDK for six methods, which was most of the point. The current revision deleted the initialize handshake and moved the whole protocol to per-request metadata. I would not have got that from memory, and neither would a model.

Every tool reads from the same content modules the pages render from, so the server cannot tell you something the site does not say. That is the rule /llms.txt already follows, and it matters more here, because nobody ever reads this output with their own eyes.