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

# Buy through MCP

> Connect your users' agents to the Agentcard MCP server with the connection token your server already holds. The buy tool runs the same purchase loop as POST /buy, confirmed in conversation.

The Agentcard MCP server gives your users' agents the `buy` tool, the same purchase loop as [`POST /buy`](/purchase/purchase-api), plus the user's card and balance tools. The agent connects with the user's connection `access_token`, the token your server stored when the user connected, so there's no second sign-in and no service to build: it's a few lines of wiring in the agent you already run.

Without MCP, your server relays every purchase turn over HTTP. With MCP, the agent talks to Agentcard directly, and when you register tools dynamically, tools Agentcard ships later appear in the agent without a deploy on your side. Most integrations take this path.

This page covers the wiring for your users' agents. For the HTTP path, where your server gets the cart back as data and confirms with a hash, see [Purchase API](/purchase/purchase-api). For the organization server, which builds and debugs the integration from your coding agent, see [MCP](/tools/mcp).

## How it works

1. Your backend takes the connection token it stored when the user [connected](/connect/users).
2. Your agent's MCP client connects to `https://mcp.agentcard.sh/mcp` with that token as the bearer.
3. The tools load through `tools/list`, and every call the agent makes runs as that user, scoped to your connection.

There's one server, and what it exposes depends on the credential. A connection token gets the user's tools. Your org credential gets the [organization server](/tools/mcp), which is for building and debugging the integration itself, not for buying.

## The flow

<Steps>
  <Step title="Get the user's connection token">
    The `access_token` returned when the user verified their one-time code. Keep it fresh with the refresh token; [Connect users](/connect/users) covers both.
  </Step>

  <Step title="Connect an MCP client">
    One client per user, pointed at `https://mcp.agentcard.sh/mcp` with `Authorization: Bearer <connection token>`. The bearer decides whose cards and purchases the agent can see, so a client shared across users would let one user's session act as another. Any spec-compliant MCP client over Streamable HTTP works.

    To try it from your own machine first, add it to Claude Code with a token from your sandbox client:

    ```bash theme={null}
    claude mcp add agentcard-user --transport http https://mcp.agentcard.sh/mcp \
      --header "Authorization: Bearer CONNECTION_ACCESS_TOKEN"
    ```

    In your own agent runtime the same thing is a client constructor:

    ```typescript theme={null}
    import { Client } from "@modelcontextprotocol/sdk/client/index.js";
    import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

    const transport = new StreamableHTTPClientTransport(
      new URL("https://mcp.agentcard.sh/mcp"),
      { requestInit: { headers: { Authorization: `Bearer ${user.agentcardAccessToken}` } } },
    );
    const client = new Client({ name: "your-app", version: "1.0.0" });
    await client.connect(transport);
    const { tools } = await client.listTools();
    ```

    `listTools()` returns the user's tools with `buy` among them. A fresh connection lists zero cards, which is expected: a connection only sees the cards your app created for that user.
  </Step>

  <Step title="Register the tools dynamically">
    Expose everything `tools/list` returns rather than a hardcoded list, so new tools ship into your agent automatically. The one your users will use most is `buy`.
  </Step>

  <Step title="Let the agent buy">
    `buy` is conversational. The agent passes the user's request in plain language and gets back a `message` and a `conversation_id`:

    ```json Output theme={null}
    {
      "status": "assistant_turn",
      "conversation_id": "cmemw5k2p00b7",
      "message": "I found a few options at Amazon. The Anker 30W USB-C charger is $15.99 and can arrive tomorrow. Want that one, or should I list alternatives?",
      "messages": ["I found a few options at Amazon. ..."]
    }
    ```

    The agent shows the message and sends the user's reply back, word for word, on the same `conversation_id`. The tool asks for the delivery address, shows the cart and total, and places the order only after the user says yes in a later turn. Over HTTP the same loop returns the cart as data with a hash to confirm; over MCP the agent relays the conversation instead, which is why it must never rewrite the user's reply into a fresh order command. The [Purchase API](/purchase/purchase-api) page explains how the money moves once the order is placed.
  </Step>

  <Step title="Handle approvals and expiry">
    If a card tool comes back `approval_required`, the user decides personally (an emailed approve/deny link, or their own Agentcard session). Your connected session can't resolve it, because an approval is the user's consent and the requesting app must not approve its own ask. Actions on a card created through another app accept `approval_id` on the retry. `create_card` doesn't, and the tool its reply names is personal-session only, so a connected session has no continuation for that case today: tell the user and let them create the card from their own Agentcard session. Purchases through `buy` handle approvals inside the conversation, which is the path this page is about. Reconnect with a refreshed token when calls start returning `401`.
  </Step>
