> ## Documentation Index
> Fetch the complete documentation index at: https://docs.x402.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Bazaar (Discovery Layer)

> The x402 Bazaar is the discovery layer for the x402 ecosystem - a machine-readable catalog that helps developers and AI agents find and integrate with x402-compatible API endpoints and MCP tools.

Think of it as a search index for payable APIs and MCP tools, enabling the autonomous discovery and consumption of services.

The x402 Bazaar is in early development. While our vision is to build the "Google for agentic endpoints," we're currently more like "Yahoo search" - functional but evolving. Features and APIs may change as we gather feedback and expand capabilities.

### Overview

The Bazaar solves a critical problem in the x402 ecosystem: **discoverability**. Without it, x402-compatible endpoints and MCP tools are like hidden stalls in a vast market. The Bazaar provides:

* **For Buyers (API Consumers)**: Programmatically discover available x402-enabled services (HTTP endpoints and MCP tools), understand their capabilities, pricing, and schemas
* **For Sellers (API Providers)**: Automatic visibility for your x402-enabled services to a global audience of developers and AI agents
* **For AI Agents**: Dynamic service discovery without pre-baked integrations - query, find, pay, and use

### How It Works

Facilitators that support the Bazaar extension may provide a `/discovery/resources` endpoint that returns all x402-compatible services registered through the respective facilitator. Services (HTTP endpoints and MCP tools) are discoverable when they include the bazaar extension in their route configuration.

**Note:** The spec for marketplace items is open and part of the x402 scheme, meaning any facilitator can implement their own discovery layer.

#### Settlement Response Header

After processing a payment that includes the `bazaar` extension, facilitators **may** return an `EXTENSION-RESPONSES` HTTP header to communicate extension-specific outcomes to the client.

**Header name:** `EXTENSION-RESPONSES`

**Header value:** A base64-encoded JSON object keyed by extension name. The `bazaar` key contains the bazaar extension's response:

| Field                   | Type   | Required | Description                                                            |
| ----------------------- | ------ | -------- | ---------------------------------------------------------------------- |
| `bazaar.status`         | string | Yes      | One of `"success"`, `"processing"`, or `"rejected"`                    |
| `bazaar.rejectedReason` | string | No       | Human-readable explanation. Only present when `status` is `"rejected"` |

**Status values:**

| Value          | Meaning                                                                                            |
| -------------- | -------------------------------------------------------------------------------------------------- |
| `"success"`    | The discovery info was validated and successfully cataloged                                        |
| `"processing"` | The discovery info was accepted and is being cataloged asynchronously                              |
| `"rejected"`   | The discovery info was rejected (e.g., failed schema validation). See `rejectedReason` for details |

**Example (success):**

```
EXTENSION-RESPONSES: eyJiYXphYXIiOnsic3RhdHVzIjoic3VjY2VzcyJ9fQ==
```

*(base64 of `{"bazaar":{"status":"success"}}`)*

**Example (rejected):**

```
EXTENSION-RESPONSES: eyJiYXphYXIiOnsic3RhdHVzIjoicmVqZWN0ZWQiLCJyZWplY3RlZFJlYXNvbiI6ImluZm8gZmFpbGVkIHNjaGVtYSB2YWxpZGF0aW9uIn19
```

*(base64 of `{"bazaar":{"status":"rejected","rejectedReason":"info failed schema validation"}}`)*

Clients that understand the `bazaar` extension should read the `bazaar` key of this header to confirm cataloging succeeded and surface any rejection reason for debugging.

#### Basic Flow

1. **Discovery**: Clients query the `/discovery/resources` endpoint to find available services
2. **Selection**: Choose a service based on price, capabilities, and requirements
3. **Execution**: Use x402 to pay for and access the selected service
4. **No Manual Setup**: No API keys, no account creation, just discover and pay

### API Reference

#### List Endpoint

Retrieve all available x402-compatible endpoints and MCP tools:

##### Coinbase

```bash theme={null}
GET https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources
```

