Skip to main content
Glama
john-walkoe

USPTO Final Petition Decisions MCP Server

by john-walkoe

Search_petitions_minimal

Search USPTO final petition decisions using simple parameters like applicant name, decision type, or date ranges to discover relevant petitions quickly.

Instructions

Ultra-fast discovery search for Final Petition Decisions (50-100 results).

NEW: Minimal tier convenience parameters (9 total) - no query syntax needed!

Use for: High-volume petition discovery, finding petitions by applicant, decision type, or date range. Returns: 8 essential fields - petition ID, application number, patent number, applicant name, decision type, petition mail date, decision date, deciding office.

Convenience Parameters:

  • applicant_name: Company/party name (e.g., 'Apple Inc.')

  • application_number: Application number (e.g., '17896175')

  • patent_number: Patent number if granted (e.g., '11788453')

  • decision_type: Outcome (e.g., 'GRANTED', 'DENIED', 'DISMISSED')

  • deciding_office: Office that decided (e.g., 'OFFICE OF PETITIONS')

  • petition_date_start/end: Filing date range (YYYY-MM-DD)

  • decision_date_start/end: Decision date range (YYYY-MM-DD)

Examples:

# Denied petitions for company fpd_search_petitions_minimal(applicant_name="TechCorp Inc.", decision_type="DENIED", limit=50) # Hybrid: keywords + convenience fpd_search_petitions_minimal(query="machine learning", decision_type="DENIED", limit=50)

Progressive Disclosure Workflow:

  1. Use THIS TOOL for discovery with minimal params (50-100 results)

  2. Present top results to user for selection

  3. Use fpd_search_petitions_balanced for detailed analysis (10-20 selected)

    • Balanced tier adds: petition_type_code, art_unit, technology_center, prosecution_status, entity_status

  4. Use fpd_get_petition_details for complete petition data

Cross-MCP Integration:

  • {QueryFieldNames.APPLICATION_NUMBER} -> Links to Patent File Wrapper MCP

  • {QueryFieldNames.PATENT_NUMBER} -> Links to PTAB MCP for post-grant challenges

  • Use balanced tier to get {QueryFieldNames.ART_UNIT} for PFW cross-reference

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryNo
limitNo
offsetNo
applicant_nameNo
application_numberNo
patent_numberNo
decision_typeNo
deciding_officeNo
petition_date_startNo
petition_date_endNo
decision_date_startNo
decision_date_endNo

