Highlights
FastMCP 2 → 3 upgrade
- Bumped
fastmcpfrom 2.14.3 to 3.2.4 - Dropped removed constructor kwargs (
include_fastmcp_meta,on_duplicate_tools) - Converted all 4 prompts from raw
{"role","content"}dicts to typedfastmcp.prompts.Message - Deleted dead
MCPPaginationManager(FastMCP 3 handles list-pagination natively vialist_page_size, not needed for a 10-tool server)
Middleware stack rebuild
- Swapped custom Timing / Logging / ErrorHandling for FastMCP built-ins
- Added
SlidingWindowRateLimitingMiddleware(100 req / session / min) - Added
ResponseCachingMiddlewarescoped to URL-fetching tools only (see bug fix below) - Added
ResponseLimitingMiddleware(1 MB cap oncontent_operations,map_website,document_analysis) - Added
PingMiddleware(30 s keepalive for streaming HTTP) - Kept custom
SecurityMiddleware+PerformanceMonitoringMiddleware
Tools features
ToolAnnotationson all 10 tools: 9 read-only getreadOnlyHint=True, openWorldHint=True;research_memoryis correctly flaggedreadOnlyHint=False, destructiveHint=True, openWorldHint=False- Per-tool
timeout=values (15 s for local-only tools up to 180 s forresearch_topicentity mode +document_analysis) ToolResultdual-channel output oncontent_operations scoreandfind_conflicts— humans see markdown, agents parsestructured_contentmask_error_details=Trueon the server;ValueError → ToolErrorconversions inanalysis.pyso legit validation messages still reach clients unmaskedctx.report_progress()at phase boundaries inresearch_topicentity mode,map_website,content_operations find_conflicts
Critical bug squashed
ResponseCachingMiddleware defaulted to caching tools/list, resources/list, prompts/list, read_resource, and get_prompt alongside call_tool. That froze tool schemas on the client side — when annotations, timeouts, or params changed, clients still saw the old schema until the 5-minute TTL expired. The tool list cache also caused cross-test pollution during development (an earlier inline_tool test stuck around as a ghost tool for the rest of the run). All list/read/get surfaces are now cache-disabled; only call_tool stays cached, and only for content_operations + document_analysis whose output is a near-pure function of the URL.
Dead code purge
Audited every .py under src/core/ against its actual callers. Removed:
src/core/bypass/— paywall/proxy helpers, never calledsrc/core/search/core/main.py— orphaned, broken import to nonexistent google scrapersrc/core/search/core/engine.py—MultiEngineSearch, superseded bymulti_engines.pysrc/core/scientific/academic_search.py— wrapper classes, tools bypass themsrc/core/content/cleaners.py— 4 cleaner classes, unusedsrc/core/content/parsers.py— 3 parser classes, unusedsrc/core/fetch/{batch,enhanced,resource}.py— never calledGenericContentExtractor,GoogleSpecificExtractor— unused subclasses- 5-class
Fetcherhierarchy infetch/base.py— kept onlybase_fetch_url+stream_fetch CacheManagerforwarding wrapper incache/__init__.py- 4 unused traverse convenience wrappers
- 5 never-called metrics functions
- Multiple stale
__init__.pyre-exports (GoogleTrendsAPI,ContentProcessor,LLMsTxtGenerator, …)
Three real bugs fixed along the way
metrics.get_all_metricscrashed the/metricsendpoint — it was sync but calledasyncio.run(cache_manager.get_stats())inside;asyncio.run()can't be called from a running event loop. Made it async, useawait.easyocr.image_to_string()doesn't exist —pdf/analyzer.py::_analyze_imagecalled a nonexistent function. Real API isReader([...]).readtext(image). Fixed withdetail=0, paragraph=True._ocr_pdf_pageswas a stub returning""— butocr_used: Truewas being reported anyway. Removed the stub call, report honestocr_used: Falseuntilpdf2imageis wired up.
Also
- Added
pre-commit>=3.5.0to dev deps (CI'suv run pre-commitwas failing with "binary not found") - Renamed
test_rejects_localhost_origin_by_default→test_allows_localhost_for_local_developmentto match the actual CORS policy - Marked
test_reddit_searchasskipif CI(Cloudflare blocks GitHub Actions IP ranges; source is resilient locally) - New
tests/test_inmemory_transport.py— sub-1s MCP-protocol smoke tests that catch schema/prompt/middleware regressions
71/71 tests pass, 5/5 CI checks green on the merge commit.