zenodo-mcp-server
Server Details
Search and resolve Zenodo datasets, software, and publications by DOI; trace versions and funding.
- Status
- Healthy
- Uptime
- 99.9% over 22 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- cyanheads/zenodo-mcp-server
- GitHub Stars
- 1
- Server Listing
- zenodo-mcp-server
TDQS
Scored across 6 tools
Each tool targets a distinct action and resource: single-record resolution, version listing, file manifest paging, text excerpt reading, vocabulary lookup, and repository search. The boundaries are clear even where tools touch similar data, such as get_record returning initial files and list_files paging the full manifest.
All tool names use a consistent snake_case verb_noun pattern (get_record, list_files, list_versions, lookup_vocabulary, read_file, search_records) with a uniform zenodo_ server prefix. No mixed conventions or vague verbs.
Six tools are well-scoped for a read-only Zenodo client: search, record retrieval, version history, file listing, file reading, and vocabulary resolution. Each tool earns its place without redundancy or excessive fragmentation.
The surface covers the core read-only lifecycle: search, full metadata retrieval, versions, file manifests, text content, and filter vocabulary. Minor gaps remain, such as no direct binary file download tool and no write/upload operations, but the read-oriented workflows are well supported.
Available Tools
6 toolszenodo_get_recordGet a Zenodo recordARead-onlyIdempotentInspect
Resolve one Zenodo deposit from a record id, a Zenodo DOI (10.5281/zenodo.N), a concept DOI or concept record id (resolves to the latest version), another DOI deposited on Zenodo, or a zenodo.org or doi.org URL, and return its full metadata: description, creators with ORCIDs and ROR affiliations, license, access and embargo, funding and grants, related identifiers, communities, version position, usage counts, and the first 25 files. Optionally includes a formatted citation. Long text and lists are cut at display caps with their totals reported; every cut except the file list (paged with zenodo_list_files) is listed in continuations with a cursor and the record id it is bound to, and passing both back returns the next window of that field (8,000 characters of text, or the next page of entries) in place of the record. A miss (an unknown id, a deleted record with its removal tombstone, restricted metadata, or a DOI not registered on Zenodo) returns found: false with guidance instead of an error.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The deposit to resolve: a record id (22705923), a Zenodo DOI (10.5281/zenodo.22705923, doi: prefix and any case accepted), a concept DOI or concept record id such as 10.5281/zenodo.591564 (resolves to the latest version), another DOI registered to a Zenodo record, or a zenodo.org/records or doi.org URL. | |
| cursor | No | A continuations[].cursor from an earlier zenodo_get_record response, passed unchanged with that continuation’s id as id. Returns that field’s next window (8,000 characters of text, or the next page of entries) as window, in place of record. Omit to get the record. | |
| citation_style | No | Include a formatted citation of the resolved version: bibtex, csl-json, or a text style (apa, chicago-author-date, harvard-cite-them-right, ieee, modern-language-association, nature). Case, spaces, hyphens, and underscores are ignored when matching (BibTeX, APA, CSL JSON). Omit for none. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | Without cursor: maximum file entries shown (25). With cursor: the window size (8,000 characters, or the field’s page of entries). |
| error | No | Present when the call failed. Absent on success. |
| found | No | True when the record resolved. |
| shown | No | Without cursor: file entries shown. With cursor: characters or entries in the window. |
| notice | No | File access notes or a pointer to zenodo_list_files. |
| record | No | The record. Present when found and no cursor was passed. |
| window | No | The next window of the field the cursor continues. Present when found and a cursor was passed, in place of record. |
| citation | No | The formatted citation. Present when requested and found. |
| guidance | No | What to do next. Present when not found. |
| miss_kind | No | Why nothing resolved. Present when not found. |
| tombstone | No | Removal tombstone. Present when miss_kind is deleted. |
| truncated | No | Without cursor: true when anything was cut, files past the 25 shown or any field in continuations. With cursor: true when continuations lists a next step, because the field continues past this window or an additional description on this page was cut. |
| input_kind | No | How id was parsed: record_id (digits), zenodo_doi (10.5281/zenodo.N or zenodo.N), external_doi (another DOI), or url (a zenodo.org or doi.org link). |
| continuations | No | Every field this response cut short, each with a cursor for the rest. Absent when nothing was cut; files are paged with zenodo_list_files instead. |
| resolved_from | No | How the record was reached: a version id, a concept id resolved to the latest version, or a non-Zenodo DOI. Present when found. |
| citation_style | No | The citation style used. Present with citation. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnly/idempotent/openWorld annotations: it discloses display caps, the continuations/cursor mechanism bound to a record id, the 8,000-character window size, and that misses return found: false with guidance rather than an error. This is exactly the behavioral context an agent needs before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in the first clause and every sentence carries substantive information about resolution, truncation, and failure. The three sentences are very dense/long, which slightly hurts readability, but little is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a resolver with an output schema and annotations covering safety, the description supplies the remaining behavior an agent needs: identifier acceptance, truncation/continuation flow, optional citation, and miss handling. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds the interaction rule that cursor and the continuation's id must be passed together to return the next window in place of the record. It reinforces rather than duplicates the enum and id semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (resolve/get) and resource (one Zenodo deposit) and enumerates the accepted identifier forms. It also distinguishes itself from the sibling zenodo_list_files by naming it as the tool for the paged file list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clear context for when to use it (resolving a single record from an id/DOI/URL) and it names zenodo_list_files as the alternative for file pagination. It does not explicitly say when to prefer sibling tools like zenodo_search_records or zenodo_list_versions, leaving that to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
zenodo_list_filesList Zenodo record filesARead-onlyIdempotentInspect
Page through a Zenodo deposit's file manifest (key, size, MIME type, MD5, download URL, previewability), optionally filtered by a substring of the file key, or list the members inside one of its .zip files by setting archive_key. Restricted and embargoed files return the access status and embargo date with no entries. Read a small text file or ZIP member with zenodo_read_file.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The deposit: a record id (22705923), a Zenodo DOI (10.5281/zenodo.22705923), another DOI registered to a Zenodo record, or a zenodo.org/records or doi.org URL. A concept id lists the latest version’s files. | |
| limit | No | Entries per page, at most 200 per call; larger values return 200. | |
| offset | No | Entries to skip before this page. | |
| archive_key | No | Exact file key of a .zip in this record (from the manifest) to list its members instead of the manifest. Omit to list the manifest. | |
| key_contains | No | Case-insensitive substring filter on file keys (manifest) or member paths (archive), applied before paging. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | Page size applied (at most 200). |
| kind | No | manifest: the record’s files; archive: members of the .zip named by archive_key. |
| error | No | Present when the call failed. Absent on success. |
| limit | No | Page size applied: limit, or 200 when limit asked for more. |
| recid | No | Record id whose files are listed (the latest version for a concept id). |
| shown | No | Entries returned on this page. |
| notice | No | File access notes, empty-filter guidance, listing caps, the 200-per-call limit cap, or paging guidance. |
| offset | No | Entries skipped before this page. |
| archive | No | The archive being listed (archive kind); absent when files are restricted. |
| entries | No | Manifest files on this page (manifest kind); empty when files are restricted. |
| matched | No | Entries matching the filter, before paging. |
| members | No | Archive members on this page (archive kind); empty when files are restricted. |
| has_more | No | True when more matching entries follow this page. |
| truncated | No | True when more matching entries follow this page. |
| file_count | No | Total files in the record (manifest kind); absent when files are restricted or embargoed. |
| totalCount | No | Entries matching the filter, before paging. |
| next_offset | No | Offset of the next page, when has_more. |
| total_bytes | No | Total size of the record’s files in bytes (manifest kind); absent when files are restricted or embargoed. |
| files_access | No | File access: public or restricted; absent when Zenodo does not report it. |
| key_contains | No | The key filter applied, when set. |
| access_status | No | Record access status: open, restricted, embargoed, or metadata-only. |
| embargo_until | No | Embargo end date, when an embargo is active. |
| files_enabled | No | False for a metadata-only deposit. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/openWorld, so the safety profile is covered; the description adds real behavioral context the schema cannot: restricted and embargoed files return access status and embargo date with no entries, and the per-call entry cap. It stops short of describing pagination termination or error behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense, front-loaded paragraph where the listing scope, optional filter, archive mode, and the sibling redirect each carry weight. The parenthetical field list is slightly list-heavy but justified for a manifest tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be re-explained, yet the description still covers paging, filtering, archive mode, and embargo/restricted handling. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3; the description restates the substring filter and archive_key semantics that the schema already documents in more detail. It adds no syntax or edge-case guidance beyond what the parameter descriptions provide.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb (page through/list) and resource (a Zenodo deposit's file manifest), enumerates the returned fields, and covers both operating modes (manifest vs. archive member listing). An agent can distinguish it from zenodo_get_record and zenodo_read_file without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the reader case elsewhere ('Read a small text file or ZIP member with zenodo_read_file') and states that omitting archive_key lists the manifest, giving clear mode-selection guidance. It does not discuss when to prefer zenodo_list_versions or get_record, so it falls short of full when/when-not coverage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
zenodo_list_versionsList Zenodo record versionsARead-onlyIdempotentInspect
List every version of a Zenodo deposit's version series, newest first, with each version's record id, DOI, version label, publication date, file totals, and usage counts. Accepts any identifier zenodo_get_record accepts; a concept DOI and any single version's DOI list the same series. Use it to find the version a paper cited or the current release. A miss (an unknown id, a deleted record with its removal tombstone, restricted metadata, or a DOI not registered on Zenodo) returns found: false with guidance instead of an error.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Any version or concept identifier of the deposit: a record id (22705923), a Zenodo DOI (10.5281/zenodo.22705923) or concept DOI (10.5281/zenodo.591564), another DOI registered to a Zenodo record, or a zenodo.org/records or doi.org URL. | |
| page | No | Result page, starting at 1. Zenodo pages through only the first 10,000 versions, so the last reachable page is 10,000 ÷ size rounded up (400 at size 25). | |
| size | No | Versions per page, at most 25 per call; larger values return 25. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | Page size applied (at most 25). |
| page | No | Page returned. |
| size | No | Page size applied: size, or 25 when size asked for more. |
| error | No | Present when the call failed. Absent on success. |
| found | No | True when the version series resolved. |
| shown | No | Versions returned on this page. |
| notice | No | Guidance on paging, the 25-per-call size cap, or a page past the end. |
| guidance | No | What to do next. Present when not found. |
| has_more | No | True when another page of versions follows. |
| versions | No | Versions on this page, newest first; empty when not found. |
| miss_kind | No | Why nothing resolved. Present when not found. |
| next_page | No | The next page number, when has_more. |
| tombstone | No | Removal tombstone. Present when miss_kind is deleted. |
| truncated | No | True when more versions follow this page. |
| input_kind | No | How id was parsed: record_id (digits), zenodo_doi (10.5281/zenodo.N or zenodo.N), external_doi (another DOI), or url (a zenodo.org or doi.org link). |
| totalCount | No | Number of versions in the series. |
| concept_doi | No | Concept DOI of the series, when minted; absent when not found or on a page past the end. |
| latest_recid | No | Record id of the newest version. Present when found, unless Zenodo cannot name it for a page past the end. |
| concept_recid | No | Concept record id naming the whole series; absent when not found or on a page past the end. |
| total_versions | No | Number of versions in the series. Present when found. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, open-world safety. The description adds substantial behavioral context beyond them: newest-first ordering, the fields returned per version, the concept-DOI/version-DOI equivalence, and notably the soft-fail contract (found: false with guidance instead of an error) for unknown, deleted, or restricted ids.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, each load-bearing: scope and returned fields first, then identifier equivalence, then the lookup/soft-fail behavior. No filler and the most decision-relevant facts are front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though an output schema exists, the description complements it with ordering, identifier semantics, and failure behavior. For a three-parameter read tool with rich structured metadata, nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema coverage the baseline is 3, but the description adds real meaning: 'Accepts any identifier zenodo_get_record accepts' and the point that a concept DOI and any single version's DOI resolve to the same series clarify the semantics of the id parameter. Pagination syntax is left to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (list) and resource (every version of a Zenodo deposit's version series) with scope and ordering. It implicitly distinguishes itself from zenodo_get_record by describing the series-wide result rather than a single record.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context for use ('find the version a paper cited or the current release') and ties its identifier acceptance to zenodo_get_record, which signals the relationship between siblings. It does not explicitly state when not to use it, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
zenodo_lookup_vocabularyLook up Zenodo filter idsARead-onlyIdempotentInspect
Resolve names to the ids zenodo_search_records filters on, and browse Zenodo's reference vocabularies: communities (slug), funders (ROR id), awards and grants (award id), licenses (license id), and resource types (type id). Search by name, acronym, or keyword; awards can be scoped to one funder. Each entry names the zenodo_search_records parameter its id feeds.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Result page, starting at 1. Only the first 10,000 entries of a list are reachable, so the last reachable page is 10,000 ÷ size rounded up (400 at size 25). | |
| size | No | Entries per page, at most 25 per call; larger values return 25. | |
| query | No | Name, acronym, or keyword, e.g. "SYMBA", "wellcome", "mit", "journal article". For resource_types every word must appear in the type id or label. Omit to browse the vocabulary. | |
| funder | No | awards only: scope grants to one funder, given as a ROR id (00k4n6c32), a ROR URL, or a Crossref Funder DOI (10.13039/100000002). Resolve a funder name to its ROR id with vocabulary funders first. | |
| vocabulary | Yes | Which vocabulary to search: communities, funders, awards (grants), licenses, or resource_types. Case, spaces, hyphens, and underscores are ignored when matching, and the singular (funder, license, resource type) and grants are accepted. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | Page size applied (at most 25). |
| page | No | Page returned. |
| size | No | Page size applied: size, or 25 when size asked for more. |
| error | No | Present when the call failed. Absent on success. |
| query | No | The query as applied; absent when browsing. |
| shown | No | Entries returned on this page. |
| total | No | Total entries matching the query. |
| notice | No | Guidance on empty results, ambiguous funders, the 10,000-entry window, the 25-per-call size cap, or further pages. |
| entries | No | Matching entries for this page. |
| has_more | No | True when another page of reachable entries follows. |
| next_page | No | The next page number, when has_more. |
| reachable | No | Entries reachable by paging: min(total, 10,000). |
| truncated | No | True when more reachable entries follow this page. |
| totalCount | No | Total entries matching the query. |
| vocabulary | No | The vocabulary searched. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety and side-effect profile is covered. The description adds the useful workflow fact that entries carry the parameter name their id feeds, but says nothing extra about pagination caps, remote-call behavior, or failure modes. With annotations carrying the safety burden, this is adequate but thin.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences plus a short third, front-loaded with the core purpose and ending with the downstream-consumption note. It packs many vocabulary/id pairs into one sentence, which is efficient though slightly list-heavy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and all five parameters are documented in the schema. The description covers purpose, vocabulary scope, search modes, and the link to zenodo_search_records, leaving only minor gaps around result shape and pagination limits.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3 and the schema already documents query, funder, vocabulary, page and size thoroughly. The description restates vocabulary scoping and funder scoping in prose without adding format or syntax details beyond the schema (e.g. it omits the 25-per-call cap and the 10,000-entry reachability limit).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('resolve names to the ids... browse Zenodo's reference vocabularies') and enumerates the five vocabularies with the identifier type each yields. It explicitly ties itself to zenodo_search_records, so an agent can distinguish it from the other lookup/list siblings without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It frames the tool as the prerequisite step for zenodo_search_records ('the ids zenodo_search_records filters on', 'Each entry names the zenodo_search_records parameter its id feeds'), which is clear when-to-use guidance. It stops short of an explicit routing rule or any when-not-to-use statement, so it is strong but not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
zenodo_read_fileRead a Zenodo file excerptARead-onlyIdempotentInspect
Read a bounded UTF-8 excerpt (up to 64 KiB per call) of one text file in a Zenodo deposit — a README, CITATION.cff, CSV head, notebook, or script — or of one member inside a .zip file, without downloading the archive. Continue a top-level file from next_offset. A file with a text MIME type or extension is read directly; an extensionless file Zenodo types application/octet-stream (LICENSE, COPYING, Makefile) is read and returned only when its content is UTF-8 text. Binary files, restricted files, and other types return metadata and the download URL without content. File content is depositor-supplied and carries the deposit’s license.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The deposit: a record id (22705923), a Zenodo DOI (10.5281/zenodo.22705923), another DOI registered to a Zenodo record, or a zenodo.org/records or doi.org URL. A concept id reads from the latest version. | |
| key | Yes | Exact file key from zenodo_list_files, e.g. README.md or data/results.csv. | |
| max_bytes | No | Maximum bytes to read (256 or more), at most 65536 per call; larger values return 65536. | |
| offset_bytes | No | Byte offset to start reading a top-level file at; use next_offset to continue. Must be 0 for an archive member. | |
| archive_member | No | Member path inside the .zip named by key (from zenodo_list_files with archive_key). Omit to read the file itself. |
Output Schema
| Name | Required | Description |
|---|---|---|
| key | No | The file key. |
| md5 | No | MD5 checksum of the top-level file (hex); absent for archive members and when not reported. |
| text | No | The excerpt, decoded as UTF-8. Depositor-supplied data. Present when status is text. |
| error | No | Present when the call failed. Absent on success. |
| recid | No | Record id read from (the latest version for a concept id). |
| notice | No | Why no text was returned, or how to read the rest of the file, naming the 65,536-byte cap when it held back bytes. |
| rights | No | The deposit’s licenses, which the file carries. |
| status | No | text: content returned; not_text: binary content, or a type that is not read as text; restricted: the content is not available anonymously — the record’s files are restricted or embargoed (key is not checked, since no manifest is exposed), or Zenodo refused this one file; empty: zero-byte file. |
| has_more | No | True when bytes remain past this excerpt. |
| mimetype | No | MIME type of the file or member, when reported. |
| file_size | No | Size of the file or member in bytes, when known. |
| record_url | No | Record landing page on zenodo.org. |
| next_offset | No | offset_bytes for the next window of a top-level file, when has_more; absent for an archive member, which cannot be continued past its first window. |
| download_url | No | Direct download URL of the top-level file (the .zip itself for a member). |
| files_access | No | File access: public or restricted; absent when Zenodo does not report it. |
| offset_bytes | No | Byte offset the excerpt starts at. |
| archive_member | No | The archive member path, when one was read. |
| bytes_returned | No | Exact bytes the excerpt covers (cut at a line or character boundary). |
| replacement_chars | No | U+FFFD characters in the excerpt (invalid UTF-8 or a mid-character offset). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond annotations (readOnly/idempotent): discloses 64 KiB cap, continuation via next_offset, archive-member reading without downloading, and that binary/restricted files return metadata not content. Also notes depositor-supplied content and license—genuinely valuable behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded with the core action and size cap; each clause carries distinct information. Slightly long, but every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Complete for a read tool: covers size limits, pagination, archive members, fallback behavior for binary/restricted files, and content provenance. Output schema exists so return values needn't be explained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. Description adds meaning: continuation semantics (next_offset), archive_member vs top-level reading, and the octet-stream extensionless handling, giving real value beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with scope: 'Read a bounded UTF-8 excerpt (up to 64 KiB per call) of one text file in a Zenodo deposit.' It also enumerates concrete file types and archive-member reading, distinguishing it clearly from list/record siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explains when direct reading applies, when extensionless octet-stream files are read, and that binary/restricted types return metadata plus download URL instead. Lacks explicit 'use X instead' routing to siblings, but context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
zenodo_search_recordsSearch Zenodo recordsARead-onlyIdempotentInspect
Search Zenodo's open research repository — datasets, software releases, publications, and other deposits — by keyword query plus filters for resource type, community, funder, grant, creator ORCID, file type, license, access status, and publication date. Returns one summary per deposit (ids, DOIs, title, type, version, creators, license, access, file totals, usage counts) plus facet counts over the full match set, every filter applied. Query terms are OR-ed unless joined with AND, quoted phrases match exactly, and field syntax works on record fields (metadata.title:"…", metadata.subjects.subject:"…"). Only the latest version of each deposit is searched unless all_versions is true, and only the first 10,000 matches are reachable by paging. Resolve community, funder, and grant names to ids with zenodo_lookup_vocabulary first; open one deposit in full with zenodo_get_record.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Result page, starting at 1. Only the first 10,000 matches are reachable, so the last reachable page is 10,000 ÷ size rounded up (400 at size 25). | |
| size | No | Results per page, at most 25 per call; larger values return 25. | |
| sort | No | Sort order: bestmatch, newest, oldest, mostviewed, mostdownloaded, updated-desc, updated-asc. Case, spaces, hyphens, and underscores are ignored when matching (MostViewed reads as mostviewed). Defaults to bestmatch with a query, newest without. | |
| award | No | One grant: an award id <funder-ror>::<number> (00k4n6c32::101135562), a bare grant number, or a CORDIS award DOI (10.3030/101135562). Find ids with zenodo_lookup_vocabulary (vocabulary: awards). | |
| query | No | Keyword query. Terms are OR-ed unless joined with AND; "quoted phrases" (double quotes) match exactly; field syntax such as metadata.title:"…" or doi:"10.5281/zenodo.N" works. Escape a literal / as \/. A bare DOI or record URL is rejected; open it with zenodo_get_record instead. With any filter other than community and all_versions, a query that is not valid search syntax (AND AND, a field: with no value, an unclosed [a TO b]) is rejected; without one, Zenodo matches it as plain text. Omit to browse with filters only. | |
| funder | No | One funder: a ROR id (01cwqze88), a ROR URL, or a Crossref Funder DOI (10.13039/100000002). Resolve a funder name with zenodo_lookup_vocabulary (vocabulary: funders). | |
| license | No | License id, e.g. cc-by-4.0, cc0-1.0, mit (lowercased). Find ids with zenodo_lookup_vocabulary (vocabulary: licenses). | |
| community | No | One community: its slug, UUID, or zenodo.org/communities/<slug> URL. Find slugs with zenodo_lookup_vocabulary (vocabulary: communities). | |
| file_type | No | File extensions, OR-ed (a single string is accepted): csv, zip, pdf, … Lowercased with any leading dot stripped. | |
| all_versions | No | Include superseded versions; by default only the latest version is searched. | |
| published_to | No | Latest publication date, YYYY, YYYY-MM, or YYYY-MM-DD; a partial date ends at its last day. | |
| access_status | No | Access status: open, restricted, embargoed, or metadata-only. Case, spaces, hyphens, and underscores are ignored when matching (Metadata Only reads as metadata-only). | |
| creator_orcid | No | Creator ORCID iD, e.g. 0000-0002-1825-0097; an https://orcid.org/ prefix is stripped and a trailing x uppercased. | |
| resource_type | No | Resource type ids, OR-ed (a single string is accepted): dataset, software, publication, publication-article, image-photo, … Any case; a subtype may also be written in the <type>::<id> form zenodo_lookup_vocabulary shows as its search value (publication::publication-article). A top-level type includes its subtypes. Look ids up with zenodo_lookup_vocabulary (vocabulary: resource_types). | |
| published_from | No | Earliest publication date, YYYY, YYYY-MM, or YYYY-MM-DD; a partial date starts at its first day. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | Page size applied (at most 25). |
| hits | No | Matching deposits on this page. |
| page | No | Page returned. |
| size | No | Page size applied: size, or 25 when size asked for more. |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Hits returned on this page. |
| total | No | Exact number of matching records. |
| facets | No | Facet counts over the full match set (every filter applied, so they agree with total), not just this page. |
| notice | No | Guidance on a query Zenodo matched as plain text, empty results, the 10,000-result window, the 25-per-call size cap, or further pages. |
| has_more | No | True when another reachable page follows. |
| next_page | No | The next page number, when has_more. |
| reachable | No | Matches reachable by paging: min(total, 10,000). |
| truncated | No | True when more reachable matches follow this page. |
| totalCount | No | Exact number of matching records. |
| allVersions | No | Whether superseded versions were searched. |
| appliedSort | No | The sort order applied. |
| effectiveQuery | No | The exact q sent to Zenodo. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare read-only/idempotent/open-world; the description adds substantive behavior the annotations cannot express: only the latest version is searched unless all_versions is true, only the first 10,000 matches are pageable, facets are computed over the full match set, and invalid query syntax is rejected only when certain filters are present. Those are real operational constraints an agent needs before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and scope, then filter list, then return shape, then syntax/limits/routing — a sensible order for a 15-parameter tool. The middle sentences are dense and pack many clauses, but for a search tool of this breadth the length is largely earned; only minor overlap with the schema could be trimmed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, filter semantics, result shape, facet behavior, version scoping, pagination ceiling, query-syntax validation, and sibling routing — arguably more than needed given an output schema exists. Nothing an agent requires to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and every parameter (page, sort, award, license, community, resource_type, etc.) already carries detailed per-field documentation, so the baseline is 3. The description restates query syntax, version scope, and the id-lookup dependency rather than adding new per-parameter meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ("Search Zenodo's open research repository — datasets, software releases, publications, and other deposits") and enumerates the filter surface, so the agent knows exactly what this tool does. It also names the two siblings it must not be confused with (zenodo_lookup_vocabulary for id resolution, zenodo_get_record for a single deposit), giving clean sibling separation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing rules: resolve community/funder/grant names to ids with zenodo_lookup_vocabulary first, and open one deposit in full with zenodo_get_record. It also states when a query is rejected versus treated as plain text, and that omitting query lets you browse with filters only — clear when-to-use conditions rather than inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
- Changed
zenodo_get_record24 fields changed- added
Input schema / properties / cursorAdded value: +{ + "description": "A continuations[].cursor from an earlier zenodo_get_record response, passed unchanged with that continuation’s id as id. Returns that field’s next window (8,000 characters of text, or the next page of entries) as window, in place of record. Omit to get the record.", + "maxLength": 500, + "type": "string" +} - changed
Output schema / properties / cap / descriptionPrevious value: -"Maximum file entries shown (25)."New value: +"Without cursor: maximum file entries shown (25). With cursor: the window size (8,000 characters, or the field’s page of entries)." - added
Output schema / properties / continuationsAdded value: +{ + "description": "Every field this response cut short, each with a cursor for the rest. Absent when nothing was cut; files are paged with zenodo_list_files instead.", + "items": { + "additionalProperties": false, + "description": "One field cut short in this response.", + "properties": { + "cursor": { + "description": "Pass as cursor, with this entry’s id, to get the next window of this field.", + "type": "string" + }, + "field": { + "description": "The field that was cut.", + "enum": [ + "description", + "additional_descriptions", + "creators", + "contributors", + "keywords", + "funding", + "related_identifiers", + "communities" + ], + "type": "string" + }, + "id": { + "description": "Record id the cursor is bound to; pass it as id beside the cursor, whatever id form this call took.", + "type": "string" + }, + "index": { + "description": "Position of the additional description whose text was cut (0 = first). Present only for an additional description’s text.", + "type": "number" + }, + "shown": { + "description": "Characters or entries of the field returned so far, counted from its start; the cursor resumes here.", + "type": "number" + }, + "total": { + "description": "Full length of the field in characters, or its total entries.", + "type": "number" + }, + "unit": { + "description": "characters for description text, entries for a list (additional_descriptions without index is the list).", + "enum": [ + "characters", + "entries" + ], + "type": "string" + } + }, + "required": [ + "field", + "unit", + "shown", + "total", + "id", + "cursor" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `invalid_identifier`: id matches no accepted form, or is a GitHub-badge latestdoi id or a non-zenodo.org host. `record_unavailable`: Zenodo could not serve this record: HTTP 500 after one retry, HTTP 500 while resolving a non-Zenodo DOI, or no complete response within the time budget (its gateway cuts off near 30 s, which deposits with about 10,000 or more files hit). `rate_limited`: Zenodo answered HTTP 429, or this server's shared Zenodo request budget is spent for the current window. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `invalid_identifier`: id matches no accepted form, or is a GitHub-badge latestdoi id or a non-zenodo.org host. `invalid_cursor`: cursor is not one this tool returned in continuations, belongs to another record, or the record was edited after the cursor was issued. `record_unavailable`: Zenodo could not serve this record: HTTP 500 after one retry, HTTP 500 while resolving a non-Zenodo DOI, or no complete response within the time budget (its gateway cuts off near 30 s, which deposits with about 10,000 or more files hit). `rate_limited`: Zenodo answered HTTP 429, or this server's shared Zenodo request budget is spent for the current window. Other values are possible when a failure originates below the handler." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "invalid_identifier", - "record_unavailable", - "rate_limited" -]New value: +[ + "invalid_identifier", + "invalid_cursor", + "record_unavailable", + "rate_limited" +] - changed
Output schema / properties / record / descriptionPrevious value: -"The record. Present when found."New value: +"The record. Present when found and no cursor was passed." - added
Output schema / properties / record / properties / additional_description_countAdded value: +{ + "description": "Total additional descriptions.", + "type": "number" +} - changed
Output schema / properties / record / properties / additional_descriptions / descriptionPrevious value: -"Up to 5 additional descriptions."New value: +"First 5 additional descriptions, in record order (index 0 first)." - added
Output schema / properties / record / properties / additional_descriptions / items / properties / lengthAdded value: +{ + "description": "Full plain-text length in characters.", + "type": "number" +} - changed
Output schema / properties / record / properties / additional_descriptions / items / properties / text / descriptionPrevious value: -"Plain text, capped at 1,000 characters."New value: +"Plain text, first 1,000 characters." - added
Output schema / properties / record / properties / additional_descriptions / items / properties / truncatedAdded value: +{ + "description": "True when text was cut at 1,000 characters; continuations carries a cursor for the rest.", + "type": "boolean" +} - changed
Output schema / properties / record / properties / additional_descriptions / items / requiredPrevious value: -[ - "text" -]New value: +[ + "text", + "length", + "truncated" +] - changed
Output schema / properties / record / properties / communities / descriptionPrevious value: -"Up to 25 communities holding this record."New value: +"First 25 communities holding this record." - added
Output schema / properties / record / properties / community_countAdded value: +{ + "description": "Total communities holding this record.", + "type": "number" +} - changed
Output schema / properties / record / properties / description / descriptionPrevious value: -"Description converted from HTML to plain text, capped at 4,000 characters; absent when the record has none."New value: +"Description converted from HTML to plain text, first 4,000 characters; absent when the record has none." - changed
Output schema / properties / record / properties / description_truncated / descriptionPrevious value: -"True when the description was cut at 4,000 characters. Present with description."New value: +"True when the description was cut at 4,000 characters; continuations carries a cursor for the rest. Present with description." - changed
Output schema / properties / record / properties / funding / descriptionPrevious value: -"Up to 50 funding entries (funders and grants)."New value: +"First 50 funding entries (funders and grants)." - added
Output schema / properties / record / properties / funding_countAdded value: +{ + "description": "Total funding entries.", + "type": "number" +} - added
Output schema / properties / record / properties / keyword_countAdded value: +{ + "description": "Total subject keywords.", + "type": "number" +} - changed
Output schema / properties / record / properties / keywords / descriptionPrevious value: -"Up to 50 subject keywords."New value: +"First 50 subject keywords." - changed
Output schema / properties / record / requiredPrevious value: -[ - "recid", - "title", - "additional_descriptions", - "creators", - "creator_count", - "contributors", - "contributor_count", - "keywords", - "rights", - "access", - "funding", - "related_identifiers", - "related_identifier_count", - "communities", - "versions", - "files", - "zenodo_url" -]New value: +[ + "recid", + "title", + "additional_descriptions", + "additional_description_count", + "creators", + "creator_count", + "contributors", + "contributor_count", + "keywords", + "keyword_count", + "rights", + "access", + "funding", + "funding_count", + "related_identifiers", + "related_identifier_count", + "communities", + "community_count", + "versions", + "files", + "zenodo_url" +] - changed
Output schema / properties / shown / descriptionPrevious value: -"File entries shown."New value: +"Without cursor: file entries shown. With cursor: characters or entries in the window." - changed
Output schema / properties / truncated / descriptionPrevious value: -"True when the record has more files than the 25 shown."New value: +"Without cursor: true when anything was cut, files past the 25 shown or any field in continuations. With cursor: true when continuations lists a next step, because the field continues past this window or an additional description on this page was cut." - added
Output schema / properties / windowAdded value: +{ + "additionalProperties": false, + "description": "The next window of the field the cursor continues. Present when found and a cursor was passed, in place of record.", + "properties": { + "additional_descriptions": { + "description": "Up to 5 additional descriptions starting at offset, each text cut at 1,000 characters. Present when field is additional_descriptions and unit is entries.", + "items": { + "additionalProperties": false, + "description": "One additional description.", + "properties": { + "length": { + "description": "Full plain-text length in characters.", + "type": "number" + }, + "text": { + "description": "Plain text, first 1,000 characters.", + "type": "string" + }, + "truncated": { + "description": "True when text was cut at 1,000 characters; continuations carries a cursor for the rest.", + "type": "boolean" + }, + "type": { + "description": "Description type, e.g. Notes or Methods.", + "type": "string" + } + }, + "required": [ + "text", + "length", + "truncated" + ], + "type": "object" + }, + "type": "array" + }, + "communities": { + "description": "Up to 25 communities starting at offset. Present when field is communities.", + "items": { + "additionalProperties": false, + "description": "One community.", + "properties": { + "slug": { + "description": "Community slug — feeds zenodo_search_records community.", + "type": "string" + }, + "title": { + "description": "Community title.", + "type": "string" + } + }, + "required": [ + "slug" + ], + "type": "object" + }, + "type": "array" + }, + "contributors": { + "description": "Up to 25 contributors starting at offset. Present when field is contributors.", + "items": { + "additionalProperties": false, + "description": "A creator or contributor.", + "properties": { + "affiliations": { + "description": "Affiliations as deposited.", + "items": { + "additionalProperties": false, + "description": "One affiliation.", + "properties": { + "name": { + "description": "Affiliation name.", + "type": "string" + }, + "ror": { + "description": "Affiliation ROR id, when linked.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "name": { + "description": "Display name as deposited.", + "type": "string" + }, + "orcid": { + "description": "ORCID iD, when the depositor supplied one.", + "type": "string" + }, + "role": { + "description": "Contributor role, e.g. Editor (contributors only).", + "type": "string" + }, + "type": { + "description": "personal or organizational.", + "type": "string" + } + }, + "required": [ + "name", + "affiliations" + ], + "type": "object" + }, + "type": "array" + }, + "creators": { + "description": "Up to 25 creators starting at offset. Present when field is creators.", + "items": { + "additionalProperties": false, + "description": "A creator or contributor.", + "properties": { + "affiliations": { + "description": "Affiliations as deposited.", + "items": { + "additionalProperties": false, + "description": "One affiliation.", + "properties": { + "name": { + "description": "Affiliation name.", + "type": "string" + }, + "ror": { + "description": "Affiliation ROR id, when linked.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "name": { + "description": "Display name as deposited.", + "type": "string" + }, + "orcid": { + "description": "ORCID iD, when the depositor supplied one.", + "type": "string" + }, + "role": { + "description": "Contributor role, e.g. Editor (contributors only).", + "type": "string" + }, + "type": { + "description": "personal or organizational.", + "type": "string" + } + }, + "required": [ + "name", + "affiliations" + ], + "type": "object" + }, + "type": "array" + }, + "field": { + "description": "The field this window continues.", + "enum": [ + "description", + "additional_descriptions", + "creators", + "contributors", + "keywords", + "funding", + "related_identifiers", + "communities" + ], + "type": "string" + }, + "funding": { + "description": "Up to 50 funding entries starting at offset. Present when field is funding.", + "items": { + "additionalProperties": false, + "description": "One funding entry.", + "properties": { + "award_acronym": { + "description": "Award acronym.", + "type": "string" + }, + "award_doi": { + "description": "Award DOI, e.g. 10.3030/101135562.", + "type": "string" + }, + "award_id": { + "description": "Award id (<funder-ror>::<number>) — feeds zenodo_search_records award.", + "type": "string" + }, + "award_number": { + "description": "Grant number.", + "type": "string" + }, + "award_program": { + "description": "Funding program.", + "type": "string" + }, + "award_title": { + "description": "Award title.", + "type": "string" + }, + "award_url": { + "description": "Award landing page URL.", + "type": "string" + }, + "funder_id": { + "description": "Funder ROR id.", + "type": "string" + }, + "funder_name": { + "description": "Funder name.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "index": { + "description": "Position of the additional description whose text this window continues (0 = first). Present only for an additional description’s text.", + "type": "number" + }, + "keywords": { + "description": "Up to 50 subject keywords starting at offset. Present when field is keywords.", + "items": { + "type": "string" + }, + "type": "array" + }, + "offset": { + "description": "Characters or entries of the field before this window.", + "type": "number" + }, + "related_identifiers": { + "description": "Up to 50 related identifiers starting at offset. Present when field is related_identifiers.", + "items": { + "additionalProperties": false, + "description": "One related identifier.", + "properties": { + "identifier": { + "description": "The related identifier (DOI, arXiv id, URL, PMID, …).", + "type": "string" + }, + "relation": { + "description": "Relation type id, e.g. issupplementto or cites.", + "type": "string" + }, + "resource_type": { + "description": "Resource type id of the related item.", + "type": "string" + }, + "scheme": { + "description": "Identifier scheme, e.g. doi, arxiv, url.", + "type": "string" + } + }, + "required": [ + "identifier" + ], + "type": "object" + }, + "type": "array" + }, + "shown": { + "description": "Characters or entries in this window.", + "type": "number" + }, + "text": { + "description": "Up to 8,000 characters of the field’s plain text, starting at offset. Present when unit is characters.", + "type": "string" + }, + "total": { + "description": "Full length of the field in characters, or its total entries.", + "type": "number" + }, + "unit": { + "description": "characters for a text window, entries for a list window.", + "enum": [ + "characters", + "entries" + ], + "type": "string" + } + }, + "required": [ + "field", + "unit", + "offset", + "shown", + "total" + ], + "type": "object" +}
- Changed
zenodo_list_files5 fields changed- changed
Input schema / properties / limit / descriptionPrevious value: -"Entries per page (1–200)."New value: +"Entries per page, at most 200 per call; larger values return 200." - changed
Input schema / properties / limit / maximumPrevious value: -200New value: +10000 - changed
Output schema / properties / cap / descriptionPrevious value: -"Page size applied."New value: +"Page size applied (at most 200)." - changed
Output schema / properties / limit / descriptionPrevious value: -"Page size applied."New value: +"Page size applied: limit, or 200 when limit asked for more." - changed
Output schema / properties / notice / descriptionPrevious value: -"File access notes, empty-filter guidance, listing caps, or paging guidance."New value: +"File access notes, empty-filter guidance, listing caps, the 200-per-call limit cap, or paging guidance."
- Changed
zenodo_list_versions7 fields changed- changed
Input schema / properties / page / descriptionPrevious value: -"Result page, starting at 1. page × size may not exceed 10,000."New value: +"Result page, starting at 1. Zenodo pages through only the first 10,000 versions, so the last reachable page is 10,000 ÷ size rounded up (400 at size 25)." - changed
Input schema / properties / size / descriptionPrevious value: -"Versions per page (1–25)."New value: +"Versions per page, at most 25 per call; larger values return 25." - changed
Input schema / properties / size / maximumPrevious value: -25New value: +10000 - changed
Output schema / properties / cap / descriptionPrevious value: -"Page size applied."New value: +"Page size applied (at most 25)." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `invalid_identifier`: id matches no accepted form, or is a GitHub-badge latestdoi id or a non-zenodo.org host. `result_window_exceeded`: page × size exceeds 10,000. `record_unavailable`: Zenodo could not serve this record or its versions page: HTTP 500 after one retry, HTTP 500 while resolving a non-Zenodo DOI, or no complete record response within the time budget (its gateway cuts off near 30 s, which deposits with about 10,000 or more files hit). `upstream_timeout`: The versions page got no complete response within its time budget. `rate_limited`: Zenodo answered HTTP 429, or this server's shared Zenodo request budget is spent for the current window. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `invalid_identifier`: id matches no accepted form, or is a GitHub-badge latestdoi id or a non-zenodo.org host. `result_window_exceeded`: The page starts past the first 10,000 versions: (page − 1) × size is 10,000 or more, counting a size above 25 as 25. `record_unavailable`: Zenodo could not serve this record or its versions page: HTTP 500 after one retry, HTTP 500 while resolving a non-Zenodo DOI, or no complete record response within the time budget (its gateway cuts off near 30 s, which deposits with about 10,000 or more files hit). `upstream_timeout`: The versions page got no complete response within its time budget. `rate_limited`: Zenodo answered HTTP 429, or this server's shared Zenodo request budget is spent for the current window. Other values are possible when a failure originates below the handler." - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance on paging or a page past the end."New value: +"Guidance on paging, the 25-per-call size cap, or a page past the end." - changed
Output schema / properties / size / descriptionPrevious value: -"Page size applied."New value: +"Page size applied: size, or 25 when size asked for more."
- Changed
zenodo_lookup_vocabulary11 fields changed- changed
Input schema / properties / page / descriptionPrevious value: -"Result page, starting at 1."New value: +"Result page, starting at 1. Only the first 10,000 entries of a list are reachable, so the last reachable page is 10,000 ÷ size rounded up (400 at size 25)." - changed
Input schema / properties / size / descriptionPrevious value: -"Entries per page (1–25)."New value: +"Entries per page, at most 25 per call; larger values return 25." - changed
Input schema / properties / size / maximumPrevious value: -25New value: +10000 - changed
Output schema / anyOfPrevious value: -[ - { - "not": { - "required": [ - "error" - ] - }, - "required": [ - "vocabulary", - "total", - "page", - "size", - "has_more", - "entries", - "truncated", - "shown", - "cap", - "totalCount" - ] - }, - { - "required": [ - "error" - ] - } -]New value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "vocabulary", + "total", + "reachable", + "page", + "size", + "has_more", + "entries", + "truncated", + "shown", + "cap", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - changed
Output schema / properties / cap / descriptionPrevious value: -"Page size applied."New value: +"Page size applied (at most 25)." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `funder_only_for_awards`: funder is set with a vocabulary other than awards. `unknown_funder`: funder (awards) resolves to no Zenodo funder. `result_window_exceeded`: page × size exceeds 10,000. `rate_limited`: Zenodo answered HTTP 429, or this server's shared Zenodo request budget is spent for the current window. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `funder_only_for_awards`: funder is set with a vocabulary other than awards. `unknown_funder`: funder (awards) resolves to no Zenodo funder. `result_window_exceeded`: The page starts past the first 10,000 entries: (page − 1) × size is 10,000 or more, counting a size above 25 as 25. `rate_limited`: Zenodo answered HTTP 429, or this server's shared Zenodo request budget is spent for the current window. Other values are possible when a failure originates below the handler." - changed
Output schema / properties / has_more / descriptionPrevious value: -"True when more pages follow this one."New value: +"True when another page of reachable entries follows." - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance on empty results, ambiguous funders, or further pages."New value: +"Guidance on empty results, ambiguous funders, the 10,000-entry window, the 25-per-call size cap, or further pages." - added
Output schema / properties / reachableAdded value: +{ + "description": "Entries reachable by paging: min(total, 10,000).", + "type": "number" +} - changed
Output schema / properties / size / descriptionPrevious value: -"Page size applied."New value: +"Page size applied: size, or 25 when size asked for more." - changed
Output schema / properties / truncated / descriptionPrevious value: -"True when more entries exist beyond this page."New value: +"True when more reachable entries follow this page."
- Changed
zenodo_read_file3 fields changed- changed
Input schema / properties / max_bytes / descriptionPrevious value: -"Maximum bytes to read (256–65536)."New value: +"Maximum bytes to read (256 or more), at most 65536 per call; larger values return 65536." - changed
Input schema / properties / max_bytes / maximumPrevious value: -65536New value: +9007199254740991 - changed
Output schema / properties / notice / descriptionPrevious value: -"Why no text was returned, or how to read the rest of the file."New value: +"Why no text was returned, or how to read the rest of the file, naming the 65,536-byte cap when it held back bytes."
- Changed
zenodo_search_records8 fields changed- changed
Input schema / properties / page / descriptionPrevious value: -"Result page, starting at 1. page × size may not exceed 10,000."New value: +"Result page, starting at 1. Only the first 10,000 matches are reachable, so the last reachable page is 10,000 ÷ size rounded up (400 at size 25)." - changed
Input schema / properties / query / descriptionPrevious value: -"Keyword query. Terms are OR-ed unless joined with AND; \"quoted phrases\" match exactly; field syntax such as metadata.title:\"…\" or doi:\"10.5281/zenodo.N\" works. Escape a literal / as \\/. A bare DOI or record URL is rejected; open it with zenodo_get_record instead. Omit to browse with filters only."New value: +"Keyword query. Terms are OR-ed unless joined with AND; \"quoted phrases\" (double quotes) match exactly; field syntax such as metadata.title:\"…\" or doi:\"10.5281/zenodo.N\" works. Escape a literal / as \\/. A bare DOI or record URL is rejected; open it with zenodo_get_record instead. With any filter other than community and all_versions, a query that is not valid search syntax (AND AND, a field: with no value, an unclosed [a TO b]) is rejected; without one, Zenodo matches it as plain text. Omit to browse with filters only." - changed
Input schema / properties / size / descriptionPrevious value: -"Results per page (1–25)."New value: +"Results per page, at most 25 per call; larger values return 25." - changed
Input schema / properties / size / maximumPrevious value: -25New value: +10000 - changed
Output schema / properties / cap / descriptionPrevious value: -"Page size applied."New value: +"Page size applied (at most 25)." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `query_is_identifier`: The query is a single DOI, doi.org URL, or zenodo.org record URL. `query_syntax`: The query has an unpaired unescaped / outside quotes. `query_failed`: Zenodo answered HTTP 500 for a query that passed the local checks. `upstream_timeout`: The search attempt got no complete response within its time budget. `unknown_community`: community resolves to no Zenodo community. `unknown_funder`: funder is not a known ROR id and no funder carries that Crossref Funder DOI. `invalid_date_range`: The expanded published_from is after published_to. `result_window_exceeded`: page × size exceeds 10,000. `rate_limited`: Zenodo answered HTTP 429, or this server's shared Zenodo request budget is spent for the current window. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `query_is_identifier`: The query is a single DOI, doi.org URL, or zenodo.org record URL. `query_syntax`: The query holds something Zenodo cannot run: a regular expression with no closing / (an unescaped / outside double quotes) or with a \" inside /…/ left open; a \" inside a word whose phrase never closes (with a filter other than community and all_versions set, only when the query still fails once that phrase is closed at its end) or closes past a bracket the query needs; a range bound ending in a backslash, as one holding an escaped space, ] or } does; an unescaped ! with nothing after it; or a boost, fuzziness, or proximity value it cannot convert. Or a filter other than community and all_versions is set and the query is not valid search syntax, which Zenodo would match as plain text with every filter dropped. `query_failed`: Zenodo answered HTTP 500 for a query that passed the local checks. `upstream_timeout`: The search attempt got no complete response within its time budget. `unknown_community`: community resolves to no Zenodo community. `unknown_funder`: funder is not a known ROR id and no funder carries that Crossref Funder DOI. `invalid_date_range`: The expanded published_from is after published_to. `result_window_exceeded`: The page starts past the first 10,000 matches: (page − 1) × size is 10,000 or more, counting a size above 25 as 25. `rate_limited`: Zenodo answered HTTP 429, or this server's shared Zenodo request budget is spent for the current window. Other values are possible when a failure originates below the handler." - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance on empty results, the 10,000-result window, or further pages."New value: +"Guidance on a query Zenodo matched as plain text, empty results, the 10,000-result window, the 25-per-call size cap, or further pages." - changed
Output schema / properties / size / descriptionPrevious value: -"Page size applied."New value: +"Page size applied: size, or 25 when size asked for more."
6 tool updates
- First observed
zenodo_get_record - First observed
zenodo_list_files - First observed
zenodo_list_versions - First observed
zenodo_lookup_vocabulary - First observed
zenodo_read_file - First observed
zenodo_search_records
Related MCP Connectors
Search DataCite datasets and software, fetch DOI metadata, trace relations, format citations.
Resolve DOIs, search ~188M scholarly works, and fetch references via the Crossref REST API.
Search 150M+ academic works, journals, and funders via Crossref API.
Resolve DOI identifiers to Crossref titles, venues, dates and citation counts for reference checks.
Related MCP Servers
- AlicenseAqualityAmaintenanceSearches and fetches research datasets across Zenodo, DataCite (Dryad/Figshare/Dataverse/OSF), NCBI omics archives (GEO/SRA/BioProject), and the literature (PubMed/OpenAIRE) through one normalized model — deduplicating by DOI, expanding organism queries with NCBI Taxonomy synonyms, and bridging papers to the datasets they produced. Resolves citations and open-access full text, and downloads files.6520 PyPI4MIT
- AlicenseNot gradedqualityBmaintenanceProvides access to DataCite DOIs for research datasets, enabling searching and retrieval of dataset metadata.273 npmMIT
- AlicenseAqualityCmaintenanceEnables retrieval of academic literature metadata via DOI or search using the Crossref REST API.2MIT
- AlicenseNot gradedqualityBmaintenanceEnables searching academic papers, journals, and citations via the Crossref API, and resolving DOIs to canonical metadata with authors, references, and citation graphs.252 npmMIT
Glama MCP Gateway
Add one secure layer between your agents and this server.