@cyanheads/cern-inspire-mcp-server
MCP serverSearchSearch INSPIRE-HEP papers, authors, experiments, HEPData records; get citation metrics and BibTeX.
Available today. Use it from your connected AI after setup.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the cern inspire search literature tool from @cyanheads/cern-inspire-mcp-server
Install @cyanheads/cern-inspire-mcp-server
The server’s own address, for the clients that take one directly. Or connect ahel once and every client you use reads it from one address, with the account kept on ahel rather than in each client’s config.
Claude Code
claude mcp add --transport http --scope user cyanheads-cern-inspire-mcp-serve 'https://cern-inspire.caseyjhand.com/mcp'Run it once in your project, then open /mcp to approve any sign-in the server asks for.
Claude Desktop
https://cern-inspire.caseyjhand.com/mcpAdd a custom connector in Settings, paste this address, and approve the sign-in.
Cursor
cursor://anysphere.cursor-deeplink/mcp/install?name=cyanheads-cern-inspire-mcp-serve&config=eyJ1cmwiOiJodHRwczovL2Nlcm4taW5zcGlyZS5jYXNleWpoYW5kLmNvbS9tY3AifQ==Open the link and Cursor adds the server at that address.
ChatGPT
https://cern-inspire.caseyjhand.com/mcpIn Settings, enable Developer mode, create an MCP app, and paste this address. Your plan and workspace must allow custom apps.
Codex
codex mcp add cyanheads-cern-inspire-mcp-serve --url 'https://cern-inspire.caseyjhand.com/mcp'Run it once, then sign in with codex mcp login cyanheads-cern-inspire-mcp-serve if the server asks for an account.
From the project's README
As published by cyanheads/cern-inspire-mcp-server in README.md.
Public Hosted Server: https://cern-inspire.caseyjhand.com/mcp
Overview
High-energy-physics literature from INSPIRE-HEP, including its index of HEPData measurement records. Search papers, authors, and experiments, read a paper's full record, compute citation summaries, h-indices, and citations per year, export BibTeX or LaTeX entries, and find the HEPData record that holds a paper's numerical tables. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
Tools
| Tool | Description |
|---|---|
cern_inspire_search_literature | Search papers with INSPIRE query syntax or free text, filtered by document type, subject, and year |
cern_inspire_get_paper | Fetch one paper's full record by recid, arXiv ID, or DOI, with its HEPData availability |
cern_inspire_export_citations | Export INSPIRE's BibTeX or LaTeX \bibitem entries for the papers a query selects |
cern_inspire_search_authors | Find physicist profiles by name, BAI, ORCID, INSPIRE ID, or author recid |
cern_inspire_get_citation_summary | h-index, citation totals, citation buckets, and citations per year for one author or any literature query |
cern_inspire_search_experiments | Find experiments, collaborations, and facilities, with a query that selects their papers |
cern_inspire_search_hepdata | Find HEPData measurement records by process, observable, energy, or collaboration |
cern_inspire_list_reference | Decode query syntax, identifier forms, filter values, citation buckets, and HEPData DOIs |
Resources
| Resource | Description |
|---|---|
inspire://literature/{recid} | One literature record as the cern_inspire_get_paper dossier in JSON |
The same record is reachable through cern_inspire_get_paper for clients that don't surface resources.
Capability reference
cern_inspire_search_literature tool
- INSPIRE query syntax or free text, with
sort(relevance,mostrecent,mostcited),document_typesandsubjects(up to 4 values each, all must hold), andyear_from/year_to;size1–100 (default 10), paged bypage - Only the first 10,000 results of a query are reachable:
page × sizebeyond that fails asbeyond_result_window; a reversed year range fails asinvalid_year_range - Hits carry
recid, title, first author, date, citation counts, arXiv ID, DOI, publication, and a 300-character abstract snippet; the page also returnstotalCount,nextPage, andappliedFilters, and anoticeflags queries matching over 100,000 records
cern_inspire_get_paper tool
papertakes a recid, arXiv ID, DOI, inspirehep.net literature URL, or HEPDatains<recid>/ hepdata.netrecord/ins<recid>URL;resolvedAsnames the form that matched, and a miss fails aspaper_not_found. A recid INSPIRE has merged into another record (older citations and HEPDatainslinks still carry such recids) returns the record INSPIRE redirects it to, withmergedFromnaming the recid asked for and a notice. A numbered hepdata.net record link, or a HEPData DOI no paper carries, names a HEPData record rather than a paper: its error gives thecern_inspire_search_hepdataquery whosepaperRecidsreach the papermax_authors0–500 (default 25) caps the author list;authorCountalways gives the full numberhepdata.statusisavailable,none, orlookup_failed, withrecordDoi,latestVersion,tableCount, andhepdataUrl(the hepdata.net page of that record number) when available; a paper with more than one HEPData record lists the rest inhepdata.otherRecords, with a notice;citingQueryandreferencesQueryfeedcern_inspire_search_literature
cern_inspire_export_citations tool
- Any literature query (
recid:451647 or arxiv:1207.7214for named papers);formatisbibtex(default),latex-eu, orlatex-us;sortas in search;size1–50 (default 10) per page, paged bypageup to the first 10,000 matches (beyond that,beyond_result_window) - Entries arrive verbatim from INSPIRE, each with its
texkey;truncatedis set when more matched papers follow the page,nextPagewith it while the next page is within the 10,000-result window, and a page past the last returns no entries with a notice naming the last page
cern_inspire_search_authors tool
- A name or one identifier (BAI, ORCID, INSPIRE ID, author recid);
limit1–25 (default 5) matchedAsisorcid,inspire_id,bai, orrecid(exact match), orname(free-text search returning ranked candidates to choose from)- Profiles carry
recid,bai, ORCID, positions (with aninstitutionRecidthataffid:Ntakes for the institution's papers), advisors, arXiv categories, awards, and aliteratureQueryselecting the person's papers
cern_inspire_get_citation_summary tool
- Exactly one of
author(BAI, ORCID, INSPIRE ID, or author recid) orquery(any literature query, such asaffid:902725for an institution's papers); otherwisemissing_target, and a name passed asauthorfails asauthor_not_identifier document_typesandsubjectsnarrow every figure;year_from/year_tonarrow the summary, andexclude_self_citationsdrops self-citations from it- h-index, citation totals and averages, and paper counts in the buckets
0,1–9,10–49,50–99,100–249,250–499,500+, each for all citeable and for published papers citationsByYear: citations received per year (the citing record's year, self-citations included, every matched record), ascending, with no row for a year without citations; left out, with a notice, underyear_from,year_to, orexclude_self_citations, which INSPIRE's per-year series cannot apply, when INSPIRE does not return it, and for a query matching more than about 150,000 records, which INSPIRE cannot count in time, unless INSPIRE answers within about 2 s (a series it has cached); the call then returns in about 2 s- An unfiltered call spends two of the pacer's request starts (three with
author, which is resolved first); withyear_from,year_to, orexclude_self_citationsset, one (two). The per-year request holds one of the pacer's four in-flight slots for as long as INSPIRE takes (up to 15 s), so at most two per-year series run at once and other calls keep at least two slots
cern_inspire_search_experiments tool
- An experiment, collaboration, accelerator, or facility name, an INSPIRE legacy name (
CERN-LHC-CMS), or an experiment recid (digits only);limit1–25 (default 5) - Records carry the accelerator, host institutions, collaboration, lifecycle dates,
ongoing(omitted when INSPIRE records neither state), INSPIRE's paper count, and aliteratureQueryforcern_inspire_search_literatureorcern_inspire_get_citation_summary
cern_inspire_search_hepdata tool
- Free text or INSPIRE syntax over HEPData submissions (
collaborations.value:LHCb,literature.control_number:<recid>);sortisrelevanceormostrecent;size1–50 (default 10), within the same 10,000-result window - Records carry
paperRecids, collaborations, keywords (reactions, observables, centre-of-mass energies),recordDoi,latestVersion,tableCount, andhepdataUrl(each record's own hepdata.net page); table values are not returned
cern_inspire_list_reference tool
topic:search_syntax,identifiers,document_types,subjects,citation_buckets, orhepdata- Static
term/meaning/exampleentries; no upstream call
inspire://literature/{recid} resource
- The
cern_inspire_get_paperdossier asapplication/json, listing the first 25 authors - Takes a recid only; use the tool for arXiv IDs, DOIs, or a higher author cap. A merged recid serves the surviving record, with
mergedFrom
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
INSPIRE-specific:
- One process-wide pacer under INSPIRE's published limit of 15 requests per 5 s: 12 request starts per 5 s, at most 4 in flight (no more than 2 of them slow citations-per-year requests), and a shared cooldown after a 429 that starts at 5 s and doubles on each consecutive 429, up to 30 s
- One 55 s budget per tool call covers queue wait, up to 2 retries, and every request the call makes; a request that can't start in time fails at once as
pacer_shedwith aretryAfter - Requests select only the fields a tool returns, under an 8 MiB response ceiling; author email addresses are never requested
- Forgiving inputs: paper identifiers accept
arXiv:/doi:prefixes, version suffixes, arxiv.org, doi.org, or inspirehep.net URLs, and HEPData'sins<recid>, a recid INSPIRE has merged away is followed to the surviving record, and every documented spelling passes a client's validation against the advertised schema; author identifiers accept an orcid.org URL
Agent-friendly output:
- Chainable identifiers: hits carry
recid, author profiles and experiments carry a readyliteratureQuery, andcern_inspire_get_paperreturnscitingQueryandreferencesQuery - Query echo and paging state:
totalCount,truncated/shown/cap,nextPage,appliedFilters, andeffectiveQuery, plus anoticewith next-step text on empty, capped, or suspiciously broad results - Discriminated fields:
hepdata.status,resolvedAs,matchedAs, andtarget.kindlet callers branch on data; typed failure reasons (paper_not_found,author_not_found,beyond_result_window,inspire_rate_limited) each carry a recovery hint - No fabrication: a field INSPIRE leaves out stays absent and prints as "Not available" or "not recorded"
- Titles and abstracts as text: publisher HTML, JATS, and MathML become plain text (
σ_γ,^{23}Na(n,γ)) on every tool that returns titles or abstracts and on the resource, with LaTeX left as published; citation export entries stay verbatim, and other upstream strings reachstructuredContentas INSPIRE sends them, less any invisible Unicode tag characters, which are dropped. The text output escapes them all, leaving identifiers such as DOIs and texkeys copyable as written
Data and licensing
- INSPIRE-HEP metadata is mostly CC0 under INSPIRE's terms of use; credit INSPIRE when you reuse it.
- HEPData records are CC0; cite the HEPData record DOI (
recordDoi) when you reuse the data. - This is an independent project, not affiliated with or endorsed by INSPIRE-HEP, HEPData, or CERN.
Known limitations
- No HEPData table values. hepdata.net's bot challenge refuses the server's User-Agent, so the server never calls it.
cern_inspire_get_paperandcern_inspire_search_hepdatareturn the record DOI and the hepdata.net page where the values are read. - Malformed INSPIRE syntax doesn't fail. An unparsed operator widens or empties the match; zero hits or a very large
totalCountusually means a syntax slip (cern_inspire_list_referencetopicsearch_syntax). - 10,000-result window. Only the first 10,000 results of a query are reachable; narrow the query to reach the rest.
- Shared request queue. All callers of one server process share one queue under INSPIRE's 15 requests per 5 s per address, so a burst can delay or shed other calls with a retryable rate-limit error.
Getting started
Public Hosted Instance
A public instance is available at https://cern-inspire.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"cern-inspire-mcp-server": {
"type": "streamable-http",
"url": "https://cern-inspire.caseyjhand.com/mcp"
}
}
}
Every caller of the hosted instance shares one INSPIRE request budget of 12 request starts per 5 seconds. For sustained use, run your own instance.
Self-Hosted / Local
Add the following to your MCP client configuration file. No API key is needed.
{
"mcpServers": {
"cern-inspire-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/cern-inspire-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"cern-inspire-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/cern-inspire-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"cern-inspire-mcp-server": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/cern-inspire-mcp-server:latest"]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
Prerequisites
- Bun v1.4.0 or higher (or Node.js v24+).
- Nothing else: INSPIRE-HEP's API is public and keyless.
Installation
- Clone the repository:
git clone https://github.com/cyanheads/cern-inspire-mcp-server.git
- Navigate into the directory:
cd cern-inspire-mcp-server
- Install dependencies:
bun install
- Configure environment (optional):
cp .env.example .env
# edit .env to change the transport, logging, or session settings
Configuration
The server has no settings of its own: INSPIRE needs no key, and the request pacing is fixed in code. These framework variables cover most deployments.
| Variable | Description | Default |
|---|---|---|
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | HTTP server port. | 3010 |
MCP_SESSION_MODE | HTTP session mode: stateless, stateful, or auto. .env.example and the Docker image set stateless. | auto |
MCP_AUTH_MODE | Authentication: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (debug, info, notice, warning, error, etc.). The Docker image sets info. | debug |
LOGS_DIR | Directory for log files (Node.js only). | <app-root>/logs |
STORAGE_PROVIDER_TYPE | Storage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1. | in-memory |
OTEL_ENABLED | Enable OpenTelemetry. | false |
See .env.example for the full list of framework overrides.
Running the server
Local development
-
Build and run the production version:
# One-time build bun run rebuild # Run the built server bun run start:http # or bun run start:stdio -
Run checks and tests:
bun run devcheck # Lints, formats, type-checks, and more bun run test # Runs the test suite
Project structure
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point: registers tools and resource, sets server instructions, starts and disposes the INSPIRE service. |
src/mcp-server/tools | Tool definitions (*.tool.ts) and shared input schemas (inputs.ts). |
src/mcp-server/resources | The literature record resource. |
src/services/inspire | INSPIRE service: pacer, per-call budget, retries, identifier routing, normalization, controlled vocabularies. |
src/services/http | Bounded fetch: per-attempt timeout and response byte ceiling. |
src/utils | Escaping for upstream text in tool output and error messages (render.ts). |
tests/ | Vitest suites with INSPIRE response fixtures. |
docs/design.md | Tool surface, verified INSPIRE behavior, design decisions, and the deferred HEPData-direct tools. |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Every INSPIRE request goes through
InspireService, with the call opened bybeginCall(ctx); handlers neverfetchdirectly - Register new tools and resources in the barrels at
src/mcp-server/tools/definitions/index.tsandsrc/mcp-server/resources/definitions/index.ts - Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
License
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
Tools it offers (8)
What this server listed when ahel dialed its public endpoint in Oct 2026, with no key and no account of yours. The names are the server’s own.
cern_inspire_search_literaturecern_inspire_get_papercern_inspire_export_citationscern_inspire_search_authorscern_inspire_get_citation_summarycern_inspire_search_experimentscern_inspire_search_hepdatacern_inspire_list_reference
Signals
- GitHub stars
- 1
- Last commit
- Oct 2026
Advanced
- Delivery
- cern-inspire-mcp-server MCP server → your ahel connector (mcp.ahel.ai) → your AI.
- Item type
- mcp-server
- Key
io-github-cyanheads-cern-inspire-mcp-server- Source
- github.com/cyanheads/cern-inspire-mcp-server
- Hosted endpoint
https://cern-inspire.caseyjhand.com/mcp
github.com/cyanheads/cern-inspire-mcp-server