Claude & ChatGPT

Connect Claude & ChatGPT

Hosted agents that speak MCP — Claude, ChatGPT, and others — connect to TAP with one URL:

https://mcp.tap.human.tech/mcp

Add it as a custom connector (leave OAuth Client ID and Secret empty) and authorize in your browser with your normal TAP login. That’s the whole setup — no API key to paste, no per-service configuration.

What your agent gets

Two tools, and every credential in your dashboard is reachable through them:

  • tap_discover — lists the credentials this connection can use and how to call each.
  • tap_call — calls any API by credential name. TAP injects the secret, enforces your policies, and pauses writes for your approval. The agent never sees the secret.

Reads and writes follow the same policies, approvals, and audit log as every other TAP agent. The connection holds an OAuth token — never an API key or a credential value — and you can revoke it from the dashboard anytime.

OAuth scopes

When you authorize a connection, the consent screen names what it is asking for. Two grants exist, and they are separate on purpose.

ScopeWhat it lets the connection do
tap:fullAct as you: call tap_call / /forward and /sign with your credentials, and manage your workspace’s people on the team routes below. Your policies, approvals and audit log all still apply.
tap:approveApprove or deny credential requests that are waiting for you, as you. It opens no credential of its own.

A client may ask for both — an app that runs the agent and shows you the approval in its own UI asks for tap:full tap:approve. They are then shown as two rows on the consent screen, because they are two different things to agree to. tap:identity (“Sign in with TAP”) is a third, identity-only grant.

What tap:approve does not do. It cannot use a credential: a token holding only tap:approve is inert at /forward, /sign and every agent endpoint. And it does not weaken a passkey policy — a credential you protect with a passkey still requires your passkey, and the host is told to send you to the approval page instead.

An agent cannot approve its own request. The endpoint this scope unlocks, POST /agent/approvals/:txn_id/decide, refuses an agent API key outright and refuses any token that was not granted tap:approve — including the tap:full token the agent half of the same connection uses. Approving stays a person’s act.

Revoke a connection any time from the dashboard; that ends both grants at once.

What tap:full may do on team routes

An app that signs you in with TAP holds your access token and no dashboard session, so it could not previously read your workspace’s people at all. A tap:full token now authenticates the same person on a named set of team routes — the ones a Team panel needs and no others:

Route
GET /team/membersmembers and pending invites
POST /team/members/inviteinvite someone
POST /team/members/invite/{id}/resendreissue an invite
DELETE /team/members/invites/{id}withdraw a pending invite
GET /billing (and /billing/status)plan, seat cap, seats used
GET /team/credentialscredential names and descriptions — never a value
GET/POST /team/members/{id}/credentials, PATCH/PUT/DELETE /team/members/{id}/credentials/{name}which accounts a teammate holds

Three things this does not change:

  • Your role still decides. The token resolves to you, in the workspace it was minted for, and the membership is re-read on every request. A member-tier token cannot invite, exactly as a member-tier login cannot.
  • Nothing else moved. Every other team route — policy changes, passkey resets, role changes, approvals, checkout — still requires a dashboard session and, where it already did, a passkey. A token is refused there.
  • tap:identity and tap:approve are still inert here. A token without tap:full is refused with token_scope_insufficient, and an expired or revoked token is refused like any other.

Writes made this way are audited, and the audit row names whether the caller authenticated with a dashboard session or a Sign-in-with-TAP token.

Signing in from an app that embeds TAP

An app that hides TAP entirely — a work box — can run the whole sign-in on its own page and hand the result to /authorize. Both box-hosted ceremonies end the same way, with a one-time tap_login_code:

Attach the code to the normal authorization redirect:

GET {TAP_MCP_PUBLIC_URL}/authorize?response_type=code&client_id=…&redirect_uri=…
    &code_challenge=…&code_challenge_method=S256&tap_login_code=<login_code>

TAP redeems it internally and redirects straight back to the app’s redirect_uri with an authorization code — no consent screen and no second passkey prompt. Exchange that code at /token as usual. The code is single-use, lives two minutes, is bound to the origin it was minted for, and carries exactly the scopes that were consented to; any refusal falls through to the normal consent screen rather than failing the login.

Which connection to use

Your agentUse
Claude, ChatGPT, other hosted MCP clientsThis page — paste the URL, authorize in the browser
Claude Code, Cursor, scripts, anything that can curlQuickstart — an API key and /instructions

Both use the same credentials, policies, approvals, and audit log.


Note — this isn’t a per-service toolbox. You don’t install a separate Gmail, Stripe, and GitHub MCP server, each holding its own copy of your keys. You connect TAP once and reach every API through those two tools. It’s the same idea as TAP’s Socratic API: the agent works from a couple of generic calls and learns the rest from what TAP tells it, instead of a hand-written catalog per service.