Skip to main content
Glama
aratan

ucp-mcp-server

by aratan

ucp-mcp-server

Let AI assistants shop. An MCP server that gives Claude, Cursor, and any MCP-compatible AI the ability to interact with UCP-enabled merchants.

UCP (Universal Commerce Protocol) is Google's new open standard for agentic commerce, backed by Shopify, Stripe, Visa, Mastercard, Target, Walmart, and 20+ partners.

MCP (Model Context Protocol) is the standard for giving AI assistants access to tools.

This project connects them.


What Can It Do?

Tool

Description

ucp_discover

Find out what a merchant supports (capabilities, payment methods)

ucp_products_list

List all products from a merchant's catalog

ucp_products_search

Search and filter products by color, category, location, price, specs

ucp_checkout_create

Start a purchase (add items to cart, set buyer info)

ucp_checkout_update

Apply discount codes to an existing checkout

ucp_checkout_set_fulfillment

Set up shipping (auto-selects address and delivery option)

ucp_checkout_complete

Complete the purchase by submitting payment

ucp_order_get

Get the current status of an order, including fulfillment

ucp_testing_simulate_shipping

Mark an order as shipped via the merchant's testing endpoint

Your AI assistant gets structured, type-safe access to the entire UCP shopping flow. No scraping, no browser automation, no brittle hacks.

Quick Start

Install

pip install ucp-mcp-server

Or with uv:

uv pip install ucp-mcp-server

Use with Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "ucp-shopping": {
      "command": "ucp-mcp-server"
    }
  }
}

Use with Cursor

Add to your .cursor/mcp.json:

{
  "mcpServers": {
    "ucp-shopping": {
      "command": "ucp-mcp-server"
    }
  }
}

Run Directly

# As a module
python -m ucp_mcp_server

# Or via the entry point
ucp-mcp-server

Tools Reference

ucp_discover

Discover what a UCP merchant supports before shopping.

Arguments:
  merchant_url (str): Base URL of a UCP-enabled merchant

Returns:
  capabilities: List of supported UCP capabilities (checkout, discount, fulfillment)
  payment_handlers: Accepted payment methods (Shop Pay, Google Pay, etc.)
  ucp_version: Protocol version the merchant implements

ucp_products_list

List all products from a merchant's catalog.

Arguments:
  merchant_url (str): Base URL of the merchant

Returns:
  products: List of products with id, title, price, and image_url

Search and filter products from a merchant's catalog with advanced filtering.

Arguments:
  merchant_url (str): Base URL of the merchant
  query (str): Text search query to match against product titles
  color (str): Filter by color (e.g., "red", "blue", "black")
  category (str): Filter by category (e.g., "pc", "laptop", "monitor")
  location (str): Filter by location/availability (e.g., "Madrid", "Barcelona")
  max_price (int): Maximum price filter in cents (e.g., 200000 for 2000 EUR)
  min_price (int): Minimum price filter in cents
  sort_by (str): Sort results by "price_asc", "price_desc", or "name"
  specs (dict): Filter by specifications (e.g., {"use_case": "ai", "gpu": "RTX 4090"})

Returns:
  products: List of matching products with all fields
  total: Number of products found
  filters_applied: Summary of filters that were applied

Example: Find a red PC for AI in Madrid under 2000 EUR

result = await ucp_products_search(
    merchant_url="http://localhost:8182",
    color="red",
    category="pc",
    location="Madrid",
    max_price=200000,  # 2000 EUR in cents
    specs={"use_case": "ai"},
    sort_by="price_asc",
)
# Returns: PC IA Rojo NVIDIA H100 at 1850 EUR

ucp_checkout_create

Create a new shopping cart / checkout session.

Arguments:
  merchant_url (str): Base URL of the merchant
  items (list): Items to buy, each with "id" and "quantity"
  buyer_name (str): Full name of the buyer
  buyer_email (str): Email address
  currency (str): Currency code (default: "USD")

Returns:
  checkout_id: Session ID for tracking this purchase
  status: Current checkout status
  total: Total price in smallest currency unit (cents)
  subtotal: Subtotal before discounts
  line_items: What's in the cart

ucp_checkout_update

Apply discount codes or modify an existing checkout.

