Rivul MCP Tool Reference
The Rivul MCP server exposes three read-only tools. This reference lists every parameter, bound, response field, and error they return.
On this page
search_papers
Searches the Rivul Index and returns structured scholarly metadata. The tool is read-only and does not modify anything in your workspace. It is free under fair-use rate limits.
Only the parameters below are accepted. An unrecognized parameter is rejected rather than ignored, so a typo fails loudly instead of silently changing your search. When both are supplied, year_min must not be greater than year_max.
| Parameter | Type | Required | Accepted range | Default |
|---|---|---|---|---|
| query | string | Yes | 1 to 500 characters | — |
| limit | integer | No | 1 to 50 | 10 |
| offset | integer | No | 0 to 1,000 | 0 |
| sort | string | No | relevance, most_cited, newest, oldest | relevance |
| year_min | integer | No | 1000 to 2100 | — |
| year_max | integer | No | 1000 to 2100 | — |
| min_citations | integer | No | 0 or greater; rounded down to 0, 10, 50, 100, 500, 1,000, 5,000 or 10,000 | — |
| open_access_only | boolean | No | true or false | — |
| topic | string | No | 1 to 200 characters; exact, case-sensitive name | — |
| field | string | No | 1 to 200 characters; exact, case-sensitive name | — |
{
"query": "retrieval-augmented generation",
"limit": 5,
"sort": "most_cited",
"year_min": 2020,
"open_access_only": true
}What a search returns
A result carries a list of short work records, a meta block describing the page you received, and the workspace's usage for the current UTC day. Each short record holds only what ranks and identifies a paper: openalex_id, title, and authors are always present, and the rest appear when the underlying record has them, so treat any other field as optional in your own code.
The short record lists the first three authors, adds more_authors when the record holds more, and cuts the snippet at about 200 characters on a word boundary, ending it with an ellipsis. For venue, work type, topic, field, publication date, open-access status, and links, call get_paper_details with the openalex_id.
A record is a discovery lead. It tells you a paper exists and how to identify it, not that the paper supports a claim you are about to make.
| Field | Type | Present |
|---|---|---|
| openalex_id | string | Always |
| title | string | Always |
| authors | string array | Always; at most the first 3 |
| more_authors | integer | When the record holds more than 3 authors |
| publication_year | integer | When known |
| doi | string | When known |
| cited_by_count | integer | When known |
| snippet | string | When known; about 200 characters |
get_paper_details
Returns the full Rivul Index record for one work, identified by an openalex_id from a search_papers result. The tool is read-only and requires the search:read scope. It is free under fair-use rate limits, and each lookup is recorded like a search, because Rivul MCP looks the work up through the index search route.
The id can be a bare work id such as W2626778328 or an OpenAlex URL such as https://openalex.org/W2626778328. Any other value, or any extra parameter, is rejected before any usage is recorded. If the id is valid but not in the current index snapshot, the call returns not_found and is still recorded as usage, because the index was queried.
A successful call returns the work and a meta block with source, request_id, and, when the index reports them, generation_id and snapshot_at, followed by the workspace's usage for the current UTC day.
| Parameter | Type | Required | Accepted range | Default |
|---|---|---|---|---|
| openalex_id | string | Yes | 1 to 256 characters; an OpenAlex work id or work URL | — |
What a paper lookup returns
get_paper_details returns the full normalized record. Only openalex_id, title, authors, and is_oa are always present; the rest appear when the underlying record has them. The REST API returns this same full record for each search result.
| Field | Type | Present |
|---|---|---|
| openalex_id | string | Always |
| title | string | Always |
| authors | string array | Always |
| is_oa | boolean | Always |
| publication_year | integer | When known |
| publication_date | string | When known |
| doi | string | When known |
| venue | string | When known |
| work_type | string | When known |
| snippet | string | When known |
| cited_by_count | integer | When known |
| topic | string | When known |
| field | string | When known |
| oa_url | string | When known |
| landing_url | string | When known |
Why a field can be missing
Rivul MCP normalizes every record before publishing it, and a value that does not survive normalization is left out of the record rather than returned as null or an empty string. That is why a full record can carry four keys, or a search result three, and still be correct.
Text is HTML-entity decoded and its whitespace collapsed, so a title stored as A & B is published as A & B. A string that is empty after that is dropped. A URL is dropped unless it parses and uses http or https, so a malformed oa_url disappears even though the index sent one. A number is dropped unless it is a non-negative whole number, which is why a cited_by_count of 0 is kept.
is_oa behaves differently from the rest: it is always present, and anything other than a literal true becomes false rather than being omitted.
Truncated values and what that means for citation
Rivul MCP publishes metadata and links. It does not host or redistribute full text, so a long value is shortened rather than returned whole. One shared function normalizes every record before the MCP or REST adapter sees it, so the bounds below apply on every channel. get_paper_details and the REST API return the full normalized record; search_papers returns the shorter summary described above.
Two of these bounds change what the data means rather than just its length. The snippet is an abstract excerpt cut at 1,500 characters, not the abstract. The author list stops at eight names.
The full record does not tell you whether either was shortened. There is no total author count and no truncation flag, and more_authors in a search result counts only up to that same cap of eight, so eight names can mean a paper with eight authors or a paper with eight hundred. Do not build a bibliography from the authors field without confirming the author list against the DOI or landing page. Rivul MCP is a discovery surface; the source record remains the authority for anything you cite.
| Field | Bound | Effect |
|---|---|---|
| authors | 8 names | Longer lists are cut with no indication that they were |
| snippet | 1,500 characters | An excerpt of the abstract, not the whole abstract |
| title | 500 characters | A record with no usable title is not returned at all |
| openalex_id | 256 characters | A record with no usable identifier is not returned at all |
| venue | 500 characters | Truncated |
| doi | 512 characters | Truncated |
| topic, field | 300 characters each | Truncated |
| work_type | 100 characters | Truncated |
| publication_date | 32 characters | Truncated |
| oa_url, landing_url | 2,048 characters | Dropped unless the value is a valid http or https URL |
Paging through results
The meta block describes the page you received. Use offset, page_size, and next_offset rather than guessing, and remember that every page is another search under the fair-use rate limits.
snapshot_at and generation_id identify which index build answered you, which is what makes a search reproducible later. Record them alongside a result set you intend to cite.
| Field | Type | Present |
|---|---|---|
| source | string | Always, and always rivul_index |
| offset | integer | Always |
| page_size | integer | Always |
| has_more | boolean | Always |
| next_offset | integer | Only when has_more is true |
| total_matches | integer | When the index reports it |
| corpus_records | integer | When the index reports it |
| filtered_records | integer | When the index reports it |
| generation_id | string | When the index reports it |
| snapshot_at | string | When the index reports it |
usage_status
Returns the approved workspace's current MCP usage. It takes no parameters, is read-only and idempotent, and never counts toward usage, so it is always safe to call when you are unsure whether a connection still works.
The response names the workspace, the usage period as a UTC calendar day, and the usage recorded for the MCP channel. limit and remaining are null when no cap is set, which is the default.
{
"usage": {
"workspace_id": "...",
"period": "2026-09-16",
"mcp": { "used": 8, "limit": null, "remaining": null }
}
}Errors you can get back
Insufficient scope. The grant is missing search:read or usage:read. The error names the scope it needs. Authorize again and approve both read-only scopes.
Invalid parameters. A value fell outside the ranges above, an openalex_id is not an OpenAlex work id, or an unrecognized parameter was sent. A rejected call records no usage.
Not found. get_paper_details received a valid openalex_id that is not in the current index snapshot. The call is still recorded as usage, because the index was queried.
Invalid key. A dedicated MCP key that has been revoked returns HTTP 401 Invalid Rivul Atlas key. This is distinct from a rate limit.
Rate limited or capped. The key or account exceeded a fair-use limit per minute, hour, or day, or an operator set a cap on the workspace. Wait for the window to pass and retry. usage_status never counts toward usage, so read it to confirm.
Search temporarily unavailable. Rivul MCP rejects a whole page rather than returning part of it: if the index returns more rows than the requested limit, or any row without a usable identifier and title, the call fails instead of quietly returning fewer records. Usage reserved for a failed search is released. Retry, and treat a persistent failure as an index problem rather than a bad query.
Something here wrong or missing? Use the contact form.