IntraChat as an MCP client
This page describes how IntraChat, the Intra AI platform, connects to an MCP server that a provider hosts. It is written for two readers: reviewers at a provider who decide whether to allow IntraChat as an OAuth client of their MCP server, and IT departments at our customers who want to know what happens when someone connects an account.
What IntraChat is
IntraChat is the AI workspace Intra AI sets up for a customer company. Every customer gets a dedicated instance, operated by us: the application, its databases and its storage are not shared with other customers. On request, the instance can run in the customer's own infrastructure instead. Development, data storage and AI inference in Germany.
Users, their connections and their tokens belong to one instance and are never shared with another customer's instance.
Connection at a glance
This page describes clients that belong to one instance: a client the instance registers itself, or one an administrator creates at the provider and pastes.
| Aspect | Value |
|---|---|
| Transport | Streamable HTTP |
| Authorization | OAuth 2.1 authorization code grant with PKCE (S256) |
| Metadata discovery | RFC 9728 protected resource metadata, then RFC 8414 authorization server metadata |
| Client registration | Dynamic Client Registration (RFC 7591) where the server offers it, otherwise a client the administrator creates at the provider and pastes |
| Client name sent at registration | IntraChat |
| Grant types registered | authorization_code, refresh_token |
| Redirect URI | https://<instance-host>/api/v1/integrations/mcp-oauth/<slug>/callback |
| Consent | Per user: everyone connects their own account |
| Tool names inside IntraChat | mcp__<slug>__<tool> |
<slug> is derived from the server's name: lowercased, spaces replaced by hyphens, every character other than a–z, 0–9 and the hyphen removed, repeated hyphens collapsed into one, and leading and trailing hyphens dropped. A server named Notion gets notion, a server named monday.com gets mondaycom.
Discovery
When the server is set up on an instance, IntraChat sends an unauthenticated MCP initialize request to the server's address and reads the resource_metadata link from the WWW-Authenticate challenge of the 401 response (RFC 9728). If the challenge carries no link, it tries /.well-known/oauth-protected-resource with the server's path, then without it.
The protected resource metadata names the authorization server. IntraChat reads that server's RFC 8414 metadata, or its OpenID Connect configuration if there is none, and refuses a document whose issuer differs from the authorization server named. It also refuses protected resource metadata that describes a different address than the server being set up. Only when no protected resource metadata exists at all does it read /.well-known/oauth-authorization-server on the server's own origin.
Every endpoint taken from this metadata must be an http or https address that does not resolve to a private, loopback or link-local address. For a provider that publishes no metadata, the endpoints are fixed in IntraChat's setup for that provider instead.
When the protected resource metadata names a resource, IntraChat sends it as the RFC 8707 resource parameter on the authorization request, the code exchange and every refresh.
Client registration
If the authorization server offers a registration_endpoint, IntraChat registers one client there (RFC 7591) with the redirect URI of that instance, the grant types authorization_code and refresh_token, the response type code and the scopes it will ask for. It registers a confidential client with client_secret_post. It registers a public client (none) only when the server lists none and neither secret method, and only when the server lists S256 in code_challenge_methods_supported.
If the server offers no registration endpoint, an administrator creates an OAuth client at the provider, enters the redirect URI shown in the setup guide, and pastes the client ID and secret into IntraChat. Such a client authenticates at the token endpoint with client_secret_post when the server lists it or lists no method, otherwise with client_secret_basic.
A client the instance registers itself is registered once per instance, stored there and reused for every user of that instance. A pasted client is stored the same way. IntraChat does not register a new client per user or per session.
Redirect URI
For a client the instance registers itself or an administrator pastes, the redirect URI is built from the instance's own host name and the server's slug:
https://<instance-host>/api/v1/integrations/mcp-oauth/<slug>/callback
For a pasted client, this is the address to allow at the provider. With Dynamic Client Registration, IntraChat sends it in the registration request itself. An instance that answers on several host names signs people in on the one it registered with.
Per-user consent
Nobody connects an account on someone else's behalf. Each user signs in at the provider with their own account and approves the requested access there:
- The user opens the provider's tile under Integrations in IntraChat and adds a connection. This works only once the integration has been released, and only for the users it was released to. Once it is released, even only for a test group, administrators with global admin rights can also connect to test it.
- IntraChat creates a random
stateand a random PKCE code verifier, and sends the browser to the provider's authorization endpoint withresponse_type=code, the client ID, the redirect URI, the scopes,code_challengeandcode_challenge_method=S256. - The provider sends the browser back to the redirect URI. IntraChat accepts the
stateonly once and only in the browser that started the sign-in, then exchanges the code together with the code verifier at the token endpoint.
IntraChat asks for the scopes its setup for that provider declares or, where the setup declares none, the scopes the server advertises in its metadata.
After the exchange, IntraChat tries to find out which account the token belongs to, so the connection can be labeled with it. It asks the authorization server with RFC 7662 token introspection or the OpenID Connect userinfo endpoint, on the token endpoint's own origin or at a userinfo endpoint that IntraChat's setup for that provider declares. For some providers it also uses the user's new token to call a read-only tool of the server itself, or the provider's own account API, to name the account. If none of these answers, the connection is labeled with the server's name.
Connecting writes the event integration.mcp_oauth.connected to the instance's audit log.
Tokens
- Storage: access token, refresh token and expiry are stored per user in the instance's database, encrypted with a data key that belongs to that user. A client secret is stored on the server's record, encrypted with the instance's system key.
- Use: every tool call carries the calling user's own access token as a
Bearertoken, never another user's. - Refresh: when the provider returns
expires_in, IntraChat refreshes a token that is within 60 seconds of expiry before the call. If the server answers a call with 401, IntraChat refreshes once and retries the call once. - Rotation: refreshes for one user and one server run one at a time across all API processes of the instance, so a rotating refresh token is spent only once. A rotated refresh token is stored before the new access token.
- Dead grant: if the token endpoint answers a refresh with
invalid_grant, IntraChat deletes that user's stored tokens, and the user has to connect again. Any other refresh failure, such as a timeout or a 5xx answer, keeps the stored tokens. - Reconnect: connecting again replaces the user's previous tokens completely.
Disconnect and revocation
A user disconnects on the provider's tile under Integrations. IntraChat then deletes that user's stored tokens for the server and writes the event integration.mcp_oauth.revoked to the audit log.
IntraChat does not call the provider's token revocation endpoint (RFC 7009). The grant at the provider stays until it expires or the user removes the app in their account settings with the provider.
When an administrator removes a server that uses such a client, IntraChat deletes the server and every user's stored connection to it.
Tools
IntraChat lists a server's tools with tools/list, sent with the token of a connected user. Until the first user connects, IntraChat sends no authenticated request to the server and lists no tools. One user's tool list stands for every user of the instance, and a tool outside another user's plan is refused by the provider when that user calls it.
Inside IntraChat a tool is named mcp__<slug>__<tool>, for example mcp__notion__notion-search.
Which tools an agent may use is set per agent: each agent is granted a list of tools per server. For each granted tool, the agent's settings can mark it as reading, as needing a confirmation, or as running without asking. The reading mark is a label only and restricts nothing; the confirmation and running-without-asking settings change how a call proceeds.
- Confirmation: a tool set to confirmation pauses the conversation before the call and shows the user a card with what the agent wants to do. The call goes to the provider only after the user approves it. Tools in chat: confirmations and errors describes the card.
- Annotations: by default, IntraChat removes the tool annotations, such as
destructiveHint, that a provider's server publishes. Whether a call needs a confirmation is decided by the agent's settings, not by the server. - Running without asking: the author of an agent can set a write tool to run without asking. The instance can forbid that for single tools or in general.
Tool results are processed by the language model the instance is configured with. In our standard configuration we run open-weight models hosted in Germany.
For administrators: enabling a hosted integration
Hosted MCP servers that IntraChat has a setup for are listed in the admin area under Integrations. Each one has a step-by-step guide:
- Steps at the provider. For a server with Dynamic Client Registration there are usually none. For a pasted client, the guide lists what to create at the provider, the scopes with a reason for each, and the redirect URI to enter.
- Values. With Dynamic Client Registration, IntraChat registers itself and you enter nothing. Otherwise, paste the client ID and secret. Saving registers the server on the instance.
- Release. Nobody can connect to a registered integration yet, administrators included. Release it for a test group or for everyone.
After the release, every user connects their own account as described in Connecting integrations.
Test access for vendor reviews
Test access for vendor reviews is available on request. Write to info@intra-ai.de or use the contact form, and name the MCP server your review is about.