Arguments:
  merchant_url (str): Base URL of the merchant
  checkout_id (str): The checkout session to update
  discount_codes (list[str]): Promo codes to apply

Returns:
  checkout_id: Session ID
  total: Updated total after discounts
  discount_applied: How much was saved
  discounts: Details of applied discounts

ucp_checkout_set_fulfillment

Set up shipping for a checkout. Automatically selects the first available address and delivery option.

Arguments:
  merchant_url (str): Base URL of the merchant
  checkout_id (str): The checkout session

Returns:
  checkout_id: Session ID
  status: Current status
  total: Updated total (may include shipping costs)
  fulfillment: Details of selected shipping method

ucp_checkout_complete

Complete a checkout by submitting payment. This finalizes the purchase and returns an order ID.

Arguments:
  merchant_url (str): Base URL of the merchant
  checkout_id (str): The checkout session to complete
  payment_handler_id (str): Payment handler to use (from ucp_discover)
  card_token (str): Payment token from the provider
  card_brand (str): Card brand (e.g., "Visa")
  card_last_digits (str): Last 4 digits of the card

Returns:
  checkout_id: Session ID
  status: "complete" or "completed"
  total: Final amount charged
  order_id: Order ID for tracking
  order_url: Permalink to the order

ucp_order_get

Get the current status of an order, including fulfillment details.

Arguments:
  merchant_url (str): Base URL of the merchant
  order_id (str): The order to track

Returns:
  order_id: The order ID
  status: Current order status
  currency: Order currency
  total: Total amount charged
  fulfillment: Fulfillment details (method, tracking, status)

ucp_testing_simulate_shipping

Simulate shipping an order via the merchant's testing endpoint. Useful for end-to-end tests and demos.

Arguments:
  merchant_url (str): Base URL of the merchant
  order_id (str): The order to mark as shipped

Returns:
  status: The result of the simulation (e.g., "shipped")

Example Conversation

Basic Shopping Flow

You: "Find out what the flower shop at http://flowers.example.com supports"

Claude: calls ucp_discover "This merchant supports checkout, discounts, and fulfillment tracking. They accept Shop Pay and Google Pay."

You: "Buy 2 bouquets of roses for me"

Claude: calls ucp_checkout_create "I've created a checkout for 2 Bouquet of Red Roses. Total: $70.00. Would you like to proceed?"

You: "Try the code 10OFF first"

Claude: calls ucp_checkout_update "Applied 10OFF - saved $7.00! New total: $63.00."

Product Search Flow

You: "I'm looking for a red PC for AI work in Madrid, budget under 2000 EUR"

Claude: calls ucp_products_search(color="red", category="pc", location="Madrid", max_price=200000, specs={"use_case": "ai"}, sort_by="price_asc") "I found 1 matching PC: PC IA Rojo NVIDIA H100 at 1,850 EUR. It has 128GB RAM, AMD EPYC 9654 CPU, and NVIDIA H100 GPU. This is the cheapest option that meets your criteria. Would you like to proceed with checkout?"

You: "Yes, add it to cart"

Claude: calls ucp_checkout_create "Added to cart! Checkout session created. Total: 1,850 EUR. Ready to complete purchase?"

Use Cases

๐Ÿ›’ E-commerce Personal Assistant

Why: Users want to shop naturally through conversation, not browse websites.

How: The AI acts as a personal shopper that understands preferences and finds the best deals.

User: "I need a gift for my mom, she loves gardening, budget 50 euros"
AI: ucp_products_search(query="garden", max_price=5000, sort_by="price_desc")
AI: "I found 3 gardening items. The Premium Pruning Set at โ‚ฌ45 has great reviews."
User: "Perfect, buy it"
AI: ucp_checkout_create โ†’ ucp_checkout_complete

Value: No app switching, no browser tabs, no remembering passwords. Just conversation.


๐Ÿข Enterprise Procurement

Why: Companies need to buy equipment across multiple vendors while tracking budgets.

How: The AI compares products across merchants and follows procurement rules.

