OpenAlex MCP Demo

by geraldineco.huggingface.geraldine/openalex-mcp

Search scholarly works through the openalex database.

  • Remote endpoint
  • 9 tools

Uptime

Checked  · every day

98.89%from 4 days of checks

Up without downtime on 3 of 4 days with data; down 60 minutes in all, on 31 October.

  • No downtime
  • Degraded
  • Down over 5 minutes
  • No data
  • Not checked yet

Response time

Median 1313 ms, slowest 5% 1611 ms for the handshake and the tool list, over 30 days.

2000 ms1000 ms0

How far each check got

  • Reached the address 93.7%
  • Completed the handshake 25.0%
  • Listed its tools 25.0%

9 tools at the last answer.

Every day
DayResultChecksMedian
3 Nov (today)No downtime11611 ms
2 NovNo downtime1of 11313 ms
1 NovNo downtime1of 11465 ms
31 OctDown 60 minutes131150 ms

A failure counts as down time only when a second check five minutes later fails too. How we check

Connect to the publisher's own endpoint

Add to ~/.llm/config.json:

{
  "mcpServers": {
    "openalex-mcp": {
      "url": "https://geraldine-openalex-mcp.hf.space/gradio_api/mcp/sse"
    }
  }
}

This server's endpoint speaks only SSE, which this client's documentation does not list among its transports; use another client for it.

For agents: the install prompt

Every step above as one Markdown text, for an assistant installing it for you.

# Install the MCP server OpenAlex MCP Demo (`co.huggingface.geraldine/openalex-mcp`)

Its page: https://plug.directory/servers/co.huggingface.geraldine/openalex-mcp

It runs on the publisher's servers; the client connects to its URL.

Use the section for the person's client.

## Claude Desktop

Paste into Settings › Connectors › Add custom connector:

```text
https://geraldine-openalex-mcp.hf.space/gradio_api/mcp/sse
```

## Claude Code

Run in a terminal:

```sh
claude mcp add --transport sse openalex-mcp https://geraldine-openalex-mcp.hf.space/gradio_api/mcp/sse
```

## Cursor, Devin Desktop, LM Studio, Gemini CLI, oterm, ECA

Merge into the place for the person's client:

- Cursor: ~/.cursor/mcp.json
- Devin Desktop: ~/.config/devin/mcp_config.json
- LM Studio: mcp.json (Program › Install › Edit mcp.json)
- Gemini CLI: ~/.gemini/settings.json
- oterm: config.json in oterm's data folder (~/Library/Application Support/oterm on macOS, ~/.local/share/oterm on Linux, %APPDATA%\oterm on Windows)
- ECA: ~/.config/eca/config.json (global) or .eca/config.json in the project

```json
{
  "mcpServers": {
    "openalex-mcp": {
      "url": "https://geraldine-openalex-mcp.hf.space/gradio_api/mcp/sse"
    }
  }
}
```

## VS Code

Merge into .vscode/mcp.json:

```json
{
  "servers": {
    "openalex-mcp": {
      "type": "sse",
      "url": "https://geraldine-openalex-mcp.hf.space/gradio_api/mcp/sse"
    }
  }
}
```

## Zed

This server's endpoint speaks only SSE, which this client's documentation does not list among its transports; use another client for it.

## Cline, AnythingLLM, Augment Code

Merge into the place for the person's client:

- Cline: cline_mcp_settings.json (MCP Servers › Configure › Configure MCP Servers)
- AnythingLLM: anythingllm_mcp_servers.json in the AnythingLLM storage plugins directory
- Augment Code: Augment Settings Panel – MCP section – Import from JSON (VS Code extension)

```json
{
  "mcpServers": {
    "openalex-mcp": {
      "type": "sse",
      "url": "https://geraldine-openalex-mcp.hf.space/gradio_api/mcp/sse"
    }
  }
}
```

## Continue

Merge into ~/.continue/config.yaml:

```yaml
mcpServers:
  - name: "openalex-mcp"
    type: sse
    url: "https://geraldine-openalex-mcp.hf.space/gradio_api/mcp/sse"
```

