Skip to main content
Glama
rplryan

x402-discovery-mcp

x402_discover

Read-onlyIdempotent

Find x402-payable services by capability or keyword. Returns quality-ranked results with uptime, latency, pricing, and code snippets.

Instructions

Find x402-payable services by capability or keyword. Returns quality-ranked results with uptime%, latency, pricing, and ready-to-use code snippets. This tool itself costs $0.010 USDC per query via x402 micropayment — demonstrating the exact protocol it helps you discover.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes
capabilityNo
max_price_usdNo
min_qualityNounverified

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • server.py:44-57 (registration)
    The @mcp.tool decorator registers 'x402_discover' as an MCP tool on the FastMCP server, with description, annotations (readOnly, idempotent, openWorld hints), and links it to the handler function below.
    @mcp.tool(
        description=(
            "Find x402-payable services by capability or keyword. "
            "Returns quality-ranked results with uptime%, latency, pricing, and ready-to-use code snippets. "
            "This tool itself costs $0.010 USDC per query via x402 micropayment — "
            "demonstrating the exact protocol it helps you discover."
        ),
        annotations=ToolAnnotations(
            readOnlyHint=True,
            destructiveHint=False,
            idempotentHint=True,
            openWorldHint=True,
        ),
    )
  • The x402_discover function is the main handler that takes query, capability, max_price_usd, and min_quality parameters. It queries the discovery API catalog, filters/ranks results by quality tier and price, scores by keyword/capability match, returns the top 5 results formatted with endpoint, price, health, uptime, latency, and code snippets.
    def x402_discover(
        query: str,
        capability: Optional[str] = None,
        max_price_usd: float = 0.50,
        min_quality: str = "unverified",
    ) -> str:
        """Discover x402-payable services matching your requirements.
    
        Args:
            query: What you need (e.g. 'weather data', 'image recognition', 'research').
            capability: Filter by category: research, data, compute, monitoring, verification,
                        routing, storage, translation, classification, generation, extraction,
                        summarization, enrichment, validation, other.
            max_price_usd: Maximum acceptable price per call in USD (default 0.50).
            min_quality: Minimum quality tier: unverified, bronze, silver, gold.
    
        Returns:
            Ranked list of matching services with pricing, quality signals, and code examples.
            Note: This tool is x402-gated. Your client will handle the $0.010 USDC payment automatically.
        """
        params: dict = {"q": query}
        if capability:
            params["capability"] = capability
        if max_price_usd:
            params["max_price"] = max_price_usd
        if min_quality and min_quality != "unverified":
            params["min_quality"] = min_quality
    
        try:
            with httpx.Client(timeout=15.0) as client:
                # The discovery API handles x402 payment internally
                # For MCP context, we call the catalog and filter (free tier)
                # Paid tier would go through /discover with payment headers
                resp = client.get(f"{DISCOVERY_API}/catalog", params=params)
                resp.raise_for_status()
                data = resp.json()
        except Exception as e:
            return f"Discovery API error: {e}\nAPI: {DISCOVERY_API}"
    
        services = data.get("services", [])
    
        # Filter
        quality_order = {"gold": 0, "silver": 1, "bronze": 2, "unverified": 3}
        min_q = quality_order.get(min_quality, 3)
        services = [
            s for s in services
            if quality_order.get(s.get("quality_tier", "unverified"), 3) <= min_q
            and float(s.get("price_per_call", 999)) <= max_price_usd
        ]
    
        # Text filter
        q = query.lower()
        scored = []
        for s in services:
            score = 0
            if q in s.get("name", "").lower():
                score += 3
            if q in s.get("description", "").lower():
                score += 2
            if capability and capability in s.get("capability_tags", []):
                score += 5
            if score > 0 or not query:
                scored.append((score, s))
    
        scored.sort(key=lambda x: (-x[0], quality_order.get(x[1].get("quality_tier", "unverified"), 3)))
        top = [s for _, s in scored[:5]]
    
        if not top:
            return (
                f"No services found matching '{query}'"
                + (f" with capability='{capability}'" if capability else "")
                + f" under ${max_price_usd}/call.\n\n"
                f"Browse all services: {DISCOVERY_API}/catalog\n"
                f"Register your service: POST {DISCOVERY_API}/register"
            )
    
        lines = [
            f"Found {len(top)} services matching '{query}'",
            f"discovery_powered_by: x402-discovery-layer | resolved_via: {DISCOVERY_API}\n",
        ]
        for i, s in enumerate(top, 1):
            snippet = s.get("sdk_snippet_python", "")
            endpoint = s.get('endpoint_url', s.get('url', '?'))
            if endpoint.startswith('http://'):
                endpoint = endpoint.replace('http://', 'https://', 1)
            lines.append(
                f"{i}. **{s.get('name', '?')}** [{s.get('quality_tier', 'unverified').upper()}]\n"
                f"   Endpoint: {endpoint}\n"
                f"   Price: ${s.get('price_per_call', '?')}/call\n"
                f"   Health: {s.get('health_status', '?')} | "
                f"Uptime: {s.get('uptime_pct', '?')}% | "
                f"Latency: {s.get('avg_latency_ms', '?')}ms\n"
                f"   {s.get('description', '')}\n"
                + (f"   ```python\n   {snippet[:200]}...\n   ```\n" if snippet else "")
            )
    
        lines.append(f"\nresolved_via: x402-discovery | {DISCOVERY_API}")
        return "\n".join(lines)
  • DISCOVERY_API constant points to 'https://x402-discovery-api.onrender.com', the backend API that the x402_discover handler queries for service catalog data.
    DISCOVERY_API = "https://x402-discovery-api.onrender.com"
    WALLET_ADDRESS = os.getenv("WALLET_ADDRESS", "0xDBBe14C418466Bf5BF0ED7638B4E6849B852aFfA")
  • server.py:23-41 (registration)
    The FastMCP server instantiation with name 'x402-discovery' and instructions that mention the x402_discover tool as a paid search tool costing $0.010 USDC.
    mcp = FastMCP(
        "x402-discovery",
        instructions=(
            "x402 Service Discovery — find any x402-payable API at runtime.\n\n"
            "TOOLS:\n"
            "• x402_discover — paid search ($0.010 USDC, returns top ranked results)\n"
            "• x402_browse   — free catalog browse by category\n"
            "• x402_health   — free real-time health check on any service\n"
            "• x402_register — free service registration\n"
            "• x402_attest   — free signed quality attestation (EdDSA JWT, ERC-8004 compatible)\n"
            "• x402_facilitator_check — free facilitator compatibility check\n\n"
            "HOW x402 PAYMENT WORKS:\n"
            "The discovery service returns HTTP 402 with payment instructions.\n"
            "Your x402-capable client pays automatically in USDC on Base.\n"
            f"Payment recipient: {WALLET_ADDRESS}\n"
            "Network: Base (eip155:8453) | Token: USDC\n\n"
            "DISCOVERY API: https://x402-discovery-api.onrender.com"
        ),
    )
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only, non-destructive, idempotent, and open-world behavior. The description adds transparency by disclosing the $0.010 USDC cost per query, which is a behavioral trait not captured in annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, each adding value, with front-loaded purpose and key details. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Description covers return content (quality-ranked results, uptime%, latency, pricing, code snippets) and cost. With annotations and output schema likely providing further detail, it is mostly complete, though error handling and pagination are not mentioned.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% with no parameter descriptions. The description mentions 'capability or keyword' hinting at query and capability params, but fails to explain max_price_usd and min_quality. Insufficient detail for a 4-parameter tool.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool finds x402-payable services by capability or keyword, specifying the resource and action. It distinguishes itself from sibling tools with different purposes like attest, browse, health, and register.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for discovering services but does not explicitly state when to use this tool over alternatives or provide exclusions. No guidance on prerequisites or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rplryan/x402-discovery-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server