August 9, 2026
This Site as MCP Tools
A remote MCP server exposing this site's content and a curated set of admin actions as tools any MCP-speaking client can call — no bespoke integration required.
3
public tools, no auth required
4
admin tools reused from the Telegram agent
Problem
The site already had a content API and a RAG chat widget, but both were bespoke integrations: anything that wanted to search this site, check a build log entry's stats, or make a scoped edit had to hand-roll a client against a one-off REST shape. There was no standard way for an arbitrary LLM tool to talk to the site.
Approach
Built a remote MCP server at /api/mcp using Streamable HTTP transport (@modelcontextprotocol/server v2) — a fresh server instance per request, matching Vercel's serverless model with no session state to manage between calls. Two tiers, gated by whether the caller supplies a bearer token: three public, read-only tools (search_content, get_build_log_stats, get_availability) that any MCP client can call unauthenticated, and an admin tier — the exact same tool set and executor already serving the Telegram admin agent (list_site_content, update_site_content, add_testimonial, add_service) — that only registers at all when the request carries a valid Authorization: Bearer <ADMIN_API_SECRET> header. An unauthenticated caller doesn't just fail to call the admin tools; it never sees them exist in tools/list. Connecting a client is a one-line add for anything that speaks MCP over HTTP. Claude Code: claude mcp add --transport http damienkedwardstech https://damienkedwards.tech/api/mcp. Claude Desktop and most other clients take the same URL in a small JSON config block, with an optional Authorization header to unlock the admin tools. claude.ai's own web connector UI is the one exception — it only supports OAuth for custom connectors, so it can only reach the public tier there.
Outcome
The server reused nearly all of its logic from things that already existed — search_content wraps the same pgvector search behind the /search page, and the admin tools call the identical executor the Telegram bot uses, right down to sharing its audit-log instrumentation (writes now show up in the admin audit log tagged mcp_agent). Building it was mostly a protocol adapter, not new business logic. Verified live by connecting it in Claude Code against this repo and calling every tool end to end, including confirming that a missing or invalid token can't even discover the admin tools exist.