User: "We need 10 laptops for the dev team, under 1500 EUR each, from approved vendors"
AI: ucp_products_search(category="laptop", max_price=150000, specs={"use_case": "development"})
AI: "Found 5 options across 3 merchants. Best value: ThinkPad X1 at โ‚ฌ1,299 from TechStore"
User: "Add 10 to cart and apply our corporate discount CORP20"
AI: ucp_checkout_create(quantity=10) โ†’ ucp_checkout_update(discount_codes=["CORP20"])

Value: Budget compliance, audit trail, no manual PO forms.


๐Ÿ” Price Comparison Shopping

Why: Users want the best price without checking 10 different websites.

How: The AI queries multiple UCP merchants and compares results.

User: "Find me the cheapest iPhone 15 Pro across all stores"
AI: [queries 5 merchants simultaneously]
AI: "Best price: โ‚ฌ899 at TechShop (โ‚ฌ50 cheaper than average). In stock in Madrid."
User: "Buy it from there"
AI: ucp_checkout_create(merchant_url="http://techshop.example.com")

Value: Save time and money without manual comparison.


๐ŸŽ Gift Purchasing with Constraints

Why: Gift buying involves multiple constraints (budget, preferences, occasion).

How: The AI filters products based on complex requirements.

User: "Find a red gaming PC under 2000 EUR for my son's birthday, needs RTX 4070 or better"
AI: ucp_products_search(
    color="red", category="pc", max_price=200000,
    specs={"use_case": "gaming", "gpu_min": "RTX 4070"},
    sort_by="price_asc"
)
AI: "Found 2 options. Best match: Gaming PC Rojo at โ‚ฌ1,850 with RTX 4070 Ti"

Value: Complex multi-criteria search in one conversation.


๐Ÿ“ฆ Order Tracking & Support

Why: Users want to know where their order is without logging into websites.

How: The AI tracks orders across merchants and provides updates.

User: "Where's my order from TechShop?"
AI: ucp_order_get(order_id="order-abc-123")
AI: "Your order shipped yesterday via DHL. Tracking: DH123456789. Expected delivery: Friday."
User: "Can I change the delivery address?"
AI: "Let me check... [calls merchant API] The order is already in transit, so address changes aren't possible. Would you like me to contact support?"

Value: Single point for all order tracking, no multiple logins.


๐Ÿงช Development & Testing

Why: Developers need to test e-commerce integrations without real payments.

How: Use the testing endpoints to simulate the full flow.

# Full test flow without real money
result = await ucp_testing_simulate_shipping(merchant_url, order_id)
# Simulates: payment โ†’ fulfillment โ†’ shipping โ†’ delivery

Value: Test complete purchase flows in development environments.


๐Ÿค– Automated Reordering

Why: Businesses need to reorder supplies when stock is low.

How: The AI monitors inventory and triggers reorders automatically.

[Automated trigger: inventory low]
AI: ucp_products_search(category="office_supplies", query="paper")
AI: "Office paper running low. Reordering 50 reams from SuppliesCo at โ‚ฌ25/ream"
AI: ucp_checkout_create โ†’ ucp_checkout_complete

Value: Never run out of supplies, automatic procurement.


๐Ÿ’ณ Multi-Payment Method Support

Why: Different users prefer different payment methods.

How: The AI discovers and uses the user's preferred payment handler.

User: "Pay with Google Pay"
AI: ucp_discover() โ†’ finds google_pay handler
AI: ucp_checkout_complete(payment_handler_id="google_pay")

Value: Flexibility without merchant-side integration work.

Why This Exists

Every AI app is going to need shopping capabilities. UCP standardizes how merchants expose commerce APIs. MCP standardizes how AI assistants use tools. This project is the bridge.

