ip-research

IP data research tools for patents, trademarks, and related USPTO/EPO/JPO records. Use when: - Looking up patents by number (US, EP, WO, JP, etc.) - Searching patent databases by keyword, assignee, in

SKILL.md

GitHub

IP Research

Async Python clients for patent and IP data. All clients use async with context managers. All shared scaffolding (HTTP, cache, retry, errors) lives in mcp_data_core, provided by the separate mcp-data-core package.

Routing

Task Client / Module Reference
Patent lookup / search by keywords google_patents.GooglePatentsClient google_patents.md
USPTO application status + file wrapper uspto_odp.ApplicationsClient uspto_odp.md
USPTO application high-level API patent_client_agents.uspto_applications uspto_applications.md
USPTO PTAB (IPR/PGR/CBM, ex parte appeals, interferences) uspto_odp.PtabTrialsClient / PtabAppealsClient / PtabInterferencesClient uspto_odp.md
USPTO petitions uspto_odp.PetitionsClient or patent_client_agents.uspto_petitions uspto_petitions.md
USPTO bulk data products uspto_odp.BulkDataClient or patent_client_agents.uspto_bulkdata uspto_bulkdata.md
USPTO assignments uspto_assignments.AssignmentCenterClient uspto_assignments.md
USPTO publications (PPUBS) full-text uspto_publications.PublicSearchClient uspto_publications.md
USPTO office actions patent_client_agents.uspto_office_actions uspto_office_actions.md
USPTO trademark status / documents (TSDR) uspto_tsdr.TsdrClient uspto_tsdr.md
USPTO trademark search (TESS — live trademark register) uspto_tmsearch.TmsearchClient uspto_tmsearch.md
USPTO trademark assignments uspto_trademark_assignments.TrademarkAssignmentClient uspto_trademark_assignments.md
EPO bibliographic / family / legal events epo_ops.EpoOpsClient epo_ops.md
JPO application status jpo.JpoClient jpo.md
MPEP search + section lookup patent_client_agents.mpep mpep.md
TMEP search + section lookup patent_client_agents.tmep tmep.md
CPC lookup / search / mapping patent_client_agents.cpc cpc.md
Canadian case law + IP statutes (FC / FCA / SCC / TMOB / Patent Appeal Board) patent_client_agents.canlii canlii.md
Canadian Federal Court party search + live dockets patent_client_agents.canada_federal_court canada-federal-court.md
China SPC IP Court scheduled hearings + site search patent_client_agents.china_spc_ip_court china-spc-ip-court.md
Global IP statutes via WIPO Lex (~200 jurisdictions) patent_client_agents.wipo_lex wipo_lex.md
EU Trade Marks (EUTM register, ~2.3M marks) patent_client_agents.euipo_trademarks euipo.md
EU Registered Community Designs (~1.5M designs) patent_client_agents.euipo_designs euipo.md
Federal Circuit (CAFC) opinions — appellate patent law patent_client_agents.cafc cafc.md
USITC Section 337 patent enforcement (EDIS), DataWeb trade stats, HTS, IDS IP investigations patent_client_agents.usitc usitc.md
US Copyright Office — registrations, recorded transfers patent_client_agents.copyright copyright.md

Quick Examples

Lookup patent by number

from patent_client_agents.google_patents import GooglePatentsClient

async with GooglePatentsClient() as client:
    patent = await client.get_patent_data("US10123456B2")

Search USPTO applications

from patent_client_agents.uspto_odp import ApplicationsClient

async with ApplicationsClient() as client:  # Requires USPTO_ODP_API_KEY
    results = await client.search(query="inventionTitle:laser", limit=25)
    for record in results.applicationBag:
        print(record.applicationNumberText, record.filingDate)

Find PTAB proceedings

from patent_client_agents.uspto_odp import PtabTrialsClient

async with PtabTrialsClient() as client:
    proceedings = await client.search_proceedings(query="patent:US10123456")

Look up MPEP section

from patent_client_agents.mpep import SearchInput, search

response = await search(SearchInput(query="obviousness rejection", per_page=10))
for hit in response.hits:
    print(hit.section_id, hit.title)

Check trademark status (TSDR)

from patent_client_agents.uspto_tsdr import TsdrClient

async with TsdrClient() as client:  # Requires USPTO_TSDR_API_KEY
    status = await client.get_status("97123456")
    print(status.mark_text, status.status_description)

Look up TMEP section

from patent_client_agents.tmep import get_section

section = await get_section("1207.01(a)")
print(section.title)

