# Connecting a remote agent > Connect Claude, ChatGPT, or any MCP client to Myna's hosted MCP server over OAuth — no local process, no API key to paste. Myna hosts an MCP server at `https://api.myna.sh/mcp`. Any agent that speaks [streamable HTTP MCP](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports) can connect to it directly — there is nothing to install and no API key to paste. Authorization runs through OAuth: you sign in with GitHub, choose an organization, and pick what the agent may do. This is the same tool surface as the local [`@myna-sh/mcp`](/mcp/setup) server. Use the hosted endpoint for chat agents and web clients; use the local stdio server for coding agents that need filesystem access. ## Add Myna to Claude In Claude, go to **Settings → Connectors → Add custom connector** and enter: ``` https://api.myna.sh/mcp ``` Leave the client id and secret fields empty — Myna supports [dynamic client registration](https://datatracker.ietf.org/doc/html/rfc7591), so Claude registers itself. You will be sent to Myna to sign in and approve the connection, then returned to Claude. The same URL works for ChatGPT custom connectors, the [MCP Inspector](https://github.com/modelcontextprotocol/inspector), Cursor, VS Code, and anything else implementing the MCP authorization spec. ## What you are approving The consent screen asks for two things. **An organization.** A connection is scoped to exactly one organization, the same way an API key is. Every tool call runs inside it, and the agent can reach every project in it — `myna_list_projects` is how it discovers them. To connect a second organization, add a second connector. **Permissions.** The agent asks for a set of [scopes](/platform/scopes); you can uncheck any of them before approving. By default it requests read, draft, asset, and preview access — and **not** `content:publish`. That default is deliberate: without it the agent can create entries, validate them, and generate preview links, but everything it writes lands as a draft on a [change set](/concepts/change-sets) waiting for a human. Grant `content:publish` only if you actually want the agent to ship. Whatever you approve is also capped by your own role. A grant is a delegation, not a credential of its own: if you are an editor, an agent you connect cannot exceed editor capabilities even if it asked for more, and if your role is later reduced — or you leave the organization — the connection narrows or stops working on its next request. Nothing has to be revoked manually for that to take effect. ## Managing connections Every connected agent is listed under **Account → Connected agents** in the dashboard, showing which organization it can reach, whether it can publish, and when it was last used. **Disconnect** revokes the grant and every token issued under it immediately. Actions taken by a connector are attributed to it in the audit trail and on revisions, with actor type `agent` — distinct from both your own user actions and from API keys. You can always tell what an agent did. ## Using an API key instead Agents that cannot run an OAuth flow may authenticate to the same endpoint with an ordinary API key: ```http POST https://api.myna.sh/mcp Authorization: Bearer myna_sk_... Content-Type: application/json Accept: application/json, text/event-stream ``` The key's organization and scopes apply exactly as they do on the management API. This is the simplest path for scripts and self-hosted agents; prefer OAuth for anything a person connects interactively, because it produces a revocable, attributable, human-approved grant instead of a shared secret. ## For client implementers The endpoint follows the MCP authorization spec ([2025-06-18](https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization)): | | | |---|---| | MCP endpoint | `POST https://api.myna.sh/mcp` (stateless; `GET`/`DELETE` return `405`) | | Protected resource metadata | `GET /.well-known/oauth-protected-resource` ([RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728)) | | Authorization server metadata | `GET /.well-known/oauth-authorization-server` ([RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414)) | | Dynamic client registration | `POST /v1/oauth/register` ([RFC 7591](https://datatracker.ietf.org/doc/html/rfc7591)), public clients only | | Authorization | `GET /v1/oauth/authorize` — PKCE `S256` required | | Token | `POST /v1/oauth/token` — `application/x-www-form-urlencoded` | | Revocation | `POST /v1/oauth/revoke` ([RFC 7009](https://datatracker.ietf.org/doc/html/rfc7009)) | An unauthenticated request returns `401` with a `WWW-Authenticate` header naming the resource metadata URL, which is how a client discovers the authorization server: ```http WWW-Authenticate: Bearer realm="myna", resource_metadata="https://api.myna.sh/.well-known/oauth-protected-resource" ``` Notes that matter in practice: - **`resource` is validated.** Include the [RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html) `resource` parameter on both the authorization and token requests, set to `https://api.myna.sh/mcp`. A different value is rejected with `invalid_target`. - **Only PKCE `S256`.** `plain` is refused. - **Only public clients.** `token_endpoint_auth_method` must be `none`. - **Refresh tokens rotate.** Each refresh returns a new refresh token and invalidates the old one. Presenting a rotated token is treated as theft: the grant and every token under it are revoked. Store the newest one. - **Access tokens last one hour.** Refresh tokens last 60 days. - Errors from the OAuth endpoints use the [RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749) `{ "error", "error_description" }` shape, not the [problem details](/management-api/errors) the rest of the API returns. ## Self-hosting the endpoint Running Myna yourself? The hosted endpoint is part of the API service, so it is available at `/mcp` with no extra process. Set `API_URL` to the exact public URL of your API — the OAuth issuer, the canonical resource identifier, and the metadata documents are all derived from it, and clients will reject a mismatch.