# Authentication

The FullContact MCP Server is authenticated with the **same API key** you use for direct calls to the FullContact REST API. There is no separate MCP credential, no OAuth flow, and no need to provision new accounts. If your API key can call `person.enrich` today, it can drive the MCP Server tomorrow.

## Get an API key

If you do not yet have a key, see [Generate an API Key](https://docs.fullcontact.com/docs/generate-an-api-key). The key must:

* Belong to an active FullContact account.
* Have **`person.enrich`** included in its product entitlements.
* Be a production key for production traffic; sandbox keys are accepted for evaluation only.

> 📘 **Note**
>
> A single API key can be used across multiple AI clients simultaneously (e.g., Claude Desktop on a developer's laptop and a hosted Cursor workspace). All calls count against the same rate limit and quota.

## How the key is passed

The MCP Server expects the key in the standard **`Authorization`** HTTP header on every request from the client:

```
Authorization: Bearer <your-fullcontact-api-key>
```

Each client configures this differently. The patterns used in our Quickstarts are:

| Client         | Where the key is read from                                                                                                                                                                                  | How it reaches the server                                                                      |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| Claude Desktop | `Literal value pasted into the`Authorization: Bearer …`string inside`args`in`claude\_desktop\_config.json\` (no environment-variable substitution — Claude Desktop does not interpolate env vars into args) | Forwarded by the local `mcp-remote` bridge as the `Authorization` header on every HTTP request |
| Claude Code    | `--header` flag on `claude mcp add`                                                                                                                                                                         | Sent on every MCP request                                                                      |
| Gemini CLI     | `headers` block in `~/.gemini/settings.json` (env-var substitution supported)                                                                                                                               | Sent on every MCP request                                                                      |
| Cursor         | `headers` block in `mcp.json`                                                                                                                                                                               | Sent on every MCP request                                                                      |
| VS Code        | `inputs` prompt or workspace secret, referenced in `headers`                                                                                                                                                | Sent on every MCP request                                                                      |
| ChatGPT        | Token field on the Custom Connector                                                                                                                                                                         | Stored in ChatGPT's encrypted credential store                                                 |

In every case the key is sent server-to-server over TLS and is never logged in plaintext by the MCP Server.

## Rate limiting and quotas

The MCP Server enforces the same rate limits and monthly quotas as the underlying API. A successful `enrich_person` invocation counts as **one** `person.enrich` call against your account.

When the limit is exceeded, the server returns a normalized error so the agent can back off gracefully:

```json
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Retry after 30 seconds.",
    "request_id": "01HW6Q8K9XYZ...",
    "retry_after_seconds": 30
  }
}
```

See the [Errors reference](./05-mcp-errors-and-faq.md) for the full error taxonomy.

## Key rotation

To rotate a key:

1. Generate a new key in the FullContact developer dashboard.
2. Update the credential in each MCP client (env var, connector token, or VS Code prompt).
3. Revoke the old key once all clients have been updated.

Because the key only ever lives client-side, there is no MCP-Server-side cache to invalidate. The next request from each client will use the new value automatically.

## Compliance and PII handling

* **No persistence.** The MCP Server processes inputs in memory and does not write enrichment payloads to disk.
* **PII-safe logging.** Operational logs include request IDs, latency, and error codes only. Identifiers passed in (emails, phones, names) are not logged.
* **Hashed inputs supported.** You can pass MD5, SHA-1, or SHA-256 hashes of email addresses; the server forwards them unchanged. When hashed identifiers are used without a paired clear-text identifier, FullContact's API will not return clear-text PII fields in the response — see the [Multi-Field Request guide](https://docs.fullcontact.com/docs/multi-field-request) for details.
* **SOC 2.** The hosted MCP Server runs inside FullContact's existing SOC 2 boundary.

## Troubleshooting

| Symptom                          | Likely cause                                | Fix                                                                                             |
| -------------------------------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `401 unauthorized` on every call | Missing or malformed `Authorization` header | Confirm `Bearer ` prefix and that the env var is exported in the shell that launched the client |
| `403 forbidden`                  | API key lacks `person.enrich` entitlement   | Contact your FullContact account team to enable it                                              |
| `429 rate_limit_exceeded`        | Burst exceeded the per-second cap           | Have the agent honor `retry_after_seconds`                                                      |
| Tool not visible in client       | Server failed health check at startup       | Restart the client and check its MCP logs (e.g., `claude mcp list` for Claude Code)             |

## Next steps

* [Tool Reference: `enrich_person`](./04-mcp-tool-enrich-person.md) — Full input/output schema.
* [Errors and FAQ](./05-mcp-errors-and-faq.md) — Complete error taxonomy and common questions.

***

*Updated May 2026*