---
title: "Tim Benniks Developer Resources: MCP, OpenAPI & Agent API"
description: "Developer documentation for timbenniks.dev by Tim Benniks: MCP server at /.well-known/mcp, OpenAPI spec, WebMCP tools, content indexes, and markdown negotiation."
url: "https://timbenniks.dev/developers"
markdown_url: "https://timbenniks.dev/developers.md"
---

# Tim Benniks developer resources.

Machine-readable surfaces for AI agents and integrators. Start with llms.txt, read the agent contract, call the MCP server, or fetch markdown twins. No HTML scraping required.

- [OpenAPI spec](/openapi.json)

- [MCP discovery](/.well-known/mcp)

- [Agent guide](/agents.md)

---

*First call*

## Run one request

No key, no account, no signup. Every public endpoint below is unauthenticated and read-only. Copy a line, run it, and you have a working call. Errors come back as application/problem+json (RFC 9457); every response carries RateLimit and RateLimit-Policy headers.

### Search the content · REST

curl -s 'https://timbenniks.dev/api/v1/search?query=composable&limit=2'

# 200 application/json
# { "results": [ { "type": "writing",
#                  "title": "Ten AI security problems hiding in plain text",
#                  "date": "2026-08-05", "description": "…", "tags": [ … ],
#                  "url": "https://timbenniks.dev/writing/<slug>",
#                  "md": "https://timbenniks.dev/writing/<slug>.md",
#                  "source": "…" } ],
#   "engine": "index" }

### List the tools · MCP handshake

# 1. Initialize; use the returned protocolVersion below.
curl -s https://timbenniks.dev/api/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'

# 2. Confirm initialization (202, empty body).
curl -s https://timbenniks.dev/api/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'MCP-Protocol-Version: 2025-11-25' \
  -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'

# 3. List the six read-only tools (200, JSON result).
curl -s https://timbenniks.dev/api/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'MCP-Protocol-Version: 2025-11-25' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

# No session ID is required. GET with Accept: text/event-stream
# returns 405: this server sends immediate JSON responses.

### Read a page as markdown

curl -s https://timbenniks.dev/about.md
curl -s -H 'Accept: text/markdown' https://timbenniks.dev/about

# 200 text/markdown; charset=utf-8
# Vary: Accept, Accept-Encoding
# Same twin for /writing/<slug>.md, /videos/<slug>.md, /projects/<slug>.md.

### What failure looks like

curl -si 'https://timbenniks.dev/api/v1/search'   # query is required

# 400 application/problem+json; charset=utf-8
# api-version: 1
# ratelimit: "public";r=118;t=60
# ratelimit-policy: "public";q=120;w=60
# { "type": "https://timbenniks.dev/developers#missing-query",
#   "title": "Search query required", "status": 400,
#   "detail": "The query parameter is required and must not be empty.",
#   "instance": "/api/v1/search", "code": "MISSING_QUERY",
#   "resolution": "Retry with a URL such as /api/v1/search?query=developer%20experience." }
#
# 429 once you pass 120 requests / 60s, read RateLimit and Retry-After to back off.

---

*Tim Benniks MCP server*

## Model Context Protocol

Read-only tools exposed via streamable HTTP. No authentication on public endpoints.

- **/.well-known/mcp:** [GET discovery doc, or POST JSON-RPC 2.0 for a live handshake: initialize, tools/list, tools/call](/.well-known/mcp)
- **POST /api/mcp:** [Same JSON-RPC 2.0 handshake, canonical endpoint](/api/mcp)
- **/tools.json:** [Tool catalog + JSON Schema (WebMCP compatible)](/tools.json)
- **/.well-known/webmcp.json:** [Same catalog at well-known URI](/.well-known/webmcp.json)

---

*Tim Benniks Developer API*

## Versioned REST API

- **GET /api/v1:** [API status, version, and endpoint discovery](/api/v1)
- **GET /api/v1/search:** [Search public content with typed JSON responses](/api/v1/search?query=developer%20experience)
- **GET /api/v1/content:** [List or retrieve writing, videos, talks, projects, and pages](/api/v1/content)
- **GET /api/v1/press-kit:** [Structured bios, topics, photos, and booking details](/api/v1/press-kit)
- **GET /api/v1/versions:** [Live version status, deprecation policy, and sunset signal headers](/api/v1/versions)
- **/openapi.json:** [OpenAPI 3.1 contract with typed success and RFC 9457 error schemas](/openapi.json)
- **Version policy:** [Major versions in the URL; at least 90 days' notice via Deprecation and Sunset headers](/api/v1/versions)
- **Rate limits:** 120 requests per 60 seconds; inspect RateLimit and RateLimit-Policy headers

---

*Agent-readable resources*

## Indexes and content negotiation

- **/llms.txt:** [Curated site map (llmstxt.org)](/llms.txt)
- **/content-index.json:** [Writing, videos, talks, projects, pages](/content-index.json)
- **Accept: text/markdown:** [Content negotiation on canonical URLs](/ai)
- **/agents.md:** [When-to-use guidance for agents](/agents.md)

---

## Public tool summary

### 01 · get_page_context

Call first. Returns page type, markdown twin URL, and which tool to use next.

### 02 · search_site

Full-text search across writing and videos via content-index.json.

### 03 · get_content

Fetch one page or article as markdown. Includes video transcripts when available.

### 04 · get_press_kit / request_booking

Bios, photos, topics, and a draft booking message for human confirmation.
