# harjotrana.com developer resources: API, MCP server, llms.txt

Canonical URL: https://www.harjotrana.com/developers

> Every machine-readable surface of harjotrana.com in one place, with the URL, the format, and what it is for. Everything here is public, read-only, and needs no key or account.

## Start here

- [llms.txt](/llms.txt): the AI-oriented site guide, including a "When to use this site" section and how agents should call it.
- [llms-full.txt](/llms-full.txt): every public page of harjotrana.com rendered as one Markdown document.
- [OpenAPI description](/openapi.json): OpenAPI 3.1 document for every endpoint on this page, with typed response schemas and the error model.
- [API index](/api/v1): JSON list of the v1 endpoints with their documentation links.
- [API catalog](/.well-known/api-catalog): RFC 9727 linkset pointing at the OpenAPI description and this page.
- [sitemap.xml](/sitemap.xml) and [robots.txt](/robots.txt): the canonical HTML pages and crawler policy.

## REST API (harjotrana.com /api/v1)

A read-only JSON API over the same facts the HTML pages show. Base URL `https://www.harjotrana.com/api/v1`. Authentication: none. Every response is `application/json; charset=utf-8`, CORS-open (`Access-Control-Allow-Origin: *`), cacheable, and carries a `Link` header to the OpenAPI description and this page.

- `GET /api/v1`: index of endpoints with documentation links.
- `GET /api/v1/profile`: who Harjot is, with email, profiles, stack, and page URLs.
- `GET /api/v1/services`: engagement types, process, and FAQ. No prices are published.
- `GET /api/v1/projects` and `GET /api/v1/projects/{name}`: all projects, then one project with case study and features (name is case-insensitive, e.g. `Moonshift`).
- `GET /api/v1/posts` and `GET /api/v1/posts/{slug}`: technical writing, then one post with its Markdown body.
- `GET /api/v1/search?q=reinstate&limit=5`: keyword search across every public page.
- `GET /api/v1/contact-options`: email, booking link, inquiry form, and what to include.
- `GET /api/contributions`: last twelve months of GitHub contribution days.

Example: `curl -H "Accept: application/json" https://www.harjotrana.com/api/v1/projects/Moonshift` returns the Moonshift case study as JSON. Only `GET`, `HEAD`, and `OPTIONS` are supported; other methods return a `405` problem with an `Allow` header. There are no write endpoints, webhooks, or OAuth flows: to contact or hire Harjot, hand the user the links from `/api/v1/contact-options`.

## Errors

Every 4xx and 5xx from `/api/*`, `/mcp`, the discovery documents, and content negotiation is an RFC 9457 problem-details object served as `application/problem+json`. Members: `type` (a URI that resolves to the matching entry below), `title`, `status`, `detail`, `instance` (the request path), plus two extension members: `code`, a stable machine-readable identifier, and `hint`, what to do next. Validation failures add `invalidParams`.

- **bad_request (400)**: A query or path parameter is missing or invalid; `invalidParams` names it. Fix the request.
- **not_found (404)**: No endpoint or resource at that path. The `hint` names where to list valid ones. Unknown `/api/*` paths always return this, never an HTML page.
- **method_not_allowed (405)**: The endpoint is read-only. The `Allow` header lists supported methods.
- **not_acceptable (406)**: The `Accept` header on a page request allowed neither `text/html` nor `text/markdown`; `available` lists both.
- **rate_limited (429)**: Quota exhausted. Wait `Retry-After` seconds, then retry; reuse cached responses instead of re-fetching.
- **internal_error (500)**: The server failed to produce a response. Retry once; if it persists, email me@harjotrana.com with the URL.
- **upstream_unavailable (502)**: A third-party source the endpoint depends on (GitHub for `/api/contributions`) did not answer. Retry in a few minutes.

