How to Build an AI Shopping Agent That Searches Amazon and Pays With Stripe Link

A step-by-step guide to an AI shopping agent built as a remote MCP server, with SerpApi for Amazon search and Stripe Link for a one-time virtual card.

S
StartupHub.ai Staff
9 min read
How to Build an AI Shopping Agent That Searches Amazon and Pays With Stripe Link
Contents(9)

You build an AI shopping agent that takes "find me a 24,000 mAh power bank under $40", searches Amazon, picks one, and asks for a card that only works once for that amount after the customer approves on their phone.

Link agent payments work for customers in the United States and Canada while the developer and the merchant can be anywhere. A single spend request is capped at $500 and the virtual card is valid for 12 hours from creation. The whole thing is roughly 200 lines of TypeScript and a template repo is linked below.

Get the template repo Stripe Link CLI

What you need

  • Use Node.js 20 or newer.
  • Use a SerpApi account. The free plan gives 250 searches a month and the Starter plan is $25 a month for 1,000 searches. See SerpApi pricing.
  • Use a Link account in the United States or Canada with a card saved, because that account approves and pays.
  • Install the Stripe Link CLI as @stripe/link-cli. See stripe/link-cli on GitHub.
  • Use a coding agent such as Claude Code, Cursor or Codex to do the typing.
  • Host the small Node service somewhere public, because custom connectors are called from Anthropic's cloud and cannot reach localhost.

Step 1: Clone the template and brief your coding agent

git clone https://github.com/dansinger93/shopping-agent-mcp.git
cd shopping-agent-mcp
npm install
cp .env.example .env     # SERPAPI_KEY, MCP_BEARER_TOKEN

The template is at the template repo and holds three files that matter. src/serpapi.ts handles search and src/link.ts wraps the Link CLI while src/server.ts exposes both as MCP tools. Paste CLAUDE.md into your coding agent as the brief. It lists the tools and the two environment variables SERPAPI_KEY and MCP_BEARER_TOKEN, and it states the one rule that matters: card details never enter the model context.

Step 2: Search Amazon with SerpApi

// src/serpapi.ts
export async function searchAmazon(query: string, domain = 'amazon.com') {
  const url = new URL('https://serpapi.com/search');
  url.search = new URLSearchParams({
    engine: 'amazon',
    k: query,
    amazon_domain: domain,
    s: 'review-rank',
    api_key: process.env.SERPAPI_KEY!,
  }).toString();

  const { organic_results = [] } = await (await fetch(url)).json();
  return organic_results
    .filter((r: any) => !r.sponsored)
    .slice(0, 8)
    .map((r: any) => ({
      title: r.title,
      asin: r.asin,
      url: r.link_clean,          // https://www.amazon.com/dp/{ASIN}/
      price: r.extracted_price,   // number; r.price is the display string
      rating: r.rating,
      reviews: r.reviews,
    }));
}

The SerpApi Amazon Search API is a GET request with engine=amazon and k as the query. The amazon_domain parameter selects the store and defaults to amazon.com, and s=review-rank sorts by reviews. The code uses title, asin, link_clean, extracted_price, rating and reviews. link_clean is the plain https://www.amazon.com/dp/{ASIN}/ URL and the link field can be a sponsored redirect. extracted_price is a number and price is the display string. The code drops sponsored results and keeps eight, which is enough for the model to choose from without burning context. One search is one SerpApi credit.

Step 3: Pay with a one-time Stripe Link card

The agent does not hold a card. It creates a spend request with an amount, a merchant and a plain-English reason. The customer gets it in the Link app or on link.com and taps approve, and Link hands back a one-time virtual card for exactly that purchase. The customer's real card or bank number is never exposed to the agent or the merchant. Login is a device-style flow where link-cli auth login prints a verification URL and a short phrase and the customer confirms in their Link account. The wallet supports three credential types: virtual card as the default, Link Pay Token for Stripe-powered checkouts and shared payment token for machine payments.

npm install -g @stripe/link-cli
link-cli auth login --client-name "Shopping agent"
link-cli auth status
link-cli spend-request create \
  --test \
  --amount 3499 \
  --merchant-name "Amazon" \
  --merchant-url "https://www.amazon.com/dp/B0EXAMPLE/" \
  --context "Buying the Anker 737 power bank on amazon.com for \$34.99. The customer asked the shopping agent to find the best-reviewed 24,000 mAh power bank under \$40 and picked this one." \
  --line-item "name:Anker 737 power bank,unit_amount:3499,quantity:1" \
  --total "type:total,display_text:Total,amount:3499" \
  --format json
# blocks until the customer taps Approve in the Link app, polling every 2 seconds
link-cli spend-request retrieve lsrq_abc123 --interval 2 --max-attempts 300

# write the card to a 0600 file; stdout only shows brand, last4 and expiry
link-cli spend-request retrieve lsrq_abc123 \
  --include card --output-file /tmp/link-card.json --format json