##### PayAI

```bash theme={null}
GET https://facilitator.payai.network/discovery/resources
```

**Note**: The recommended way to use this endpoint is to use the `useFacilitator` hook as described below.

**Response Schema**

Each resource in the list contains the following fields:

```json theme={null}
{
  "accepts": [
    {
      "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "description": "",
      "extra": {
        "name": "USD Coin",
        "version": "2"
      },
      "maxAmountRequired": "200",
      "maxTimeoutSeconds": 60,
      "mimeType": "",
      "network": "eip155:8453",
      "outputSchema": {
        "input": {
          "method": "GET",
          "type": "http"
        },
        "output": null
      },
      "payTo": "0xa2477E16dCB42E2AD80f03FE97D7F1a1646cd1c0",
      "resource": "https://api.example.com/x402/weather",
      "scheme": "exact"
    }
  ],
  "lastUpdated": "2025-08-09T01:07:04.005Z",
  "metadata": {},
  "resource": "https://api.example.com/x402/weather",
  "type": "http",
  "x402Version": 2
}
```

**Resource Types**

The `type` field indicates the resource type:

* `"http"` - HTTP endpoints (GET, POST, PUT, PATCH, DELETE, HEAD)
* `"mcp"` - MCP (Model Context Protocol) tools

For MCP tools, the `outputSchema.input` object will contain:

* `type: "mcp"` - Identifies this as an MCP tool
* `toolName` - The MCP tool name (used in `tools/call` requests)
* `inputSchema` - JSON Schema for the tool's arguments (follows MCP `Tool.inputSchema` format)
* `description` - Human-readable description of the tool (optional)
* `transport` - MCP transport protocol: `"streamable-http"` (default) or `"sse"` (optional)
* `example` - Example arguments object (optional)

**Note:** For MCP tools, the unique resource identifier is the tuple (`resource`, `input.toolName`) since MCP multiplexes multiple tools over a single server endpoint.

### Quickstart for Buyers

#### Step 1: Discover Available Services

