{
  "markdown": "# supost-mcp\n\nRemote [MCP](https://modelcontextprotocol.io) server for **SUpost**, the\nmarketplace for Stanford — and, via `BRAND=capmus`, for **Capmus**\n(capmus.com), which serves the same public API from the same supost-web\ncodebase. One repo, two Vercel projects:\n\n| Brand | Vercel project | Endpoint | Env |\n| --- | --- | --- | --- |\n| SUpost | `supost-mcp` | `https://mcp.supost.com/mcp` | (defaults) |\n| Capmus | `capmus-mcp` | `https://mcp.capmus.com/mcp` | `BRAND=capmus` |\n\n`BRAND` selects the server name, tool titles/descriptions, and default base\nURL; `SUPOST_BASE_URL` still overrides the base URL for previews.\n\nLets AI agents search active listings, fetch\nlisting details, read verified market statistics, message posters, and\ncreate draft listings.\n\nThis is doc 190 workstream **E3** (see `supost-web/docs/dev/190-ai-agent-discovery-implementation-plan.md`).\nIt is a **pure client** of SUpost's public surfaces — the read-only listings\nAPI (E2), public listing pages, and `/stats.md`. It has **no privileged\ndatabase access and holds no secrets**; the only configuration is the public\nbase URL.\n\n## Tools\n\n| Tool | Backing surface | What it returns |\n| --- | --- | --- |\n| `search_listings` | `GET /api/public/listings` | Newest-first active listings (id, title, price, category, created_at, canonical URL) with opaque cursor pagination. Params: `q`, `cat`, `university`, `max_price`, `limit` (≤50), `cursor`. |\n| `get_listing` | `GET /post/index/<id>` → canonical listing page | One listing incl. full description, parsed from the page's schema.org `Product` JSON-LD. |\n| `get_market_stats` | `GET /stats.md` | The public stats page's markdown rendition (audience, listing volumes, response rates/times). |\n| `list_categories` | `GET /api/public/categories` | The active category/subcategory taxonomy — valid `create_post` values. |\n| `create_post` | `POST /api/public/posts` | Creates 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. |\n| `send_message` | `POST /api/public/messages` | Submits 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. |\n\nNo personal information is ever returned. `send_message` is the supported\nway to contact a poster; the listing's `url` also carries the on-site\nmessage form. API terms:\n`https://supost.com/api/public/openapi.json`.\n\n## Hosting\n\nDeployed on Vercel as a stateless **streamable-HTTP** MCP endpoint\n([`mcp-handler`](https://www.npmjs.com/package/mcp-handler) +\n`@modelcontextprotocol/sdk`):\n\n```\nhttps://mcp.supost.com/mcp        (rewritten to /api/mcp)\n```\n\nNo sessions, no Redis, no auth — every request is independently served and\nall upstream data is public and CDN-cached.\n\n### Deploy\n\n```sh\nvercel deploy          # preview\nvercel deploy --prod   # production\n```\n\nOptional env var: `SUPOST_BASE_URL` (default `https://supost.com`; set to\n`https://preview.supost.com` on preview deployments to point at the dev\nstack).\n\n### Connect a client\n\n```sh\nclaude mcp add --transport http supost https://mcp.supost.com/mcp\n```\n\nor in any MCP client that supports remote servers, add the URL above as a\nstreamable-HTTP server.\n\n## Rate limiting\n\nThe public API enforces ~60 requests/minute/IP and serves 5-minute CDN\ncaching. The client in [src/http.ts](src/http.ts) respects this: on a 429 it\nhonors `Retry-After` (capped at 5 s), retries **once**, and otherwise\nsurfaces a structured `rate_limited` error instructing the agent to back off\n— it never retries in a loop. All requests carry a `supost-mcp/…` User-Agent.\n\n## Development\n\n```sh\nnpm install\nnpm run check    # typecheck + tests\nSUPOST_BASE_URL=https://preview.supost.com npx tsx scripts/smoke.ts   # live end-to-end\n```\n\nTests (vitest) cover each tool's request/response mapping, error mapping,\nJSON-LD extraction, and the rate-limit contract (Retry-After honored, capped,\nsingle retry, structured failure).\n\n## Follow-ups (manual steps)\n\n- [ ] **Publish to the MCP registry** — [server.json](server.json) is ready.\n      Make the repo public first (`gh repo edit Capmus-Team/supost-mcp\n      --visibility public`), then:\n      ```sh\n      brew install mcp-publisher\n      mcp-publisher login github   # device flow, needs a browser\n      mcp-publisher publish        # from the repo root\n      ```\n      For the Capmus entry, publish [server.capmus.json](server.capmus.json)\n      the same way (`cp server.capmus.json server.json` in a scratch checkout,\n      or `mcp-publisher publish --file server.capmus.json` if supported).\n- [x] **`/help/mcp` docs page in supost-web** — PR\n      [#1242](https://github.com/Capmus-Team/supost-web/pull/1242) (guide\n      registry entry + llms.txt MCP line); live once merged to dev → master.\n- [ ] **PR/citation announcement** — draft and story beats in\n      [docs/announcement-draft.md](docs/announcement-draft.md); post after\n      the registry listing and /help/mcp are live (doc 190 workstream F).\n- [x] E2 is live on production (`supost.com`, 2026-07-09); smoke script\n      verified against production, and the server is deployed at\n      `https://mcp.supost.com/mcp`.\n",
  "bytes": 5327,
  "sha": "8972911d592af62db425f3c2633a015355bee13b99e190d8aca03725c6801a03",
  "repo_slug": "capmus-team/supost-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_capmus_team_capmus_mcp_b60c2880/readme"
}