saagarpatel.dev Portfolio

io.github.saagpatel由 GitHub 帳號 saagpatel 發布v0.1.0更新於 Oct 24, 2026

Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.

發布方自己的服務:PortfolioFit

已驗證Streamable HTTP可網頁執行網頁搜尋與抓取知識與記憶

概覽

AI 產生的概覽

面向 saagarpatel.dev 公開語料的唯讀 MCP 伺服器,讓助理檢索並閱讀文章、書稿與筆記,並瀏覽專案與基準結果。

可以做什麼
  • 以 BM25 全文檢索整個語料,回傳排序結果、摘要片段與 id
  • 依 id 讀取單篇文件的完整 Markdown,或列出含標題、類型、日期與字數的完整目錄
  • 取得作者簡介卡片,涵蓋 about、now 與 uses 頁面
  • 列出精選公開專案及其技術棧、狀態與活躍度訊號
  • 列出並讀取公開安全的儲存庫問答檔案,含新鮮度與佐證計數
  • 取得公開且已去識別化的 OPERANT 各模型校準結果
適用情境
適合需要根據 Saagar Patel 的寫作、專案或已發布基準結果作答、而不想爬取網站 HTML 的情境。適用於針對該特定公開語料的研究、摘要與介紹類任務。
執行需求
可作為遠端 streamable HTTP 端點執行,也可透過 npx saagar-portfolio-mcp 以 stdio 在本機執行。未宣告任何驗證、API 金鑰、標頭或環境變數;語料已內建,執行時無需連網抓取。
安裝前請注意
所有工具皆為唯讀且無狀態,且沒有工具接受 URL 或檔案系統路徑。內容僅限該作者的公開素材,儲存庫檔案是靜態產物而非即時儲存庫健康狀態;若未內建資料集,OPERANT 結果可能無法取得。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 saagarpatel.dev Portfolio,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

交給代理程式安裝

把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。

閱讀 https://sourceweft.com/mcp/io.github.saagpatel%2Fportfolio-mcp/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。

檢視代理程式所依據的安裝指南

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。

{
  "mcpServers": {
    "saagarpatel-dev-portfolio": {
      "type": "http",
      "url": "https://mcp.saagarpatel.dev/mcp"
    }
  }
}

README

portfolio-mcp

[Glama MCP server]

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-index repo): the build emits a static machine corpus — corpus-index.json, per-document corpus/<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, the WebStandardStreamableHTTPServerTransport). Zero runtime fetches.
  • Layer 2 (this repo, src/stdio.ts): the same server over stdio, for running locally via npx 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).

ToolPurpose
searchBM25 over the whole corpus; optional section filter, limit
get_documentFull Markdown of one document by id
list_corpusThe table of contents; optional type filter
get_profileThe "who is this" card (about / now / uses)
list_projectsCurated public-safe projects + anonymized aggregates
list_repo_profilesPublic-safe repo profile index with freshness and proof counts
get_repo_profileOne repo answering profile by the repoId argument
get_operant_resultsPublic, 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 tests

Develop

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.

sh
npm cimake check

make 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:

sh
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)

sh
npm run build:corpus && npm run deploy   # wrangler deploynpm 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)

sh
npm run build:corpus && npm run build:cli   # -> dist/stdio.jsnpm 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):

sh
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.pubnpm 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

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.

來源:README.md,提交 55de013

工具

8

get_document

Get a document

Return the full Markdown of one document by id, e.g. "writing/the-handoff" or "book/preface". Get ids from search or list_corpus.

輸入參數id必填

list_corpus

List the corpus

List every document with its id, title, type, date, and word count, plus per-type counts. The table of contents for the whole site. Optionally filter by type.

輸入參數type

get_profile

Get profile

Return Saagar Patel's profile: name, one-line summary, site, and the about / now / uses pages. Start here to understand who this is and what they work on.

無需輸入參數。

list_projects

List projects

List the curated, public projects with stack, status, last-active date, and test/CI signals, plus anonymized portfolio-wide aggregates. Optionally filter by status.

輸入參數limitstatus

list_repo_profiles

List repo profiles

List public-safe repo answering profiles with repo id, attention state, freshness, and proof counts. Profiles are static artifacts baked from saagarpatel.dev, not live repo health.

輸入參數limitattentionState

get_repo_profile

Get repo profile

Return one public-safe repo answering profile by repo_id, including purpose, safe commands, agent surfaces, proof refs, freshness, exclusions, limitations, and integrity metadata.

輸入參數repoId必填

get_operant_results

Get OPERANT benchmark results

Return the public, sanitized OPERANT results: per-model operator-calibration-score (OCS) profiles, the headline figures, and the calibration-profiles (not a flat leaderboard) framing. Sourced from the published OPERANT mirror. Returns availability=false if no dataset was baked.

無需輸入參數。

版本歷史

1
  1. v0.1.0最新Sep 16, 2026

評分

已滿足適用檢查項的 100%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通必需25 分
  • 已宣告認證方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分

其他 Portfolio 整合