Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
File size: 7,456 Bytes
ee0b555 3ecc591 ee0b555 3ecc591 ee0b555 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | # pwc MCP server
Anonymous, read-only Model Context Protocol access to the public
[Papers With Code](https://paperswithcode.co) catalog.
The server uses stock-client MCP `2025-11-25` over Streamable HTTP and also
serves experimental `2026-07-28` discovery on the same `/mcp` endpoint. It
returns versioned structured output with compact Markdown fallbacks.
## Run locally
```bash
uv run --project mcp_server pwc-mcp
```
The default listener is `127.0.0.1:7860`. Set `PWC_MCP_HOST`, `PORT`, or
`PWC_API_URL` to override the bind address, HTTP port, or compatible PwC API.
```bash
curl http://127.0.0.1:7860/health
```
## Tools
Every read-only `pwc` CLI research command is one tool, and every research flag
of that command is a tool parameter, so results match `pwc ... --json`. Each
result carries `schema_version` and `data`, the complete CLI JSON payload, next
to typed projections such as `items` or `evaluations`.
| Tool | CLI command |
| --- | --- |
| `search_papers` | `pwc search` |
| `get_paper_info` | `pwc paper info` |
| `get_paper_evaluations` | `pwc paper evaluations` |
| `read_paper` | `pwc paper read` (64 KiB chunks with a continuation cursor) |
| `list_papers` | `pwc paper list` |
| `list_recent_papers` | `pwc paper recent` |
| `list_trending_papers` | `pwc paper trending` |
| `get_related_papers` | `pwc paper related` |
| `get_paper_lineage` | `pwc paper lineage list` |
| `get_task` | `pwc task --name` |
| `list_tasks` | `pwc task list` |
| `get_method` | `pwc method --name` |
| `list_methods` | `pwc method list` |
| `get_conference` | `pwc conference --name` |
| `list_conferences` | `pwc conference list` |
| `get_organization` | `pwc organization --name` |
| `list_organizations` | `pwc organization list` |
| `get_framework` | `pwc framework --name` |
| `list_frameworks` | `pwc framework list` |
| `get_benchmark` | `pwc benchmark --name` |
| `list_benchmarks` | `pwc benchmark list` |
Parameter names follow the CLI flags except for the established MCP names
`published_after`/`published_before` (`--start-date`/`--end-date`), `limit`
(`--page-size`), `authors` (`--author`), `order_direction` (`--order-dir`),
`minimum_evaluations` (`--min-eval-count`), and `include_evaluations`
(`--include-evals`). Terminal-only flags (`--json`,
`--implementation-coverage`, `--flat`) have no parameter because MCP output is
always structured. Hosted differences from the CLI: `limit` is capped at 25,
`get_paper_info` returns compact official-first resources, and `read_paper`
is chunked. `search_papers` defaults to `hybrid` mode like `pwc search`.
`tests/test_parity.py` fails when the CLI parser and the tool schemas drift.
All tools are annotated read-only and idempotent. Search is deterministic;
the caller controls hybrid (default), keyword, or semantic mode. `read_paper`
fetches at most one 64 KiB catalog chunk per call and returns a signed, one-hour
continuation cursor when more Markdown remains. Continuations stay pinned to
the resolved paper and content version, so a changed paper fails with an
explicit restart response; any reference that resolves to the same paper (the
numeric catalog ID after starting from the arXiv ID, say) may carry the cursor.
A placeholder cursor such as `"next"` with nothing saved reads from the
beginning.
Paper tools fall back to the public API's `public-metadata` endpoint for papers
the catalog does not hold: `get_paper_info` and `read_paper` return Hugging Face
Papers, arXiv, or Crossref (DOI) metadata and the abstract with
`in_catalog: false`, a `note`, and labelled `available_at` links to cite instead
of a Papers With Code page; `get_related_papers` returns a catalog search for the
public title with the same `note` and links. A reference the endpoint maps to a
catalog paper returns the catalog paper. Titles go to the sibling
`public-metadata/search` endpoint, which accepts only an exact arXiv or Crossref
title match, or the single arXiv paper sharing the "Name:" before its colon.
`get_benchmark` answers a metric the leaderboard does not report with the
unfiltered leaderboard and a `metric_note` naming the available metrics.
## Resources
- `pwc://papers/{paper}`
- `pwc://papers/{paper}/markdown`
- `pwc://tasks/{task}`
- `pwc://benchmarks/{benchmark}`
## Configuration
| Variable | Purpose |
| --- | --- |
| `PWC_API_URL` | Compatible catalog API; defaults to production PwC |
| `PWC_MCP_HOST` | Listener address; defaults to loopback (`127.0.0.1`) |
| `PWC_MCP_ALLOWED_HOSTS` | Comma-separated HTTP Host allowlist |
| `PWC_MCP_ALLOWED_ORIGINS` | Comma-separated browser Origin allowlist |
| `PWC_MCP_CURSOR_KEY_CURRENT` | Required secret used to sign continuation cursors |
| `PWC_MCP_CURSOR_KEY_PREVIOUS` | Optional previous secret accepted during key rotation |
| `PORT` | HTTP port; defaults to `7860` |
| `PWC_MCP_REQUEST_LIMIT` | Requests per client per minute; defaults to `60` |
| `PWC_MCP_SEMANTIC_LIMIT` | Semantic or hybrid searches per client per minute; defaults to `10` |
| `PWC_MCP_CONCURRENCY_LIMIT` | Concurrent requests per client; defaults to `4` |
| `PWC_MCP_GLOBAL_CONCURRENCY_LIMIT` | Concurrent requests across all clients; defaults to `128` and sizes the tool thread pool |
| `PWC_MCP_TRUSTED_PROXY_CIDRS` | Comma-separated networks of a non-loopback reverse proxy whose `X-Forwarded-For` is trusted; empty by default |
| `LOG_LEVEL` | Content-free operational log level |
Native clients may omit `Origin`. Browser requests must match the configured
allowlist. A first-party client on the same host may send
`X-PwC-MCP-Client: <token>` to name its rate-limit identity (for example one
hashed chat session); the header counts only on a direct loopback connection
without `X-Forwarded-For`, so proxied public traffic cannot use it. The server does not log queries, paper references, request bodies,
raw IP addresses, or authorization headers.
Behind a reverse proxy that does not run on the same host, such as the Hugging
Face Spaces ingress, set `PWC_MCP_TRUSTED_PROXY_CIDRS` to the proxy's networks.
A request whose direct peer falls in one of them is limited by the right-most
`X-Forwarded-For` hop outside those networks; hops further left are
client-supplied and ignored. Such requests can never name an identity with
`X-PwC-MCP-Client`. Loopback peers keep the behaviour above. List only
networks that hold nothing but the proxy: any peer inside them can choose its
own rate-limit identity.
The hosted defaults allow 60 total requests and 10 semantic or hybrid searches per minute
per client IP, with at most four concurrent requests per IP and 128 globally.
Tool inputs cap list results at 25, catalog calls time out after 25 seconds, and
request, upstream, and serialized MCP response bodies are bounded to 2 MiB.
The global ceiling is 128 concurrent requests by default.
Markdown chunks use a bounded 256-entry/16 MiB in-memory cache.
`GET /.well-known/mcp` exposes connection metadata and `GET /docs` publishes
the live tool schema. A bare `GET /mcp` returns `405`; protocol requests use
`POST /mcp`. The server also exposes `find_papers`, `compare_leaderboard`, and
`survey_task` prompts.
## Test
```bash
uv run --project mcp_server pytest mcp_server/tests
```
The canonical hosted service is deployed as an immutable VPS component and
published through `https://paperswithcode.co/mcp`. The
`huggingface/paperswithcode-mcp` Docker Space remains an optional fallback; its
container explicitly binds to `0.0.0.0`.
|