The MCP endpoint keeps JSON-RPC semantics: a malformed body is a JSON-RPC `-32700` error object with HTTP 400, unknown methods are `-32601`, and tool-level failures set `isError: true` on the result.

## Rate limits

`/api/*`, `/mcp`, and the discovery documents allow 120 requests per 60 seconds per client address. Every response carries the IETF RateLimit header fields (draft-ietf-httpapi-ratelimit-headers): `RateLimit-Policy: "default";q=120;w=60` declares the quota, and `RateLimit: "default";r=<remaining>;t=<seconds until reset>` reports where you stand. Exceeding it returns a `429` problem with `Retry-After`, which takes precedence over `RateLimit`.

The counter is per server instance, so treat the headers as a live advisory signal rather than a single global cap. Text documents (`/llms.txt`, `/llms-full.txt`, `/feed.xml`, `/sitemap.xml`) and HTML pages are outside the policy.

## Versioning and deprecation

The REST API is versioned in the path: `/api/v1`. Additive changes (new fields, new endpoints) ship in place; breaking changes ship under a new prefix (`/api/v2`) and never alter v1 responses. The MCP server negotiates its protocol version on `initialize` and advertises supported versions in its server card.

Deprecation policy: an endpoint or version scheduled for removal announces it at least 90 days in advance with the `Deprecation` response header (RFC 9745) and a `Sunset` header (RFC 8594) giving the removal date, and is listed here with its replacement. Nothing is deprecated today.

## MCP server

harjotrana.com runs a read-only Model Context Protocol server over Streamable HTTP at [https://www.harjotrana.com/mcp](/mcp). It exposes the portfolio as tools: profile, services, projects, writing, search, and contact options. No authentication, no session state, no side effects.

- Endpoint: `POST https://www.harjotrana.com/mcp` (JSON-RPC 2.0, Streamable HTTP transport, protocol versions 2025-03-26, 2025-06-18, and 2025-11-25). Responses are `application/json`; the server never opens server-initiated streams, so `GET /mcp` returns a `405` problem as the transport spec allows. The legacy HTTP+SSE transport is not offered.
- Server card: [/mcp/server-card](/mcp/server-card) (`application/mcp-server-card+json`, SEP-2127), mirrored with connection hints at [/.well-known/mcp.json](/.well-known/mcp.json) and listed in [/.well-known/ai-catalog.json](/.well-known/ai-catalog.json).
- Tools: `get_profile`, `get_services`, `list_projects`, `get_project`, `list_posts`, `get_post`, `get_contact_options`, `search_site`. Resources: llms.txt, llms-full.txt, openapi.json.
- Client config: `{ "mcpServers": { "harjotrana": { "type": "http", "url": "https://www.harjotrana.com/mcp" } } }`.

## Markdown content negotiation

Every public page on harjotrana.com also has a Markdown representation, following the acceptmarkdown.com convention. Send `Accept: text/markdown` to any page URL and you get `Content-Type: text/markdown; charset=utf-8` with `Vary: Accept`. Appending `.md` to a page path (for example `/blog/turborepo-cheatsheet.md`, or `/index.md` for the home page) returns Markdown unconditionally. Requests that accept neither HTML nor Markdown receive a `406` problem. Unknown paths return a real `404` with a short Markdown body pointing back to the sitemap and llms.txt.

## Usage policy

All of the above is free to read and cache. The HTML pages are canonical; JSON, Markdown, llms.txt, and MCP responses are derived from the same source files at build time and must not be quoted as if they contained facts the HTML does not. Do not infer employment availability, client relationships, testimonials, pricing, or outcomes beyond what the pages state. Questions about these resources: [me@harjotrana.com](mailto:me@harjotrana.com).


---

Site guide for agents: https://www.harjotrana.com/llms.txt · Full site as Markdown: https://www.harjotrana.com/llms-full.txt · Sitemap: https://www.harjotrana.com/sitemap.xml · Developer resources: https://www.harjotrana.com/developers