Server data from the Official MCP Registry
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
About
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
Remote endpoints: streamable-http: https://mcp.saagarpatel.dev/mcp
Security Report
This is a well-designed, read-only MCP server exposing public portfolio content with minimal attack surface. The codebase demonstrates strong security practices: no authentication is required by design (the corpus is public), no shell execution or file I/O permissions, no network egress at runtime (corpus is baked into the bundle), and clear separation of concerns across transport layers. The server intentionally avoids dangerous patterns and has been audited against MCPAudit. Minor code quality observations around error handling and input validation exist but do not indicate security vulnerabilities. Supply chain analysis found 2 known vulnerabilities in dependencies (0 critical, 1 high severity). Package verification found 1 issue.
3 files analyzed · 7 issues found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
Permissions Required
This plugin requests these system permissions. Most are normal for its category.
How to Install & Connect
Available as Local & Remote
This plugin can run on your machine or connect to a hosted endpoint. during install.
Documentation
View on GitHubFrom the project's GitHub README.
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.
Tool surface
All read-only (readOnlyHint: true). No tool takes a URL or filesystem path (no
SSRF / exfil surface).
| Tool | Purpose |
|---|---|
search | BM25 over the whole corpus; optional section filter, limit |
get_document | Full Markdown of one document by id |
list_corpus | The table of contents; optional type filter |
get_profile | The "who is this" card (about / now / uses) |
list_projects | Curated public-safe projects + anonymized aggregates |
list_repo_profiles | Public-safe repo profile index with freshness and proof counts |
get_repo_profile | One repo answering profile by repo_id |
get_operant_results | Public, sanitized OPERANT calibration results (per-model OCS) |
Documents are also exposed as Resources (portfolio://essays/{slug}, book/{slug},
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 corpus is ~50 small 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 (+ OPERANT) 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 tests
Develop
npm install
npm run build:corpus # bake from ../portfolio-index (or --url=https://saagarpatel.dev)
npm run typecheck
npm test
npm run dev # wrangler dev -> http://localhost:8787/mcp
npm run smoke # end-to-end MCP smoke under the real workerd runtime (saagar-mcp-kit)
npm run probe:mcp # live Worker probe, or set PORTFOLIO_MCP_ENDPOINT
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 readback
Operator-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-mcp
Once 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 key
Override 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
- Built + locally verified: Layers 0–2. Shared core + 8 tools + Resources + 2 prompts +
get_operant_results. typecheck clean; test suite passes (incl. full MCP protocol via the fetch handler). Live Worker probe and deploy remain operator-gated. Public discovery advertisesmcp.saagarpatel.devwith a valid Ed25519-signed manifest. - Gated / next: publish the stdio package (
npm publish, after removing"private": trueby explicit operator approval only), glama.ai registry listing, and continued signed-manifest readback checks after website manifest changes.
Reviews
No reviews yet
Be the first to review this server!
More Developer Tools MCP Servers
Git
Freeby Modelcontextprotocol · Developer Tools
Read, search, and manipulate Git repositories programmatically
Fetch
Freeby Modelcontextprotocol · Developer Tools
Web content fetching and conversion for efficient LLM usage
Toleno
Freeby Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
mcp-creator-python
Freeby mcp-marketplace · Developer Tools
Create, build, and publish Python MCP servers to PyPI — conversationally.
MarkItDown
Freeby Microsoft · Content & Media
Convert files (PDF, Word, Excel, images, audio) to Markdown for LLM consumption
MCP Marketplace
Freeby mcp-marketplace · Developer Tools
Search and install MCP servers from inside your AI client.
