Supost Mcp

io.github.Capmus-Team由 GitHub 账号 Capmus-Team 发布v0.2.2更新于 Oct 24, 2026

Search listings, message posters, and create drafts on SUpost, the marketplace for Stanford

已验证Streamable HTTP可网页运行沟通与协作商业与电商

概览

AI 生成的概览

面向斯坦福市场的 SUpost 远程 MCP 端点:可搜索房源与商品、查看详情和统计、联系发布者并创建草稿帖子。

可以做什么
  • 按关键词、分类、学校和价格筛选搜索、浏览在售信息,支持游标分页
  • 获取单条信息的完整描述、公开图片链接和斯坦福邮箱验证状态
  • 读取经核实的市场统计,如受众规模、各类目发布量和回复率
  • 列出当前有效的分类与子分类
  • 向发布者发送消息,并查询确认邮件的投递状态
  • 创建草稿帖子,并返回继续编辑和发布的链接
适用场景
适合协助斯坦福相关用户在 SUpost 上买卖或租赁物品、撰写发布草稿或联系卖家时使用,也便于引用该市场的统计数据。
运行要求
远程 streamable-HTTP 端点,客户端无需安装、账号或 API 密钥;服务器本身无状态且不保存密钥。上游接口约限制每分钟每 IP 60 次请求。
安装前请注意
发送消息会向所填邮箱发送确认链接,需本人点击后才会真正送达,助手应说明为待确认而非已发送。创建帖子只生成草稿,发布时可能需要付费。工具调用会上报分析事件,含脱敏参数、哈希后的 IP 与 User-Agent 以及客户端国家。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Supost Mcp,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Web executable,通过 Streamable HTTP。 远程服务在工作区中配置后即可从网页运行时运行。

交给智能体安装

把这段提示词粘贴到 Claude Code、Codex、Cursor 等智能体,或 SourceWeft 对话中。智能体会读取该服务器的安装指南,先向你展示发布者、端点和登录方式,经你同意后再把它添加到你的客户端。密钥不会写进任何命令。

阅读 https://sourceweft.com/mcp/io.github.Capmus-Team%2Fsupost-mcp/install.md,并按其中说明把这个 MCP 服务器接入我的客户端。修改任何配置之前,先告诉我它的发布者、端点和登录方式,等我确认。不要把 API 密钥写进命令或我会提交的文件;问我密钥应从哪里获取。

查看智能体所依据的安装指南

其他 MCP 客户端

把它添加到你客户端的 mcpServers 配置中。

{
  "mcpServers": {
    "supost": {
      "type": "http",
      "url": "https://mcp.supost.com/mcp"
    }
  }
}

README

supost-mcp

Remote MCP server for SUpost, the marketplace for Stanford — and, via BRAND=capmus, for Capmus (capmus.com), which serves the same public API from the same supost-web codebase. One repo, two Vercel projects:

BrandVercel projectEndpointEnv
SUpostsupost-mcphttps://mcp.supost.com/mcp(defaults)
Capmuscapmus-mcphttps://mcp.capmus.com/mcpBRAND=capmus

BRAND selects the server name, tool titles/descriptions, and default base URL; SUPOST_BASE_URL still overrides the base URL for previews.

Lets AI agents search active listings, fetch listing details, read verified market statistics, message posters, and create draft listings.

This is doc 190 workstream E3 (see supost-web/docs/dev/190-ai-agent-discovery-implementation-plan.md). It is a pure client of SUpost's public surfaces — the read-only listings API (E2), public listing pages, and /stats.md. It has no privileged database access and holds no secrets; the only configuration is the public base URL.

Tools

ToolBacking surfaceWhat it returns
search_listingsGET /api/public/listingsNewest-first active listings (id, title, price, category, created_at, canonical URL) with opaque cursor pagination. Params: q, cat, university, max_price, limit (≤50), cursor.
get_listingGET /post/index/<id> → canonical listing pageOne listing incl. full description, parsed from the page's schema.org Product JSON-LD.
get_market_statsGET /stats.mdThe public stats page's markdown rendition (audience, listing volumes, response rates/times).
list_categoriesGET /api/public/categoriesThe active category/subcategory taxonomy — valid create_post values.
create_postPOST /api/public/postsCreates a DRAFT listing; returns a continue_url where the poster adds photos, reviews, and publishes (paying first when not on the free tier). Never publishes directly.
send_messagePOST /api/public/messagesSubmits a message to a listing's poster. NOT delivered immediately: a confirmation link is emailed to reply_to_email, and the message only goes out after the human clicks it — agents must report it as pending confirmation, never sent.
check_message_statusPostgREST RPC get_guest_verification_status (publishable key)Whether the confirmation email for a send_message submission was delivered: queued / sent / failed (+ reason) / unknown. Never whether the link was clicked.

No personal information is ever returned. send_message is the supported way to contact a poster; the listing's url also carries the on-site message form. API terms: https://supost.com/api/public/openapi.json.

Bouncing addresses