Fetch the list of available x402 services using the facilitator client:

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { HTTPFacilitatorClient } from "@x402/core/http";
    import { withBazaar } from "@x402/extensions";

    const facilitatorClient = new HTTPFacilitatorClient({
      url: "https://x402.org/facilitator"
    });
    const client = withBazaar(facilitatorClient);

    // List HTTP services; use type: "mcp" to list MCP tools instead
    const response = await client.extensions.bazaar.listResources({ type: "http" });

    // Filter services under $0.10
    const usdcAsset = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
    const maxPrice = 100000; // $0.10 in USDC atomic units (6 decimals)

    const affordableServices = response.items.filter(item =>
      item.accepts.find(paymentRequirements =>
        paymentRequirements.asset === usdcAsset &&
        Number(paymentRequirements.maxAmountRequired) < maxPrice
      )
    );
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    package main

    import (
        "context"
        "fmt"

        "github.com/x402-foundation/x402/go/extensions/bazaar"
        x402http "github.com/x402-foundation/x402/go/http"
    )

    func main() {
        ctx := context.Background()

        // Create facilitator client and extend with bazaar
        facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{
            URL: "https://x402.org/facilitator",
        })
        client := bazaar.WithBazaar(facilitatorClient)

        // List discovery resources
        response, err := client.ListDiscoveryResources(ctx, &bazaar.ListDiscoveryResourcesParams{
            Type:   "http",
            Limit:  20,
            Offset: 0,
        })
        if err != nil {
            panic(err)
        }

        // Filter services under $0.10
        usdcAsset := "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
        maxPrice := 100000 // $0.10 in USDC atomic units (6 decimals)

        for _, item := range response.Items {
            for _, paymentReq := range item.Accepts {
                // Parse asset and maxAmountRequired from payment requirements
                if asset, ok := paymentReq["asset"].(string); ok && asset == usdcAsset {
                    if maxAmount, ok := paymentReq["maxAmountRequired"].(string); ok {
                        // Convert and compare price
                        fmt.Printf("Found service: %s\n", item.Resource)
                    }
                }
            }
        }
    }
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from x402.http import FacilitatorConfig, HTTPFacilitatorClient
    from x402.extensions.bazaar import with_bazaar, ListDiscoveryResourcesParams

    facilitator_client = HTTPFacilitatorClient(
        FacilitatorConfig(url="https://x402.org/facilitator")
    )
    client = with_bazaar(facilitator_client)

    # List HTTP services; use type="mcp" to list MCP tools instead
    response = client.extensions.bazaar.list_resources(
        ListDiscoveryResourcesParams(type="http")
    )

    # Filter services under $0.10
    usdc_asset = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
    max_price = 100000  # $0.10 in USDC atomic units (6 decimals)

    affordable_services = [
        item
        for item in response.items
        if any(
            payment_req.get("asset") == usdc_asset
            and int(payment_req.get("amount", 0)) < max_price
            for payment_req in (item.accepts or [])
        )
    ]
    ```
  </Tab>
</Tabs>

#### Step 1b: Search for Services

You can also search for services using a natural-language query. Pagination is facilitator-defined: some facilitators may include top-level `limit` and `cursor`, and others may omit them.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    const results = await client.extensions.bazaar.search({
      query: "weather APIs",
      type: "http",
    });

    // Some facilitators return a pagination object like the list endpoint
    if (results.pagination) {
      console.log("Next page cursor:", results.pagination.cursor);
    }

    console.log(`Found ${results.resources.length} services`);
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    results, err := client.SearchDiscoveryResources(ctx, &bazaar.SearchDiscoveryResourcesParams{
        Query: "weather APIs",
        Type:  "http",
    })
    if err != nil {
        panic(err)
    }

    fmt.Printf("Found %d services\n", len(results.Resources))
    if results.Pagination != nil {
        fmt.Println("Next cursor:", results.Pagination.Cursor)
    }
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from x402.extensions.bazaar import SearchDiscoveryResourcesParams

    results = client.extensions.bazaar.search(
        SearchDiscoveryResourcesParams(query="weather APIs", type="http")
    )

    print(f"Found {len(results.resources)} services")
    if results.pagination is not None:
        print(f"Next cursor: {results.pagination.cursor}")
    ```
  </Tab>
</Tabs>

#### Step 2: Call a Discovered Service

