"""GPT Researcher MCP — deep web research as fallback for any industry. This is the universal fallback: when structured data sources don't have data for a niche/cold industry, deep web research fills the gap. Requires GPT Researcher MCP server to be running (already configured in ~/.claude.json). For direct API use, we call the MCP tools via the subprocess approach. """ from __future__ import annotations import asyncio import json import logging import subprocess from typing import Any from .base import DataSource, DataResult logger = logging.getLogger(__name__) class GPTResearcherSource(DataSource): name = "gpt_researcher" description = "Deep web research — universal fallback for any industry/topic" def supports(self, data_type: str, country: str | None = None) -> bool: # Supports everything — this is the universal fallback return True async def fetch( self, query: str, *, data_type: str = "general", country: str | None = None, **kwargs, ) -> DataResult: mode = kwargs.get("mode", "quick") # "quick" or "deep" # GPT Researcher is available as MCP tools in Claude Code. # For standalone use, we need to call it via its API. # The MCP server runs at a local port — check if available. # For now, provide a structured placeholder that agents can use # to request deep research. The actual MCP call happens at the # agent level when integrated into the pipeline. return DataResult( source=self.name, data={ "query": query, "mode": mode, "status": "ready", "note": ( "GPT Researcher MCP is available for deep web research. " "Call via MCP tools: deep_research() or quick_search(). " "This source returns research-ready queries for MCP integration." ), }, metadata={ "type": "mcp_research_request", "mode": mode, "data_type": data_type, "country": country, }, )