{
  "markdown": "# Semantic Scholar MCP Server\n\n<!-- mcp-name: io.github.smaniches/semantic-scholar-mcp -->\n\n[![CI](https://github.com/smaniches/semantic-scholar-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/smaniches/semantic-scholar-mcp/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/smaniches/semantic-scholar-mcp/graph/badge.svg)](https://codecov.io/gh/smaniches/semantic-scholar-mcp)\n[![PyPI version](https://img.shields.io/pypi/v/s2-mcp-server)](https://pypi.org/project/s2-mcp-server/)\n[![PyPI downloads/30d](https://img.shields.io/pypi/dm/s2-mcp-server?label=downloads%2F30d)](https://pypistats.org/packages/s2-mcp-server)\n[![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.19324159-3C5A99?logo=zenodo&logoColor=white)](https://doi.org/10.5281/zenodo.19324159)\n[![Provenance: SLSA + SBOM](https://img.shields.io/badge/provenance-SLSA_+_SBOM-blue)](#provenance--supply-chain)\n[![Docker](https://img.shields.io/badge/ghcr.io-semantic--scholar--mcp-blue?logo=docker)](https://ghcr.io/smaniches/semantic-scholar-mcp)\n[![GitHub Release](https://img.shields.io/github/v/release/smaniches/semantic-scholar-mcp)](https://github.com/smaniches/semantic-scholar-mcp/releases)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![MCP](https://img.shields.io/badge/MCP-Compatible-blue)](https://modelcontextprotocol.io)\n[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)\n[![Glama score](https://glama.ai/mcp/servers/smaniches/semantic-scholar-mcp/badges/score.svg)](https://glama.ai/mcp/servers/smaniches/semantic-scholar-mcp)\n[![Awesome MCP Servers](https://img.shields.io/badge/Awesome_MCP-Listed-blue?logo=github)](https://github.com/punkpeye/awesome-mcp-servers#research)\n\n**A 14-tool Semantic Scholar MCP server for academic research workflows.** Direct access to 200M+ papers from [Semantic Scholar](https://www.semanticscholar.org/) — paper search, citation graph traversal, author profiles, and recommendations — from any [Model Context Protocol](https://modelcontextprotocol.io) client (e.g., Claude Desktop, Claude Code, Cursor, Cline, Continue, and others).\n\nEvery release ships **verifiable supply-chain provenance**: Sigstore-signed SLSA build-provenance attestations on the wheel, sdist, and container image; PEP 740 attestations on the PyPI upload; and a CycloneDX SBOM — so you can prove the artifact you installed was built from this repo. See [Provenance & supply chain](#provenance--supply-chain).\n\n> Author: **Santiago Maniches** · ORCID [0009-0005-6480-1987](https://orcid.org/0009-0005-6480-1987) · TOPOLOGICA LLC\n\n---\n\n## Quick start\n\n```bash\nuvx s2-mcp-server                                      # run instantly, no install\nclaude mcp add semantic-scholar -- uvx s2-mcp-server   # or register it in Claude Code\n```\n\nNo API key is needed to start (public rate limit: 1 req/sec); set\n`SEMANTIC_SCHOLAR_API_KEY` for 10 req/sec. Claude Desktop, Docker, pip, and\nremote (Streamable HTTP) setups are in [Installation](#installation).\n\n---\n\n## Provenance & supply chain\n\nA research tool is only as trustworthy as the chain from its source to the\nbinary you run. Every release of this server ships cryptographically\nverifiable supply-chain evidence, all generated in CI from the tagged commit:\n\n| Guarantee | What it proves | Where it is produced |\n|---|---|---|\n| **SLSA build provenance** (wheel + sdist) | the published distributions were built by this repo's `publish.yml` from the released tag, not hand-uploaded | [`publish.yml`](.github/workflows/publish.yml) — `actions/attest-build-provenance` (`build` job) |\n| **SLSA build provenance** (container image) | the `ghcr.io` image digest was built by this repo's `docker.yml` | [`docker.yml`](.github/workflows/docker.yml) — `actions/attest-build-provenance`, `push-to-registry` (lines 141–147) |\n| **PEP 740 attestations** | the PyPI upload itself carries Sigstore-backed attestations under Trusted Publishing | [`publish.yml`](.github/workflows/publish.yml) — `attestations: true` (`publish-pypi` job) |\n| **CycloneDX SBOM** | a machine-readable bill of materials, generated in an unprivileged job from the exact wheel's statically resolved dependency metadata (wheels only, none of it executed), SHA-256-bound to that wheel, then attested against the wheel alone | [`publish.yml`](.github/workflows/publish.yml) — `cyclonedx-py` + `scripts/release_sbom.py` (`sbom` job) + `actions/attest-sbom` (`attest-sbom` job) |\n| **SHA-pinned Actions** | every CI action is pinned to a commit SHA, so the release pipeline itself cannot silently change | all jobs in `.github/workflows/` (e.g. `publish.yml`, `docker.yml`) |\n\nVerify the wheel and the container image against their attestations with the\nGitHub CLI:\n\n```bash\n# Wheel / sdist (download from the PyPI project or the release assets first)\ngh attestation verify s2_mcp_server-*.whl --repo smaniches/semantic-scholar-mcp\n\n# Container image\ngh attestation verify oci://ghcr.io/smaniches/semantic-scholar-mcp:latest \\\n  --repo smaniches/semantic-scholar-mcp\n```\n\nThe full supply-chain posture, including the known-limitations list, is in\n[SECURITY.md](SECURITY.md). This is **release-time** provenance (proving how\nthe artifact was built); the server does not currently attach a per-response\nreceipt to individual API results.\n\n---\n\n## How it compares\n\nThere is no public Semantic Scholar MCP standard, so the most useful\ncomparison is against the obvious alternative: calling the\n[Semantic Scholar REST API](https://api.semanticscholar.org/) yourself from an\nagent. Everything in the right-hand column is plumbing this server already owns\nand the caller would otherwise reimplement.\n\n| | This server | Raw S2 REST API from an agent |\n|---|---|---|\n| Tool surface | 14 typed MCP tools (search, retrieval, recommendations, status) | caller composes raw HTTP requests |\n| Citation graph | both directions (citations and references) in `get_paper` | manual paging over two endpoints |\n| Bulk operations | papers (≤500) and authors (≤1000) in one call | caller batches and paginates |\n| Full-text snippet search | `snippet_search` with surrounding context | separate endpoint, caller-assembled |\n| Paper-ID resolution | seven formats — Semantic Scholar ID, DOI, ArXiv, PubMed, Corpus ID, ACL, URL — validated pre-flight ([`validators.py`](src/semantic_scholar_mcp/validators.py)) | caller normalizes and validates IDs |\n| Rate limiting | client-side per-tier limiter, never exceeds the interval ([`client.py`](src/semantic_scholar_mcp/client.py)) | caller throttles by hand |\n| Retry / backoff | bounded, jittered retry on 429/502/503/timeout, honors `Retry-After` ([`client.py`](src/semantic_scholar_mcp/client.py)) | caller implements retry |\n| Errors | typed exception hierarchy, branchable by caller ([`errors.py`](src/semantic_scholar_mcp/errors.py)) | parse HTTP status strings |\n| Output | chat-tuned Markdown or JSON per call ([`formatters.py`](src/semantic_scholar_mcp/formatters.py)) | raw JSON |\n| Supply-chain provenance | SLSA + PEP 740 + CycloneDX SBOM per release ([see above](#provenance--supply-chain)) | n/a |\n| Citability | minted Zenodo DOI, MIT licensed | n/a |\n\n---\n\n## Installation\n\n### Option 1: One-Line Install (Recommended)\n```bash\n# No cloning needed — runs directly from PyPI\nuvx s2-mcp-server\n```\n\n### Option 2: Claude Code\n```bash\nclaude mcp add semantic-scholar -- uvx s2-mcp-server\n```\n\n### Option 3: Claude Desktop (Windows)\n\nAdd to `%APPDATA%\\Claude\\claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"semantic-scholar\": {\n      \"command\": \"uvx\",\n      \"args\": [\"s2-mcp-server\"],\n      \"env\": {\n        \"SEMANTIC_SCHOLAR_API_KEY\": \"your-key-here\"\n      }\n    }\n  }\n}\n```\n\n### Option 4: Claude Desktop (macOS)\n\nAdd to `~/Library/Application Support/Claude/claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"semantic-scholar\": {\n      \"command\": \"uvx\",\n      \"args\": [\"s2-mcp-server\"],\n      \"env\": {\n        \"SEMANTIC_SCHOLAR_API_KEY\": \"your-key-here\"\n      }\n    }\n  }\n}\n```\n\n### Option 5: pip / From Source\n```bash\npip install s2-mcp-server\n# or\ngit clone https://github.com/smaniches/semantic-scholar-mcp.git\ncd semantic-scholar-mcp && pip install -e .\n```\n\n### Option 6: Docker\n```bash\ndocker pull ghcr.io/smaniches/semantic-scholar-mcp:latest\ndocker run -e SEMANTIC_SCHOLAR_API_KEY=your-key ghcr.io/smaniches/semantic-scholar-mcp\n```\n\n### Option 7: Remote server (Streamable HTTP) — requires ≥ 1.5.0\n```bash\n# Serve MCP over HTTP at http://127.0.0.1:8000/mcp instead of stdio\n# (--from pins the floor: uvx may otherwise reuse a cached older version)\nuvx --from \"s2-mcp-server>=1.5.0\" s2-mcp-server --transport http\n```\nSee [Remote access (Streamable HTTP)](#remote-access-streamable-http) for client\nconfiguration, per-request API keys, and deployment guidance.\n\n> **Note:** Get a free API key at [semanticscholar.org/product/api](https://www.semanticscholar.org/product/api). Without a key, you get rate-limited public access (1 req/sec).\n\n---\n\n## Architecture\n\n```mermaid\nflowchart LR\n  Client[\"MCP client<br/>(Claude Desktop, Claude Code,<br/>Cursor, Cline, Continue, …)\"]\n  subgraph Server [\"s2-mcp-server (this package)\"]\n    direction TB\n    FastMCP[\"FastMCP runtime<br/>(stdio / Streamable HTTP, lifespan)\"]\n    Tools[\"14 @mcp.tool functions<br/>(server.py)\"]\n    Models[\"Pydantic input models<br/>+ field sets (models.py)\"]\n    Validators[\"Paper-ID validator<br/>(validators.py)\"]\n    Cache[\"TTL cache<br/>(cache.py)\"]\n    Fmt[\"Markdown formatters<br/>(formatters.py)\"]\n    HTTP[\"httpx client<br/>+ rate limit + retry/backoff<br/>(client.py)\"]\n    Errors[\"Typed exceptions<br/>(errors.py)\"]\n    Log[\"Structured JSON logger<br/>(logging_config.py)\"]\n  end\n  S2Graph[\"Semantic Scholar<br/>Graph API\"]\n  S2Recs[\"Semantic Scholar<br/>Recommendations API\"]\n\n  Client <-- \"stdio or Streamable HTTP<br/>(JSON-RPC)\" --> FastMCP\n  FastMCP --> Tools\n  Tools --> Models\n  Tools --> Validators\n  Tools --> Cache\n  Tools --> HTTP\n  Tools --> Fmt\n  HTTP --> Errors\n  HTTP --> Log\n  HTTP -- \"GET / POST<br/>x-api-key\" --> S2Graph\n  HTTP -- \"GET / POST<br/>x-api-key\" --> S2Recs\n```\n\n**Module responsibilities** (`src/semantic_scholar_mcp/`):\n\n| Module | Responsibility |\n| --- | --- |\n| `server.py` | FastMCP instance, 14 `@mcp.tool` registrations, lifespan, `main()` entry. Re-exports the helper surface for back-compat. |\n| `transport.py` | Streamable HTTP transport: CLI/env parsing (`--transport http`), uvicorn wiring, and per-request API-key extraction (header / query param / Smithery config) into a request-scoped contextvar. |\n| `client.py` | Shared `httpx.AsyncClient` singleton, per-tier rate limiter (1 req/s public, 10 req/s keyed), retry loop with exponential backoff + jitter on 429/502/503/timeout, HTTP→typed-exception mapping. |\n| `models.py` | Pydantic input models per tool, `ResponseFormat` enum, the four tiered field-set constants (`PAPER_SEARCH_FIELDS`, `…_LITE`, `PAPER_BULK_SEARCH_FIELDS`, `PAPER_DETAIL_FIELDS`, `AUTHOR_FIELDS`). |\n| `validators.py` | Pre-flight paper-ID validation. Rejects NUL bytes, `?`, `#`, path traversal; accepts the seven canonical ID formats. |\n| `cache.py` | In-memory TTL cache (5 min, 200 entries, oldest-first eviction) for paper/author lookups within a session. |\n| `formatters.py` | Markdown renderers for paper and author dicts, tuned for chat-surface readability. |\n| `errors.py` | `SemanticScholarError` hierarchy: `AuthenticationError`, `RateLimitError`, `NotFoundError`, `ValidationError`, `ServerError`. |\n| `logging_config.py` | One-JSON-per-line `StructuredFormatter` on stderr; safe to ship through any log aggregator. |\n\n**Design choices worth knowing**\n\n- **Single `httpx.AsyncClient` per process.** Created lazily, closed in the FastMCP lifespan teardown. Amortizes connection setup; respects keep-alive limits. The lifespan is reference-counted: under the Streamable HTTP transport the SDK enters it per request, so teardown only runs when the last holder exits.\n- **Rate limit is enforced at the client, not the API.** A semaphore + last-request timestamp ensures we never exceed the per-tier interval even when the MCP host issues tool calls in parallel.\n- **Retry is bounded and jittered.** Up to `MAX_RETRIES = 3`, base 1 s, capped at 30 s. Honors `Retry-After` when present.\n- **Errors are typed.** Status codes map onto a small exception hierarchy so callers can branch on `AuthenticationError` vs `RateLimitError` vs `NotFoundError` instead of parsing strings.\n- **Input validation is pre-flight.** Paper IDs are checked before any outbound request; bad IDs never hit the wire.\n- **Version is single-source.** `__version__` is derived from `importlib.metadata.version(\"s2-mcp-server\")`, so bumping `pyproject.toml` is sufficient; release-please bumps the manifest, `server.json` (×2 paths), `CITATION.cff`, and `.zenodo.json` in lockstep on every release.\n\n---\n\n## Configuration\n\n### API Key Options\n\nYou can provide your API key in three ways:\n\n1. **Environment Variable** (recommended for persistent use):\n   ```bash\n   export SEMANTIC_SCHOLAR_API_KEY=\"your-api-key-here\"\n   ```\n\n2. **Per-request HTTP header** (Streamable HTTP transport only): send\n   `x-api-key: your-key` with each request — see\n   [Remote access (Streamable HTTP)](#remote-access-streamable-http).\n\n3. **Per-Request Parameter** (overrides env var):\n   ```json\n   {\n     \"api_key\": \"your-api-key-here\"\n   }\n   ```\n\n   > **Deprecated:** per-request `api_key` is deprecated and will be removed\n   > in v2.0.0. Tool-call arguments may be visible in MCP transcripts, client\n   > logs, and the LLM's tool-call history. Use the `SEMANTIC_SCHOLAR_API_KEY`\n   > environment variable instead. See [SECURITY.md](SECURITY.md) for details.\n\nGet a free API key at: https://www.semanticscholar.org/product/api\n\n### Claude Desktop Setup\n\nAdd to your Claude Desktop config file:\n\n**Windows:** `%APPDATA%\\Claude\\claude_desktop_config.json`\n**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`\n**Linux:** `~/.config/Claude/claude_desktop_config.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"semantic-scholar\": {\n      \"command\": \"python\",\n      \"args\": [\"-m\", \"semantic_scholar_mcp\"],\n      \"env\": {\n        \"SEMANTIC_SCHOLAR_API_KEY\": \"your-api-key-here\"\n      }\n    }\n  }\n}\n```\n\nThen **restart Claude Desktop**.\n\n---\n\n## Remote access (Streamable HTTP)\n\nstdio remains the default transport. `--transport http` serves the same 14\ntools over the [MCP Streamable HTTP transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#streamable-http),\nwhich is what remote clients — claude.ai custom connectors, Smithery\nlistings, `mcp-remote` bridges — connect to.\n\n> **Requires `s2-mcp-server` ≥ 1.5.0.** Earlier releases (≤ 1.4.0) do not\n> parse CLI flags: they silently ignore `--transport http` and start a stdio\n> server instead, never opening the port.\n\n```bash\n# Local HTTP endpoint at http://127.0.0.1:8000/mcp\n# (--from pins the floor: uvx may otherwise reuse a cached older version)\nuvx --from \"s2-mcp-server>=1.5.0\" s2-mcp-server --transport http\n\n# Bind a public interface and custom port (only behind a TLS proxy — see Security)\nuvx --from \"s2-mcp-server>=1.5.0\" s2-mcp-server --transport http --host 0.0.0.0 --port 8080\n\n# Docker\ndocker run -p 8000:8000 ghcr.io/smaniches/semantic-scholar-mcp --transport http\n```\n\n### Flags and environment variables\n\n| Flag | Env var | Default | Meaning |\n| --- | --- | --- | --- |\n| `--transport` | `MCP_TRANSPORT` | `stdio` | `stdio`, `http` (alias: `streamable-http`) |\n| `--host` | `MCP_HOST` | `127.0.0.1` | Bind address (`0.0.0.0` in the Docker image) |\n| `--port` | `MCP_PORT`, then `PORT` | `8000` | Bind port (`PORT` is honored for hosting platforms) |\n| `--path` | `MCP_PATH` | `/mcp` | URL path of the MCP endpoint |\n| — | `MCP_STATELESS_HTTP` | `true` | One independent server interaction per request (recommended) |\n| — | `MCP_JSON_RESPONSE` | `true` | Plain JSON responses instead of SSE streams |\n\nCLI flags beat environment variables. The server is stateless and returns\nJSON by default — the configuration recommended for production Streamable\nHTTP deployments — and no tool relies on sessions, streaming, or\nserver-initiated messages, so there is no functional trade-off.\n\n### Per-request API keys (bring your own key)\n\nWhen served over HTTP, each request may carry its own Semantic Scholar API\nkey; concurrent users never share or observe each other's keys. Sources, in\nprecedence order:\n\n1. `x-api-key` HTTP header (recommended)\n2. `SEMANTIC_SCHOLAR_API_KEY` query parameter (Smithery session config)\n3. `api_key` query parameter\n4. Legacy base64 `?config=` parameter (older Smithery deployments)\n\nA request without a key falls back to the server's `SEMANTIC_SCHOLAR_API_KEY`\nenvironment variable, or to keyless public-tier access.\n\n### Client configuration\n\n**Claude Code**\n\n```bash\nclaude mcp add --transport http semantic-scholar http://127.0.0.1:8000/mcp \\\n  --header \"x-api-key: your-key-here\"\n```\n\n**JSON config (clients that accept a `url`)**\n\n```json\n{\n  \"mcpServers\": {\n    \"semantic-scholar\": {\n      \"type\": \"http\",\n      \"url\": \"http://127.0.0.1:8000/mcp\",\n      \"headers\": { \"x-api-key\": \"your-key-here\" }\n    }\n  }\n}\n```\n\n**claude.ai custom connectors** require a public HTTPS URL and accept either\nauthless servers or OAuth — API keys in the connector URL are not supported\nby claude.ai. Host the server with the key supplied server-side\n(`SEMANTIC_SCHOLAR_API_KEY` env var) and register the public `/mcp` URL as\nthe connector.\n\n**Smithery** lists remote servers by URL (`smithery mcp publish <url>`); the\nper-request key extraction above is compatible with Smithery session config\nout of the box.\n\n### Security notes\n\n- The HTTP transport performs **no authentication of inbound callers**. The\n  default bind is loopback (`127.0.0.1`). Expose it publicly only behind a\n  TLS-terminating reverse proxy, and prefer the `x-api-key` header over query\n  parameters (URLs end up in access logs).\n- API keys are request-scoped, and the server itself never logs them. (A key\n  placed in a URL query parameter can still appear in access logs, as noted\n  above — prefer the `x-api-key` header.)\n- See [SECURITY.md](SECURITY.md) for the project's broader threat model.\n\n---\n\n## Supported ID Formats\n\nThe server accepts the following paper identifier formats:\n\n| Format | Pattern | Example |\n|--------|---------|---------|\n| Semantic Scholar ID | 40-character hex | `649def34f8be52c8b66281af98ae884c09aef38b` |\n| DOI | `DOI:xxx` | `DOI:10.1038/s41586-021-03819-2` |\n| ArXiv | `ARXIV:xxx` | `ARXIV:2106.15928` or `ARXIV:2106.15928v2` |\n| PubMed | `PMID:xxx` | `PMID:32908142` |\n| Corpus ID | `CorpusId:xxx` | `CorpusId:215416146` |\n| ACL | `ACL:xxx` | `ACL:P19-1285` |\n| URL | `URL:xxx` | `URL:https://arxiv.org/abs/2106.15928` |\n\n---\n\n## Tools Reference\n\n### 1. `semantic_scholar_search_papers`\n\nSearch for academic papers with advanced filters.\n\n**Parameters:**\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `query` | string | Yes | Search query (supports AND, OR, NOT operators and \"phrase search\") |\n| `year` | string | No | Year filter: `\"2024\"`, `\"2020-2024\"`, or `\"2020-\"` |\n| `fields_of_study` | string[] | No | Filter by fields: `[\"Computer Science\", \"Biology\"]` |\n| `publication_types` | string[] | No | Filter by type: `[\"Review\", \"JournalArticle\"]` |\n| `open_access_only` | boolean | No | Only return open access papers (default: false) |\n| `min_citation_count` | integer | No | Minimum citation count |\n| `limit` | integer | No | Max results 1-100 (default: 10) |\n| `offset` | integer | No | Pagination offset (default: 0) |\n| `response_format` | string | No | `\"markdown\"` or `\"json\"` (default: markdown) |\n| `api_key` | string | No | Override environment API key |\n\n**Example:**\n```\nSearch for \"transformer attention mechanism\" papers from 2023 with at least 100 citations\n```\n\n**JSON Example:**\n```json\n{\n  \"query\": \"transformer attention mechanism\",\n  \"year\": \"2023\",\n  \"min_citation_count\": 100,\n  \"fields_of_study\": [\"Computer Science\"],\n  \"limit\": 20\n}\n```\n\n---\n\n### 2. `semantic_scholar_get_paper`\n\nGet detailed information about a specific paper.\n\n**Parameters:**\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `paper_id` | string | Yes | Paper ID in any supported format |\n| `include_citations` | boolean | No | Include citing papers (default: false) |\n| `include_references` | boolean | No | Include referenced papers (default: false) |\n| `citations_limit` | integer | No | Max citations to return 1-100 (default: 10) |\n| `references_limit` | integer | No | Max references to return 1-100 (default: 10) |\n| `response_format` | string | No | `\"markdown\"` or `\"json\"` (default: markdown) |\n| `api_key` | string | No | Override environment API key |\n\n**Example:**\n```\nGet details for DOI:10.1038/s41586-021-03819-2 including its top 20 citations\n```\n\n**JSON Example:**\n```json\n{\n  \"paper_id\": \"DOI:10.1038/s41586-021-03819-2\",\n  \"include_citations\": true,\n  \"citations_limit\": 20\n}\n```\n\n---\n\n### 3. `semantic_scholar_search_authors`\n\nSearch for academic authors by name.\n\n**Parameters:**\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `query` | string | Yes | Author name to search |\n| `limit` | integer | No | Max results 1-100 (default: 10) |\n| `offset` | integer | No | Pagination offset (default: 0) |\n| `response_format` | string | No | `\"markdown\"` or `\"json\"` (default: markdown) |\n| `api_key` | string | No | Override environment API key |\n\n**Example:**\n```\nFind author \"Yoshua Bengio\"\n```\n\n**JSON Example:**\n```json\n{\n  \"query\": \"Yoshua Bengio\",\n  \"limit\": 5\n}\n```\n\n---\n\n### 4. `semantic_scholar_get_author`\n\nGet author profile with publications.\n\n**Parameters:**\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `author_id` | string | Yes | Semantic Scholar author ID |\n| `include_papers` | boolean | No | Include publications (default: true) |\n| `papers_limit` | integer | No | Max papers to return 1-100 (default: 20) |\n| `response_format` | string | No | `\"markdown\"` or `\"json\"` (default: markdown) |\n| `api_key` | string | No | Override environment API key |\n\n**Example:**\n```\nGet author profile for author ID 1741101 with their top 50 publications\n```\n\n**JSON Example:**\n```json\n{\n  \"author_id\": \"1741101\",\n  \"include_papers\": true,\n  \"papers_limit\": 50\n}\n```\n\n---\n\n### 5. `semantic_scholar_recommendations`\n\nGet AI-powered paper recommendations based on a seed paper.\n\n**Parameters:**\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `paper_id` | string | Yes | Seed paper ID in any supported format |\n| `from_pool` | string | No | Recommendation pool: `\"recent\"` (default) or `\"all-cs\"` |\n| `limit` | integer | No | Max recommendations 1-100 (default: 10) |\n| `response_format` | string | No | `\"markdown\"` or `\"json\"` (default: markdown) |\n| `api_key` | string | No | Override environment API key |\n\n**Example:**\n```\nGet recommendations based on paper 649def34f8be52c8b66281af98ae884c09aef38b\n```\n\n**JSON Example:**\n```json\n{\n  \"paper_id\": \"ARXIV:1706.03762\",\n  \"limit\": 15\n}\n```\n\n---\n\n### 6. `semantic_scholar_bulk_papers`\n\nRetrieve multiple papers in a single request (max 500).\n\n**Parameters:**\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `paper_ids` | string[] | Yes | List of paper IDs (max 500) |\n| `response_format` | string | No | `\"markdown\"` or `\"json\"` (default: json) |\n| `api_key` | string | No | Override environment API key |\n\n**Example:**\n```\nRetrieve these papers: DOI:10.1038/nature12373, ARXIV:2106.15928, PMID:32908142\n```\n\n**JSON Example:**\n```json\n{\n  \"paper_ids\": [\n    \"DOI:10.1038/nature12373\",\n    \"ARXIV:2106.15928\",\n    \"PMID:32908142\"\n  ]\n}\n```\n\n---\n\n### 7. `semantic_scholar_bulk_search`\n\nSearch papers with sorting and cursor-based pagination for large result sets.\nUnlike `search_papers`, supports a `sort` order and returns a `token` for\npaging through all results.\n\n**Parameters:**\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `query` | string | Yes | Search query |\n| `sort` | string | No | Sort order, e.g. `\"citationCount:desc\"`, `\"publicationDate:asc\"` |\n| `token` | string | No | Continuation token from a previous bulk_search response |\n| `year` | string | No | Year filter: `\"2024\"`, `\"2020-2024\"`, `\"2020-\"` |\n| `fields_of_study` | string[] | No | Filter by fields: `[\"Computer Science\"]` |\n| `publication_types` | string[] | No | Filter by type: `[\"Review\", \"JournalArticle\"]` |\n| `min_citation_count` | integer | No | Minimum citation count |\n| `limit` | integer | No | Max results per page 1-1000 (default: 100) |\n| `response_format` | string | No | `\"markdown\"` or `\"json\"` (default: markdown) |\n| `api_key` | string | No | Override environment API key |\n\n**JSON Example:**\n```json\n{\n  \"query\": \"graph neural networks\",\n  \"sort\": \"citationCount:desc\",\n  \"year\": \"2020-2024\",\n  \"limit\": 100\n}\n```\n\n**Returns:** total result count, the page of papers, and a `token` for the\nnext page (when more results exist).\n\n---\n\n### 8. `semantic_scholar_export_citation`\n\nExport a citation for a paper in BibTeX format.\n\n**Parameters:**\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `paper_id` | string | Yes | Paper ID in any supported format |\n| `format` | string | No | Citation format (currently only `\"bibtex\"`) |\n| `api_key` | string | No | Override environment API key |\n\n**JSON Example:**\n```json\n{\n  \"paper_id\": \"DOI:10.1038/s41586-021-03819-2\",\n  \"format\": \"bibtex\"\n}\n```\n\n**Returns:** the BibTeX string for the requested paper.\n\n---\n\n### 9. `semantic_scholar_match_paper`\n\nFind the single best paper matching a title string. Returns a numeric\n`matchScore` alongside the matched paper.\n\n**Parameters:**\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `query` | string | Yes | Paper title to match (1-500 chars) |\n| `response_format` | string | No | `\"markdown\"` or `\"json\"` (default: markdown) |\n| `api_key` | string | No | Override environment API key |\n\n**JSON Example:**\n```json\n{\n  \"query\": \"Attention Is All You Need\"\n}\n```\n\n**Returns:** the best-matching paper plus its `matchScore`, or \"No matching\npaper found.\" if no match.\n\n---\n\n### 10. `semantic_scholar_paper_authors`\n\nGet full author profiles for a paper's authors (richer than the abbreviated\nauthor list returned by `get_paper`).\n\n**Parameters:**\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `paper_id` | string | Yes | Paper ID in any supported format |\n| `limit` | integer | No | Max authors to return 1-1000 (default: 100) |\n| `response_format` | string | No | `\"markdown\"` or `\"json\"` (default: markdown) |\n| `api_key` | string | No | Override environment API key |\n\n**JSON Example:**\n```json\n{\n  \"paper_id\": \"ARXIV:1706.03762\",\n  \"limit\": 25\n}\n```\n\n**Returns:** the list of full author records for the paper.\n\n---\n\n### 11. `semantic_scholar_author_batch`\n\nRetrieve multiple authors in a single request (max 1000).\n\n**Parameters:**\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `author_ids` | string[] | Yes | List of author IDs (1-1000) |\n| `response_format` | string | No | `\"markdown\"` or `\"json\"` (default: json) |\n| `api_key` | string | No | Override environment API key |\n\n**JSON Example:**\n```json\n{\n  \"author_ids\": [\"1741101\", \"40348417\", \"144749327\"]\n}\n```\n\n**Returns:** counts of `requested` / `retrieved`, the retrieved author\nrecords, and a `not_found` list of IDs the API did not return.\n\n---\n\n### 12. `semantic_scholar_multi_recommend`\n\nGet recommendations using multiple positive (and optional negative) example\npapers.\n\n**Parameters:**\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `positive_paper_ids` | string[] | Yes | Papers to find similar results for (1-100) |\n| `negative_paper_ids` | string[] | No | Papers to steer recommendations away from (0-100) |\n| `limit` | integer | No | Max recommendations 1-500 (default: 10) |\n| `response_format` | string | No | `\"markdown\"` or `\"json\"` (default: markdown) |\n| `api_key` | string | No | Override environment API key |\n\n**JSON Example:**\n```json\n{\n  \"positive_paper_ids\": [\"ARXIV:1706.03762\", \"ARXIV:1810.04805\"],\n  \"negative_paper_ids\": [\"DOI:10.1038/nature14539\"],\n  \"limit\": 20\n}\n```\n\n**Returns:** the recommended papers plus an echo of the positive/negative\nseeds used.\n\n---\n\n### 13. `semantic_scholar_snippet_search`\n\nSearch within paper full text and return text snippets with surrounding\ncontext. **Heavily rate-limited without an API key.**\n\n**Parameters:**\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `query` | string | Yes | Search query for paper text (1-500 chars) |\n| `paper_ids` | string[] | No | Limit search to specific papers (max 100) |\n| `year` | string | No | Year filter: `\"2024\"`, `\"2020-2024\"`, `\"2020-\"` |\n| `fields_of_study` | string[] | No | Filter by fields: `[\"Computer Science\"]` |\n| `min_citation_count` | integer | No | Minimum citation count |\n| `limit` | integer | No | Max results 1-100 (default: 10) |\n| `response_format` | string | No | `\"markdown\"` or `\"json\"` (default: markdown) |\n| `api_key` | string | No | Override environment API key |\n\n**JSON Example:**\n```json\n{\n  \"query\": \"scaling laws for language models\",\n  \"year\": \"2022-2024\",\n  \"limit\": 20\n}\n```\n\n**Returns:** matching snippets, each with the source paper title, section,\nand a short text excerpt.\n\n---\n\n### 14. `semantic_scholar_status`\n\nCheck server health and API connectivity status.\n\n**Parameters:** None\n\n**Example:**\n```\nCheck Semantic Scholar API status\n```\n\n**Response:**\n```json\n{\n  \"server\": \"semantic-scholar-mcp\",\n  \"version\": \"<current package version>\",\n  \"api_key_configured\": true,\n  \"rate_tier\": \"authenticated (10 req/sec)\",\n  \"timestamp\": \"2026-04-06T12:00:00.000000+00:00\",\n  \"api_reachable\": true,\n  \"rate_limited\": false,\n  \"retry_after\": null\n}\n```\n\n---\n\n## Rate Limits\n\n| Tier | Requests/Second | How to Get |\n|------|-----------------|------------|\n| No API Key | 1 req/sec | Default |\n| API Key | 10 req/sec | [Sign up](https://www.semanticscholar.org/product/api) (free) |\n| Academic Partner | 10-100 req/sec | Apply via S2 |\n\n> **Note:** The client-side rate limiter enforces the intervals above. The upstream Semantic Scholar API may impose stricter limits during high-traffic periods.\n\nThe server automatically handles rate limiting with:\n- Request serialization to enforce minimum intervals\n- Exponential backoff retry for 429 (rate limit), 502 (bad gateway), and 503 (service unavailable) errors\n- Maximum 3 retries with jitter\n\n---\n\n## Development\n\n```bash\n# Clone\ngit clone https://github.com/smaniches/semantic-scholar-mcp.git\ncd semantic-scholar-mcp\n\n# Install dev dependencies\npip install -e \".[dev]\"\n\n# Run tests\npytest\n\n# Run tests with coverage\npytest --cov=src/semantic_scholar_mcp --cov-report=term-missing\n\n# Type checking\nmypy src/\n```\n\n---\n\n## Security\n\nAPI keys are never persisted to disk by the server. When the server makes\nauthenticated requests, the key is sent **only** to `api.semanticscholar.org`\nover HTTPS as the `x-api-key` header. No telemetry is sent to any third\nparty. Under the default stdio transport the server runs locally on your\nmachine; if you connect to a **remotely hosted** instance over\n[Streamable HTTP](#remote-access-streamable-http), your per-request key also\ntransits that endpoint's operator before being forwarded to Semantic Scholar\n— only send keys to remote endpoints you trust, and only over HTTPS.\n\nPrefer the `SEMANTIC_SCHOLAR_API_KEY` environment variable over the\nper-request `api_key` tool parameter. The per-request parameter is\n**deprecated** (removal planned for v2.0.0) because tool-call arguments may\nbe visible in MCP transcripts and client logs. See [SECURITY.md](SECURITY.md)\nfor vulnerability reporting and the known-limitations list.\n\n---\n\n## Related MCP servers by the same author\n\n- [`alphafold-sovereign-mcp`](https://github.com/smaniches/alphafold-sovereign-mcp) — Model Context Protocol server for AlphaFold DB and other public biomedical data sources, with a local SQLite knowledge graph (`pip install alphafold-sovereign-mcp`).\n- [`uniprot-mcp`](https://github.com/smaniches/uniprot-mcp) — Model Context Protocol server for UniProt Swiss-Prot and TrEMBL (`pip install uniprot-mcp-server`).\n\n---\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file.\n\n---\n\n## Author\n\n**Santiago Maniches**\n- Founder & CEO, [TOPOLOGICA LLC](https://topologica.ai)\n- ORCID: [0009-0005-6480-1987](https://orcid.org/0009-0005-6480-1987)\n- LinkedIn: [santiago-maniches](https://www.linkedin.com/in/santiagomaniches/)\n- Website: [topologica.ai](https://topologica.ai)\n\n---\n\n## Contributing\n\nContributions welcome! Please read our [Contributing Guidelines](CONTRIBUTING.md).\n\n---\n\n## Support\n\n- Issues: [GitHub Issues](https://github.com/smaniches/semantic-scholar-mcp/issues)\n- Contact: santiago@topologica.ai\n\n---\n\n<p align=\"center\">\n  <b>Built by <a href=\"https://topologica.ai\">TOPOLOGICA LLC</a></b>\n</p>\n",
  "bytes": 33372,
  "sha": "47fa363d5634be44fac67369a0052ab1fc593ef3378a4e731b098812adfb311d",
  "repo_slug": "smaniches/semantic-scholar-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_smaniches_semantic_scholar_mcp_764712fa/readme"
}