Skip to content

Releases: damionrashford/RivalSearchMCP

v1.2.0 — FastMCP 3 upgrade + observability rebuild

Choose a tag to compare

@damionrashford damionrashford released this 17 Apr 08:07
8d9b704

Highlights

FastMCP 2 → 3 upgrade

  • Bumped fastmcp from 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 typed fastmcp.prompts.Message
  • Deleted dead MCPPaginationManager (FastMCP 3 handles list-pagination natively via list_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 ResponseCachingMiddleware scoped to URL-fetching tools only (see bug fix below)
  • Added ResponseLimitingMiddleware (1 MB cap on content_operations, map_website, document_analysis)
  • Added PingMiddleware (30 s keepalive for streaming HTTP)
  • Kept custom SecurityMiddleware + PerformanceMonitoringMiddleware

Tools features

  • ToolAnnotations on all 10 tools: 9 read-only get readOnlyHint=True, openWorldHint=True; research_memory is correctly flagged readOnlyHint=False, destructiveHint=True, openWorldHint=False
  • Per-tool timeout= values (15 s for local-only tools up to 180 s for research_topic entity mode + document_analysis)
  • ToolResult dual-channel output on content_operations score and find_conflicts — humans see markdown, agents parse structured_content
  • mask_error_details=True on the server; ValueError → ToolError conversions in analysis.py so legit validation messages still reach clients unmasked
  • ctx.report_progress() at phase boundaries in research_topic entity 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 called
  • src/core/search/core/main.py — orphaned, broken import to nonexistent google scraper
  • src/core/search/core/engine.pyMultiEngineSearch, superseded by multi_engines.py
  • src/core/scientific/academic_search.py — wrapper classes, tools bypass them
  • src/core/content/cleaners.py — 4 cleaner classes, unused
  • src/core/content/parsers.py — 3 parser classes, unused
  • src/core/fetch/{batch,enhanced,resource}.py — never called
  • GenericContentExtractor, GoogleSpecificExtractor — unused subclasses
  • 5-class Fetcher hierarchy in fetch/base.py — kept only base_fetch_url + stream_fetch
  • CacheManager forwarding wrapper in cache/__init__.py
  • 4 unused traverse convenience wrappers
  • 5 never-called metrics functions
  • Multiple stale __init__.py re-exports (GoogleTrendsAPI, ContentProcessor, LLMsTxtGenerator, …)

Three real bugs fixed along the way

  1. metrics.get_all_metrics crashed the /metrics endpoint — it was sync but called asyncio.run(cache_manager.get_stats()) inside; asyncio.run() can't be called from a running event loop. Made it async, use await.
  2. easyocr.image_to_string() doesn't existpdf/analyzer.py::_analyze_image called a nonexistent function. Real API is Reader([...]).readtext(image). Fixed with detail=0, paragraph=True.
  3. _ocr_pdf_pages was a stub returning "" — but ocr_used: True was being reported anyway. Removed the stub call, report honest ocr_used: False until pdf2image is wired up.

Also

  • Added pre-commit>=3.5.0 to dev deps (CI's uv run pre-commit was failing with "binary not found")
  • Renamed test_rejects_localhost_origin_by_defaulttest_allows_localhost_for_local_development to match the actual CORS policy
  • Marked test_reddit_search as skipif 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.

v1.1.0 — Agent Skills

Choose a tag to compare

@damionrashford damionrashford released this 18 Mar 04:18

Agent Skills for Claude Code

RivalSearchMCP now ships with a Claude Code Agent Skill — all 10 research tools packaged as a standalone CLI that AI agents can invoke directly.

What's included

  • SKILL.md — Agent instructions auto-loaded by Claude Code
  • scripts/cli.py — Self-contained CLI with PEP 723 inline dependencies (just uv run scripts/cli.py)
  • resources/ — Progressive-disclosure reference docs for all 10 tools

Install as a Claude Code Skill

# Download and extract
unzip rival-search-mcp-skill.zip

# Project-level
cp -r skills/rival-search-mcp .claude/skills/

# Or global
cp -r skills/rival-search-mcp ~/.claude/skills/

Claude will automatically discover the skill when you ask for web research, competitor analysis, or content discovery.

Use the CLI directly

uv run scripts/cli.py call-tool web_search --query "your query"
uv run scripts/cli.py call-tool social_search --query "AI agents" --platforms reddit
uv run scripts/cli.py list-tools

All 10 tools available

Tool Purpose
web_search Yahoo + DuckDuckGo with fallback
social_search Reddit, HN, Dev.to, Product Hunt, Medium
news_aggregation Google News, DuckDuckGo News, Yahoo News
github_search Public GitHub repo search
map_website Website crawling and mapping
content_operations Retrieve, analyze, extract from URLs
document_analysis PDF, Word, Images with OCR
research_topic End-to-end research workflow
scientific_research arXiv, PubMed, Semantic Scholar
research_agent AI-powered autonomous research

No API keys required (except research_agent which uses OpenRouter).