Skip to content

Patents

Patent tools reach the EPO Open Patent Services API and need EPO OPS credentials. Without SCHOLAR_MCP_EPO_CONSUMER_KEY and SCHOLAR_MCP_EPO_CONSUMER_SECRET they're hidden. Obtaining EPO OPS credentials covers setup.

search_patents

Search Patents. Read-only. Reaches outside the server. Tags: patent.

Search for patents in the European Patent Office database.

Covers European patents and global patents via INPADOC (100+ patent offices). At least one parameter must be provided. For keyword search, query searches titles and abstracts. To find all patents by an inventor or applicant, omit query and use only the structured filters. For academic paper search, use search_papers instead.

When EPO reports itself busy this waits for it to clear, which can take a few minutes, so the call may answer with a job handle to poll using get_job_result rather than the result itself. Do not reason about EPO throttle states yourself.

Parameters

Name Type Default Description
query string \| null null Keyword search over patent titles and abstracts. Optional; omit when searching purely by inventor, applicant, CPC code, or date.
cpc_classification string \| null null CPC classification code to filter by, such as "H01M10/00" for lithium-ion batteries.
applicant string \| null null Applicant (assignee) name to filter by.
inventor string \| null null Inventor name to filter by.
date_from string \| null null Earliest date (YYYY-MM-DD).
date_to string \| null null Latest date (YYYY-MM-DD).
date_type publication \| filing \| priority "publication" Date field to apply the range to: "publication", "filing" or "priority".
jurisdiction string \| null null Restrict to a single patent authority, such as "EP", "WO" or "US".
limit integer 10 Maximum results to return (default 10).
offset integer 0 Pagination offset (0-based).

Returns

A mapping with total_count and a references list, or an error mapping if the EPO client is not configured or the API fails. A busy EPO service is waited out rather than failed on, which can take a few minutes; the call is then handed back as {"status": "working", "job_id": "..."} and the result retrieved with get_job_result. If the service never clears, the outcome is {"error": "rate_limited", "retryable": true} with a hint, and an exhausted daily quota is {"error": "epo_unavailable", "retryable": false}. Do not manage or reason about EPO throttle states directly.

Each entry in references has country, number, and kind fields.

Query syntax

The tool translates parameters into EPO CQL internally. query will not find patents where the keyword appears only in inventor/applicant names. Combining query with filters applies both constraints.

get_patent

Get Patent. Read-only. Reaches outside the server. Tags: patent.

Get detailed information about a single patent.

Accepts patent numbers in any format (EP, WO, US, etc.). By default returns bibliographic data only; use the sections parameter to request additional detail (claims, description, family members, legal status, cited references). When sections includes 'citations', non-patent literature references are resolved to Semantic Scholar papers on a best-effort basis; unresolved references are returned as raw citation strings.

When EPO reports itself busy this waits for it to clear, which can take a few minutes, so the call may answer with a job handle to poll using get_job_result rather than the result itself. Do not reason about EPO throttle states yourself.

Parameters

Name Type Default Description
patent_number string required Patent number in any common format, such as "EP1234567A1", "WO2024/123456" or "US11,234,567B2".
sections array of biblio \| claims \| description \| family \| legal \| citations \| null null Sections to include in the response. Defaults to ["biblio"]. Available sections: biblio, claims, description, family, legal, citations. When citations is included, NPL references are resolved via Semantic Scholar on a best-effort basis.

Returns

A mapping with patent_number (normalised DOCDB format) and the requested section data, or an error mapping on failure. A busy EPO service is waited out rather than failed on, which can take a few minutes; the call is then handed back as {"status": "working", "job_id": "..."} and the result retrieved with get_job_result. If the service never clears, the outcome is {"error": "rate_limited", "retryable": true} with a hint, and an exhausted daily quota is {"error": "epo_unavailable", "retryable": false}. Do not manage or reason about EPO throttle states directly.

Available sections:

Section Description Status
biblio Bibliographic metadata (title, applicants, inventors, dates, classifications, abstract) Available
claims Patent claims text (English preferred) Available
description Full patent description text (English preferred) Available
family Patent family members across jurisdictions (country, number, kind, date) Available
legal Legal status events (date, code, description, country) Available
citations Patent and non-patent literature citations, with Semantic Scholar resolution for NPL Available

country is the contracting state a legal event concerns. EPO sends it only on the event types that name one, such as PG25 (lapsed in a state), REG and PGFP, so it is an empty string on the rest. It is what distinguishes the otherwise identical PG25 events a patent accumulates as it lapses state by state.

Sections are fetched concurrently where possible (cache lookups run in parallel; EPO API calls are serialised by the client). Each section is cached independently with appropriate TTLs.

A response has keys matching the requested sections:

{
  "patent_number": "EP.1234567.A1",
  "biblio": {
    "title": "...",
    "abstract": "...",
    "applicants": ["..."],
    "inventors": ["..."],
    "publication_number": "EP.1234567.A1",
    "publication_date": "2020-01-15",
    "filing_date": "2019-06-01",
    "priority_date": "2019-01-15",
    "family_id": "12345678",
    "classifications": ["H04L29/06"],
    "url": "https://worldwide.espacenet.com/..."
  },
  "claims": "1. A method for...\n\n2. The method of claim 1...",
  "family": [
    {"country": "US", "number": "11234567", "kind": "B2", "date": "2021-03-01"}
  ],
  "legal": [
    {"date": "2021-07-30", "code": "PG25", "description": "LAPSED IN A CONTRACTING STATE [...]", "country": "BG"}
  ],
  "citations": {
    "patent_refs": [
      {"country": "US", "number": "9876543", "kind": "B2"}
    ],
    "npl_refs": [
      {"raw": "Smith et al., \"Widget Processing\", 2018, doi:10.1234/test", "paper": {"paperId": "abc123", "title": "Widget Processing"}, "confidence": "high"},
      {"raw": "Doe, \"Advanced Widgets\", Ch. 5, pp. 112-130, 2019", "confidence": null, "chapter_info": {"citation_source": "parsed", "chapter_number": 5, "page_start": 112, "page_end": 130}}
    ]
  }
}

In citations, NPL references with a DOI are resolved with "confidence": "high". A DOI is recognised after doi:, DOI, or in a doi.org link, and one that does not resolve is still returned in doi. References without a DOI or that fail to resolve have "confidence": null. When citation strings contain chapter patterns (such as "Ch. 5" or "pp. 112-130"), a chapter_info dict is included with parsed chapter and page information.

get_citing_patents

Get Citing Patents. Read-only. Reaches outside the server. Tags: patent.

Find patents that cite a given academic paper.

Coverage is incomplete: it relies on EPO OPS citation search, which does not capture all patent-to-paper citations. Best results with DOIs of well-known, highly cited papers. Returns confirmed matches only, not an exhaustive list.

When EPO reports itself busy this waits for it to clear, which can take a few minutes, so the call may answer with a job handle to poll using get_job_result rather than the result itself. Do not reason about EPO throttle states yourself.

Parameters

Name Type Default Description
paper_id string required Paper identifier (DOI preferred, also accepts title keywords).
limit integer 10 Maximum number of citing patents to return (default 10, max 25).

Returns

A mapping with paper_id, a patents list (each with biblio data and match_source), total_count, and a note about coverage limitations. A busy EPO service is waited out rather than failed on, which can take a few minutes; the call is then handed back as {"status": "working", "job_id": "..."} and the result retrieved with get_job_result. If the service never clears, the outcome is {"error": "rate_limited", "retryable": true} with a hint, and an exhausted daily quota is {"error": "epo_unavailable", "retryable": false}. Do not manage or reason about EPO throttle states directly.

A response looks like:

{
  "paper_id": "10.1234/test",
  "patents": [
    {"title": "...", "publication_number": "EP.9999999.A1", "match_source": "epo_search", ...}
  ],
  "total_count": 1,
  "note": "Coverage is incomplete. Results come from EPO OPS citation search..."
}

fetch_patent_pdf

Fetch Patent PDF. Changes state, not destructive. Reaches outside the server. Tags: patent, write.

Download a patent PDF via authenticated EPO OPS and convert to Markdown.

Downloads the full-document PDF for a patent using the authenticated EPO Open Patent Services session, saves it locally, and if docling is configured converts it to Markdown. EPO serves patent images one page per request, so a long patent costs one request per page and the document is reassembled before conversion.

Not all patents have full text available through OPS: WO and older EP patents sometimes lack PDFs. Returns an error in that case.

A previously downloaded and converted patent answers immediately; a fresh download plus conversion typically takes 1-5 minutes and is returned as a background job handle instead.

When EPO reports itself busy this waits for it to clear, which can take a few minutes, so the call may answer with a job handle to poll using get_job_result rather than the result itself. Do not reason about EPO throttle states yourself.

Markdown is returned in pages of at most 20,000 characters. When next_offset is present, call this tool again with that value as text_offset; the cached conversion makes later pages inexpensive. Set max_chars to null only when the client can accept the complete document in one response.

Parameters

Name Type Default Description
patent_number string required Patent number in any format (EP, WO, US and others), such as EP3491801B1, EP 3491801 B1 or US10123456B2.
use_vlm boolean false Use VLM enrichment for formulas and figures (requires VLM to be configured).
text_offset integer 0 Character offset at which the Markdown page starts.
max_chars integer \| null 20000 Maximum Markdown characters to return, capped at 20,000. Pass null for the complete text.

Returns

pdf_path and optionally markdown / md_path.

A response looks like {"pdf_path": "/data/scholar-mcp/pdfs/<stem>.pdf", "markdown": "...", "md_path": "/data/scholar-mcp/md/<stem>.md"} when docling is configured, or just {"pdf_path": "..."} without it.

When markdown is present, the response also reports text_offset, text_returned_chars, text_total_chars, and text_truncated.

A patent with no PDF available through OPS returns {"error": "pdf_not_available"}.

Download time

A 21-page patent takes roughly 20 seconds to download; longer patents scale linearly, which is part of why this tool commonly answers with a job handle.

Write-tagged

This tool carries both gates: it is hidden when SCHOLAR_MCP_READ_ONLY=true, and like every patent tool it is hidden when EPO OPS credentials are not set.