--amount takes the smallest currency unit so 3499 means $34.99. --context must be at least 100 characters and that text is shown to the customer at approval. Describe what is being bought, where the purchase will happen and why it is needed. --merchant-name and --merchant-url are required for a virtual card. Add --test while you build and you get test credentials such as 4000009990001984 with no charge to the payment method, then remove the flag when you are ready for a real charge. Approval is requested by default and the customer has 30 minutes to respond before the request expires. The request moves through statuses such as created, pending_approval, requires_action, approved, submitted, succeeded, failed, denied, expired and canceled.

If you retrieve with --include card and omit --output-file, the PAN, CVC and billing address are written to stdout where a hosted agent will log the output and the model can read it. Use --output-file instead and the card is written to disk with 0600 permissions while stdout shows only the brand, last4, expiry and the file path, so the checkout code can read the file without exposing secrets. The virtual card cannot be used twice and it remains valid for 12 hours.

Step 4: Wrap both as a remote MCP server

// src/server.ts (trimmed; the repo has the full file)
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { z } from 'zod';
import { searchAmazon } from './serpapi.js';
import { createSpendRequest, pollSpendRequest } from './link.js';

const server = new McpServer({ name: 'shopping-agent', version: '1.0.0' });

server.tool('search_products', { query: z.string(), domain: z.string().optional() },
  async ({ query, domain }) => ({ content: [{ type: 'text', text: JSON.stringify(await searchAmazon(query, domain)) }] }));

server.tool('request_payment', {
  amount_cents: z.number().int().max(50000),
  merchant_url: z.string().url(),
  item_name: z.string(),
  context: z.string().min(100),
}, async (args) => ({ content: [{ type: 'text', text: JSON.stringify(await createSpendRequest(args)) }] }));

server.tool('check_payment', { id: z.string() },
  async ({ id }) => ({ content: [{ type: 'text', text: JSON.stringify(await pollSpendRequest(id)) }] }));
npm run build
npm start            # http://0.0.0.0:3333/mcp, Bearer token from MCP_BEARER_TOKEN

The MCP server exposes three core tools: search_products, request_payment and check_payment. request_payment shells out to link-cli and returns the spend request id and the approval_url and never a card, while check_payment returns the status. The transport is Streamable HTTP on /mcp behind a Bearer token read from MCP_BEARER_TOKEN, which is what Claude's connector settings will send as a request header. Deploy it anywhere that runs Node and gives you an https URL and run link-cli auth login once on that machine so the token store lives there.

Step 5: Add it to Claude as a custom connector

  1. Open Customize, then Connectors to manage custom connectors.
  2. Click + Add, then Add custom connector.
  3. Enter a name and the server URL ending in /mcp and continue.
  4. Under Authentication choose No sign in.
  5. Under Request headers add Authorization with the value Bearer and your MCP_BEARER_TOKEN.
  6. Click Add.
  7. In a chat press +, choose Connectors and turn it on.
  8. Connections originate from Anthropic's cloud across claude.ai, Claude Desktop, Cowork and the mobile apps so the same connector is there on the phone and the Free plan allows one custom connector.

The checkout is still a browser

Amazon has no public API that accepts a card, so the last step is the agent filling the card number, cvc, exp_month, exp_year and billing_address from the card file into Amazon's checkout with a browser tool such as Claude in Chrome, Playwright or a coding agent's browser. The Pay Token from Stripe skips the form entirely and only works on checkouts built on Stripe with Link enabled.

On StartupHub's Agent Readiness scanner, stripe.com scores 54 of 100 as of October 12, 2026 while amazon.com scored 32 in May 2026. That gap is the difference between a checkout designed for agents and one that tolerates them and it is why the payment half of this build is clean and the Amazon half needs a browser.

What it costs to run

SerpApi includes 250 searches per month free. Starter is $25 per month for 1,000 searches. The Link Agent Wallet docs list no fee to the developer for agent payments and you do not need a Stripe account to use them, though registering an OAuth client gives customers a nicer approval prompt. Hosting is whatever your platform charges for a small Node service.

Frequently asked

Can the agent spend more than I approved?

No. The card is authorized only for the amount you approve and each request is capped at $500. If shipping or tax pushes the total up the agent must call spend-request update with the new total and then request-approval again, and you re-approve before the card will cover it. Pass the new total, not the difference.

Does it work outside the United States?

Agent payments require the customer to have a US or Canadian Link account, but the developer and the merchant can be anywhere. Financial insights, the other part of Link Agent Wallet, is US only.

Does the model ever see my card?

Not if you build the server as shown. The card is written to a file with 0600 permissions and the MCP tools return only status, id and approval_url, while the browser step reads the file directly. Keep --test on until the flow works end to end, and the test card is 4000009990001984 which never charges anything.

© 2026 StartupHub.ai. All rights reserved. You may not republish this article in full without a license. Search engines and AI research tools may crawl and summarize for reference. Bulk reproduction or model training requires a license. See our terms.
StartupHub.ai Staff

Written by

StartupHub.ai Staff

Editorial team

The staff writers of StartupHub.ai, ranging from investment analysts to avid AI tool users, early adopters and critical enthusiasts. Backgrounds span engineering, business and the arts. We hold every piece to rigorous standards of research and review.