</Steps>

## What the agent can do

The connection gets the user's tools, scoped to the cards and purchases your app created for that user. Register whatever `tools/list` returns; the main areas are:

| Area        | Tools                                                                                                                                                         |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Shopping    | `buy` is the whole purchase loop. `buy_list_merchants`, `buy_connect`, and `buy_connect_status` handle merchants that need the user to link an account first. |
| Cards       | `list_cards` · `create_card` · `get_card_details` · `pause_card` · `resume_card` · `close_card`                                                               |
| Added cards | `add_card` · `list_added_cards` · `remove_added_card`                                                                                                         |
| Balance     | `get_balance` · `add_funds`                                                                                                                                   |
| Identity    | `start_kyc` · `get_kyc_status`                                                                                                                                |
| Session     | `whoami` · `get_instructions`                                                                                                                                 |

Approvals aren't in the list on purpose. An approval is the user's own consent, so `list_pending_approvals` and `approve_request` answer `personal_surface_only` to a connected session; the user resolves it from the emailed link or their own Agentcard session, and your agent retries with the `approval_id`. If a tool you expect is missing, check which credential the client connected with: the organization server has a different toolset, and it doesn't include `buy`.

## Rules for your agent

The flow above is the happy path. These are the rules a coding agent needs that the calls alone don't say:

```text Rules for your agent theme={null}
- The connection token is the auth. Don't configure OAuth on the MCP client, and never open the server's hosted sign-in page; a user who sees "Connect your account" at mcp.agentcard.sh means the client was wired for OAuth discovery instead of the bearer.
- One client per user, never shared. The bearer decides whose cards and purchases the agent can see.
- Register whatever tools/list returns instead of hardcoding names, so tools Agentcard ships later appear without a deploy.
- Call get_instructions once before the first buy; it carries the current usage guide.
- buy is the whole shopping surface. Relay the user's replies verbatim on the same conversation_id; a rewritten full order command reads as a new ask and the confirmation never lands. Don't look for separate search, cart, or checkout tools.
- Don't start a new order to get past a refused checkout or an unexpected question; new_order discards the cart and any pending confirmation. Use it only for an unrelated order, after conversation_start_failed (retry the same request with new_order: true), or when a request_failed reply says the session is gone.
- Failure replies carry no conversation_id, so keep the one from the last assistant_turn.
- On 401, refresh with the org token, not the connection token: POST /api/v2/connect/refresh with the stored refresh_token, replace both stored tokens, and reconnect the client.
- Never write card numbers or CVVs to logs, error reports, or analytics.
```

## Org-owned accounts

If your users never connect an Agentcard of their own, the bearer is a `buy_token` instead of a connection token. Create a cardholder and get one with `mint_buy_token` on the [organization server](/tools/mcp), or with `POST /api/v1/cardholders/:id/buy_token`. It lasts 30 days, works only as that one user, and the agent connects exactly the same way. Purchases then draw on your company balance; the [Purchase API](/purchase/purchase-api#how-the-money-moves) page explains that funding path.

## Sandbox behavior

Connect with a token from your sandbox client and the agent runs the real loop against real merchants, right up to the confirm. There the reply explains that sandbox test cards can't pay a real merchant and no order is placed. That's the sandbox wall, the same one `POST /buy` reports as `declined`. [Your first order in sandbox](/purchase/first-order-in-sandbox) walks that arc over HTTP; over MCP it's the same conversation in prose.

That's the whole wiring: one client per user, the connection token as the bearer, and `buy` as the surface.

Next: [Your first order in sandbox](/purchase/first-order-in-sandbox)
