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

# Model Context Protocol (MCP)

> Connect read-only MCP clients with your existing API key

Use Amber's MCP server to read the same public business data as the REST API
through typed tools. Every tool is read-only. Credentials stay in HTTP headers,
never in tool arguments or URLs.

This guide covers **API key** connections for clients that send a `Authorization`
header. **Browser OAuth** (for example Claude's remote connector flow) is not
available yet. When OAuth ships, this page will document discovery, consent, and
independent grant lifecycle separately from API keys.

## Endpoint and authentication

Each brand has its own MCP URL:

```text theme={null}
https://app.amber.ai/api/public/mcp/brands/{brand}
```

Replace `{brand}` with your brand slug. Use the same API key as REST:

```http theme={null}
Authorization: Bearer amb_sk_<prefix>_<secret>
```

Global keys must use a URL for the brand you intend to read. Brand-scoped keys
must match that slug. Revoked, expired, or wrong-brand keys return `401` with
`invalid_token`. Missing credentials never fall back to an Amber login session.

The transport accepts **POST** only. There is no long-lived MCP session, SSE
subscription, or GET stream on this URL.

If you send an `Origin` header, it must exactly match `https://app.amber.ai`.
Other origins receive `403` before your key is checked. Server-side clients
usually omit `Origin`.

Request and per-key rate limits match the [Authentication](/authentication)
guide, including `429` and `Retry-After`. Product `include` on
`read_parent_products` shares the same expansion credit bucket as REST.

## Connect with the MCP TypeScript SDK

The examples use `@modelcontextprotocol/client` against Streamable HTTP. Install
the same major versions Amber's API tests use (2.x as of this writing).

Set `AMBER_API_KEY` and `AMBER_BRAND` in a server environment. Do not embed
keys in browser bundles or paste them into model-visible tool arguments.

```javascript theme={null}
import { Client } from "@modelcontextprotocol/client";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/client";

const brand = process.env.AMBER_BRAND;
const origin = "https://app.amber.ai";
const url = `${origin}/api/public/mcp/brands/${encodeURIComponent(brand)}`;

const transport = new StreamableHTTPClientTransport(new URL(url), {
  requestInit: {
    headers: {
      Authorization: `Bearer ${process.env.AMBER_API_KEY}`,
      Accept: "application/json, text/event-stream",
    },
  },
});

const client = new Client({ name: "my-integration", version: "1.0.0" });
await client.connect(transport);

const { tools } = await client.listTools();
console.log(tools.map((tool) => tool.name).slice(0, 5));

await client.close();
```

After `connect`, call `listTools` and `callTool`. Initialization does not
create a persistent session id on Amber's server.

## Tool names and paging

Tools mirror the public REST inventory:

| Pattern | Example | Purpose |
| - | - | - |
| `list_<collection>` | `list_parent_products` | Filtered page of records |
| `read_<collection>` | `read_parent_products` | One record plus bounded `related` pages |
| Content | `read_document_content`, `read_image_content` | Binary or text payloads |

REST path `products` becomes `parent_products` in tool names. REST `rfqs` maps
to `quotes` tools. Hyphens in path segments become underscores.

List results include `items`, `nextCursor`, and `totalItems`, plus a
`collection` object with the tool name and arguments to call again (without a
cursor). When `nextCursor` is not null, call the same list tool with that
`cursor` value. Default `limit` is 25; maximum is 100.

Detail results use `{ data, related }`. Large child sets (SKUs, order lines,
quote revisions, supplier contacts) appear as bounded pages under `related`, each
with its own `collection` continuation. Follow those tools instead of expecting
unbounded arrays on `data`.

## Read a Parent Product and walk SKUs

```javascript theme={null}
const read = await client.callTool({
  name: "read_parent_products",
  arguments: { id: "00000000-0000-4000-8000-000000000001" },
});
const structured = read.structuredContent;
const skusPage = structured.related?.skus;
if (skusPage?.nextCursor) {
  await client.callTool({
    name: "list_skus",
    arguments: {
      ...skusPage.collection.arguments,
      cursor: skusPage.nextCursor,
    },
  });
}
```

Optional `include` on `read_parent_products` accepts the same comma-separated
collection names as REST product detail (for example `skus,productOptions`).
Each distinct include consumes expansion credits described in
[Product graphs](/product-graphs).

Each successful tool payload must fit within Amber's MCP byte budget (256 KiB).
Oversized graphs return a structured error with a narrower retrieval hint instead
of silent truncation.

## Verify a revoked key

Revoke the key in Amber settings, then repeat `connect` or any tool call. Amber
returns `401` with the same body shape as REST key failures. Restore access by
creating or rotating a key through your administrator.

## Client compatibility

| Client | Configuration | Status |
| - | - | - |
| MCP TypeScript SDK (Streamable HTTP) | API key in `Authorization` | **Verified** in Amber CI (`public-mcp.test.ts`, integration tests on merge) |
| Custom server integrations | Header-capable HTTP client | **Verified** (same transport and guards as SDK tests) |
| Claude remote connector | OAuth discovery and browser consent | **Not available** until Amber ships the OAuth MCP slice |
| Grok Bot apps | Vendor-specific MCP setup | **Not verified** (no recorded end-to-end run against this server) |

Protocol SDK tests in CI do not substitute for a recorded Claude or Grok Bot
session. Amber will update this table when OAuth and external client runs are
completed.

## OAuth (planned)

A future release will add OAuth protected-resource metadata, dynamic client
registration, browser consent at `/mcp-connect.html`, token exchange, refresh,
and per-client revocation without revoking your API keys. OAuth credentials will
not call REST endpoints. Until that release ships, rely on API keys only for MCP.
