← Home

Developer docs

Everything on this site is available to programs. Markdown for every page, a read-only JSON API, and an MCP server. No keys, no sign-up.

This is a personal blog, so the "API" is small and entirely read-only. There is nothing to authenticate, no API key to request, and no sandbox to set up, because every endpoint is already safe to call: the production site is the sandbox. Rate limits are generous and reported in standard headers.

Quickstart

Three ways to read the same content. Pick whichever your tool speaks.

Markdown, for any page. Send an Accept: text/markdown header, or append .md to the URL.

curl -H 'Accept: text/markdown' https://anujmulik.com/
curl https://anujmulik.com/writing/a-coach-for-the-agent.md

JSON, for lists and search.

curl https://anujmulik.com/api/v1/posts
curl 'https://anujmulik.com/api/v1/search?q=prompt%20cache'
curl https://anujmulik.com/api/v1/posts/a-coach-for-the-agent

MCP, for agents. Streamable HTTP, no auth. Add this to a client that supports remote servers:

{
  "mcpServers": {
    "anujmulik": { "url": "https://anujmulik.com/api/mcp" }
  }
}

Endpoints

MethodPathReturns
GET/api/v1/postsPosts, newest first. Query: series, page, limit (max 100).
GET/api/v1/posts/{slug}One post with body_markdown, author and series parts.
GET/api/v1/search?q=Full-text matches, best first. q needs two or more characters; limit max 50.
GET/apiA JSON index of everything on this page.
GET/openapi.jsonThe OpenAPI 3.1 description of the API above.
GET/llms.txtA guide for agents: when to use this site and how to read it.
GET/.well-known/mcp, /mcp/server-cardThe MCP server card: where the server is and which protocol versions it speaks.
GET/.well-known/ai-catalog.json, /server.json, /.well-known/api-catalogDiscovery files: the AI catalog pointing at the server card, the MCP registry metadata, and the RFC 9727 API catalog.

The path prefix /api/v1/ is stable. A breaking change would ship as /api/v2/, with v1 kept for at least 90 days.

MCP tools

ToolArgumentsReturns
list_postsseries (optional)Every post with slug, date, series and description
search_postsquery, limit (default 10)Best matches with slugs
get_postslugThe full post as Markdown

Errors

Errors are JSON with a stable shape: an error object carrying a code, a human message and a hint that says where to look next. Unknown API paths return a 404 in the same shape. Unknown pages requested as Markdown return a Markdown 404 with links to the index, the sitemap and this guide.

{ "error": { "code": "post_not_found", "message": "No post with slug \"x\".", "hint": "List posts at https://anujmulik.com/api/v1/posts" } }

Rate limits

Every API response carries the IETF RateLimit and RateLimit-Policy headers. The policy is 600 requests per minute per client, which no reasonable use of a blog will approach. A 429 would carry Retry-After. Responses are cacheable for an hour at the edge, so repeated reads are cheap for everyone.

Attribution

Quote with a link to the post URL. The author is Anuj Mulik; questions go through the contact page.