Connectors
An mcp deployment is a standard MCP server.
Connector OAuth makes it connectable from an MCP host — Claude custom
connectors and ChatGPT developer-mode connectors today — with no out-of-band
token handling: the host gets one URL, discovers the rest, and each person
authorizes their own connection.
Connect in Claude
-
Deploy the agent:
# Authorization: tenant-admin token (server-side only) curl -X POST https://api.cloud.ingram.tech/v1/deployments \ -H "Authorization: Bearer $IC_TOKEN" \ -H "IC-Api-Version: 2026-05-01" \ -H "Content-Type: application/json" \ -d '{ "target": { "type": "agent", "id": "agt_…" }, "kind": "mcp" }' # → 201 { "id": "dep_…", "kind": "mcp", … } -
In Claude, open Add custom connector (Customize → Connectors → + → Add custom connector; Team and Enterprise plans: Settings → Organization settings → Connectors) and fill it in:
- Name — anything; the agent's name reads best.
- Remote MCP server URL —
https://api.cloud.ingram.tech/v1/deployments/dep_…/mcp. - Advanced settings (OAuth Client ID / Client Secret) — leave empty. Claude registers itself with the API automatically.
-
Claude opens the Ingram Cloud consent page. The person pastes their connect token (below) and clicks Authorize. Done — Claude holds its own short-lived credentials from here on and refreshes them itself.
The console has the same walkthrough with the URL pre-filled: Deployments →
Connect on any mcp deployment.
Connect in ChatGPT
Same server, same URL. In ChatGPT, Settings → Apps & Connectors → Advanced → Developer mode (once), then Create connector with the deployment's MCP URL. ChatGPT runs the identical OAuth flow through the same consent page.
The connect token
The consent page authenticates the person with a token you already mint — nothing new to build:
agenttarget — the smith token you minted for that person's smith. The smith must run the deployment's agent; the connection is bound to it, so the person talks to their smith — own memory, own threads.smithtarget — that smith's token, or a tenant-admin token.
The pasted token authorizes once. Afterwards the connection runs on tokens the
API mints for it: 1-hour access tokens (ordinary smith tokens scoped to
runs:write approvals:write, so the host resolves the smith's tool
approvals in-band — the inputResponses
retry or tasks/update) and a rotating refresh token that lapses after 90 days
unused.
So a short-TTL connect token is fine — mint it, show it to the person, let it
expire.
Delegated consent (your own authorize page)
The connect-token paste is the one manual step, and you can remove it: register
an authorize_url on any of your OAuth providers
(PUT /v1/tenant/providers/{provider}) and the API redirects the person to
your hosted page instead of rendering its own —
# Authorization: tenant-admin token (server-side only)
curl -X PUT https://api.cloud.ingram.tech/v1/tenant/providers/acme \
-H "Authorization: Bearer $IC_TOKEN" \
-H "IC-Api-Version: 2026-05-01" \
-H "Content-Type: application/json" \
-d '{ "authorize_url": "https://app.example.com/connect/authorize" }'
The API stays the authorization server and token issuer; only the consent + identity step moves to you. The flow:
-
The host opens
GET /oauth/authorizeas usual. The API validates the request, stashes it as a single-use pending request (10-minute expiry), and 302s the browser to<authorize_url>?request_id=…. Therequest_idis opaque — the browser never carries an identity assertion. -
Your page authenticates the person with your own session, then reads the request server-side to render consent:
# Authorization: tenant-admin token (server-side only) curl https://api.cloud.ingram.tech/v1/oauth/authorize-requests/$REQUEST_ID \ -H "Authorization: Bearer $IC_TOKEN" \ -H "IC-Api-Version: 2026-05-01" # → { "client_name": "Claude", "target_name": "Concierge", # "deployment_id": "dep_…", "resource": "…/deployments/dep_…/mcp", … } -
On approve, name the smith the person authorized —
# Authorization: tenant-admin token (server-side only) curl -X POST https://api.cloud.ingram.tech/v1/oauth/authorize-requests/$REQUEST_ID/complete \ -H "Authorization: Bearer $IC_TOKEN" \ -H "IC-Api-Version: 2026-05-01" \ -H "Content-Type: application/json" \ -d '{ "smith_id": "smt_…" }' # → { "redirect_url": "https://claude.ai/…?code=…&state=…" }— and 302 the browser to
redirect_url.…/declinemirrors it with anaccess_deniedredirect. Requests are single-use: asmith_idthat doesn't fit the deployment gets422 smith_mismatchand leaves the request live for a retry; one naming no live smith here gets404, as it would anywhere else. A completed or declined request reads as404too.
The API re-verifies the smith against the deployment (same checks as the
connect-token path) before minting the code, so your page can only complete
grants for smiths that actually belong to the deployment. Hosts can't tell the
difference — the code exchange, tokens, and refresh are unchanged. Providers
without an authorize_url keep the built-in consent page.
What the host sees
Exactly the MCP server surface: the ask tool
and the smith's working memory as a read-only resource. Isolation is the
deployment's: distinct people authorize distinct smiths.
How discovery works
Everything is a published standard; no Ingram-specific client code exists in the loop:
-
The host POSTs the MCP URL unauthenticated →
401with aWWW-Authenticateheader naming the Protected Resource Metadata (RFC 9728) and the scope to ask for (runs:write). -
That metadata names the authorization server; its AS metadata (RFC 8414) lists the endpoints:
# Unauthenticated (discovery) curl https://api.cloud.ingram.tech/.well-known/oauth-authorization-server # → { "authorization_endpoint": "…/oauth/authorize", # "token_endpoint": "…/oauth/token", # "registration_endpoint": "…/oauth/register", # "client_id_metadata_document_supported": true, # "authorization_response_iss_parameter_supported": true, … } -
The host identifies itself. Either way works:
- Client ID Metadata Document: the host's
client_idis an HTTPS URL it serves a JSON registration at (client_id,client_name,redirect_uris). The API fetches and validates it; nothing is stored. - Dynamic Client Registration (RFC 7591) at
/oauth/register, for hosts that still register this way.
- Client ID Metadata Document: the host's
-
It runs the authorization-code flow with PKCE (
S256only). Every redirect back to the host carriesiss(RFC 9207), so the host can check the answer came from the authorization server it discovered. -
The tokens it receives verify against
/.well-known/jwks.json— the same RS256 key family as every Ingram Cloud token.
Claude's connector directory and the ChatGPT Apps SDK (rich in-chat UI, app-store listing) are distribution steps on top of this same server and are not available yet; a connector needs nothing beyond the URL.