Docs · Updated 2026-08-21 · Markdown
Developer and agent docs
How to read this site by machine: REST API, MCP server, markdown negotiation, discovery files and error format. Public, read-only, no authentication.
This site is built to be read by people and by agents. Everything below is public, read-only and free to use without an API key. The same data backs the web pages, the REST API and the MCP server, so pick whichever interface suits your client.
Overview
- REST API at
https://www.tomborvan.com/api/v1(JSON), described by OpenAPI 3.1 - MCP server at
https://www.tomborvan.com/api/mcp(Streamable HTTP) - Markdown versions of every page via
Accept: text/markdown, orGET /api/markdown?path=/ - Plain-text profiles: /llms.txt (short) and /llms-full.txt (full)
- Discovery files under
/.well-known/: API catalog, MCP server card, AI catalog, agent skills, A2A agent card
Quick start
Three ways to get the profile, from the simplest up:
# 1. Plain markdown, no tooling required
curl https://www.tomborvan.com/llms.txt
# 2. JSON over REST
curl https://www.tomborvan.com/api/v1/profile
# 3. Any page as markdown via content negotiation
curl -H "Accept: text/markdown" https://www.tomborvan.com/writingTo connect an MCP client, point it at the Streamable HTTP endpoint. With Claude Code:
claude mcp add --transport http tomborvan https://www.tomborvan.com/api/mcpGeneric client configuration:
{
"mcpServers": {
"tomborvan": {
"type": "http",
"url": "https://www.tomborvan.com/api/mcp"
}
}
}REST API
Base URL https://www.tomborvan.com/api/v1. All endpoints are GET, return application/json; charset=utf-8, allow cross-origin reads (Access-Control-Allow-Origin: *) and are cached for up to an hour. The full contract, including response schemas and operationIds for function calling, lives in /openapi.json.
GET /api/v1: index of endpoints and discovery linksGET /api/v1/profile: who Tom is: role, employer, location, summary, education, certifications, languages, linksGET /api/v1/projects: featured projects (title, company, year, description, url, tags, metrics)GET /api/v1/timeline: career timeline, newest firstGET /api/v1/skills: skill categories and spoken languagesGET /api/v1/writing: list of essays with slug, title, dek, date, reading time and URLGET /api/v1/writing/{slug}: one essay, including its body as markdownGET /api/v1/contact: public contact channels
List responses carry a source field: cms when the data came from the Sanity CMS, bundled when the site fell back to its built-in defaults. Both are authoritative; the values only differ while an edit is in flight.
curl -s https://www.tomborvan.com/api/v1/projects | jq '.items[0].title'MCP server
Endpoint https://www.tomborvan.com/api/mcp, transport Streamable HTTP (JSON-RPC 2.0 over POST; protocol versions 2025-11-25, 2025-06-18 and 2025-03-26). No authentication, no sessions to manage, no write operations. A plain GET on the endpoint returns a short JSON description instead of the protocol error most servers give.
Tools:
get_profile: full markdown profile, optionalformat: "brief" | "full"list_projects: featured projects as JSONlist_timeline: career timeline as JSONlist_skills: skill categories and languages as JSONget_contact_info: public contact channels as JSON
Resources: profile://brief (same text as /llms.txt) and profile://full (same text as /llms-full.txt), both text/markdown.
Manifests: MCP server card, MCP Registry server.json and an AI catalog that points at the card. An A2A agent card describes the same capabilities for A2A clients. Background on why the server exists: Why my portfolio runs an MCP server.
Markdown negotiation
Every page on the site (the home page, /writing, each essay, this page and /privacy) can be fetched as markdown. Send Accept: text/markdown and the response is Content-Type: text/markdown; charset=utf-8 with Vary: Accept and an x-markdown-tokens header giving a rough token count. Clients that cannot set headers can call GET /api/markdown?path=/writing for the same document.
The home page markdown is the full profile (the same text as /llms-full.txt). Unknown paths return a markdown 404 with links back to the main indexes.
Discovery files
- /llms.txt and /llms-full.txt: profile summaries written for language models, with a section on when to use this site
- /openapi.json: OpenAPI 3.1 description of the REST API, the MCP endpoint and the markdown endpoint
- /.well-known/api-catalog: RFC 9727 API catalog (linkset)
- /.well-known/mcp/server-card.json, /server.json, /.well-known/ai-catalog.json: MCP discovery
- /.well-known/agent-skills/index.json: Agent Skills index pointing at a SKILL.md that explains when and how to use this site
- /.well-known/agent-card.json: A2A agent card
- /sitemap.xml and /robots.txt: crawl map; robots.txt carries
Content-Signaldirectives allowing search, AI input and AI training
Errors
API errors are JSON, never HTML. They use RFC 9457 Problem Details with Content-Type: application/problem+json and always include a stable code, a human-readable detail and a resolution hint.
{
"type": "https://www.tomborvan.com/developers#errors",
"title": "API route not found",
"status": 404,
"detail": "The requested API route does not exist on www.tomborvan.com.",
"instance": "https://www.tomborvan.com/api/v1/nope",
"code": "api_route_not_found",
"resolution": "Discover the public API through https://www.tomborvan.com/openapi.json, https://www.tomborvan.com/.well-known/api-catalog, or the index at https://www.tomborvan.com/api/v1.",
"documentation_url": "https://www.tomborvan.com/developers#errors"
}api_route_not_found(404): no such route under /apiarticle_not_found(404): unknown essay slugmethod_not_allowed(405): only GET, HEAD and OPTIONS are supported on /api/v1invalid_json(400): the MCP endpoint received a body that is not valid JSON; the body is a JSON-RPC error with code -32700
The MCP endpoint answers protocol-level problems with JSON-RPC 2.0 error objects: for example -32000 Not Acceptable when a client does not accept both application/json and text/event-stream, or -32000 Method not allowed with an Allow header for verbs other than GET, POST and DELETE. Page-level 404s return the HTML not-found page, or a markdown one when Accept: text/markdown is sent.
Versioning and caching
The REST API is versioned in the path. /api/v1 is stable: fields may be added, never removed or renamed, and a breaking change would ship as /api/v2 with /api/v1 kept alive. Responses are cached at the CDN for up to an hour (Cache-Control: public, max-age=300, s-maxage=3600, stale-while-revalidate=86400); content changes in the CMS revalidate the pages on publish. The MCP server and the markdown 404 are not cached.
Authentication, writes and rate limits
There is nothing to authenticate: all interfaces are public and read-only. No API keys, OAuth, webhooks, write endpoints or pagination exist. There is no hard rate limit; please keep automated traffic reasonable and cache what you fetch. If you build something with the data, a link back is appreciated but not required.
Contact
Questions, corrections or integration ideas: email tborvan@gmail.com or message on LinkedIn. Privacy information for this site is at /privacy.