Resolve a CPC symbol

from patent_client_agents.cpc import retrieve_cpc

entry = await retrieve_cpc(symbol="H04L63/08", ancestors=True)

Search Canadian IP case law (CanLII)

from patent_client_agents.canlii import BrowseCasesInput, browse_cases

# 20 most recent Federal Court IP decisions
recent = await browse_cases(BrowseCasesInput(
    database_id="fct",
    result_count=20,
    decision_date_after="2024-01-01",
))

Search Canadian Federal Court patent dockets

from patent_client_agents.canada_federal_court import CanadaFederalCourtClient

async with CanadaFederalCourtClient() as client:
    cases = await client.search_party_cases("Pfizer", patent_only=True)
    docket = await client.list_docket_entries(cases.cases[0].court_number)

The Court does not publish an official open/closed field. Treat likely_pending / likely_closed as conservative docket-text inferences and unknown as unresolved, not as evidence that no case is pending.

Monitor China SPC IP Court hearings

from patent_client_agents.china_spc_ip_court import ChinaSpcIpCourtClient

async with ChinaSpcIpCourtClient() as client:
    index = await client.list_hearing_index(page=1)
    notice = await client.get_hearing_notice(index.notices[0].notice_id)
    chip_material = await client.search_site("芯片")

Hearing notices are pending-hearing signals, not complete dockets. They often omit case and patent numbers, and the official site may be unreachable from some foreign DNS or cloud-egress environments.

Fetch a global IP statute via WIPO Lex

from patent_client_agents.wipo_lex import (
    SearchLegislationInput, SubjectMatter, search_legislation, get_legislation,
)

# Find Canadian patent statutes, then pull the Patent Act detail with PDFs
hits = await search_legislation(SearchLegislationInput(
    country_codes=["CA"], subject_matter=[SubjectMatter.PATENTS],
))
detail = await get_legislation(hits.hits[0].legislation_id)

Error Handling

All clients raise typed exceptions from mcp_data_core.exceptions. ApiError and its subclasses include a path to the log file in their string representation so agents can inspect stacktraces without keeping them in context.

from mcp_data_core.exceptions import (
    McpDataCoreError,
    NotFoundError,
    RateLimitError,
)

try:
    async with GooglePatentsClient() as client:
        patent = await client.get_patent_data("US99999999")
except NotFoundError as e:
    print(e)  # "... (HTTP 404, details: ~/.cache/patent_client_agents/patent_client_agents.log)"
except RateLimitError as e:
    if e.retry_after:
        await asyncio.sleep(e.retry_after)
except McpDataCoreError as e:
    print(e)  # Fallback for any other typed error

Exception hierarchy (from mcp_data_core.exceptions):

Exception When
NotFoundError Resource not found (404)
RateLimitError Rate limit exceeded (429); retry_after set if server supplied it
AuthenticationError Bad or missing API credentials (401/403)
ServerError Remote API 5xx
ApiError Other HTTP errors (base for all HTTP-level errors; appends log path)
ParseError Failed to parse response data
ConfigurationError Missing API key / invalid config
ValidationError Invalid input; also inherits ValueError
McpDataCoreError Base for all typed errors

Log file: ~/.cache/patent_client_agents/patent_client_agents.log — full tracebacks, request/response details, debug info. Read this when concise error messages aren't enough.

Environment Variables

Variable Required For
USPTO_ODP_API_KEY All USPTO ODP clients (Applications, PTAB, BulkData, Petitions, Office Actions)
USPTO_TSDR_API_KEY TSDR (trademark status / documents / images)
EPO_OPS_API_KEY EPO OPS, CPC (CPC uses EPO OPS under the hood)
EPO_OPS_API_SECRET EPO OPS, CPC
JPO_API_USERNAME JPO client
JPO_API_PASSWORD JPO client
CANLII_API_KEY CanLII (Canadian courts + IP statutes); free key by request

USPTO Publications, USPTO Assignments, USPTO Trademark Assignments, Google Patents, MPEP, TMEP, Canada Federal Court case files, China SPC IP Court hearing notices, Japan IP High Court patent and utility-model case lists, and WIPO Lex require no API key.

Cache Management

All clients cache HTTP responses to ~/.cache/patent_client_agents/ using hishel with a SQLite backend and WAL pragmas. See cache.md for TTL, invalidation, and statistics APIs.

Issue Reporting

Source: parkerhancock/patent-client-agents

Report bugs with version, minimal reproduction code, and relevant API response if applicable.

References