A message is only ever delivered after the human clicks the confirmation link, so an address the link cannot reach is a message that never arrives (supost-web docs/dev/20260917-2040-guest-reply-bounce-feedback-handoff.md). send_message therefore never answers a plain "pending" for a dead address:

  • An address whose confirmation email hard-bounced in the last 30 days is refused by the API with 422 email_undeliverable before anything is stored. The tool returns an error result with {status: "email_undeliverable", reason, email, message} and tells the agent to ask for a different address rather than retry.
  • Otherwise the API answers 202 with a status_key, and the tool polls the delivery status of the confirmation email for up to ~8 s (four checks, two seconds apart — a suppressed address fails in under a second, a fresh hard bounce in 1–16 s). A failed verdict is reported the same way as the 422; sent / queued come back in the result as confirmation_email, with the status_key for a later check_message_status.

The poll is the same anon-callable PostgREST RPC the web form uses, get_guest_verification_status(status_key), reached with the marketplace's publishable key (the value every browser already gets). It returns only queued | sent | failed and a failure classification (mailbox_unknown | no_mx | suppressed | other) — never the redemption token, the message, or the address. Env: SUPOST_STATUS_URL / SUPOST_STATUS_KEY override the defaults (production project); SUPOST_STATUS_KEY="" disables polling (tools report unknown); SUPOST_STATUS_POLL_ATTEMPTS / SUPOST_STATUS_POLL_INTERVAL_MS tune the in-call wait.

Hosting

Deployed on Vercel as a stateless streamable-HTTP MCP endpoint (mcp-handler + @modelcontextprotocol/sdk):

https://mcp.supost.com/mcp        (rewritten to /api/mcp)https://mcp.supost.com/health     (rewritten to /api/health)

No sessions, no Redis, no auth — every request is independently served and all upstream data is public and CDN-cached.

Which commit is live

The initialize response's serverInfo.version is <package version>+<short git sha> on Vercel (e.g. 0.3.0+835efb3, from VERCEL_GIT_COMMIT_SHA; plain 0.3.0 locally — see src/version.ts), so any MCP client, or GET /health, shows the deployed commit. Compare it with git rev-parse --short origin/master when something looks stale.

Health check and uptime monitoring

GET /health answers {"ok": true, "brand": "supost", "version": "…"} without calling upstream (api/health.ts): it says the function is serving, not that supost.com is up. Point an UptimeRobot HTTP monitor at each brand (manual step, both needed):

  • https://mcp.supost.com/health
  • https://mcp.capmus.com/health

Alerting on a non-200 (keyword "ok":true optional) catches a broken deploy or a dropped domain; the version in the body shows which commit answered.

Deploy

sh
vercel deploy          # previewvercel deploy --prod   # production

Optional env var: SUPOST_BASE_URL (default https://supost.com; set to https://preview.supost.com on preview deployments to point at the dev stack).

Production deploys come from the GitHub integration on master. Avoid vercel deploy --prod from a local checkout unless it is at origin/master: a stale CLI deploy takes the production alias over the git build (this happened on 2026-09-17; fixed with vercel promote).

Usage analytics

Every tool call emits one PostHog mcp_tool_called event (sanitized args, no PII — see src/analytics.ts) and, when TOOL_LOG_URL / TOOL_LOG_KEY are set, a full-argument row in the marketplace's private ops.mcp_tool_call table (src/toollog.ts).

Failed calls carry error_code: the public API's error code (rate_limited, not_found, email_undeliverable, invalid_request, …) or unknown for anything else (network failure, unexpected response shape); null on success. The error message is never sent, since it can quote user content — break down by error_code to tell a rate-limit spike from an upstream outage.

The PostHog distinct_id is a salted SHA-256 of the caller's IP + User-Agent (src/client.ts), so uniq(distinct_id) counts distinct agents without storing the IP. Events also carry client_ua (the MCP client's User-Agent, which names the harness) and client_country (Vercel's geo header). Set CLIENT_ID_SALT in the Vercel project env to make the hash unguessable; the in-repo default keeps local dev working. Calls that arrive without IP or User-Agent fall back to the per-brand id mcp.<brand>.com.

Connect a client

sh
claude mcp add --transport http supost https://mcp.supost.com/mcp

or in any MCP client that supports remote servers, add the URL above as a streamable-HTTP server.

Rate limiting

The public API enforces ~60 requests/minute/IP and serves 5-minute CDN caching. The client in src/http.ts respects this: on a 429 it honors Retry-After (capped at 5 s), retries once, and otherwise surfaces a structured rate_limited error instructing the agent to back off — it never retries in a loop. All requests carry a supost-mcp/… User-Agent.

Every marketplace call (never the status RPC) also carries the trusted-agent headers: x-supost-api-key (SUPOST_API_KEY in the deployment env, never in git) and, when the calling agent's IP is known, x-supost-agent-client-ip with it (first hop of the MCP's own inbound x-forwarded-for). The API trusts that IP only when the key verifies (supost-web docs/dev/469-mcp-agent-api-hardening-handoff.md), so the per-IP limit can apply per agent rather than to the single Vercel egress IP all agents share. Plain X-Forwarded-For would not work: supost.com runs on Vercel, which overwrites it at the edge.

