# Connect any MCP client

Use this page for any other MCP client. For Claude Code, Claude and ChatGPT, follow
[Claude Code](/guides/claude-code/), [Connect Claude](/guides/connect-claude/) or
[Connect ChatGPT](/guides/connect-chatgpt/).

## Endpoint

| | |
| --- | --- |
| URL | `https://api.passion.io/mcp`, or `https://api.passion.io/mcp/chatgpt` for ChatGPT |
| Transport | Streamable HTTP, `POST` only |
| Header | `Authorization: Bearer <token>`: an API key `psn_key_…` ([API keys](/guides/api-keys/)) or an OAuth access token |

There are no sessions. The token on each request decides everything, so every request must carry
it.

`/mcp/chatgpt` has the same tools and checks as `/mcp`, except `api_search`, `api_read` and
`api_write`. It is its own OAuth resource: its protected resource metadata is at
`https://api.passion.io/.well-known/oauth-protected-resource/mcp/chatgpt`, and a sign-in for one
address does not work on the other. An API key works on both.

## Sign in with OAuth

A client that supports MCP authorization can let the creator sign in with their Passion account
instead of using a key.

| | |
| --- | --- |
| Protected resource metadata | `https://api.passion.io/.well-known/oauth-protected-resource/mcp` |
| Authorization server metadata | `https://api.passion.io/.well-known/oauth-authorization-server` |
| Client registration | Dynamic client registration at `https://api.passion.io/oauth/reg`, or a client ID metadata document |
| Grant | Authorization code with PKCE (`S256` only), then refresh tokens |
| Resource | `https://api.passion.io/mcp` (send it as `resource`) |
| Scopes | `read`, or `read write` for full access |
| Redirect URI | HTTPS, an app scheme, or `http://localhost` on any port |

A request without a token gets `401` with
`WWW-Authenticate: Bearer resource_metadata="https://api.passion.io/.well-known/oauth-protected-resource/mcp"`,
so a client can find the rest by itself.

The creator signs in to Passion Studio, picks the Apps and **Read only** or **Full access**, and
can revoke the connection later in **Settings › Integrations › Connected apps**. A client that
asks for `read` only cannot get full access.

## Protocol versions

| Version | Support |
| --- | --- |
| `2026-07-28` | Yes. No session and no `initialize` call are needed. |
| `2025-11-25` | Yes. |
| `2025-06-18` | Yes. |

## What the token decides

- **Tools.** A read key or read access lists only the tools that read. Full access also lists the tools that make
  changes. See [Scopes](/guides/scopes/).
- **Apps.** When the token reaches one App, no tool asks for an App. When it reaches several Apps,
  every tool has an `appId` argument, and its description lists the App ids the token reaches.

The tool list is private to the token. Do not cache it for another token.

## Tool results

- Each tool says whether it only reads (`readOnlyHint`). A tool that makes changes is marked, so
  the client can ask you before it runs. A tool that deletes, replaces content or sends
  something members see is marked destructive (`destructiveHint`). No tool moves money.
- A tool returns `structuredContent`, and the same JSON as text.
- A tool returns the same data as the matching [REST route](/api/), and goes through the same
  checks.

The full list is in [MCP tools](/mcp/tools/).

## Browsers

A request sent from a web page on another site is refused with `403`. Call the MCP from a server
or from a local client, not from a browser page.

## Errors

See [Errors in the MCP](/guides/errors/#errors-in-the-mcp).