Where do you approve apps for Claude?
Finance asks for Xero in Claude. You switch something on. A month later somebody has connected a note-taking app nobody reviewed. There are two places you approve apps for Claude, and they answer different questions. Claude's own admin console decides which connectors exist in your Claude organization. Elaichi decides which company apps sit behind the one custom connector you added, and which tools inside them each role may reach.
MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. A connector in Claude is an MCP server Claude is allowed to talk to. An app in Elaichi is a connected account: one Zendesk workspace, one Salesforce org, one Xero company file. Approving a connector and approving an app are different units of control, which is why one surface does not replace the other:
| Claude admin console | Elaichi control plane | |
|---|---|---|
| Unit of approval | MCP server (connector) | Connected account (app), per role or per user |
| Granularity | Per tool or tool group, connector-wide | Per tool, per app, per role, per user, with exceptions |
| Who can approve | Owner / Primary Owner (Enterprise: custom role with Libraries Manage) | Writing an allow rule needs restriction:manage; access requests are resolved with member:manage |
| Default state | Off until added | Permissive until a restriction is written |
| Cross-client coverage | Claude only | Any MCP client pointed at the same endpoint (Claude, ChatGPT, Cursor) |
| Local/unmanaged servers | Out of scope (see below) | Out of scope |
| Revocation | Not documented by Anthropic (see below) | Documented: user-initiated or admin-initiated, logged |
This same two-surface pattern, client-level connector approval plus a server-side control plane for app-level and tool-level approval, applies to any MCP client, not just Claude. The specifics below are Claude's, but the pattern generalizes to ChatGPT, Cursor, or any other MCP-capable client pointed at the same custom connector.
Approving connectors inside Claude Team and Enterprise
In Claude Team and Enterprise, a connector stays off until an Owner adds it. Directory connectors are added by an Owner or Primary Owner at Organization settings, then Connectors, by browsing the directory and adding one to the team. Adding connects nobody. Each member still signs in to that connector with their own account (support.claude.com, checked October 2026).
On Team, members have an intake path. A member sees a Request button on a directory connector. Owners find the pending ones under "Requested by your team" in Organization settings, Connectors, and on the Requests tab in Notifications, then enable or dismiss them (claude.com/docs/connectors/directory, checked October 2026). Anthropic's page does not say Enterprise members get the same button, so do not plan a rollout around it.
Custom connectors are narrower. A custom connector is a remote MCP server you point Claude at, which is what Elaichi's endpoint is. Owners and Primary Owners add one. On Enterprise, so can a custom role carrying Libraries (Manage). Ordinary members cannot add one; they connect and enable what was already added, and a Free account is limited to a single custom connector (support.claude.com, checked October 2026).
Then there are tool permissions. Each connector's tools can be set to Always allow, Needs approval or Blocked, per tool or per group, set by Owners and binding on members. On Enterprise, custom roles narrow that further. Know one thing before planning per-app approval there: Elaichi's connected tools all run through a single tool called execute_tool, so a permission set on that one tool in Claude's console covers every connected app at once, undifferentiated. Claude's console cannot distinguish "allow Xero" from "allow Zendesk" once both sit behind the same custom connector. Per-app and per-tool approval for those apps has to happen in Elaichi, not in Claude's connector settings.
What Claude's connector controls do not reach
Anthropic is explicit about the edge of these controls. Its guidance on custom roles says connector tool permissions "don't govern connectors a member runs locally on their own machine" (support.claude.com, checked October 2026). A server an engineer installed in a local config file sits outside the console entirely, and no Owner setting reaches it. Shrinking that population is a separate job, covered in replacing personal MCP servers on laptops.
A second gap is worth putting to Anthropic directly. As of this writing, Anthropic's published docs do not state whether removing a connector revokes members' already-issued OAuth tokens for it or merely hides the connector from the UI going forward. Treat that as an open question, not a settled fact, until Anthropic documents it. Do not assume removal equals revocation. On the Elaichi side the behavior is written down. A person ends their own grant under Settings, then Connected apps. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.
Writing the approved-apps list in Elaichi
Behind the single custom connector, Elaichi starts permissive and you narrow it. Every organization uses one address, https://api.elaichi.ai/mcp, added once. A Member role holds connection:create, so with no restriction in place a member can connect any of the 600+ apps in the catalog using their own account. That is the right default for a pilot and the wrong one for a company of 300.
A restriction is a rule naming which connectors and which individual tools a target may reach. Targets are a role or a single user. There is no organization-level target, because the organization default is the absence of any rule, which means allow everything. So the approved-apps list is an allow rule written on the role. There is no separate "approved apps" object; the rule itself is the list.
Three properties decide whether the rule you write is the rule you meant:
- In Elaichi, the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. It is easy to create by accident, for example by saving a rule before adding any entries to it.
- An allow rule naming a connector whole reaches all of that connector and denies everything else. That is how an approved-apps list is written.
- An allow rule naming a connector whole and some of its tools reaches all of that connector anyway. The tool entries grant nothing extra and read as tighter than they are. The API refuses that overlap on new rules, so it cannot be created going forward, but check existing rules for this pattern if they predate the validation.
Blocks union with blocks, allows union with allows, and blocks always beat allows. A user-targeted rule replaces the role's rules entirely rather than layering on them. It is a full substitution, not an addition. Enforcement runs at four points, all checked against the same resolver:
- Browse: what the member sees when listing available connectors and tools.
- Connect: whether the member is permitted to link an account to a given app.
- Advertise: whether the tool is included in the schema Claude's model actually sees.
- Execute: whether a specific call is allowed to run.
Plus a final check on the outbound URL, independent of the above four. A tool withheld at the advertise step is invisible: the model is never told it exists, so it never tries to call it. For the split between allowing an app whole and allowing single tools, see restricting one tool or the whole app.
A role or restriction change takes effect within about two minutes. Plan a change window of a few minutes, then verify with a test account before telling the requester it's done.
Write blocks and allows knowing they match differently. A block matches the tool's advertised name or the operation pinned at write time. An allow matches the pinned operation only. A tool's advertised name can be changed by whoever edits the connector's documentation, so governance binds the operation, never the label. A rename should not silently reopen something you blocked. The reasoning is in why blocks match names and allows do not.
Whose account does an approved app run on?
Approving the app is half the decision. The other half is whose credential the calls run on. When each person connects their own account, the app's own permission model stays in play, and the audit trail inside that app names the right person. A shared connection runs on its owner's credential, so every call through it reaches the app as that one account, regardless of who initiated the call from Claude.
If one argument has to be fixed for a whole team, say a specific wire-transfer receiver, a specific Slack channel or a specific cost-center ID, a restriction is the wrong instrument, because a restriction only decides reachability, not argument values. Use frozen parameters on a toolbox entry instead. Frozen keys are stripped from the advertised schema, so the model never sees them and cannot be prompted into overriding them; frozen values are merged over whatever the caller passes, after the fact. Precedence runs: entry defaults, then caller arguments, then frozen parameters. Frozen always wins last.
The freeze holds only on the path that runs through the entry. So the owner leaves the connection unshared, pins it into a toolbox entry with the frozen values, and shares the toolbox at use. Grantees run the tool only through that entry. Anyone who also holds use on the connection itself can still call the same tool unfrozen, through the raw connection. Closing that second path with a restriction does not work, because a block would withhold the frozen entry too, not just the raw path. The worked example is in locking an agent's tool arguments.
Access requests as the intake for the next app
Access requests are Elaichi's version of Claude's Request button, and they work across every connected app, not just directory ones. Any member can file one, with no permission needed to ask. Resolving one needs member:manage, and an admin cannot decide their own request. That is a hard rule, not a convention.
Approving a request that was caused by a restriction opens that connector or tool for that one requester only. A requester restricted through their role gets an except rule layered on top, so the role's other rules still bind them and the approval does not quietly widen the list for everyone else sharing that role. The approval is standing, not a one-time pass. It persists until someone revokes it.
Two limits belong in your runbook. First, restrictions stay read-only on AI surfaces: neither an MCP client nor the Elaichi Agent can approve a restriction-caused request from inside a chat. Denying still works there, as does approving a request whose cause was a missing permission rather than a restriction. Second, when the request names an app Elaichi does not carry, such as GitHub, Datadog, Linear, or any app outside the catalog, the answer is different: either the app's own MCP server, or a custom connector pointed at it. Keep connector:create on roles you already gate carefully, because a custom connector can be pointed at any destination, including ones you did not intend.
The record of what was approved and used
The audit trail turns an approval into evidence. An audit log here is an append-only record of actions.
Elaichi writes one entry per tool-call attempt, succeeded or failed, not just successful calls. The entry also records the surface the call came through and the OAuth client it came from, with the client's name marked verified only when its registered redirect URIs prove it. Claude is among the clients that verify.
Approval is stated in plain words on the entry. For example, "Allowed by the access Claude was granted" for a call over MCP, or "Didn't need approval because it only read data." That sentence, read next to your allow rule, is the before-and-after pair a reviewer wants: the rule as written, and the system's own statement of why a specific call was or wasn't let through. Give the reviewer the free read-only Auditor seat rather than an admin login. They need to read the trail, not change the rules. More on what belongs in those records: what an AI agent audit log must capture.
A checklist to run for each new app
Run this once per app request, in order. It takes a few minutes and it survives a change of admin.
- Name the app and check the catalog. If Elaichi does not carry it, decide between the app's own MCP server and a custom connector before anything else.
- Decide whose account it runs on. Per-person connections keep the app's own permissions in play. A shared connection reaches the app as its owner, for every caller.
- Decide app-wide or tool-level. Allow the connector whole when the whole app is approved. Do not mix a whole-connector entry and tool entries in one allow rule. The API will reject the overlap.
- Write the rule on the role. A user-targeted rule replaces that person's role rules completely, so keep user rules for exceptions you can name individually, not for standing policy.
- Verify what a member sees. Wait about two minutes for the change to take effect, then check the tool list from a test account on that role. A withheld tool looks exactly like a tool the connector never had, so there is no error to spot and you have to check directly. The other reasons a tool goes missing are in the missing-tool checklist.
- Leave access requests as the intake. The next app should arrive as a request you decide on, not as a connection you discover later in an audit log.
- Name the reviewer. Decide who reads the audit trail each month, and give them the Auditor seat, not an admin login.
When one approval surface is enough
If your company runs Claude and nothing else, and the approved list is one or two SaaS tools that ship their own MCP servers, Anthropic's directory and tool permissions are the whole job. A second control plane buys you nothing yet. The case for a control plane like Elaichi starts when the same approval has to hold across Claude, ChatGPT and Cursor at once, when the number of approved apps is large enough that per-connector console toggles stop scaling, or when a leaver's access through the endpoint has to end for every connected app in one action. That threshold is argued in when you do not need an MCP gateway yet.
For the shape of the thing behind the single custom connector, read what an MCP control plane is. For the rollout order across clients, see how to roll out Claude and ChatGPT to employees, and for the setup itself, connecting Elaichi to Claude. To check which apps are already covered before you write the allow rule, browse the connector catalog and the team use cases.