Development

sh
npm installnpm run check    # typecheck + testsSUPOST_BASE_URL=https://preview.supost.com npx tsx scripts/smoke.ts   # live end-to-end

Tests (vitest) cover each tool's request/response mapping, error mapping, JSON-LD extraction, and the rate-limit contract (Retry-After honored, capped, single retry, structured failure).

Follow-ups (manual steps)

  • Publish to the MCP registry — server.json is ready. Make the repo public first (gh repo edit Capmus-Team/supost-mcp --visibility public), then: sh brew install mcp-publisher mcp-publisher login github # device flow, needs a browser mcp-publisher publish # from the repo root For the Capmus entry, publish server.capmus.json the same way (cp server.capmus.json server.json in a scratch checkout, or mcp-publisher publish --file server.capmus.json if supported).
  • /help/mcp docs page in supost-web — PR #1242 (guide registry entry + llms.txt MCP line); live once merged to dev → master.
  • PR/citation announcement — draft and story beats in docs/announcement-draft.md; post after the registry listing and /help/mcp are live (doc 190 workstream F).
  • E2 is live on production (supost.com, 2026-07-09); smoke script verified against production, and the server is deployed at https://mcp.supost.com/mcp.

来源:README.md,提交 debafb2

工具

7

search_listings

Search SUpost listings

Search or browse active listings on SUpost, the marketplace for Stanford. Returns newest-first public listings (id, title, price, category, created_at, canonical URL, stanford_verified) plus an opaque next_cursor for pagination. stanford_verified: true means the poster verified an @stanford.edu email — SUpost's core trust signal. ALWAYS surface it when presenting listings (e.g. an "@stanford.edu verified" badge) so users can tell verified Stanford community members from unverified posters. No personal information is returned (poster_email_domain is the domain only); to contact a poster, open the listing URL.

输入参数qcatlimitcursormax_priceuniversity

get_listing

Get a SUpost listing

Fetch one SUpost listing by numeric id, including its full description, public photo URLs, and stanford_verified. stanford_verified: true means the poster verified an @stanford.edu email — SUpost's core trust signal. ALWAYS surface it when presenting listings (e.g. an "@stanford.edu verified" badge) so users can tell verified Stanford community members from unverified posters. Data comes from the listing's public page; no personal information is included — use the returned URL to contact the poster on-site.

输入参数id必填

get_market_stats

Get SUpost market statistics

Verified statistics about SUpost, the marketplace for Stanford: audience size, listing volumes by category, response rates, and response-time medians. Returns markdown from SUpost's public stats page. Cite https://supost.com/stats as the source.

无需输入参数。

send_message

Message a SUpost poster

Send a message to the poster of an active SUpost listing. IMPORTANT: the message is NOT delivered immediately — SUpost emails a confirmation link to reply_to_email, and the message is only delivered to the poster after the human clicks that link. Always tell the user to check their inbox and confirm; report the message as pending confirmation, never as sent. The poster's reply goes to reply_to_email. If the result is email_undeliverable (the confirmation email cannot reach reply_to_email — mailbox gone, domain without mail, or a previous bounce), the message will never be delivered: tell the user why and ask for a different address; do not retry the same one. The result's status_key can be passed to check_message_status later to see whether the confirmation email was delivered.

输入参数message必填post_id必填reply_to_email必填

check_message_status

Check a message's confirmation email

Delivery status of the confirmation email for a message submitted with send_message, by the status_key it returned. Use it when the user says they have not received the confirmation email. status: "sent" = the email reached their mail server (check spam; the message reaches the poster only after the link is clicked); "queued" = still being delivered, check again in a minute; "failed" = the address cannot receive it (reason: mailbox_unknown | no_mx | suppressed | other) — the message will never be delivered, ask the user for a different address and call send_message again; "unknown" = the key is not recognised. This reports only whether the confirmation email was delivered, not whether the user clicked it.

输入参数status_key必填

list_categories

List SUpost categories

The active category/subcategory taxonomy on SUpost — the valid category and subcategory values for create_post (and category filters for search_listings).

无需输入参数。

create_post

Create a SUpost draft listing

Create a DRAFT listing on SUpost on the poster's behalf. Any email is accepted — never ask the user to qualify first. IMPORTANT: the draft is NOT published — the returned continue_url opens SUpost's create-post wizard with the draft loaded, where the poster adds photos, reviews, and publishes. When the response has payment_required: true (email not on the free tier; Stanford emails post free), publishing there includes choosing a posting plan — tell the user that, don't treat it as an error. Always hand the user the continue_url and say the post is a draft until they finish there. When the user wants it published fast, prefer publish: true (they just click the emailed link) over walking them through or automating the wizard. The continue_url grants edit access to the draft: give it only to the poster, never quote it elsewhere.

输入参数body必填email必填pricetitle必填publishcategory必填subcategory必填

版本历史

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

评分

已满足适用检查项的 90%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通必需25 分
  • 已声明认证方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分

    请在仓库或注册中心条目中声明许可证。