harshdipsaha-mcp
by HarshdipSaha
README.md
# harshdipsaha-mcp
A public, read-only [Model Context Protocol](https://modelcontextprotocol.io) server for
[harshdipsaha.tech](https://harshdipsaha.tech). Add its URL to any MCP client (Claude Code, Codex,
Cursor, …) to query Harshdip Saha's projects and profile directly, instead of scraping the site.
Design doc: [`docs/plans/2026-09-05-mcp-server-design.md`](https://github.com/HarshdipSaha/HARSHDIPSAHA.github.io/blob/main/docs/plans/2026-09-05-mcp-server-design.md)
in the portfolio repo. Originated from [issue #62](https://github.com/HarshdipSaha/HARSHDIPSAHA.github.io/issues/62).
**Not to be confused with WebMCP.** The portfolio site separately registers a WebMCP tool
(`document.modelContext`, [ADR 0014](https://github.com/HarshdipSaha/HARSHDIPSAHA.github.io/blob/main/docs/adr/0014-agent-facing-site-llms-txt-and-webmcp.md)/[0020](https://github.com/HarshdipSaha/HARSHDIPSAHA.github.io/blob/main/docs/adr/0020-webmcp-document-modelcontext.md))
— a browser API consumed by an agent embedded in a browser tab. This repo is the real Model
Context Protocol, consumed by external clients over a network connection. They share a name and
nothing else.
## Tools
- **`searchProjects(query, limit?)`** — keyword search over the project list, same matching
semantics as the portfolio's own WebMCP tool: every whitespace-separated term must appear in the
title, summary, slug, or year.
- **`getProfile()`** — bio, skills, research interests (each with how it's being pursued), contact
info, résumé link, and site URL.
Deliberately just these two, matching ADR 0014's minimal-surface reasoning: every additional tool
is a schema that has to stay correct.
## Architecture
```
harshdipsaha.tech/agent-data.json -> fetch (10 min edge cache) -> this Worker -> MCP client
```
The Worker holds no data of its own except `interests` (`src/lib/interests.mjs`, MCP-only copy that
needs no site rebuild; if `agent-data.json` ever ships its own `interests`, that wins). It fetches `agent-data.json` (generated by the portfolio
repo's `scripts/build-agent-data.mjs`) on every tool call, cached at Cloudflare's edge via the
`cf.cacheTtl` fetch option, so a burst of MCP traffic never hits GitHub Pages more than once per
10-minute window. There is no database, no KV, no Durable Object — the server is stateless, per the
MCP spec's 2026-07-28 revision.
- `src/lib/search-projects.mjs`, `src/lib/format.mjs`, `src/lib/interests.mjs` — pure logic,
unit-tested with `node --test`.
- `src/lib/agent-data-client.mjs` — the one place that does I/O (the fetch).
- `src/server.mjs` — builds the `McpServer` and registers both tools.
- `src/index.mjs` — the Worker entry point, wrapping `createServer` with Cloudflare's
`createMcpHandler` (`agents/mcp/server`) for the Streamable HTTP transport.
## Run locally
```bash
npm install
npm run typecheck # tsc, split into tsconfig.json (src, Workers types) + tsconfig.test.json (test, Node types)
npm test # node --test (default discovery) — the pure-function suite
npm run dev # wrangler dev — needs Node >= 22 (see below)
```
**Node version:** `wrangler` hard-requires Node ≥ 22. This project's own code runs fine on Node 20+
(`npm test`/`npm run typecheck` don't need 22), but `npm run dev`/`npm run deploy` will refuse to
start otherwise. If you're on an older Node, switch first (`nvm use 22` or equivalent).
Verified locally (Node 22.23.2, `wrangler dev`, no deploy): `initialize`, `tools/list`, and a real
`tools/call` for both tools against the live `agent-data.json` all returned correct responses.
## Deploy
```bash
npx wrangler login # one-time, opens a browser OAuth flow — do this yourself, not from an agent session
npm run deploy
```
Publishes to `<worker-name>.<your-subdomain>.workers.dev` with no custom domain and no
authentication configured, matching the design doc's scope (public, read-only, no auth).
## Keeping this in sync
`src/lib/types.mjs`'s JSDoc typedefs mirror the portfolio repo's `scripts/lib/agent-data.mjs`
output field-for-field. There's no shared package between the two repos — if that shape changes on
the portfolio side, update the typedefs and `src/server.mjs`'s Zod schemas here by hand.
## Out of scope (see the design doc)
- Any write/contact tool.
- Auth of any kind.
- The portfolio site's own discoverability addition (a footer link / `/mcp` section) — a separate,
later change to `HARSHDIPSAHA.github.io`.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessUnresponsive