paypal-agent-store
Integrates with PayPal Orders v2 and the PayPal Agent Toolkit (sandbox only) to let AI agents create and track orders, request refunds, and open disputes within buyer-defined spending mandates. Buyer approval in PayPal is required for every charge, while merchant-side Toolkit tools can list disputes, issue refunds, and accept claims.
Click on "Deploy 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., "@paypal-agent-storesearch the tea shop for sencha and order one within my budget"
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.
paypal-agent-store (Leafline)
Status: prototype, PayPal sandbox only, not audited. Not a product.
Live demo (sandbox): https://leafline-agent-store.onrender.com - store /, merchant panel /merchant, MCP
endpoint POST /mcp. Free Render instance: the first request after ~15 idle minutes takes up to a minute, and the
order book resets to the seeded sandbox orders on every restart.
An agent-ready storefront: a small tea shop on PayPal Orders v2 that lets AI agents shop for a buyer inside a spending mandate the buyer sets, while every payment is still approved by the buyer in PayPal.
Six agent tools —
search_products,get_budget,create_order,get_order_status,request_refund,open_dispute— defined once (web/webmcp.js) and offered two ways:WebMCP in the page (
document.modelContext), used by the in-page agent and browser agents;MCP for external agents: stdio (
src/mcp-stdio.ts) and Streamable HTTP atPOST /mcp(src/mcp.ts).
Spending mandates (budget, per-order cap, categories, expiry, revoke) are enforced by the store server on every agent order, before a PayPal order exists; refusals come back as
OVER_BUDGET,OVER_PER_ORDER,CATEGORY_NOT_ALLOWED,EXPIRED,REVOKED,NOT_FOUND.Agent receipt: every agent tool call is journaled per session and linked to the order it produced.
Merchant side on the PayPal Agent Toolkit (
@paypal/agent-toolkit1.11.0,src/toolkit.ts): order status (get_order), PayPal disputes (list_disputes,get_dispute,accept_dispute_claim), refunds (create_refund,get_refund). Post-purchase claims go to a DisputeDesk module that cites the agent journal as evidence; the merchant refunds or accepts the dispute from the panel (AG Grid Community tables).Merchant analytics on AG Studio 3.0 (
web/analytics.js): a pre-built report over the store's own records (orders, order lines, agent call journal, DisputeDesk cases, joined by order id) - agent vs human revenue, refused agent calls by tool, claim value by DisputeDesk advice - with cross-filtering and an "Edit layout" switch to Studio's drag-and-drop editor.The dashboard is agent-readable too (
web/studio_webmcp.js): AG Studio's AI module (Studio Agent Framework) toolsview_schema,view_page,view_widget,execute_queryare published over WebMCP as read-onlydashboard_*tools, so an agent in the merchant's browser can query the analytics ("allowed vs refused agent calls by tool") instead of scraping charts. Mutating Studio tools are not exposed.
Run
npm install
npm test # unit + HTTP + MCP-client tests, no network
scripts/with-sandbox-env.sh node src/server.ts # http://localhost:8787 (store, /order, /merchant, /mcp)
scripts/with-sandbox-env.sh node scripts/toolkit_smoke.ts # live Toolkit check (read-only)
scripts/with-sandbox-env.sh python scripts/e2e_browser.py --flags # full browser E2E against the running store
node scripts/reset_demo_data.ts [--apply] [--wipe] [--export-seed demo/seed] # clean test orders (store stopped)
python scripts/render_deploy.py # deploy the public demo, check live version == HEADEnvironment (all optional except the PayPal pair): PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET (sandbox app),
MERCHANT_KEY (signs merchant actions), PUBLIC_MERCHANT_VIEW=1 (demo: panel readable without the key),
AG_STUDIO_LICENSE_KEY (AG Studio trial key; without it Studio shows a watermark), GEMINI_API_KEY (one or
more comma-separated keys), MISTRAL_API_KEY, DATA_DIR, DEMO_SEED_DIR, LLM_STEPS_PER_10MIN,
WRITES_PER_10MIN. scripts/with-sandbox-env.sh fills them from a secrets file outside the repo.
Connect an external agent (the buyer first delegates a budget on the store page and copies the mandate id):
# Streamable HTTP
npx @modelcontextprotocol/inspector --cli http://localhost:8787/mcp --header "X-Agent-Mandate: md_..." --method tools/list
# stdio (e.g. Claude Desktop / Claude Code config: command node, args [src/mcp-stdio.ts])
STORE_URL=http://localhost:8787 STORE_MANDATE=md_... node src/mcp-stdio.ts
# minimal SDK client used by the E2E
node scripts/mcp_client.ts --url http://localhost:8787 --mandate md_... call create_order '{"items":[{"sku":"TEA-SENCHA-80","quantity":1}]}'Related MCP server: dukaan-agent
Threat model (what is and is not enforced)
An agent is identified by its own headers. WebMCP tools and the MCP server send
X-Agent-Tool,X-Agent-Sessionand (when delegated)X-Agent-Mandate. A request with only some of them is refused (400). An agent that sends none of them is indistinguishable from a human visitor: it gets no mandate, no journal, and the human checkout. The store cannot prove who is calling; mandates bound well-behaved agents and anything that holds a mandate id.Every charge is approved by the buyer. An agent can create an order but cannot pay: the buyer approves in PayPal (popup or
approveUrl), and only the merchant server captures. That approval, not the headers, is the real limit on money leaving the buyer.A mandate id is a bearer capability (
md_+ 64 random bits) for spending up to its limits. Whoever has it can create orders inside it; each still needs buyer approval. The buyer can revoke it at any time.Prices come from the server catalog; agents send only
sku+quantity.Merchant actions (refund, decline, accept dispute) refuse agent headers and require
X-Merchant-KeywhenMERCHANT_KEYis set (constant-time check). Merchant views (all buyers' orders, journal, cases, Toolkit log) refuse agent headers and also need the key, except on the public demo (PUBLIC_MERCHANT_VIEW=1), where they are readable so the panel can be judged - all data there is sandbox data with masked payer emails. The panel takes the key from a#key=URL fragment (never sent to the server) or a form, keeps it insessionStorage.Dashboard WebMCP tools are read-only (
readOnlyHint) and see only what the panel shows. Any agent the merchant runs in that browser tab can read the analytics; none can change the report or touch money.Rate limits behind the proxy: the client IP comes from
CF-Connecting-IP(Render is behind Cloudflare) before the client-controlledX-Forwarded-For; on top of per-IP limits there are whole-server ceilings for LLM steps and writes, so spoofed IPs cannot burn the free LLM quotas or flood the sandbox.AG Studio licence key is a front-end key by design (it ends up in the page); it is injected from env via
/api/configand never committed. The trial keys expire on 12.11.2026 (Grid/Charts) and 16.11.2026 (Studio); after that the live demo shows AG's watermark until a new key is set.PayPal Agent Toolkit 1.11.0 guards (found in its source):
run()/handleToolCallexecute any tool name regardless of the configured actions, so the server enforces its own allow-list of six tools beforerun(); the Toolkit caches its OAuth token forever, so we pass our own refreshed token; refund idempotency needs a per-callrequest_id(PayPal-Request-Id), so each refund gets its own Toolkit instance; Toolkit errors come back as JSON strings and are turned into exceptions. Order creation and capture stay on our own Orders v2 client because the Toolkit'screate_orderhas nocustom_id/ itemsku(the order could not carry the agent session and mandate) and itspay_ordersends no PayPal-Request-Id.Sandbox is enforced in code (
assertSandbox, Toolkit host check); credentials come from env only.Known dependency advisories:
npm auditreports transitive issues through the Toolkit's dependencies (@langchain/core,ai,mathjs,jsondiffpatch,uuid). We import only@paypal/agent-toolkit/mcpand never pass buyer or agent input to the Toolkit's order builder (themathjspath).
Verified
16.10.2026, public Render deployment (version checked against the commit), Chrome 155 with the WebMCP flag:
scripts/e2e_browser.py --url https://leafline-agent-store.onrender.com --flags18/18, twice - the 15 steps below plus the AG Studio dashboard: licensed render, fourdashboard_*tools registered in native WebMCP, anddashboard_execute_queryanswering allowed vs refused agent calls by tool. Second run with the LLM planner (Gemini 3 Flash); the first fell back to rules (free-tier quota), which led to the multi-key chain.Merchant key on: the same claims flow with
MERCHANT_KEYset passes 8/8 (panel sendsX-Merchant-Key).Unit, HTTP and MCP-client tests: 79/79 (
npm test), including the official MCP SDK client over Streamable HTTP and over stdio (child process): order inside the mandate; over-budget, per-order, category, revoked and no-mandate refusals.Live sandbox, 16.10.2026, Chrome 155 with the WebMCP flag,
scripts/e2e_browser.py: 15/15, twice — human checkout through the JS SDK v6 popup; in-page agent (run 1: Gemini planner; run 2: the free-tier LLM was unavailable and the rule-based planner took over, as designed) orders via WebMCP inside a 40 USD mandate, buyer approves, COMPLETED; over-budget refused; claim -> DisputeDesk case with agent evidence -> refund through the Toolkit'screate_refund(COMPLETED); external MCP agent orders via/mcpinside a 20 USD mandate, buyer approves theapproveUrlin PayPal, COMPLETED; its over-budget order refused (OVER_BUDGET).MCP Inspector CLI 2.11.0 (independent client) against
/mcp:tools/listreturns the six tools,create_ordercreates a sandbox PayPal order inside a 12 USD mandate, the second one is refusedOVER_BUDGET.Known sandbox flakiness, handled and printed as
NOTEby the E2E script, never hidden: the popup sometimes shows "Things don't appear to be working" (one "Try again" fixes it), and about 1 in 10 page loads the SDK opens no window on click (a reload fixes it). Accounts created with country BY could not complete payments; US sandbox accounts are used.
WebMCP (verified 2026-10-16, Chrome 155): native API is document.modelContext and only exists with
--enable-features=WebMCP,WebMCPTesting (chrome://flags/#enable-webmcp-testing). Without the flag the
MCP-B polyfill (@mcp-b/global, MIT) provides the same surface.
Reviews
Independent code review by Google Jules (sessions 1877010590083434047, 11669279245805133758, 4709167192530215068).
From 4709167192530215068, all taken: PayPal REST error bodies recognised as Toolkit errors, a refund without a
refund id is an error (claim stays open), /mcp transport closed once on every path, Toolkit log merchant-only.
Earlier, taken: fail-closed
agent detection, single in-flight capture per order and refund per claim, server-side tool descriptions for the
LLM step, tool_call_id validation, key stripping in LLM error bodies, escaping in notice(), control-character
cleanup in evidence. Not taken: replacing journal snapshots in evidence with the current catalog (evidence must
show what the agent saw at the time).
License: MIT.
This server cannot be deployed
Maintenance
Related MCP Connectors
Agentic Commerce Protocol sandbox: agent builds a cart, human approves a real PayPal payment.
Pink Agentic AI Payments: AI agents pay within spending rules (budgets, caps, approval). Sandbox.
Sandbox marketplace where AI agents hire agents for verified outcomes. Test money only.
Agent-to-business commerce sandbox: intents, offers, bookings. Demo data, ed25519-signed calls.
Related MCP Servers
- 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.-
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to search a merchant's product catalog and complete UPI checkouts via Razorpay test-mode APIs, with spend mandates and full audit logging.MIT
- FlicenseNot gradedqualityBmaintenanceEnables AI agents to securely search products, obtain signed quotes, create checkouts, and track orders without directly handling prices or payment amounts, enforcing spending policies and audit trails.1-
- AlicenseNot gradedqualityBmaintenanceEnables AI buyer agents to search an agent-ready storefront, receive structured margin-aware quotes, pass deterministic guardrails, and create Razorpay Test Mode payment orders without a human checkout flow.1MIT