## Goose

This server's endpoint speaks only SSE, which this client's documentation does not list among its transports; use another client for it.

## Codex

This server's endpoint speaks only SSE, which this client's documentation does not list among its transports; use another client for it.

## mcp-client-cli, TUUI, BoltAI, Bob Shell, Kiro, Kiro CLI

This server's endpoint speaks only SSE, which this client's documentation does not list among its transports; use another client for it.

## Agenvoy

This server's endpoint speaks only SSE, which this client's documentation does not list among its transports; use another client for it.

## Amp

Merge into ~/.config/amp/settings.json (user) or .amp/settings.json (workspace):

```json
{
  "amp.mcpServers": {
    "openalex-mcp": {
      "url": "https://geraldine-openalex-mcp.hf.space/gradio_api/mcp/sse"
    }
  }
}
```

Then restart the client, or reload its MCP servers, and ask it to list the server's tools to confirm it started.

Tools 9

  • openalex_mcp_browse_topics Explore the OpenAlex "aboutness" hierarchy. Four levels: 4 domains, 26 fields, 252 subfields, 4516 topics. Each record carries the short id, its parent levels, works_count and the filter key for that level — feed the id back into search_works or group_by. Returns: {"source": "openalex", "command": "browse_topics", "total_found": int, "returned": int, "results": [{"source": "openalex", "id": str, "url": str, "display_name": str, "level": str, "description": str | null, "works_count": int | null, "filter_key": str, "subfield": object, "field": object, "domain": object}], "level": str, "query_used": str | null, "filters_used": [str], "cost_usd": float | null, "error": str | null}
  • openalex_mcp_classify_text Place a text in the OpenAlex topic hierarchy. OpenAlex retired its /text endpoint. This tool rebuilds the capability: one semantic search finds the nearest works, then their topics are aggregated weighted by relevance and rolled up to subfields, fields and domains. It returns real OpenAlex identifiers at all four levels plus the filter keys needed to reuse them — feed the ids straight back into search_works. Returns its own shape, not the record envelope: this tool returns no records. Calls run on the anonymous daily budget unless an X-Openalex-Api-Key request header is sent, or the deployment configured a key of its own. Returns: {"source": "openalex", "command": "classify_text", "query_used": str, "truncated": bool, "based_on_works": int, "topics": [{"id": str, "display_name": str, "score": float, "works": int}], "subfields": [object], "fields": [object], "domains": [object], "keywords": [str], "filter_keys": object, "cost_usd": float | null, "error": str | null}
  • openalex_mcp_get_citing_works Fetch the works that cite a given OpenAlex work, most-cited first. Forward citation lookup: who built on this paper. Resolve a DOI with lookup_by_doi first if you only have one — this tool takes an OpenAlex id. Calls run on the anonymous daily budget unless an X-Openalex-Api-Key request header is sent, or the deployment configured a key of its own. Returns: {"source": "openalex", "command": "get_citing_works", "total_found": int, "returned": int, "cited_work_id": str, "cost_usd": float | null, "results": [{"source": "openalex", "id": str, "title": str, "authors": [str], "doi": str | null, "url": str, "year": int | null, "journal": str | null, "cited_by_count": int}], "error": str | null}
  • openalex_mcp_group_by Count along a dimension without retrieving any record. Answers "how many", "which are the top" and "how has it evolved" in one call, at the price of a single request whatever the size of the set being aggregated — the cheapest way to frame a corpus before walking it. Returns its own shape, not the record envelope: this tool returns no records. Returns: {"source": "openalex", "command": "group_by", "entity": str, "dimension": str, "query_used": str | null, "filters_used": str | null, "total_found": int | null, "groups_count": int | null, "groups": [{"key": str, "key_url": str | null, "key_display_name": str | null, "count": int}], "oql": str | null, "cost_usd": float | null, "error": str | null}
  • openalex_mcp_lookup_by_doi Resolve one or more DOIs to full OpenAlex work records. Free — single-entity lookups are not billed. Use this when the DOI is already known: it is exact, unlike search_works, and it answers for several DOIs in a single call. A DOI OpenAlex does not index is simply absent from the results. Returns: {"source": "openalex", "command": "lookup_by_doi", "total_found": int, "returned": int, "requested": int, "cost_usd": float | null, "results": [{"source": "openalex", "id": str, "title": str, "authors": [str], "doi": str | null, "url": str, "year": int | null, "journal": str | null}], "error": str | null}
  • openalex_mcp_resolve_entity Resolve a name to an OpenAlex entity — id, external id, and filter key. Free and fast. Backed by /autocomplete, which returns a filter_key alongside each suggestion: the API itself saying which filter that identifier belongs in ("authorships.institutions.lineage" for an institution, "topics.id" for a topic). Run this before filtering on a name. Autocomplete is prefix-based and diacritic-sensitive, and the two combine badly: "strasbourg" alone finds nothing because it is not a prefix of the name, and "universite de stras" finds nothing either because the name is spelled "Université". "université de stras" finds it on the first try. When the prefix match is empty, a widened search is tried and what it finds goes into "suggestions", never into "results", with "error" still set — the caller chooses. Returns: {"source": "openalex", "command": "resolve_entity", "total_found": int, "returned": int, "results": [{"source": "openalex", "id": str, "url": str, "display_name": str, "entity_type": s
  • openalex_mcp_search_semantic Search OpenAlex by meaning rather than by keyword. Ranks works by semantic proximity to a descriptive text, so a paper matches even when it shares none of the words used to ask for it. Give it a sentence or a whole abstract, not two keywords. Use search_works instead when a keyword genuinely names the subject. Three limits come from the endpoint: no paging past the result cap, "total_found" always null because OpenAlex reports the cap and not a count, and date bounds expressed as years — the from/to dates search_works accepts are rejected here. Topic filters are rejected too. Calls run on the anonymous daily budget unless an X-Openalex-Api-Key request header is sent, or the deployment configured a key of its own. Returns: {"source": "openalex", "command": "search_semantic", "total_found": null, "returned": int, "query_used": str, "filters_used": [str], "truncated": bool, "cost_usd": float | null, "results": [{"source": "openalex", "id": str, "title": str, "authors": [str], "doi": str |
  • openalex_mcp_search_works Search OpenAlex for academic works by keyword query. Query syntax: "phrase in quotes", "near each other"~5, fuzzy~2, AND/OR/NOT in uppercase. Wildcards (* and ?) work only with exact=true. Calls run on the anonymous daily budget unless an X-Openalex-Api-Key request header is sent, or the deployment configured a key of its own. Returns: {"source": "openalex", "command": "search_works", "total_found": int, "returned": int, "query_used": str, "filters_used": [str], "corpus": str, "oql": str | null, "cost_usd": float | null, "results": [{"source": "openalex", "id": str, "title": str, "authors": [str], "doi": str | null, "url": str, "year": int | null, "journal": str | null, "fwci": float | null, "primary_topic": object | null, "topics": [object]}], "error": str | null}
  • openalex_mcp_translate_query Translate a query between OQL, OQO and a REST URL, and validate it. Three forms of the same query: OQL (readable text, "works where institution is Sorbonne Université"), OQO (a JSON object) and oxurl (the REST URL). "form" names what you are giving it. Translation never touches the index and is billed at the cheapest rate, so it is the way to check a filter before paying to run it — and how you find out that "institution is X" compiles to authorships.institutions.lineage rather than .id. Returns its own shape, not the record envelope: this tool returns no records. An invalid query comes back valid:false with the parser's own message — a diagnosis, not a failure. Returns: {"source": "openalex", "command": "translate_query", "form": str, "query_used": str, "valid": bool, "oql": str | null, "oql_oneline": str | null, "oqo": object | null, "oxurl": str | null, "api_url": str | null, "diagnostics": [object], "error": str | null}

From Hugging Face Spaces. Report a problem