# Connect with MCP (/mcp)

Find a ticket and read its messages and orders from your assistant.

Connect EcomSquad through MCP (Model Context Protocol) to ask your assistant about
support tickets without building an integration.

## Before you begin [#before-you-begin]

You need:

* Access to your EcomSquad organization.
* A mailbox with stored conversations, plus a Shopify store for order context.
* An assistant that supports remote **Streamable HTTP** MCP servers.
* The EcomSquad MCP URL:

```text title="MCP endpoint"
https://api.meetwillow.cx/api/v1/mcp
```

If your sources are not ready, start with [Connect your sources](/connect).

## Choose how to connect [#choose-how-to-connect]

Use sign-in when your assistant supports MCP OAuth. Use an API key when it
supports custom HTTP headers.

### Connect with sign-in [#connect-with-sign-in]

#### Add the server [#add-the-server]

In your assistant's remote MCP or custom connector settings, add the MCP URL.
Choose **Streamable HTTP** if asked for a transport.

For Claude Code, run:

```sh title="Terminal"
claude mcp add --transport http ecomsquad https://api.meetwillow.cx/api/v1/mcp
```

Start Claude Code and open `/mcp` to authenticate. See the
[Claude Code MCP documentation](https://code.claude.com/docs/en/mcp) for its client controls.

#### Sign in and approve access [#sign-in-and-approve-access]

Follow the client's authentication prompt. Use your provisioned EcomSquad email
address and the sign-in link sent to your inbox.

Review the client name, redirect destination, and requested access. Keep context
reading enabled. Leave **Refresh context from connected providers** unchecked
for this read-only walkthrough, if requested.

#### Return to your assistant [#return-to-your-assistant]

Confirm EcomSquad's tools are available. With `context:read`, you should see the
five read tools, including `list_tickets` and `get_ticket`.

The assistant uses your current membership permissions, narrowed by the access
you approve.

### Connect with an API key [#connect-with-an-api-key]

#### Create a key [#create-a-key]

Follow [Create a key](/api-keys#create-a-key). Give it
**Support context → Read** and access to the mailbox and store you want to read.

#### Configure your client [#configure-your-client]

Enter these values in the client's private MCP settings:

| Setting      | Value                                  |
| ------------ | -------------------------------------- |
| Transport    | Streamable HTTP                        |
| URL          | `https://api.meetwillow.cx/api/v1/mcp` |
| Header name  | `x-api-key`                            |
| Header value | Your EcomSquad API key                 |

Keep the secret in the client's credential settings, not in a chat message.
EcomConnect agent keys cannot authenticate this endpoint.

#### Check the tool list [#check-the-tool-list]

Connect the client. With `context:read`, you should see the five
[read tools](#tools). Connection limits determine which records those tools can return.

<Callout type="info" title="Switching to sign-in?">
  Remove the `x-api-key` header first. It takes precedence over OAuth even when its value is empty
  or invalid.
</Callout>

## Read your first ticket [#read-your-first-ticket]

Ask your assistant:

> Use EcomSquad to list up to five tickets. Ask me which one to open, then read
> its messages and its stored orders. Explain which orders are verified and
> anything missing. Do not refresh it yet.

The assistant should call `list_tickets`, then use the selected ticket's `id` as
`ticketId` for `get_ticket` and `get_ticket_messages`.

<Callout type="success" title="Check your result">
  You should see the selected ticket's messages and an explanation of its orders. Missing order
  information can be a valid result; the assistant should explain what is missing.
</Callout>

## Common problems [#common-problems]

* **No tools appear:** check that the key or approved sign-in access includes
  `context:read`, then reconnect.
* **No tickets appear:** check mailbox data and connection access. Only
  conversations the support classifier judged a support request have a ticket;
  see [Tickets](/tickets).

For repeated sign-in prompts or other errors, see
[MCP troubleshooting](/troubleshooting#mcp-will-not-connect-or-shows-no-tools).

## Tools [#tools]

Each tool runs the same procedure as the REST operation beside it, takes the same
inputs as JSON arguments, and returns the same data as JSON text.

| Tool                  | Same as                                                                             | Permission                    |
| --------------------- | ----------------------------------------------------------------------------------- | ----------------------------- |
| `list_tickets`        | [List tickets](/reference/tickets#list-tickets)                                     | `context:read`                |
| `get_ticket`          | [Get a ticket](/reference/tickets#get-a-ticket)                                     | `context:read`                |
| `get_ticket_messages` | [List ticket messages](/reference/tickets#list-ticket-messages)                     | `context:read`                |
| `refresh_ticket`      | [Refresh a ticket](/reference/tickets#refresh-a-ticket)                             | `context:refresh`             |
| `get_order`           | [Get an order](/reference/orders-and-customers#get-an-order)                        | `context:read`                |
| `get_customer`        | [Get a customer](/reference/orders-and-customers#get-a-customer)                    | `context:read`                |
| `refresh_inbox`       | [Refresh mailboxes](/reference/mailbox-refresh#refresh-mailboxes)                   | `inbox:refresh`, API key only |
| `get_inbox_refresh`   | [Get mailbox Refresh status](/reference/mailbox-refresh#get-mailbox-refresh-status) | `inbox:refresh`, API key only |

A client sees only the tools its permissions allow; calling a hidden tool fails
like an unknown tool. Each call still checks the permission. The Needs reply feed
has no MCP tool; it answers API keys only. The mailbox Refresh tools are offered
to API keys only, never to sign-in. The tools never send email, issue
refunds, or change merchant orders.

A key uses its permissions and connection limits. Sign-in uses your role, narrowed
to the scopes you approve (`context:read`, `context:refresh`), and reaches
connections like a key with no connection limits. Approving `context:refresh` also
grants `context:read`. A missing or invalid key answers HTTP 401 before any tool
runs; a sign-in whose membership has ended gets a 401 that asks the client to sign
in again. A request with neither a key nor a token gets this JSON-RPC error:

```json title="No credentials"
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32000,
    "message": "Authentication required: send an API key in the x-api-key header, or an OAuth access token in the Authorization header"
  },
  "id": null
}
```

An invalid key gets the REST error body instead, with code `UNAUTHORIZED`.

A tool failure can arrive inside an HTTP 200 response: check the tool result's
`isError` flag. When the procedure fails, the text is the same JSON error body as
REST, such as `{"code":"NOT_FOUND","message":"Ticket not found"}`. An unexpected
failure returns `INTERNAL_SERVER_ERROR` with the message `Tool call failed`.
Invalid arguments are refused before the procedure runs, as plain text starting
`Input validation error`.

Every MCP response carries an `x-request-id` header, as the
[Context API does](/reference#errors). Quote it when you report a problem.

## Docs for assistants [#docs-for-assistants]

Every page on this site is available as plain Markdown.

| Resource                        | What it is                                                                                                                        |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| [llms.txt](/llms.txt)           | Index of every page with a one-line description. Point an assistant here first.                                                   |
| [llms-full.txt](/llms-full.txt) | Every page as Markdown in one file, in sidebar order.                                                                             |
| Per-page Markdown               | Add `.md` to any page path, for example [`/quickstart.md`](/quickstart.md). Each page also has **Copy Markdown** under its title. |

Paste a page's Markdown, or its `.md` link, into your assistant when you want it to
follow a procedure exactly as written. Use `llms.txt` when it should decide which
page applies. The documentation describes EcomSquad; your tickets come only from
the MCP server or the Context API, scoped by your sign-in or key.

Learn [which orders are verified](/tickets#linked-orders) before using a result
to answer a customer.