Once you've found a suitable service, use an x402 client to call it:

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { wrapAxiosWithPayment, x402Client } from "@x402/axios";
    import { ExactEvmScheme } from "@x402/evm/exact/client";
    import axios from "axios";
    import { privateKeyToAccount } from "viem/accounts";

    // Set up your payment account
    const account = privateKeyToAccount("0xYourPrivateKey");
    const client = new x402Client();
    client.register("eip155:*", new ExactEvmScheme(account));

    // Select a service from discovery
    const selectedService = affordableServices[0];

    // Create a payment-enabled client for that service
    const api = wrapAxiosWithPayment(
      axios.create({ baseURL: selectedService.resource }),
      client
    );

    // Select the payment method of your choice
    const selectedPaymentRequirements = selectedService.accepts[0];
    const inputSchema = selectedPaymentRequirements.outputSchema.input;

    // Build the request using the service's schema
    const response = await api.request({
      method: inputSchema.method,
      url: inputSchema.resource,
      params: { location: "San Francisco" } // Based on inputSchema
    });

    console.log("Response data:", response.data);
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import asyncio

    from eth_account import Account

    from x402 import x402Client
    from x402.http.clients import x402HttpxClient
    from x402.mechanisms.evm import EthAccountSigner
    from x402.mechanisms.evm.exact.register import register_exact_evm_client


    async def main() -> None:
        account = Account.from_key("0xYourPrivateKey")
        client = x402Client()
        register_exact_evm_client(client, EthAccountSigner(account))

        # Select a service from discovery (from Step 1)
        selected_service = affordable_services[0]

        # Select the payment method of your choice
        selected_payment_requirements = selected_service.accepts[0]
        input_schema = selected_payment_requirements.output_schema.input

        # Make the request using httpx client
        async with x402HttpxClient(client) as http:
            response = await http.request(
                method=input_schema.method,
                url=input_schema.resource,
                params={"location": "San Francisco"}  # Based on input_schema
            )
            await response.aread()
            print(f"Response data: {response.json()}")


    asyncio.run(main())
    ```
  </Tab>
</Tabs>

#### Step 2 (MCP tools): Call a Discovered MCP Tool

For discovered MCP tools, use the x402 MCP client to call the tool after paying:

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { createx402MCPClient } from "@x402/mcp";
    import { ExactEvmScheme } from "@x402/evm/exact/client";
    import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
    import { privateKeyToAccount } from "viem/accounts";

    const account = privateKeyToAccount("0xYourPrivateKey");

    // Discover MCP tools from the Bazaar
    const mcpItems = await client.extensions.bazaar.listResources({ type: "mcp" });
    const selectedTool = mcpItems.items[0];
    const { toolName } = selectedTool.discoveryInfo.input;

    // Connect the x402 MCP client to the tool's server
    const x402Mcp = createx402MCPClient({
      name: "my-mcp-client",
      schemes: [{ network: "eip155:8453", scheme: new ExactEvmScheme(account) }],
    });

    // selectedTool.resource is an identifier like mcp://tool/get_weather, not a transport URL
    const mcpServerUrl = "https://your-mcp-server.example.com";
    const transport = new SSEClientTransport(new URL(`${mcpServerUrl}/sse`));
    await x402Mcp.connect(transport);

    // Call the paid tool — x402Mcp handles payment automatically
    const result = await x402Mcp.callTool(toolName, { city: "San Francisco" });
    console.log("Tool result:", result);

    await x402Mcp.close();
    ```
  </Tab>
</Tabs>

### Quickstart for Sellers

#### Listing with Bazaar Extension

Add the bazaar extension to your route configuration to make your API or MCP tools discoverable.

**Supported Resource Types:**

* **HTTP Endpoints** - Standard REST APIs (GET, POST, PUT, PATCH, DELETE, HEAD)
* **MCP Tools** - Model Context Protocol tools for AI agent integration

#### Dynamic Routes

The Bazaar extension supports parameterized routes (e.g., `/users/[userId]`, `/weather/[country]/[city]`). When you use route parameters:

* The extension automatically extracts concrete parameter values into `pathParams` (e.g., `{ "userId": "123" }`)
* A `routeTemplate` field is added using `:param` syntax (e.g., `/users/:userId`)
* Facilitators use `routeTemplate` as the catalog key, consolidating all requests to the same route pattern into a single discovery entry

This means `/users/123`, `/users/456`, and `/users/789` all map to the same catalog entry: `/users/:userId`.

**Note:** Wildcard segments (`*`) are automatically converted to named parameters (`:var1`, `:var2`, etc.) for catalog normalization.

#### Service Metadata

Resource servers can publish provider-level metadata on the **`resource` object** of the 402 response. Facilitators use these fields to enrich Bazaar search results with a human-readable name, topical tags, and an icon — no out-of-band admin step required.

All three fields are optional. Servers that omit them produce byte-identical 402 responses; clients that don't recognize them ignore them.

| Field         | Type      | Description                                                                                                        |
| ------------- | --------- | ------------------------------------------------------------------------------------------------------------------ |
| `serviceName` | string    | Human-readable name for the service (≤ 32 printable ASCII characters).                                             |
| `tags`        | string\[] | Up to 5 short topical tags (each ≤ 32 printable ASCII characters). Used for facilitator-side filtering and search. |
| `iconUrl`     | string    | Absolute `https://` or `http://` URL to an icon image representing the service (≤ 2048 characters).                |

