portfolio-mcp
This server has a remotely hosted endpoint. Open its connector listing for connection details, authentication requirements, and setup instructions:
portfolio-mcp
The agent-native layer of saagarpatel.dev: a Model Context Protocol server that lets any AI agent query Saagar's writing, projects, public-safe repo profiles, and benchmark results directly, instead of scraping HTML.
Read-only. Stateless. Public. No auth, no tracking, no database, no runtime egress.
How it fits
The website stays a pure static site. This server is a sibling, not a backend bolted onto it:
Layer 0 (in the
portfolio-indexrepo): the build emits a static machine corpus —corpus-index.json, per-documentcorpus/<id>.json, and.well-known/mcp.json— plus public-safe repo profile artifacts when present, served alongside the HTML. Already public.Layer 1 (this repo,
src/index.ts): a stateless Cloudflare Worker that bakes the Layer 0 corpus into its bundle and serves it over MCP (streamable HTTP, theWebStandardStreamableHTTPServerTransport). Zero runtime fetches.Layer 2 (this repo,
src/stdio.ts): the same server over stdio, for running locally vianpx saagar-portfolio-mcp. Identical tool/resource/prompt surface.
The shared core (src/server.ts) is transport-agnostic; both layers wrap it.
Related MCP server: CodeAlive MCP
Tool surface
All read-only (readOnlyHint: true). No tool takes a URL or filesystem path (no
SSRF / exfil surface).
Tool | Purpose |
| BM25 over the whole corpus; optional |
| Full Markdown of one document by |
| The table of contents; optional |
| The "who is this" card (about / now / uses) |
| Curated public-safe projects + anonymized aggregates |
| Public-safe repo profile index with freshness and proof counts |
| One repo answering profile by the |
| Public, sanitized OPERANT calibration results (per-model OCS) |
Documents are also exposed as Resources (portfolio://essays/{slug}, portfolio://book/{slug},
portfolio://notes/{slug}, portfolio://profile), and there are two Prompts:
introduce_saagar and summarize_writing_on (grounded in a live search).
Retrieval
BM25 over a baked index (no embeddings in v1 — the committed corpus contains 166 docs and the calling LLM supplies the semantics). Titles are boosted. Embeddings are a measured Phase 3 upgrade, added only if retrieval quality proves insufficient.
Layout
src/
types.ts corpus + projects + operant shapes
bm25.ts dependency-free BM25 + snippet (pure)
tools.ts createTools(corpus) -> the 8 tools (pure, injectable)
corpus.ts loads the baked corpus + accessors
corpus.generated.ts AUTO-GENERATED by build:corpus
server.ts buildServer(): shared MCP core (tools + resources + prompts)
index.ts Cloudflare Worker transport (streamable HTTP)
stdio.ts Layer 2 stdio transport (the npx CLI)
scripts/
build-corpus.mjs bakes Layer 0 and local OPERANT inputs into corpus.generated.ts
probe-mcp.mjs probes an MCP HTTP endpoint (saagar-mcp-kit driver + domain calls)
audit-mcp.sh connected MCPAudit scan of this server (dogfood)
test/ vitest: bm25, tools, full-protocol server testsDevelop
From the repository root, use the pinned Node and npm versions from
.node-version and package.json. The checked-in public-safe corpus is enough
for routine checks; no sibling checkout, local portfolio import, signing key,
or Cloudflare credentials are needed.
npm ci
make checkmake check runs lint, format validation, typecheck, tests, the stdio build and
protocol test, smoke, parity, and a package-content check. See
CI for the same aggregate gate. npm run dev starts
the local Worker.
npm run build:corpus regenerates source from a sibling checkout or an explicit
network URL; URL-mode builds omit OPERANT because its build inputs are not
published. Corpus generation is not required for ordinary fixture verification. npm run probe:mcp targets the live Worker by default, and the connected audit starts a
local Worker and invokes the separately installed mcp-audit CLI. Keep those
separate from local gates; deployment and signing remain operator-gated as
described below.
Inspect either transport with the MCP inspector:
npx @modelcontextprotocol/inspector http://localhost:8787/mcp # Layer 1 (HTTP)
npx @modelcontextprotocol/inspector node dist/stdio.js # Layer 2 (stdio, after build:cli)Deploy (Layer 1)
npm run build:corpus && npm run deploy # wrangler deploy
npm run probe:mcp # post-deploy live MCP readbackOperator-gated (needs Cloudflare auth). v1 still deploys to the default
portfolio-mcp.<account>.workers.dev URL, and npm run probe:mcp uses that stable
Worker URL by default. Public discovery now advertises the verified custom endpoint
https://mcp.saagarpatel.dev/mcp; after any deploy, verify both the Worker and the
website manifest/readback path before changing .well-known/mcp.json.
wrangler.jsonc pins workers_dev: true so the public Worker URL stays live during any
future custom-domain experiments; do not remove it unless the website manifest has already
moved to a verified replacement endpoint.
Publish (Layer 2)
npm run build:corpus && npm run build:cli # -> dist/stdio.js
npm login && npm publish # public package: saagar-portfolio-mcpOnce published, anyone can run it locally with npx saagar-portfolio-mcp (no install).
Sign the manifest (optional trust signal)
Ed25519-sign .well-known/mcp.json so an agent or registry can verify it authentically
comes from Saagar (via saagar-mcp-kit's signing CLI, Node built-in crypto):
npx mcp-kit-sign gen-key --manifest=../portfolio-index/.well-known/mcp.json # one-time; private key -> .signing/ (gitignored, NEVER commit)
npm run sign # writes <manifest>.sig + publishes mcp-ed25519.pub
npm run sign:verify # checks manifest bytes against .sig + public keyOverride paths with --manifest=/--key=/--pub=/--sig=.
Commit the .sig + mcp-ed25519.pub (never the private key) into portfolio-index next to the manifest, then
redeploy the site. Re-run sign whenever the manifest changes (it signs the exact served bytes).
Audit posture
Designed to pass MCPAudit / mcp-trust (Saagar's own tools): only the inbound MCP
transport, no shell_execution / file_access / destructive / exfiltration, and no
caller-controlled egress (the corpus is baked). All tools are annotated read-only with
plain, non-injectable descriptions. bash scripts/audit-mcp.sh runs a connected scan.
Dogfooding this server surfaced a substring-matching false-positive bug in MCPAudit (it
matched port inside portfolio://); that fix lives in the MCPAudit repo and cut this
server's findings 62 → 14. The genuine tool surface scans clean (high_risk_servers: 0).
Status
Stack
Node.js 24.21.0, npm 12.2.0, TypeScript, Cloudflare Workers, and the MCP SDK.
Known risks
URL-mode corpus builds omit OPERANT, whose inputs are only available to local corpus builds. Worker deployment and package publication are not part of local verification.
Next steps
Keep the published MCP endpoint and signed discovery manifest in sync when an operator authorizes a deployment. Registry publication remains a separate, explicitly authorized release action.
This server cannot be deployed
Maintenance
Related MCP Connectors
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
A Model Context Protocol server for Wix AI tools
Real-time planetary signal engine and Model Context Protocol (MCP) server for autonomous AI agents.
Turn any public website into an MCP server for agents to search, read and navigate.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA simple Model Context Protocol server that enables searching and retrieving relevant documentation snippets from Langchain, Llama Index, and OpenAI official documentation.-

CodeAlive MCPofficial
AlicenseNot gradedqualityBmaintenanceA Model Context Protocol server that enhances AI agents by providing deep semantic understanding of codebases, enabling more intelligent interactions through advanced code search and contextual awareness.90MIT- FlicenseCqualityDmaintenanceA Model Context Protocol server that provides Retrieval-Augmented Generation capabilities using Contextual AI, enabling AI interfaces like Cursor IDE and Claude Desktop to query domain-specific knowledge with context-aware responses and source citations.121-
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to access structured content by building static Markdown/JSON files served as a Model Context Protocol server.1-