
Mpep Search
- 58 installs
- 167 repo stars
- Updated August 2, 2026
- robthepcguy/claude-patent-creator
Helps with ai & agent building tasks during AI-assisted development.
About
mpep-search is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- mpep-search
- AI & Agent Building
- AI-coding skill
Mpep Search by the numbers
- 58 all-time installs (skills.sh)
- +2 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #6,589 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/robthepcguy/claude-patent-creator --skill mpep-searchAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 58 |
|---|---|
| repo stars | ★ 167 |
| Last updated | August 2, 2026 |
| Repository | robthepcguy/claude-patent-creator ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
MPEP Search Skill
Search MPEP corpus through hybrid RAG (FAISS vector + BM25 keyword + HyDE + cross-encoder reranking).
Sources:
- MPEP: Manual of Patent Examining Procedure
- 35 USC: United States Code Title 35
- 37 CFR: Code of Federal Regulations Title 37
- Subsequent Publications: Federal Register updates (post-Jan 2024)
Core Operations
1. search_mpep
Inputs:
query(string, required): Search query (minimum 3 characters)top_k(int, optional): Number of results (default: 5, max: 20)retrieve_k(int | None, optional): Candidates before reranking (default: top_k * 4, max: 100)source_filter(string | None, optional): Filter by source ("MPEP","35_USC","37_CFR","SUBSEQUENT", orNone)is_statute(bool | None, optional): Filter for statute contentis_regulation(bool | None, optional): Filter for regulation contentis_update(bool | None, optional): Filter for recent updates
Outputs:
{
"rank": int,
"source": str,
"section": str,
"file": str,
"page": int,
"has_statute": bool,
"has_mpep_ref": bool,
"has_rule_ref": bool,
"is_statute": bool,
"is_regulation": bool,
"is_update": bool,
"relevance_score": float,
"text": str,
# Optional for SUBSEQUENT:
"doc_type": str,
"fr_citation": str,
"effective_date": str
}Examples:
# Basic search
search_mpep("enablement requirement 35 USC 112", top_k=5)
# Search only statutes
search_mpep("written description", top_k=10, is_statute=True)
# Search recent updates
search_mpep("AI inventorship", is_update=True)
# Filter by source
search_mpep("fee schedule", source_filter="37_CFR")2. get_mpep_section
Retrieve all content from specific MPEP section.
Inputs:
section_number(string, required): MPEP section number (e.g.,"2100","608.01")max_chunks(int, optional): Maximum chunks to return (default: 50)
Outputs:
{
"section": str,
"total_chunks": int,
"chunks": [
{
"text": str,
"metadata": {
"source": str,
"file": str,
"page": int,
"section": str,
"has_statute": bool,
"has_mpep_ref": bool,
"has_rule_ref": bool,
"is_statute": bool,
"is_regulation": bool,
"is_update": bool
}
}
]
}Error Response:
{"error": "No content found for MPEP section {section_number}"}Examples:
# Get MPEP 2100 (Patentability)
get_mpep_section("2100", max_chunks=50)
# Get subsection
get_mpep_section("608.01")Input Validation
Query validation:
- Minimum 3 characters
- Case-insensitive
- No empty/whitespace-only queries
Section number validation:
- Numeric with optional decimal (e.g., "100", "2100", "608.01")
Limits:
top_kcapped at 20retrieve_kcapped at 100
Implementation Notes
Index Location:
- FAISS index:
mcp_server/index/mpep_index.faiss - Metadata:
mcp_server/index/mpep_metadata.json - BM25 index:
mcp_server/index/mpep_bm25.json
Search Architecture: 1. HyDE Query Expansion (hypothetical documents) 2. Hybrid Retrieval (FAISS vector + BM25 keyword via RRF) 3. Cross-Encoder Reranking (final relevance scores) 4. Metadata Filtering (source/type filters)
Dependencies:
- sentence-transformers (BGE-base-en-v1.5)
- FAISS (vector search)
- rank-bm25 (keyword search)
- Cross-encoder (reranking)
- HyDE (optional, graceful degradation)
Error Handling:
- Clear error messages for missing index/invalid queries
- Graceful degradation if HyDE fails
- Input validation before processing
"""
MPEP Search Skill
Provides search and retrieval operations for USPTO MPEP, 35 USC, 37 CFR, and updates.
"""
import sys
from pathlib import Path
from typing import Any, Optional
# Add mcp_server to path for imports
PROJECT_ROOT = Path(__file__).parent.parent.parent.parent
sys.path.insert(0, str(PROJECT_ROOT))
try:
from mcp_server.mpep_search import MPEPIndex
except ImportError as e:
raise ImportError(
f"Could not import MPEPIndex from mcp_server: {e}\n"
"Make sure mcp_server is installed and the index is built."
)
# Global index instance (lazy-loaded)
_mpep_index: Optional[MPEPIndex] = None
def _get_mpep_index() -> MPEPIndex:
"""Get or initialize the MPEP index singleton."""
global _mpep_index
if _mpep_index is None:
_mpep_index = MPEPIndex(use_hyde=True)
# Load the index (should already be built)
if not _mpep_index.index_file.exists():
raise RuntimeError(
"MPEP index not found. Please run the setup/installation first:\n"
" python install.py\n"
"This will download and index the MPEP, 35 USC, and 37 CFR."
)
_mpep_index.build_index(force_rebuild=False)
return _mpep_index
def search_mpep(
query: str,
top_k: int = 5,
retrieve_k: Optional[int] = None,
source_filter: Optional[str] = None,
is_statute: Optional[bool] = None,
is_regulation: Optional[bool] = None,
is_update: Optional[bool] = None,
) -> dict[str, Any]:
"""
Search the MPEP corpus using hybrid RAG (vector + keyword + reranking).
Args:
query: Search query string (minimum 3 characters)
top_k: Number of final results to return (default: 5, max: 20)
retrieve_k: Number of candidates to retrieve before reranking (default: top_k * 4)
source_filter: Filter by source type ("MPEP", "35_USC", "37_CFR", "SUBSEQUENT", or None)
is_statute: Filter for statute content (True/False/None)
is_regulation: Filter for regulation content (True/False/None)
is_update: Filter for recent updates (True/False/None)
Returns:
Dictionary with:
- success: bool
- results: List of search result dictionaries
- query_info: Metadata about the query
Or on error:
- success: False
- error: Error message
"""
# Input validation
if not query or not query.strip():
return {"success": False, "error": "Query cannot be empty"}
query = query.strip()
if len(query) < 3:
return {
"success": False,
"error": f"Query too short (minimum 3 characters, got {len(query)})",
}
# Validate source_filter if provided
if source_filter is not None:
valid_sources = ["MPEP", "35_USC", "37_CFR", "SUBSEQUENT"]
if source_filter not in valid_sources:
return {
"success": False,
"error": f"Invalid source_filter '{source_filter}'. Must be one of: {', '.join(valid_sources)}",
}
# Cap top_k
top_k = min(max(1, top_k), 20)
try:
# Get the index
index = _get_mpep_index()
# Perform search
raw_results = index.search(
query=query,
top_k=top_k,
retrieve_k=retrieve_k,
source_filter=source_filter,
is_statute=is_statute,
is_regulation=is_regulation,
is_update=is_update,
)
# Format results
formatted_results = []
for i, r in enumerate(raw_results):
result = {
"rank": i + 1,
"source": r["metadata"].get("source", "MPEP"),
"section": r["metadata"]["section"],
"file": r["metadata"]["file"],
"page": r["metadata"]["page"],
"has_statute": r["metadata"].get("has_statute", False),
"has_mpep_ref": r["metadata"].get("has_mpep_ref", False),
"has_rule_ref": r["metadata"].get("has_rule_ref", False),
"is_statute": r["metadata"].get("is_statute", False),
"is_regulation": r["metadata"].get("is_regulation", False),
"is_update": r["metadata"].get("is_update", False),
"relevance_score": round(r["relevance_score"], 3),
"text": r["text"],
}
# Add source-specific fields
if r["metadata"].get("source") == "SUBSEQUENT":
result["doc_type"] = r["metadata"].get("doc_type")
result["fr_citation"] = r["metadata"].get("fr_citation")
result["effective_date"] = r["metadata"].get("effective_date")
formatted_results.append(result)
return {
"success": True,
"results": formatted_results,
"query_info": {
"query": query,
"top_k": top_k,
"retrieve_k": retrieve_k or (top_k * 4),
"source_filter": source_filter,
"results_count": len(formatted_results),
},
}
except RuntimeError as e:
return {"success": False, "error": str(e)}
except Exception as e:
return {"success": False, "error": f"Search failed: {str(e)}"}
def get_mpep_section(
section_number: str,
max_chunks: int = 50,
) -> dict[str, Any]:
"""
Get all text chunks from a specific MPEP section by number.
Args:
section_number: MPEP section number (e.g., "2100", "700", "608.01")
Do NOT include "MPEP" prefix, just the number.
max_chunks: Maximum number of chunks to return (default: 50)
Returns:
Dictionary with:
- success: bool
- section: The section number requested
- total_chunks: Total number of chunks found
- chunks: List of chunk dictionaries (up to max_chunks)
Or on error:
- success: False
- error: Error message
"""
# Input validation
if not section_number or not section_number.strip():
return {"success": False, "error": "Section number cannot be empty"}
section_number = section_number.strip()
# Validate that it looks like a section number (digits with optional dots)
if not all(c.isdigit() or c == "." for c in section_number):
return {
"success": False,
"error": f"Invalid section number format: '{section_number}'. Use numeric format like '2100' or '608.01'",
}
try:
# Get the index
index = _get_mpep_index()
# Search for matching chunks
section_pattern = f"MPEP {section_number}"
matching_chunks = []
for chunk, meta in zip(index.chunks, index.metadata):
if section_pattern in meta["section"]:
matching_chunks.append({"text": chunk, "metadata": meta})
if not matching_chunks:
return {
"success": False,
"error": f"No content found for MPEP section {section_number}. The section may not exist or the index may be incomplete.",
}
return {
"success": True,
"section": section_number,
"total_chunks": len(matching_chunks),
"chunks": matching_chunks[:max_chunks],
"truncated": len(matching_chunks) > max_chunks,
}
except RuntimeError as e:
return {"success": False, "error": str(e)}
except Exception as e:
return {"success": False, "error": f"Section retrieval failed: {str(e)}"}
def check_index_status() -> dict[str, Any]:
"""
Check if the MPEP index is available and ready to use.
Returns:
Dictionary with status information:
- ready: bool
- index_exists: bool
- total_chunks: int (if ready)
- message: str
"""
try:
index = _get_mpep_index()
return {
"ready": True,
"index_exists": True,
"total_chunks": len(index.chunks),
"message": f"MPEP index loaded with {len(index.chunks):,} chunks",
}
except RuntimeError as e:
return {"ready": False, "index_exists": False, "message": str(e)}
except Exception as e:
return {
"ready": False,
"index_exists": False,
"message": f"Error checking index status: {str(e)}",
}