These fields are set on the `resource` object in your route configuration, alongside `description` and `mimeType`:

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    const routes = {
      "GET /weather": {
        price: "$0.001",
        network: "eip155:8453",
        payTo: "0xYourAddress",
        resource: {
          url: "https://api.example.com/weather",
          description: "Get real-time weather data",
          mimeType: "application/json",
          serviceName: "Example Weather",
          tags: ["weather", "forecast"],
          iconUrl: "https://api.example.com/icon.png",
        },
        extensions: { bazaar: { ... } },
      },
    };
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from x402.schemas.payments import ResourceInfo

    routes: dict[str, RouteConfig] = {
        "GET /weather": RouteConfig(
            accepts=[...],
            resource=ResourceInfo(
                url="https://api.example.com/weather",
                description="Get real-time weather data",
                mime_type="application/json",
                service_name="Example Weather",
                tags=["weather", "forecast"],
                icon_url="https://api.example.com/icon.png",
            ),
            extensions={"bazaar": {...}},
        ),
    }
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    routes := x402http.RoutesConfig{
        "GET /weather": {
            Accepts: x402http.PaymentOptions{{...}},
            Resource: &types.ResourceInfo{
                URL:         "https://api.example.com/weather",
                Description: "Get real-time weather data",
                MimeType:    "application/json",
                ServiceName: "Example Weather",
                Tags:        []string{"weather", "forecast"},
                IconURL:     "https://api.example.com/icon.png",
            },
            Extensions: map[string]interface{}{
                types.BAZAAR: discoveryExtension,
            },
        },
    }
    ```
  </Tab>
</Tabs>

**Validation rules:** Facilitators apply soft-drop rules — a field that fails validation is silently discarded while the rest of the metadata is preserved. `serviceName` and `tags` are restricted to printable ASCII (U+0020–U+007E) so that string-length checks are consistent across TypeScript, Python, and Go. `iconUrl` must be an absolute `http://` or `https://` URL with no IP literals or loopback hostnames (SSRF defense).

#### Adding Metadata