Implementation Reference

  • Primary handler for Search_petitions_minimal tool. Includes @mcp.tool registration decorator. Validates inputs, builds Lucene query from 9 convenience parameters, calls FPDClient.search_petitions with petitions_minimal fields, filters response with FieldManager, adds metadata and LLM guidance.
    @mcp.tool(name="Search_petitions_minimal") @async_tool_error_handler("minimal_search") async def fpd_search_petitions_minimal( query: str = "", limit: int = 50, offset: int = 0, # NEW: Minimal tier convenience parameters (9 total) # Core Identity & Party applicant_name: Optional[str] = None, # e.g., "Apple Inc.", "TechCorp" application_number: Optional[str] = None, # e.g., "17896175" patent_number: Optional[str] = None, # e.g., "11788453" # Decision Filters decision_type: Optional[str] = None, # e.g., "GRANTED", "DENIED", "DISMISSED" deciding_office: Optional[str] = None, # e.g., "OFFICE OF PETITIONS" # Date Ranges petition_date_start: Optional[str] = None, # e.g., "2024-01-01" (YYYY-MM-DD) petition_date_end: Optional[str] = None, # e.g., "2024-12-31" (YYYY-MM-DD) decision_date_start: Optional[str] = None, # e.g., "2024-01-01" (YYYY-MM-DD) decision_date_end: Optional[str] = None # e.g., "2024-12-31" (YYYY-MM-DD) ) -> Dict[str, Any]: """Ultra-fast discovery search for Final Petition Decisions (50-100 results). **NEW: Minimal tier convenience parameters (9 total) - no query syntax needed!** Use for: High-volume petition discovery, finding petitions by applicant, decision type, or date range. Returns: 8 essential fields - petition ID, application number, patent number, applicant name, decision type, petition mail date, decision date, deciding office. **Convenience Parameters:** - `applicant_name`: Company/party name (e.g., 'Apple Inc.') - `application_number`: Application number (e.g., '17896175') - `patent_number`: Patent number if granted (e.g., '11788453') - `decision_type`: Outcome (e.g., 'GRANTED', 'DENIED', 'DISMISSED') - `deciding_office`: Office that decided (e.g., 'OFFICE OF PETITIONS') - `petition_date_start/end`: Filing date range (YYYY-MM-DD) - `decision_date_start/end`: Decision date range (YYYY-MM-DD) **Examples:** ```python # Denied petitions for company fpd_search_petitions_minimal(applicant_name="TechCorp Inc.", decision_type="DENIED", limit=50) # Hybrid: keywords + convenience fpd_search_petitions_minimal(query="machine learning", decision_type="DENIED", limit=50) ``` **Progressive Disclosure Workflow:** 1. Use THIS TOOL for discovery with minimal params (50-100 results) 2. Present top results to user for selection 3. Use fpd_search_petitions_balanced for detailed analysis (10-20 selected) - Balanced tier adds: petition_type_code, art_unit, technology_center, prosecution_status, entity_status 4. Use fpd_get_petition_details for complete petition data **Cross-MCP Integration:** - {QueryFieldNames.APPLICATION_NUMBER} -> Links to Patent File Wrapper MCP - {QueryFieldNames.PATENT_NUMBER} -> Links to PTAB MCP for post-grant challenges - Use balanced tier to get {QueryFieldNames.ART_UNIT} for PFW cross-reference""" # Input validation if limit < api_constants.MIN_SEARCH_LIMIT or limit > api_constants.MAX_SEARCH_LIMIT: raise ValidationError(f"Limit must be between {api_constants.MIN_SEARCH_LIMIT} and {api_constants.MAX_SEARCH_LIMIT}", generate_request_id()) if offset < 0: raise ValidationError("Offset must be non-negative", generate_request_id()) # Build query from convenience parameters final_query, convenience_params_used = _build_convenience_query( query=query, applicant_name=applicant_name, application_number=application_number, patent_number=patent_number, decision_type=decision_type, deciding_office=deciding_office, petition_date_start=petition_date_start, petition_date_end=petition_date_end, decision_date_start=decision_date_start, decision_date_end=decision_date_end, allow_balanced_params=False # Minimal tier only ) # Additional query length validation if len(final_query) > 2000: raise ValidationError("Combined query too long (max 2000 characters)", generate_request_id()) # Get fields from field manager fields = field_manager.get_fields("petitions_minimal") # Search petitions result = await api_client.search_petitions( query=final_query, fields=fields, limit=limit, offset=offset ) # Check for errors if "error" in result: return result # Filter response using field manager filtered_result = field_manager.filter_response(result, "petitions_minimal") # Add query metadata filtered_result["query_info"] = { "final_query": final_query, "convenience_parameters_used": convenience_params_used, "tier": "minimal", "available_parameters": [ "applicant_name", "application_number", "patent_number", "decision_type", "deciding_office", "petition_date_start", "petition_date_end", "decision_date_start", "decision_date_end" ] } # Add usage guidance filtered_result["llm_guidance"] = { "workflow": "Discovery -> User Selection -> Balanced Analysis -> Cross-MCP Integration", "parameter_guidance": { "current_tier": "minimal (9 convenience parameters available)", "next_tier": "Use fpd_search_petitions_balanced for 5 additional parameters: petition_type_code, art_unit, technology_center, prosecution_status, entity_status", "progressive_disclosure": "Start here for discovery, advance to balanced for analysis" }, "next_steps": [ "Present top results to user for selection", "Use fpd_search_petitions_balanced for detailed analysis of selected petitions", "Use fpd_search_petitions_by_application to get all petitions for specific application", "Cross-reference with PFW using applicationNumberText for prosecution history", "Cross-reference with PTAB using patentNumber for post-grant challenges" ], "red_flags": { "revival_petitions": "Look for ruleBag containing '37 CFR 1.137' (abandoned applications)", "examiner_disputes": "Look for ruleBag containing '37 CFR 1.181' (supervisory review)", "denied_petitions": "decisionTypeCodeDescriptionText: 'DENIED' indicates potential quality issues" } } return filtered_result
  • MCP tool registration decorator specifying the exact tool name 'Search_petitions_minimal'.
    @mcp.tool(name="Search_petitions_minimal")
  • Output schema definition for minimal field set (8 essential fields). Used by field_manager.get_fields('petitions_minimal') and filter_response to reduce context by 95-99%.
    "petitions_minimal": { "description": "Essential fields for petition discovery", "fields": [ "petitionDecisionRecordIdentifier", "applicationNumberText", "patentNumber", "firstApplicantName", "decisionTypeCodeDescriptionText", "petitionMailDate", "decisionDate", "finalDecidingOfficeName" ]
  • Type definitions and constants for all input query fields and output response fields used in the tool.
    class FPDFields: """ Constants for USPTO Final Petition Decisions API field names. These constants represent the exact field names used by the USPTO API. Use these instead of hardcoded strings to enable: - IDE autocomplete - Easier refactoring - Catching typos at development time """ # === TOP-LEVEL FIELDS === PETITION_DECISION_DATA_BAG = "petitionDecisionDataBag" # === CORE IDENTIFICATION FIELDS === PETITION_DECISION_RECORD_IDENTIFIER = "petitionDecisionRecordIdentifier" # UUID APPLICATION_NUMBER_TEXT = "applicationNumberText" # Links to PFW MCP PATENT_NUMBER = "patentNumber" # Links to PTAB MCP # === APPLICANT/INVENTOR FIELDS === FIRST_APPLICANT_NAME = "firstApplicantName" INVENTOR_BAG = "inventorBag" CUSTOMER_NUMBER = "customerNumber" FIRST_INVENTOR_TO_FILE_INDICATOR = "firstInventorToFileIndicator" # AIA indicator # === DECISION FIELDS === DECISION_TYPE_CODE_DESCRIPTION_TEXT = "decisionTypeCodeDescriptionText" # GRANTED/DENIED/DISMISSED PETITION_MAIL_DATE = "petitionMailDate" # When petition filed DECISION_DATE = "decisionDate" # When Director decided DECISION_MAIL_DATE = "decisionMailDate" # When decision mailed FINAL_DECIDING_OFFICE_NAME = "finalDecidingOfficeName" # Deciding office # === PETITION TYPE FIELDS === DECISION_PETITION_TYPE_CODE = "decisionPetitionTypeCode" # Type code (551, etc.) DECISION_PETITION_TYPE_CODE_DESCRIPTION_TEXT = "decisionPetitionTypeCodeDescriptionText" # === CLASSIFICATION FIELDS === GROUP_ART_UNIT_NUMBER = "groupArtUnitNumber" # Art unit (→ PFW cross-ref) TECHNOLOGY_CENTER = "technologyCenter" # TC # === STATUS FIELDS === PROSECUTION_STATUS_CODE = "prosecutionStatusCode" PROSECUTION_STATUS_CODE_DESCRIPTION_TEXT = "prosecutionStatusCodeDescriptionText" BUSINESS_ENTITY_STATUS_CATEGORY = "businessEntityStatusCategory" # Small/Undiscounted # === LEGAL CONTEXT FIELDS (ARRAYS) === PETITION_ISSUE_CONSIDERED_TEXT_BAG = "petitionIssueConsideredTextBag" # Issues raised RULE_BAG = "ruleBag" # CFR rules cited (e.g., "37 CFR 1.137") STATUTE_BAG = "statuteBag" # Statutes cited # === COURT INFORMATION === COURT_ACTION_INDICATOR = "courtActionIndicator" # Boolean ACTION_TAKEN_BY_COURT_NAME = "actionTakenByCourtName" # === INVENTION DETAILS === INVENTION_TITLE = "inventionTitle" # === METADATA === LAST_INGESTION_DATE_TIME = "lastIngestionDateTime" # Data freshness # === DOCUMENT FIELDS === DOCUMENT_BAG = "documentBag" DOCUMENT_IDENTIFIER = "documentIdentifier" DOCUMENT_CODE = "documentCode" DOCUMENT_CODE_DESCRIPTION_TEXT = "documentCodeDescriptionText" DOCUMENT_FILE_NAME = "documentFileName" PAGE_COUNT = "pageCount" # === DOWNLOAD FIELDS === DOWNLOAD_OPTION_BAG = "downloadOptionBag" MIME_TYPE_IDENTIFIER = "mimeTypeIdentifier" # PDF, etc. DOWNLOAD_URL = "downloadUrl" PAGE_TOTAL_QUANTITY = "pageTotalQuantity" class QueryFieldNames: """ Field names as they appear in Lucene/search queries. Use these for building search queries with convenience parameters. """ # Core search fields APPLICATION_NUMBER = "applicationNumberText" PATENT_NUMBER = "patentNumber" APPLICANT_NAME = "firstApplicantName" # Classification search ART_UNIT = "groupArtUnitNumber" TECHNOLOGY_CENTER = "technologyCenter" # Date search PETITION_MAIL_DATE = "petitionMailDate" DECISION_DATE = "decisionDate" # Decision search DECISION_TYPE = "decisionTypeCodeDescriptionText" PETITION_TYPE = "decisionPetitionTypeCodeDescriptionText" # Status search PROSECUTION_STATUS = "prosecutionStatusCodeDescriptionText" BUSINESS_ENTITY = "businessEntityStatusCategory" # Legal search RULE = "ruleBag" # Search for CFR rules STATUTE = "statuteBag" # Search for statutes # Metadata search INVENTION_TITLE = "inventionTitle" # === RED FLAG RULES FOR PETITION QUALITY ASSESSMENT === class PetitionRedFlags: """ Common petition types and rules that indicate potential quality issues. Use these constants when analyzing petition patterns for red flags. """ # Revival petitions (application was abandoned) RULE_REVIVAL = "37 CFR 1.137" # Petitions for supervisory review (examiner disputes) RULE_SUPERVISORY_REVIEW = "37 CFR 1.181" # Petitions for reconsideration (restriction issues) RULE_RECONSIDERATION = "37 CFR 1.182" # Special petitions RULE_SPECIAL_PETITION = "37 CFR 1.183" # Decision outcomes DECISION_DENIED = "DENIED" DECISION_GRANTED = "GRANTED"
  • Supporting service method with caching and performance monitoring. Similar logic to tool handler but with added cache_manager and structured logging.
    async def search_petitions_minimal( self, query: str, limit: int = 50, offset: int = 0 ) -> Dict[str, Any]: """ Perform minimal petition search with context reduction and caching Args: query: Search query limit: Number of results to return offset: Offset for pagination Returns: Filtered search results """ with PerformanceTimer(self.structured_logger, "search_petitions_minimal", {"query_length": len(query), "limit": limit, "offset": offset}): # Check cache first cache_key_args = (query, limit, offset) cached_result = self.cache_manager.get("search_petitions_minimal", *cache_key_args) if cached_result is not None: self.structured_logger.log_cache_event( cache_key=str(hash(cache_key_args)), hit=True, method_name="search_petitions_minimal", ttl_seconds=300 ) return cached_result # Log cache miss self.structured_logger.log_cache_event( cache_key=str(hash(cache_key_args)), hit=False, method_name="search_petitions_minimal" ) # Get minimal field set fields = self.field_manager.get_fields("petitions_minimal") # Perform search result = await self.api_client.search_petitions( query=query, fields=fields, limit=limit, offset=offset ) # Check for errors if "error" in result: return result # Filter response using field manager filtered_result = self.field_manager.filter_response(result, "petitions_minimal") # Cache successful results self.cache_manager.set("search_petitions_minimal", filtered_result, *cache_key_args) return filtered_result

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/john-walkoe/uspto_fpd_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server