"""Rug Munch Intelligence — MCP Server. 97 tools for scam detection, rug pull prevention, and crypto intelligence across 7 chains. The Bloomberg of Shitcoins Terminal Ultimate Edition. Each tool sends POST to /api/v1/x402-tools/{tool_name} with chain + params. x402 payment is handled transparently by the backend/gateway. """ import os from typing import Any import httpx from mcp.server.fastmcp import FastMCP # --------------------------------------------------------------------------- # Configuration — NO secrets, only public endpoints # --------------------------------------------------------------------------- API_BASE = os.environ.get("RUG_MUNCH_API_BASE", "https://mcp.rugmunch.io/api/v1") API_KEY = os.environ.get("RUG_MUNCH_API_KEY", "") SUPPORTED_CHAINS = ["base", "solana", "ethereum", "bsc", "arbitrum", "optimism", "polygon"] DEFAULT_CHAIN = "solana" # --------------------------------------------------------------------------- # MCP Server # --------------------------------------------------------------------------- mcp = FastMCP( name="Rug Munch Intelligence", instructions="97 tools for scam detection, rug pull prevention, and crypto intelligence across 7 chains.", ) # --------------------------------------------------------------------------- # HTTP helper # --------------------------------------------------------------------------- async def _call_tool(tool_name: str, payload: dict[str, Any]) -> dict[str, Any]: """POST to the x402-tools endpoint. Payment is handled by the gateway.""" url = f"{API_BASE}/x402-tools/{tool_name}" headers: dict[str, str] = {"Content-Type": "application/json"} if API_KEY: headers["Authorization"] = f"Bearer {API_KEY}" async with httpx.AsyncClient(timeout=30) as client: resp = await client.post(url, json=payload, headers=headers) resp.raise_for_status() return resp.json() def _chain_payload(chain: str, **kwargs: Any) -> dict[str, Any]: """Build a standard payload with chain + extra kwargs.""" payload: dict[str, Any] = {"chain": chain or DEFAULT_CHAIN} payload.update({k: v for k, v in kwargs.items() if v is not None}) return payload # =========================================================================== # INTELLIGENCE (28 tools) # =========================================================================== @mcp.tool() async def whale_scan(chain: str = DEFAULT_CHAIN, address: str | None = None, min_usd: float | None = None) -> dict: """Track whale wallet movements and large transactions.""" return await _call_tool("whale_scan", _chain_payload(chain, address=address, min_usd=min_usd)) @mcp.tool() async def smartmoney(chain: str = DEFAULT_CHAIN, address: str | None = None, timeframe: str | None = None) -> dict: """Identify smart money wallets and their positions.""" return await _call_tool("smartmoney", _chain_payload(chain, address=address, timeframe=timeframe)) @mcp.tool() async def cluster(chain: str = DEFAULT_CHAIN, address: str | None = None, depth: int | None = None) -> dict: """Cluster related wallets by behavior patterns.""" return await _call_tool("cluster", _chain_payload(chain, address=address, depth=depth)) @mcp.tool() async def airdrop_finder(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict: """Find eligible airdrops for a wallet.""" return await _call_tool("airdrop_finder", _chain_payload(chain, address=address)) @mcp.tool() async def whale_profile(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict: """Deep profile of a whale wallet's history.""" return await _call_tool("whale_profile", _chain_payload(chain, address=address)) @mcp.tool() async def insider(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Detect insider trading patterns before launches.""" return await _call_tool("insider", _chain_payload(chain, token=token)) @mcp.tool() async def smart_money_alpha(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Alpha signals from smart money activity.""" return await _call_tool("smart_money_alpha", _chain_payload(chain, token=token)) @mcp.tool() async def social_signal(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Social media signal aggregation for tokens.""" return await _call_tool("social_signal", _chain_payload(chain, token=token)) @mcp.tool() async def sentiment(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Market sentiment analysis across sources.""" return await _call_tool("sentiment", _chain_payload(chain, token=token)) @mcp.tool() async def copy_trade_finder(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict: """Find wallets worth copy-trading.""" return await _call_tool("copy_trade_finder", _chain_payload(chain, address=address)) @mcp.tool() async def liquidity_flow(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Track liquidity inflows and outflows.""" return await _call_tool("liquidity_flow", _chain_payload(chain, token=token)) @mcp.tool() async def risk_monitor(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Continuous risk monitoring for positions.""" return await _call_tool("risk_monitor", _chain_payload(chain, token=token)) @mcp.tool() async def rug_pull_predictor(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """ML-based rug pull prediction scoring.""" return await _call_tool("rug_pull_predictor", _chain_payload(chain, token=token)) @mcp.tool() async def meme_vibe_score(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Meme coin community vibe and virality scoring.""" return await _call_tool("meme_vibe_score", _chain_payload(chain, token=token)) @mcp.tool() async def nft_wash_detector(chain: str = DEFAULT_CHAIN, collection: str | None = None) -> dict: """Detect NFT wash trading patterns.""" return await _call_tool("nft_wash_detector", _chain_payload(chain, collection=collection)) @mcp.tool() async def gas_forecast(chain: str = DEFAULT_CHAIN) -> dict: """Gas price forecasting and optimization.""" return await _call_tool("gas_forecast", _chain_payload(chain)) @mcp.tool() async def bridge_security(chain: str = DEFAULT_CHAIN, bridge: str | None = None) -> dict: """Cross-chain bridge risk assessment.""" return await _call_tool("bridge_security", _chain_payload(chain, bridge=bridge)) @mcp.tool() async def defi_yield_scanner(chain: str = DEFAULT_CHAIN, protocol: str | None = None) -> dict: """Scan DeFi yields and risk-adjusted returns.""" return await _call_tool("defi_yield_scanner", _chain_payload(chain, protocol=protocol)) @mcp.tool() async def portfolio_tracker(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict: """Track and analyze portfolio composition.""" return await _call_tool("portfolio_tracker", _chain_payload(chain, address=address)) @mcp.tool() async def token_deep_dive(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Deep fundamental analysis of any token.""" return await _call_tool("token_deep_dive", _chain_payload(chain, token=token)) @mcp.tool() async def token_comparison(chain: str = DEFAULT_CHAIN, token_a: str | None = None, token_b: str | None = None) -> dict: """Side-by-side token comparison analysis.""" return await _call_tool("token_comparison", _chain_payload(chain, token_a=token_a, token_b=token_b)) @mcp.tool() async def forensic_valuation(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Forensic-based token valuation modeling.""" return await _call_tool("forensic_valuation", _chain_payload(chain, token=token)) @mcp.tool() async def comprehensive_audit(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Full-scope audit of a token or contract.""" return await _call_tool("comprehensive_audit", _chain_payload(chain, token=token)) @mcp.tool() async def investigation_report(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Generate detailed investigation reports.""" return await _call_tool("investigation_report", _chain_payload(chain, token=token)) @mcp.tool() async def market_overview(chain: str = DEFAULT_CHAIN) -> dict: """Real-time market overview and metrics.""" return await _call_tool("market_overview", _chain_payload(chain)) @mcp.tool() async def chain_health(chain: str = DEFAULT_CHAIN) -> dict: """Blockchain network health and congestion metrics.""" return await _call_tool("chain_health", _chain_payload(chain)) @mcp.tool() async def anomaly(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Detect anomalous on-chain behavior.""" return await _call_tool("anomaly", _chain_payload(chain, token=token)) @mcp.tool() async def honeypot_check(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Check if a token is a honeypot scam.""" return await _call_tool("honeypot_check", _chain_payload(chain, token=token)) @mcp.tool() async def mev_protection(chain: str = DEFAULT_CHAIN) -> dict: """Assess MEV exposure and protection strategies.""" return await _call_tool("mev_protection", _chain_payload(chain)) # =========================================================================== # SECURITY (17 tools) — some shared names, different tool registration context # =========================================================================== @mcp.tool() async def urlcheck(url: str | None = None) -> dict: """Check URLs for phishing and scam indicators.""" return await _call_tool("urlcheck", {"url": url} if url else {}) @mcp.tool() async def rugshield(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Real-time rug pull shield and protection.""" return await _call_tool("rugshield", _chain_payload(chain, token=token)) @mcp.tool() async def clone_detect(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Detect cloned/fake tokens and contracts.""" return await _call_tool("clone_detect", _chain_payload(chain, token=token)) @mcp.tool() async def fresh_pair(chain: str = DEFAULT_CHAIN, pair: str | None = None) -> dict: """Analyze freshly launched trading pairs.""" return await _call_tool("fresh_pair", _chain_payload(chain, pair=pair)) @mcp.tool() async def profile_flip(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Profile flip risk for token distributions.""" return await _call_tool("profile_flip", _chain_payload(chain, token=token)) @mcp.tool() async def audit(chain: str = DEFAULT_CHAIN, contract: str | None = None) -> dict: """Smart contract security audit.""" return await _call_tool("audit", _chain_payload(chain, contract=contract)) # =========================================================================== # MARKET (14 tools) # =========================================================================== @mcp.tool() async def pulse(chain: str = DEFAULT_CHAIN) -> dict: """Real-time market pulse and momentum.""" return await _call_tool("pulse", _chain_payload(chain)) @mcp.tool() async def coingecko_global(chain: str = DEFAULT_CHAIN) -> dict: """Global market data from CoinGecko.""" return await _call_tool("coingecko_global", _chain_payload(chain)) @mcp.tool() async def coingecko_trending(chain: str = DEFAULT_CHAIN) -> dict: """Trending tokens on CoinGecko.""" return await _call_tool("coingecko_trending", _chain_payload(chain)) @mcp.tool() async def coingecko_markets(chain: str = DEFAULT_CHAIN, category: str | None = None) -> dict: """Market cap and volume data.""" return await _call_tool("coingecko_markets", _chain_payload(chain, category=category)) @mcp.tool() async def coingecko_categories(chain: str = DEFAULT_CHAIN) -> dict: """CoinGecko category analysis.""" return await _call_tool("coingecko_categories", _chain_payload(chain)) # =========================================================================== # ANALYSIS (12 tools) # =========================================================================== @mcp.tool() async def tx_decoder(chain: str = DEFAULT_CHAIN, tx_hash: str | None = None) -> dict: """Decode and interpret transactions.""" return await _call_tool("tx_decoder", _chain_payload(chain, tx_hash=tx_hash)) @mcp.tool() async def wallet(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict: """Comprehensive wallet analysis.""" return await _call_tool("wallet", _chain_payload(chain, address=address)) @mcp.tool() async def contract_info(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict: """Extract smart contract information.""" return await _call_tool("contract_info", _chain_payload(chain, address=address)) @mcp.tool() async def storage_reader(chain: str = DEFAULT_CHAIN, contract: str | None = None, slot: str | None = None) -> dict: """Read contract storage slots.""" return await _call_tool("storage_reader", _chain_payload(chain, contract=contract, slot=slot)) # =========================================================================== # FORENSICS (7 tools) # =========================================================================== @mcp.tool() async def forensics_threat_check(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict: """Threat intelligence check for addresses.""" return await _call_tool("forensics_threat_check", _chain_payload(chain, address=address)) @mcp.tool() async def forensics_risk_report(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict: """Detailed forensics risk report.""" return await _call_tool("forensics_risk_report", _chain_payload(chain, address=address)) @mcp.tool() async def forensics_deep_scan(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict: """Deep forensic scan of wallet/activity.""" return await _call_tool("forensics_deep_scan", _chain_payload(chain, address=address)) @mcp.tool() async def forensics_cross_chain(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict: """Cross-chain forensic correlation.""" return await _call_tool("forensics_cross_chain", _chain_payload(chain, address=address)) @mcp.tool() async def bundle_security_pack(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict: """Bundle of security forensics tools.""" return await _call_tool("bundle_security_pack", _chain_payload(chain, token=token)) @mcp.tool() async def forensics_trace(chain: str = DEFAULT_CHAIN, address: str | None = None, depth: int | None = None) -> dict: """Trace funds through complex transaction graphs.""" return await _call_tool("forensics_trace", _chain_payload(chain, address=address, depth=depth)) @mcp.tool() async def forensics_entity(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict: """Entity resolution from on-chain footprints.""" return await _call_tool("forensics_entity", _chain_payload(chain, address=address)) # =========================================================================== # SOCIAL (7 tools) # =========================================================================== @mcp.tool() async def tw_profile(username: str | None = None) -> dict: """Twitter/X profile analysis.""" payload = {"chain": DEFAULT_CHAIN} if username: payload["username"] = username return await _call_tool("tw_profile", payload) @mcp.tool() async def tw_timeline(username: str | None = None, limit: int | None = None) -> dict: """Twitter/X timeline analysis.""" payload: dict[str, Any] = {"chain": DEFAULT_CHAIN} if username: payload["username"] = username if limit: payload["limit"] = limit return await _call_tool("tw_timeline", payload) @mcp.tool() async def tw_search(query: str | None = None) -> dict: """Twitter/X search for crypto mentions.""" payload: dict[str, Any] = {"chain": DEFAULT_CHAIN} if query: payload["query"] = query return await _call_tool("tw_search", payload) @mcp.tool() async def profile_get(address: str | None = None) -> dict: """Get Rug Munch user profile.""" payload: dict[str, Any] = {"chain": DEFAULT_CHAIN} if address: payload["address"] = address return await _call_tool("profile_get", payload) @mcp.tool() async def profile_badges(address: str | None = None) -> dict: """Get user badges and reputation.""" payload: dict[str, Any] = {"chain": DEFAULT_CHAIN} if address: payload["address"] = address return await _call_tool("profile_badges", payload) # =========================================================================== # OSINT (3 tools) # =========================================================================== @mcp.tool() async def osint_search(query: str | None = None) -> dict: """Open source intelligence search.""" payload: dict[str, Any] = {"chain": DEFAULT_CHAIN} if query: payload["query"] = query return await _call_tool("osint_search", payload) @mcp.tool() async def osint_identity_hunt(identifier: str | None = None) -> dict: """Cross-reference identities across platforms.""" payload: dict[str, Any] = {"chain": DEFAULT_CHAIN} if identifier: payload["identifier"] = identifier return await _call_tool("osint_identity_hunt", payload) @mcp.tool() async def osint_investigate(target: str | None = None) -> dict: """Deep OSINT investigation.""" payload: dict[str, Any] = {"chain": DEFAULT_CHAIN} if target: payload["target"] = target return await _call_tool("osint_investigate", payload) # =========================================================================== # LAUNCHPAD (3 tools) # =========================================================================== @mcp.tool() async def launch(chain: str = DEFAULT_CHAIN) -> dict: """Track token launches in real-time.""" return await _call_tool("launch", _chain_payload(chain)) @mcp.tool() async def launch_intel(chain: str = DEFAULT_CHAIN) -> dict: """Intelligence on upcoming launches.""" return await _call_tool("launch_intel", _chain_payload(chain)) @mcp.tool() async def sniper_alert(chain: str = DEFAULT_CHAIN) -> dict: """Snipe alerts for high-potential launches.""" return await _call_tool("sniper_alert", _chain_payload(chain)) # =========================================================================== # META (3 tools) # =========================================================================== @mcp.tool() async def list_bundles() -> dict: """List available tool bundles.""" return await _call_tool("list_bundles", {"chain": DEFAULT_CHAIN}) @mcp.tool() async def tools_discovery() -> dict: """Discover all available tools.""" return await _call_tool("tools_discovery", {"chain": DEFAULT_CHAIN}) @mcp.tool() async def framework_discovery() -> dict: """Discover framework capabilities.""" return await _call_tool("framework_discovery", {"chain": DEFAULT_CHAIN}) # =========================================================================== # NEWS (3 tools) # =========================================================================== @mcp.tool() async def news_headlines(category: str | None = None) -> dict: """Latest crypto news headlines.""" payload: dict[str, Any] = {"chain": DEFAULT_CHAIN} if category: payload["category"] = category return await _call_tool("news_headlines", payload) @mcp.tool() async def news_twitter(query: str | None = None) -> dict: """Crypto news from Twitter/X.""" payload: dict[str, Any] = {"chain": DEFAULT_CHAIN} if query: payload["query"] = query return await _call_tool("news_twitter", payload) @mcp.tool() async def news_combined(category: str | None = None) -> dict: """Combined news from all sources.""" payload: dict[str, Any] = {"chain": DEFAULT_CHAIN} if category: payload["category"] = category return await _call_tool("news_combined", payload) # =========================================================================== # Entry point # =========================================================================== def main(): """Run the Rug Munch Intelligence MCP server.""" mcp.run() if __name__ == "__main__": main()