To enhance your listing with descriptions and schemas, include them when setting up your x402 middleware. **You should include descriptions for each parameter to make it clear for agents to call your endpoints**:

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { paymentMiddleware } from "@x402/express";
    import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server";
    import { ExactEvmScheme } from "@x402/evm/exact/server";
    import { bazaarResourceServerExtension } from "@x402/extensions";

    const facilitatorClient = new HTTPFacilitatorClient({
      url: "https://x402.org/facilitator"
    });
    const server = new x402ResourceServer(facilitatorClient);
    server.register("eip155:*", new ExactEvmScheme());

    const routes = {
      "GET /weather": {
        price: "$0.001",
        network: "eip155:8453",
        resource: "0xYourAddress",
        description: "Get current weather data for any location",
        extensions: {
          bazaar: {
            discoverable: true,
            inputSchema: {
              queryParams: {
                location: {
                  type: "string",
                  description: "City name or coordinates",
                  required: true
                }
              }
            },
            outputSchema: {
              type: "object",
              properties: {
                temperature: { type: "number" },
                conditions: { type: "string" },
                humidity: { type: "number" }
              }
            }
          }
        }
      }
    };

    app.use(paymentMiddleware(routes, server));
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from fastapi import FastAPI

    from x402.http import FacilitatorConfig, HTTPFacilitatorClient, PaymentOption
    from x402.http.middleware.fastapi import PaymentMiddlewareASGI
    from x402.http.types import RouteConfig
    from x402.mechanisms.evm.exact import ExactEvmServerScheme
    from x402.server import x402ResourceServer

    app = FastAPI()

    # Create facilitator client (CDP mainnet)
    facilitator = HTTPFacilitatorClient(
        FacilitatorConfig(url="https://x402.org/facilitator")
    )

    # Create resource server and register EVM scheme
    server = x402ResourceServer(facilitator)
    server.register("eip155:8453", ExactEvmServerScheme())

    # Define routes with Bazaar discovery metadata
    routes: dict[str, RouteConfig] = {
        "GET /weather": RouteConfig(
            accepts=[
                PaymentOption(
                    scheme="exact",
                    pay_to="0xYourAddress",
                    price="$0.001",
                    network="eip155:8453",
                ),
            ],
            mime_type="application/json",
            description="Get current weather data for any location",
            extensions={
                "bazaar": {
                    "discoverable": True,
                    "inputSchema": {
                        "queryParams": {
                            "location": {
                                "type": "string",
                                "description": "City name or coordinates",
                                "required": True,
                            }
                        }
                    },
                    "outputSchema": {
                        "type": "object",
                        "properties": {
                            "temperature": {"type": "number"},
                            "conditions": {"type": "string"},
                            "humidity": {"type": "number"},
                        },
                    },
                }
            },
        ),
    }

    app.add_middleware(PaymentMiddlewareASGI, routes=routes, server=server)
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    package main

    import (
        x402 "github.com/x402-foundation/x402/go"
        "github.com/x402-foundation/x402/go/extensions/bazaar"
        "github.com/x402-foundation/x402/go/extensions/types"
        x402http "github.com/x402-foundation/x402/go/http"
        ginmw "github.com/x402-foundation/x402/go/http/gin"
        evm "github.com/x402-foundation/x402/go/mechanisms/evm/exact/server"
        "github.com/gin-gonic/gin"
    )

    func main() {
        r := gin.Default()

        facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{
            URL: "https://x402.org/facilitator",
        })

        // Create Bazaar Discovery Extension with input/output schemas
        discoveryExtension, _ := bazaar.DeclareDiscoveryExtension(
            bazaar.MethodGET,
            map[string]interface{}{"location": "San Francisco"},
            types.JSONSchema{
                "properties": map[string]interface{}{
                    "location": map[string]interface{}{
                        "type":        "string",
                        "description": "City name or coordinates",
                    },
                },
                "required": []string{"location"},
            },
            "",
            &types.OutputConfig{
                Schema: types.JSONSchema{
                    "properties": map[string]interface{}{
                        "temperature": map[string]interface{}{"type": "number"},
                        "conditions":  map[string]interface{}{"type": "string"},
                        "humidity":    map[string]interface{}{"type": "number"},
                    },
                },
            },
        )

        routes := x402http.RoutesConfig{
            "GET /weather": {
                Accepts: x402http.PaymentOptions{{
                    Scheme:  "exact",
                    PayTo:   "0xYourAddress",
                    Price:   "$0.001",
                    Network: x402.Network("eip155:8453"),
                }},
                Description: "Get current weather data for any location",
                Extensions: map[string]interface{}{
                    types.BAZAAR: discoveryExtension,
                },
            },
        }

        r.Use(ginmw.X402Payment(ginmw.Config{
            Routes:      routes,
            Facilitator: facilitatorClient,
            Schemes: []ginmw.SchemeConfig{{
                Network: x402.Network("eip155:8453"),
                Server:  evm.NewExactEvmScheme(),
            }},
        }))

        r.GET("/weather", func(c *gin.Context) {
            location := c.DefaultQuery("location", "San Francisco")
            c.JSON(200, gin.H{
                "location":    location,
                "temperature": 70,
                "conditions":  "sunny",
                "humidity":    45,
            })
        })

        r.Run(":4021")
    }
    ```
  </Tab>
</Tabs>

#### Adding Metadata for MCP Tools

To make paid MCP tools discoverable, pass the discovery extension in your payment wrapper config:

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { createPaymentWrapper } from "@x402/mcp";
    import { declareDiscoveryExtension } from "@x402/extensions/bazaar";

    const paid = createPaymentWrapper(resourceServer, {
      accepts,
      resource: {
        url: "mcp://tool/get_weather",
        description: "Get current weather for a city",
      },
      extensions: declareDiscoveryExtension({
        toolName: "get_weather",
        description: "Get current weather for a city",
        transport: "sse",
        inputSchema: {
          properties: { city: { type: "string", description: "City name" } },
          required: ["city"],
        },
        example: { city: "San Francisco" },
      }),
    });

    mcpServer.tool("get_weather", "Get current weather ($0.001)", { city: z.string() },
      paid(async ({ city }) => ({ content: [{ type: "text", text: JSON.stringify(await fetchWeather(city)) }] }))
    );
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from x402.mcp import create_payment_wrapper
    from x402.extensions.bazaar import DeclareMcpDiscoveryConfig, declare_mcp_discovery_extension

    weather_discovery = declare_mcp_discovery_extension(
        DeclareMcpDiscoveryConfig(
            tool_name="get_weather",
            description="Get current weather for a city",
            transport="sse",
            input_schema={
                "properties": {"city": {"type": "string", "description": "City name"}},
                "required": ["city"],
            },
            example={"city": "San Francisco"},
        )
    )

    weather_wrapper = create_payment_wrapper(
        resource_server,
        accepts=weather_accepts,
        resource=ResourceInfo(
            url="mcp://tool/get_weather",
            description="Get current weather for a city",
        ),
        extensions=weather_discovery,
    )

    @mcp.tool(name="get_weather", description="Get current weather ($0.001)")
    @weather_wrapper
    async def get_weather(city: str) -> str:
        return json.dumps(await fetch_weather(city))
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    import (
        "github.com/x402-foundation/x402/go/extensions/bazaar"
        mcp402 "github.com/x402-foundation/x402/go/mcp"
        "github.com/x402-foundation/x402/go/types"
    )

    weatherDiscovery, _ := bazaar.DeclareMcpDiscoveryExtension(bazaar.DeclareMcpDiscoveryConfig{
        ToolName:    "get_weather",
        Description: "Get current weather for a city",
        Transport:   bazaar.TransportSSE,
        InputSchema: bazaar.JSONSchema{
            "properties": map[string]interface{}{
                "city": map[string]interface{}{
                    "type":        "string",
                    "description": "City name",
                },
            },
            "required": []string{"city"},
        },
        Example: map[string]interface{}{"city": "San Francisco"},
    })

    paymentWrapper := mcp402.NewPaymentWrapper(resourceServer, mcp402.PaymentWrapperConfig{
        Accepts: weatherAccepts,
        Resource: &types.ResourceInfo{
            URL:         "mcp://tool/get_weather",
            Description: "Get current weather for a city",
        },
        Extensions: map[string]interface{}{
            bazaar.BAZAAR.Key(): weatherDiscovery,
        },
    })
    ```
  </Tab>
