# MCP

The MCP surface is the primary one. Every operation in [Operations](/docs/operations) is a tool with the same name, inputs, and results.

## Two endpoints

| URL | Tools | Auth |
|---|---|---|
| `https://api.emailimport.com/mcp` | `sandbox_create` and the starter schema resources | none |
| `https://api.emailimport.com/mcp/<key>` | the full set for one tenant | the key is in the URL |

The key travels in the URL because hosted MCP clients cannot set headers. Treat the URL as a secret. Sandbox keys expire with the sandbox; account keys can be revoked.

Transport: Streamable HTTP, stateless. Each request is independent; no session id is needed.

## Connect

1. Call `sandbox_create` on the public endpoint, or `POST https://api.emailimport.com/sandbox` over HTTP.
2. Add the returned `mcp_url` as a remote MCP server in your client.
3. Call `get_tenant`, then `ingest_message`.

Claude Code:

```bash
claude mcp add --transport http mximp "https://api.emailimport.com/mcp/<key>"
```

Claude.ai and ChatGPT: add a custom connector with the `mcp_url`. No OAuth is needed for a tokenized URL.

Any MCP SDK: connect with the Streamable HTTP client transport to the `mcp_url`.

## Resources

`mximp://starters/<name>` returns each starter schema as JSON. `list_starters` returns the same over tools.

## Tenancy

A credential reaches a set of tenants. A sandbox key reaches exactly one, so `tenant` is implied on every operation. A credential that reaches several must pass `tenant`; a value outside the set is refused with the valid values listed, never a silent empty result. `list_tenants` is always available. Every result carries `tenant_id`, so a model sees what it acted on rather than inferring it. Over HTTP the same value travels as `?tenant=` or the `x-mximp-tenant` request header, and every response carries `x-mximp-tenant`.

## Conventions

- Tools return JSON as text. Errors come back as `isError` results whose text names the tool that would fix the miss (for example "Use list_buckets").
- Read tools are marked read-only in their annotations. Mutating tools are not.
- Nothing a tool returns includes raw MIME. Bodies are sanitized text; hidden HTML text is reported separately.
- `submit_feedback` tells the people running the platform what was confusing or missing. A person reads it; nothing acts on it automatically.
- Tool names are specific on purpose: `ingest_message`, `dry_run_schema`, `approve_capture`. No bare verbs.