Without this, connecting AI to commerce means:

  • Scraping websites (brittle, breaks constantly)

  • Building custom integrations per merchant (doesn't scale)

  • Browser automation (slow, unreliable, expensive)

With UCP + MCP:

  • One protocol, every merchant

  • Structured data in, structured data out

  • Works with any MCP-compatible AI assistant

Improvements Roadmap

๐Ÿ”ง Optimization (Protocol-Compliant)

Area

Before

After

Why

HTTP Client

New client per request

Connection pooling with httpx.AsyncClient reuse

Reduce latency, reuse TCP connections

Response Caching

No caching

Cache ucp_discover results (5min TTL)

Discovery rarely changes, saves round-trips

Parallel Queries

Sequential product search

asyncio.gather() for multi-merchant search

Search 5 merchants in time of 1

Retry Logic

No retries

Exponential backoff (3 attempts)

Handle transient network failures

Timeout Handling

Default httpx timeout

Configurable per-tool timeouts (10s/30s/60s)

Prevent hanging on slow merchants

๐Ÿ›ก๏ธ Robustness (UCP Protocol Compliance)

Area

Current

Improvement

Why

Error Messages

Generic errors

UCP-compliant error codes + details

Merchants expect structured errors

Input Validation

Basic Pydantic

Field-level validators (URL format, price ranges)

Fail fast with clear messages

Rate Limiting

None

Client-side rate limiter (100 req/min)

Respect merchant limits

Graceful Degradation

Fail on first error

Partial results with warnings

Show what works, note what failed

๐Ÿ’ป Code Quality

Area

Current

Improvement

Why

Type Hints

Partial

Full typing with py.typed marker

Better IDE support, catch errors early

Docstrings

Minimal

Google-style docstrings on all public APIs

Auto-generate API docs

Logging

Print statements

Structured logging with structlog

Production observability

Config

Hardcoded defaults

Environment-based config (UCP_* env vars)

Deploy anywhere without code changes

Metrics

None

Prometheus metrics (request count, latency)

Monitor in production

๐Ÿงช Testing

Area

Current

Improvement

Why

Mock Fidelity

Static responses

Dynamic mocks from OpenAPI specs

Test against real merchant schemas

Property Tests

None

Hypothesis-based property testing

Find edge cases automatically

Load Testing

None

Locust scenarios for 100+ concurrent users

Verify production readiness

Contract Tests

None

UCP protocol compliance suite

Guarantee merchant compatibility

Configuration

All settings are configurable via environment variables:

Variable

Default

Description

UCP_TIMEOUT

30.0

HTTP request timeout in seconds

UCP_CONNECT_TIMEOUT

10.0

Connection timeout in seconds

UCP_MAX_CONCURRENT

10

Max concurrent HTTP connections

UCP_RATE_LIMIT

100

Max requests per second to merchants

UCP_MAX_RETRIES

3

Max retry attempts on failure

UCP_RETRY_BACKOFF_BASE

0.5

Base backoff time in seconds

UCP_RETRY_BACKOFF_MAX

10.0

Max backoff time in seconds

UCP_DISCOVERY_CACHE_TTL

300

Discovery cache TTL in seconds

UCP_LOG_LEVEL

INFO

Logging level

Example: Production Configuration

export UCP_TIMEOUT=60
export UCP_RATE_LIMIT=50
export UCP_MAX_RETRIES=5
export UCP_LOG_LEVEL=WARNING

Development

# Clone the repo
git clone https://github.com/nguthrie/ucp-mcp-server.git
cd ucp-mcp-server

# Install dependencies
uv sync --extra dev

# Run tests
uv run pytest -v

# Run integration tests (requires a live UCP server on port 8182)
uv run pytest -v -m integration --run-integration

End-to-end functional tests

The repository also ships with self-contained end-to-end scripts that start the sample UCP merchant and exercise the full shopping flow via the MCP stdio client.

# Run a single end-to-end flow against a freshly started sample merchant
uv run python scripts/test_mcp_e2e.py

# Run all built-in scenarios (single items, multiple items, discounts, out-of-stock, ...)
uv run python scripts/test_mcp_scenarios.py

# Use an already running merchant (e.g., on localhost:8182)
uv run python scripts/test_mcp_e2e.py --skip-merchant
uv run python scripts/test_mcp_scenarios.py --skip-merchant --merchant-url http://localhost:8182

# Generate a sample scenarios file to customize
uv run python scripts/test_mcp_scenarios.py --generate-sample scenarios.json

Project Structure

ucp-mcp-server/
โ”œโ”€โ”€ src/ucp_mcp_server/
โ”‚   โ”œโ”€โ”€ __init__.py        # Package version
โ”‚   โ”œโ”€โ”€ __main__.py        # python -m entry point
โ”‚   โ”œโ”€โ”€ server.py          # MCP server + tool definitions
โ”‚   โ”œโ”€โ”€ ucp_client.py      # HTTP client for UCP APIs
โ”‚   โ””โ”€โ”€ models.py          # Pydantic models for UCP data
โ””โ”€โ”€ tests/
    โ”œโ”€โ”€ conftest.py         # Test fixtures with mock UCP responses
    โ”œโ”€โ”€ test_discovery.py   # Discovery tool tests
    โ”œโ”€โ”€ test_products.py    # Product listing tests
    โ”œโ”€โ”€ test_product_search.py # Product search/filter tests
    โ”œโ”€โ”€ test_checkout.py    # Checkout tool tests
    โ”œโ”€โ”€ test_order.py       # Order tracking tool tests
    โ”œโ”€โ”€ test_errors.py      # Error handling tests
    โ”œโ”€โ”€ test_e2e_user_journey.py # End-to-end user journey tests
    โ””โ”€โ”€ test_integration.py # Live server integration tests

Architecture

System Overview

flowchart LR
    subgraph AI["AI Assistant"]
        A1[Claude / Cursor / MCP Client]
    end

    subgraph MCP["MCP Server Layer"]
        B1[FastMCP Server]
        B2[ucp_discover]
        B3[ucp_products_list]
        B4[ucp_products_search]
        B5[ucp_checkout_create]
        B6[ucp_checkout_update]
        B7[ucp_checkout_set_fulfillment]
        B8[ucp_checkout_complete]
        B9[ucp_order_get]
        B10[ucp_testing_simulate_shipping]
    end

    subgraph Client["HTTP Client Layer"]
        C1[UCPClient]
        C2[httpx AsyncClient]
    end

    subgraph Models["Data Models (Pydantic)"]
        D1[UCPDiscoveryResponse]
        D2[CheckoutSession]
        D3[LineItem]
        D4[PaymentHandler]
    end

    subgraph External["UCP Merchant API"]
        E1[/.well-known/ucp]
        E2[/checkout-sessions]
        E3[/checkout-sessions/:id/complete]
    end

    A1 -->|"MCP Protocol (stdio)"| B1
    B1 --> B2 & B3 & B4 & B5 & B6 & B7 & B8 & B9 & B10
    B2 & B3 & B4 & B5 & B6 & B7 & B8 & B9 & B10 --> C1
    C1 --> C2
    C2 -->|"HTTPS"| E1 & E2 & E3
    C1 --> D1 & D2 & D3 & D4

Layer

Package

Purpose

AI Assistant

External

MCP-compatible client (Claude, Cursor, etc.)

MCP Server

server.py

Tool definitions, input/output transformation

HTTP Client

ucp_client.py

Async HTTP calls to UCP merchant APIs

Data Models

models.py

Pydantic validation for requests/responses

UCP Merchant

External

Google UCP-compliant commerce server

Class Diagram

classDiagram
    class FastMCP {
        +tool() decorator
        +run(transport)
    }

    class UCPClient {
        -timeout: float
        -_client: AsyncClient
        +__aenter__()
        +__aexit__()
        +discover(merchant_url) UCPDiscoveryResponse
        +create_checkout(...) CheckoutSession
        +update_checkout(...) CheckoutSession
        +setup_fulfillment(...) dict
        +complete_checkout(...) CheckoutSession
        +get_checkout(...) dict
        +raw_update_checkout(...) dict
    }

    class UCPClientError {
        +message: str
    }

    class UCPDiscoveryResponse {
        +ucp_version: str
        +capabilities: list~UCPCapability~
        +payment_handlers: list~PaymentHandler~
    }

    class UCPCapability {
        +name: str
        +version: str
        +spec: str
    }

    class PaymentHandler {
        +id: str
        +name: str
        +version: str
        +config: dict
    }

    class CheckoutSession {
        +id: str
        +status: str
        +currency: str
        +line_items: list~LineItem~
        +totals: list~CheckoutTotals~
        +discounts: dict
        +order: OrderInfo
        +total: int
        +subtotal: int
        +discount_amount: int
    }

    class LineItem {
        +id: str
        +item: dict
        +quantity: int
        +totals: list
    }

    class CheckoutTotals {
        +type: str
        +amount: int
    }

    class DiscountApplied {
        +code: str
        +title: str
        +amount: int
        +automatic: bool
    }

    class OrderInfo {
        +id: str
        +permalink_url: str
    }

    FastMCP --> UCPClient : uses
    UCPClient --> UCPDiscoveryResponse : returns
    UCPClient --> CheckoutSession : returns
    UCPClient --> UCPClientError : throws
    UCPDiscoveryResponse *-- UCPCapability : contains
    UCPDiscoveryResponse *-- PaymentHandler : contains
    CheckoutSession *-- LineItem : contains
    CheckoutSession *-- CheckoutTotals : contains
    CheckoutSession *-- OrderInfo : contains
    LineItem --> CheckoutTotals : has

Shopping Flow (Sequence)

sequenceDiagram
    actor User
    participant AI as AI Assistant
    participant MCP as MCP Server
    participant Client as UCPClient
    participant Merchant as UCP Merchant

    User->>AI: "Buy 2 roses from flower shop"
    
    AI->>MCP: ucp_discover(merchant_url)
    MCP->>Client: discover()
    Client->>Merchant: GET /.well-known/ucp
    Merchant-->>Client: capabilities, handlers
    Client-->>MCP: UCPDiscoveryResponse
    MCP-->>AI: capabilities + payment_handlers
    AI-->>User: "Merchant supports checkout, Shop Pay"

    AI->>MCP: ucp_checkout_create(items, buyer)
    MCP->>Client: create_checkout()
    Client->>Merchant: POST /checkout-sessions
    Merchant-->>Client: CheckoutSession
    Client-->>MCP: CheckoutSession
    MCP-->>AI: checkout_id, total
    AI-->>User: "Cart ready: $35.00"

    AI->>MCP: ucp_checkout_update(discount_codes=["10OFF"])
    MCP->>Client: update_checkout()
    Client->>Merchant: PUT /checkout-sessions/:id
    Merchant-->>Client: CheckoutSession (updated)
    Client-->>MCP: CheckoutSession
    MCP-->>AI: total, discount_applied
    AI-->>User: "Applied 10OFF: $31.50"

    AI->>MCP: ucp_checkout_set_fulfillment()
    MCP->>Client: setup_fulfillment()
    Client->>Merchant: PUT /checkout-sessions/:id (3 steps)
    Merchant-->>Client: CheckoutSession
    Client-->>MCP: fulfillment details
    MCP-->>AI: shipping selected
    AI-->>User: "Shipping configured"

    AI->>MCP: ucp_checkout_complete(payment)
    MCP->>Client: complete_checkout()
    Client->>Merchant: POST /checkout-sessions/:id/complete
    Merchant-->>Client: Order confirmed
    Client-->>MCP: OrderInfo
    MCP-->>AI: order_id, order_url
    AI-->>User: "Order placed! ๐ŸŽ‰"

    User->>AI: "Has my order shipped?"
    AI->>MCP: ucp_order_get(order_id)
    MCP->>Client: get_order()
    Client->>Merchant: GET /orders/:id
    Merchant-->>Client: Order + fulfillment status
    Client-->>MCP: Order details
    MCP-->>AI: status, fulfillment
    AI-->>User: "Your order is still being prepared"

Roadmap

โœ… Completed

  • Merchant capability discovery (ucp_discover)

  • Product catalog listing (ucp_products_list)

  • Product search and filtering (ucp_products_search)

  • Checkout session creation (ucp_checkout_create)

  • Discount code application (ucp_checkout_update)

  • Fulfillment / shipping setup (ucp_checkout_set_fulfillment)

  • Purchase completion / payment submission (ucp_checkout_complete)

  • Order fulfillment tracking (ucp_order_get, ucp_testing_simulate_shipping)

  • End-to-end user journey tests

  • UCP protocol compliance tests

๐Ÿšง In Progress

  • Returns and exchanges

๐Ÿ“‹ Planned

  • Multi-merchant comparison shopping

  • Hosted managed version (so you don't have to self-host)

Resources

License

MIT

-
license - not tested
-
quality - not tested
B
maintenance

Maintenance

โ€“Maintainers
โ€“Response time
โ€“Release cycle
โ€“Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

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/aratan/ucp-mcp-server'

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