</Tabs>

### Coming Soon

The x402 Bazaar is rapidly evolving, and your feedback helps us prioritize features.

### Support

* **GitHub**: [github.com/x402-foundation/x402](https://github.com/x402-foundation/x402)
* **Discord**: [Join #x402 channel](https://discord.com/invite/cdp)

### FAQ

**Q: How do I get my service listed?**
A: Add the bazaar extension to your route configuration. See the examples above.

**Q: How can I make endpoint calls more accurate?**
A: Include descriptions clearly stating what each parameter does and how to call your endpoint, but do so as succinctly as possible.

**Q: How does pricing work?**
A: Listing is free. Services set their own prices per API call, paid via x402.

**Q: What networks are supported?**
A: Currently Base (`eip155:8453`), Base Sepolia (`eip155:84532`), Solana (`solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`), and Solana Devnet (`solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1`) with USDC payments.

**Q: Can I list non-x402 services?**
A: No, only x402-compatible endpoints can be listed. See our [Quickstart for Sellers](/getting-started/quickstart-for-sellers) to make your API x402-compatible.

**Q: What are MCP tools and how do they work with Bazaar?**
A: MCP (Model Context Protocol) tools are AI-agent-friendly interfaces that can be discovered and paid for through x402. When listing an MCP tool, include `type: "mcp"` in the bazaar extension along with the tool name and input schema. The unique identifier for MCP tools is the combination of the resource URL and tool name, since multiple tools can be served from a single MCP endpoint.
