# 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.

Last updated 2026-08-21 · https://www.tomborvan.com/developers

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](https://www.tomborvan.com/openapi.json)
- MCP server at `https://www.tomborvan.com/api/mcp` (Streamable HTTP)
- Markdown versions of every page via `Accept: text/markdown`, or `GET /api/markdown?path=/`
- Plain-text profiles: [/llms.txt](https://www.tomborvan.com/llms.txt) (short) and [/llms-full.txt](https://www.tomborvan.com/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:

```sh
# 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/writing
```

To connect an MCP client, point it at the Streamable HTTP endpoint. With Claude Code:

```sh
claude mcp add --transport http tomborvan https://www.tomborvan.com/api/mcp
```

Generic client configuration:

```json
{
  "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 `operationId`s for function calling, lives in [/openapi.json](https://www.tomborvan.com/openapi.json).

- `GET /api/v1`: index of endpoints and discovery links
- `GET /api/v1/profile`: who Tom is: role, employer, location, summary, education, certifications, languages, links
- `GET /api/v1/projects`: featured projects (title, company, year, description, url, tags, metrics)
- `GET /api/v1/timeline`: career timeline, newest first
- `GET /api/v1/skills`: skill categories and spoken languages
- `GET /api/v1/writing`: list of essays with slug, title, dek, date, reading time and URL
- `GET /api/v1/writing/{slug}`: one essay, including its body as markdown
- `GET /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.

```sh
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, optional `format: "brief" | "full"`
- `list_projects`: featured projects as JSON
- `list_timeline`: career timeline as JSON
- `list_skills`: skill categories and languages as JSON
- `get_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](https://www.tomborvan.com/.well-known/mcp/server-card.json), [MCP Registry server.json](https://www.tomborvan.com/server.json) and an [AI catalog](https://www.tomborvan.com/.well-known/ai-catalog.json) that points at the card. An [A2A agent card](https://www.tomborvan.com/.well-known/agent-card.json) describes the same capabilities for A2A clients. Background on why the server exists: [Why my portfolio runs an MCP server](https://www.tomborvan.com/writing/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](https://www.tomborvan.com/llms.txt) and [/llms-full.txt](https://www.tomborvan.com/llms-full.txt): profile summaries written for language models, with a section on when to use this site
- [/openapi.json](https://www.tomborvan.com/openapi.json): OpenAPI 3.1 description of the REST API, the MCP endpoint and the markdown endpoint
- [/.well-known/api-catalog](https://www.tomborvan.com/.well-known/api-catalog): RFC 9727 API catalog (linkset)
- [/.well-known/mcp/server-card.json](https://www.tomborvan.com/.well-known/mcp/server-card.json), [/server.json](https://www.tomborvan.com/server.json), [/.well-known/ai-catalog.json](https://www.tomborvan.com/.well-known/ai-catalog.json): MCP discovery
- [/.well-known/agent-skills/index.json](https://www.tomborvan.com/.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](https://www.tomborvan.com/.well-known/agent-card.json): A2A agent card
- [/sitemap.xml](https://www.tomborvan.com/sitemap.xml) and [/robots.txt](https://www.tomborvan.com/robots.txt): crawl map; robots.txt carries `Content-Signal` directives 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.

```json
{
  "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 /api
- `article_not_found` (404): unknown essay slug
- `method_not_allowed` (405): only GET, HEAD and OPTIONS are supported on /api/v1
- `invalid_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](mailto:tborvan@gmail.com) or message on [LinkedIn](https://linkedin.com/in/tomborvan). Privacy information for this site is at [/privacy](https://www.tomborvan.com/privacy).