agent_commerce
Enables payment processing through Razorpay, including creating payment orders, capturing payments, verifying webhooks, and reconciling payment state in test mode.
Provides access to a Shopify merchant's commerce capabilities, including catalog search, cart creation, checkout via draft orders, and order management through the Shopify Admin GraphQL API.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@agent_commerceFind me a blue jacket under $50 and add it to my cart."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Agent Commerce SDK
Install our SDK on a Shopify merchant, connect Razorpay, and expose the merchant's commerce capabilities through MCP so AI agents can shop and transact on behalf of users under explicit authorization and policy.
This is a control plane, not another storefront, chatbot, or payment gateway.
Shopify remains the system of record for commerce; Razorpay remains the
system of record for payments. This SDK owns orchestration, identity,
delegated authorization, deterministic policy, approval, reconciliation, and
audit — see docs/ARCHITECTURE.md for the full design and the boundaries
between what Shopify/Razorpay/our SDK each own.
Architecture
AI AGENT (Local, or any external MCP client)
|
v
UNIFIED MCP SERVER (/mcp -- official `mcp` SDK, streamable-HTTP)
|
v
mcp.tools.execute_tool <-- the single dispatch choke point
|
v
AGENT COMMERCE SDK (sdk/agent_commerce/)
commerce/ identity/ policy/ audit/ security/
| |
v v
shopify/ (ShopifyPort) razorpay/ (RazorpayPort)
| |
v v
Shopify commerce state Razorpay payment stateFull component/data-flow diagrams, the database ERD, the Shopify/Razorpay
integration boundaries, and every ambiguity resolved during the build are in
docs/ARCHITECTURE.md. The REST API contract both the
backend and the dashboard build against is in
docs/API_CONTRACT.md.
Related MCP server: Commerce MCP Server
Repository layout
sdk/agent_commerce/ the SDK -- all business logic lives here
core/ shared types, errors, Protocols (ShopifyPort/RazorpayPort)
shopify/ Admin API GraphQL client, webhooks, demo-mode fallback
razorpay/ orders, payments, verification, webhooks, reconciliation
identity/ users, agents, delegated grants, scopes
policy/ deterministic rules, evaluator, versioning
commerce/ catalog, cart, checkout, orders, fingerprinting
agent/ Ollama qwen2.5:7b bounded tool-calling loop
mcp/ the unified MCP server + tool dispatcher
audit/ append-only ledger + evidence-backed decision records
security/ input validation, idempotency, signatures, encryption
client.py the `AgentCommerce` SDK facade (see below)
api/app/ FastAPI REST routes + app wiring; mounts the MCP server
frontend/ Next.js merchant dashboard
tests/ unit, security, shopify, razorpay, ai, e2e, mcp, integration
scripts/ seed_demo.pyPrerequisites
Python 3.12+
PostgreSQL (via Docker Compose, or your own instance)
Ollama, running locally, with
qwen2.5:7bpulled:ollama pull qwen2.5:7bThe application never substitutes another model —
OLLAMA_MODELis hard-validated to equal exactlyqwen2.5:7bat startup.Node 20+ (for the dashboard)
A Razorpay account in TEST MODE for real payment testing (optional — see "Running without credentials" below)
A Shopify development store for real catalog/order testing (optional — see below)
1. Install the SDK
python -m venv .venv
# Windows: .venv\Scripts\activate macOS/Linux: source .venv/bin/activate
pip install -e ./sdk
pip install -r api/requirements.txt
pip install -r requirements-dev.txt # adds pytest, ruff for development2. Configure environment variables
cp .env.example .envFill in what you have; the application runs with partial configuration (see "Running without credentials"). Key variables:
Variable | Required for | Notes |
| everything | defaults to local Postgres |
| dashboard sessions, credential encryption | set a real random value outside development |
| the agent runtime | model must be exactly |
| real Shopify catalog/orders | the app mints + refreshes its own token; see step 4 |
| real payments | test mode only — see step 5 |
3. Start Postgres and run migrations
docker compose up -d postgres
alembic upgrade head4. Connect a Shopify store (optional)
Without this step, the SDK runs against a dynamically generated demo catalog
(shopify/demo_data.py) so the full search → cart → checkout → policy →
approval flow is usable immediately. Real Shopify activates automatically the
moment credentials are set — nothing else changes.
To connect a real development store:
In the Shopify Dev Dashboard, create an app (custom-app creation moved out of store admin in 2026).
Grant Admin API scopes:
read_products,read_inventory,read_orders,write_draft_orders,read_customers— pluswrite_discountsandwrite_ordersif you want the growth agent's campaigns and synthetic seeding. Scopes take effect only once you release a version and the store approves it.Install the app on your store.
Set
SHOPIFY_SHOP_DOMAIN(e.g.your-store.myshopify.com) plusSHOPIFY_CLIENT_IDandSHOPIFY_CLIENT_SECRETin.env. LeaveSHOPIFY_ACCESS_TOKENempty — see below.Sync the catalog via the dashboard's onboarding flow, or
POST /api/merchants/{id}/shopify/sync.
You do not paste an access token. Shopify stopped issuing non-expiring
tokens for custom apps in January 2026 — every token now lasts about 24 hours,
so a pasted one dies overnight (it surfaces as a 401 mid-session). Instead the
app mints its own from SHOPIFY_CLIENT_ID/SHOPIFY_CLIENT_SECRET via the
client-credentials grant, caches it in-process, refreshes it five minutes
before expiry, and re-mints once automatically if a request is rejected with a
401 — see sdk/agent_commerce/shopify/tokens.py. Setting
SHOPIFY_ACCESS_TOKEN still works and takes precedence, but a pinned token is
never refreshed.
One prerequisite worth knowing: the client-credentials grant only works when the app and the store belong to the same Shopify organization (a store created from the Dev Dashboard's Dev stores page). A store created from Shopify admin sits outside the org and the grant is refused regardless of how correct the credentials are.
The SDK uses Shopify's GraphQL Admin API exclusively — never storefront HTML
scraping. Checkout is built on Shopify Draft Orders (not Storefront
Cart/Checkout), since payment capture happens through Razorpay rather than
Shopify's native checkout; see docs/ARCHITECTURE.md for why.
5. Connect Razorpay Test Mode (optional)
Without this, every read/browse/cart/checkout/policy/approval tool call still
works — only complete_checkout (the one tool that moves money) fails with a
clear "Razorpay Test Mode integration is ready to wire" message rather than
faking a payment result. Money movement is never simulated.
Razorpay Dashboard → Settings → API Keys, generate a Test Mode key pair.
Set
RAZORPAY_KEY_IDandRAZORPAY_KEY_SECRETin.env.For webhook-driven payment reconciliation, add a webhook endpoint pointing at
POST /api/webhooks/razorpaysubscribed topayment.capturedandpayment.failed, and setRAZORPAY_WEBHOOK_SECRETfrom the webhook configuration.
Never use live/production Razorpay credentials with this project.
6. Start the backend
python run_api.py --reloadThis serves the REST API under /api/* and mounts the unified MCP server at
/mcp in the same process (see api/app/main.py for how the two ASGI apps'
lifespans are combined).
Use run_api.py, not uvicorn directly — especially on Windows. psycopg's
async mode cannot run on Windows' ProactorEventLoop, and uvicorn hardcodes
that loop on win32 via an explicit loop_factory, which bypasses the asyncio
event-loop policy entirely (so setting the policy has no effect). run_api.py
passes a SelectorEventLoop factory through uvicorn's supported loop= hook.
Running uvicorn api.app.main:app directly on Windows starts fine but fails
every database request with
InterfaceError: Psycopg cannot use the 'ProactorEventLoop'.
Verify it's up:
curl http://localhost:8000/api/healthInteractive API docs: http://localhost:8000/docs
7. Start the dashboard
cd frontend
npm install
npm run devVisit http://localhost:3000. The onboarding flow walks through connecting
Shopify, connecting Razorpay, configuring policy, and confirming MCP is live.
8. Connect an MCP-compatible agent
Fastest path — one command creates a user, merchant, policy, agent, and grant, syncs the catalog, and prints a ready-to-use bearer token:
python scripts/seed_demo.py(Or do the same through the dashboard's onboarding flow.) Then point any MCP client (Claude Desktop, a custom client, etc.) at:
http://localhost:8000/mcp
Authorization: Bearer <session token from the grant>The token is shown exactly once — only its SHA-256 hash is stored.
9. Perform a test transaction
With the dashboard's chat interface (backed by agent/runtime.py and real
Ollama inference) or any connected MCP client:
"Find me a black hoodie under ₹2,000."
-> search_catalog (real Shopify or demo catalog)
"Choose the best one."
-> agent selects from actual returned products
"Buy it."
-> create_cart -> create_checkout -> policy evaluation
-> ALLOW: proceeds automatically
-> REQUIRES_APPROVAL: approve via the dashboard's Purchase Approval screen
-> complete_checkout -> real Razorpay order (test mode) -> webhook -> reconciliationRunning without credentials
Per the project's design, missing external credentials never block development:
No Shopify credentials →
shopify/demo_data.pyprovides a dynamically generated (Faker-backed, never hardcoded) catalog satisfying the exact sameShopifyPortinterface the real client does.No Razorpay credentials → every tool up through
request_purchase_approvalworks;complete_checkoutraises a clear, actionable configuration error instead of faking success.
Accounts: admin and customer
Two roles share one login form. The role is a property of the stored account, decided at registration — it is never sent in a request body or picked on the login screen, because a self-selected role would be a bypassable boundary.
The first account to register becomes the admin. They connect Shopify and Razorpay, register agents, edit policy, and see Transactions/Audit.
Every account after that is a customer. They get their own spending policy (inherited from the admin's active policy), and can chat with an agent an admin has assigned to them, approving their own purchases.
Assigning is one click: Agents → Assign customer. Mechanically it issues an
AgentGrant whose user_id is the customer, which is what that column already
means — identity/grants.py:resolve_request_context sets
RequestContext.user_id = grant.user_id, so the customer's carts, checkouts,
approvals, and daily-spend tracking are all their own. One agent can therefore
serve many customers, each isolated from the others by the same
require_ownership checks that protect any two users.
Enforcement lives in api/app/deps.py:current_admin (403 for a customer), not in
the UI — hiding a nav item is presentation, not security.
Customers are also mirrored into Shopify as Customer records. That needs the
write_customers scope and protected-customer-data approval on your app; if
Shopify refuses, registration logs a warning and continues, and the local
customer works fully regardless.
Security model
The LLM never authorizes payment. Qwen2.5:7B selects tools and explains results; it never computes prices, evaluates policy, or resolves identity. Every tool call is treated as untrusted input.
Deterministic policy engine.
policy/evaluator.pyis pure, rule-based logic (scope → inventory → category → max transaction → daily limit → approval threshold). No LLM involvement, ever.Checkout fingerprinting. Every checkout is hashed from its trusted commerce facts (merchant, currency, total, line items). An approval is bound to that exact fingerprint; if it changes before payment (e.g. a price change), the approval is invalidated and a new one is required.
Ownership enforcement. Every resource load checks
identity/grants.py:require_ownership— one user's agent cannot read or mutate another user's cart, checkout, or order.Explicit tool allowlist.
security/validation.pydefines a strict Pydantic schema per tool (extra="forbid"); there is no raw GraphQL, raw SQL, or arbitrary HTTP passthrough anywhere in the tool surface.Prompt-injection resistance. Product descriptions/tags are treated as untrusted data; the agent's system prompt explicitly instructs it never to follow instructions embedded in tool output. See
tests/security/.Idempotency everywhere it matters. Webhook processing, payment execution, and approval creation are all deduplicated via
security/idempotency.pyso a retried request with the same key replays its prior result rather than double-charging, double-creating, or double-applying state. Reusing a key with a different payload raises a conflict instead of silently applying the new payload.Signed webhooks only. Shopify (
X-Shopify-Hmac-Sha256, base64) and Razorpay (X-Razorpay-Signature, hex) webhooks are verified via HMAC-SHA256 before any processing; an invalid or missing signature is rejected.
Full details, including the exact evidence-backed Decision Record format and
the audit event schema, are in docs/ARCHITECTURE.md.
MCP tools
Exposed by the unified MCP server — the agent never talks to Shopify or Razorpay directly.
Tool | Risk | Scope |
| READ |
|
| READ | various |
| LOW_WRITE |
|
| MONEY / LOW_WRITE |
|
| MONEY |
|
| MONEY |
|
| READ |
|
| MONEY |
|
Read-only MCP resources (resources/read): merchant://catalog,
merchant://policies, user://orders/{id}, checkout://{id},
transaction://{id}.
Connecting Claude / ChatGPT
The /mcp endpoint is a standard streamable-HTTP MCP server, so Claude
Desktop, Claude Code, ChatGPT (Developer Mode, paid plan) and any other MCP
client can drive the full user-side surface: browse, cart, checkout, request
approval, pay via Razorpay, read orders and the audit timeline. Setup steps
per client — including the ngrok tunnel ChatGPT needs, since it cannot reach
localhost — are in docs/MCP_CLIENTS.md.
approval:decide is the one scope to think about before granting. It lets a
client approve its own pending purchase from inside the chat instead of the
dashboard — convenient for an agent you drive personally, but it means the
agent that proposed a purchase can approve it, turning the approval threshold
into a speed bump rather than a two-party gate. It is in no default scope set,
and POST /api/agents/{id}/assign refuses it outright so an agent assigned to
a customer can never hold it. Ownership, stale-price invalidation, and an
audit record marked source="mcp" all still apply when it is granted.
Merchant companion agent (growth/revenue insights for admins)
A second agent persona, admin-facing rather than shopper-facing: it reads a
merchant's real Shopify order/customer data, surfaces growth insights (e.g.
"revenue is up 12% this month, largely from N repeat customers"), and can
propose campaigns like a loyalty discount for repeat buyers — but a proposed
campaign only takes effect on Shopify after an admin approves it on the
dashboard. Built on the same MCP-tool/scope architecture as the shopper
agent, so it's pluggable the same way: create one via
POST /api/agents {"kind": "merchant_companion"}, issue it a grant with
analytics:read/campaign:write/data:seed_write scopes, then chat with it
through the same /api/chat/{agent_id} endpoint used for shopping.
Tool | Risk | Scope |
| READ |
|
| LOW_WRITE (drafts only — never touches Shopify) |
|
| HIGH_WRITE (creates a real discount code) |
|
| HIGH_WRITE |
|
These scopes are disjoint from the shopper scopes above: a shopper-scoped
grant can never call a growth tool, and a growth-scoped grant can never move
money. Full flow (insights → propose → admin approves → launch → metrics
snapshot) and the campaign state machine are in docs/ARCHITECTURE.md
"Merchant companion agent"; the REST surface is in docs/API_CONTRACT.md
"Growth & Campaigns".
Example: using the SDK directly
from agent_commerce import AgentCommerce
commerce = AgentCommerce(session=session, shopify=shopify, razorpay=razorpay, ctx=ctx)
products = await commerce.catalog.search(query="hoodie", max_price=Decimal("2000"))
cart = await commerce.cart.create(lines=[{"variant_id": "...", "quantity": 1}])
checkout = await commerce.checkout.create(cart_id=cart["cart_id"])
if checkout["next_step"] == "request_purchase_approval":
await commerce.checkout.request_approval(checkout["checkout_id"])
# ... user approves via the dashboard ...
payment = await commerce.checkout.complete(checkout["checkout_id"])Both this facade and the MCP transport route through the identical
mcp.tools.execute_tool dispatcher — business logic exists in exactly one
place.
Testing
pytest tests/unit tests/security # fast, no external dependencies
pytest tests/mcp # MCP protocol conformance (tools/call, resources/read)
pytest tests/razorpay # real Razorpay test-mode API (needs credentials)
pytest tests/shopify # real Shopify Admin API (needs credentials; skips cleanly without)
pytest tests/ai tests/e2e # real Ollama qwen2.5:7b inference, no mocking (slower)tests/ai/test_real_ollama.py and tests/e2e/test_real_agent_shopify_flow.py
never mock the LLM, the policy engine, or the commerce layer — they exercise
real inference against a real (demo or seeded) catalog and real PostgreSQL,
per the project's testing philosophy: prefer real integrations over mocked
demonstrations. tests/shopify/ and tests/integration/ are reserved for
real-Shopify-credential coverage and cross-module integration tests
respectively — currently unpopulated (no test files yet).
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Agentic commerce gateway: discovery, search, checkout across Shopify/Woo/Odoo/PrestaShop.
Policy review and purchase discovery for AI-agent commerce actions.
Shopify product discovery and x402-paid offer verification for AI agents.
Security gateway for AI agents: policy, approval, and audited execution, no secrets shared.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI agents to autonomously browse inventory, negotiate terms, manage carts, and execute secure payments on Shopify stores using standardized protocols. It provides a bridge for LLMs to handle the entire commerce lifecycle from discovery to order tracking through a verifiable mandate chain.52MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to browse product catalogs, search products with filters, and initiate checkouts, generating order summaries and checkout URLs.
- FlicenseNot gradedqualityBmaintenanceEnables AI agents to browse product catalogs and make purchases through a policy engine that enforces spending limits, requires human approval for certain amounts, and logs all actions to an audit trail.
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to browse a merchant catalog and place Razorpay test-mode orders with budget gating, persistent monthly limits, and full audit trails.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/PR-HARIHARAN/agent_commerce'
If you have feedback or need assistance with the MCP directory API, please join our Discord server