# Okta MCP access for IT team: reads in Cursor, writes blocked

> Okta MCP access for IT team: give IT read access to Okta users and groups from Cursor, block deactivation and app assignment, and keep connector:create tight.

**TL;DR** Okta MCP access for IT team work means IT reads users and groups from Cursor while deactivation and app-assignment tools stay blocked. In Elaichi you write the block rules on the IT role, then connect Okta with a narrow account. Keep connector:create with Org Owner and Org Admin, because a new connector aimed at the same API is not caught by a block on the old one.

## The situation

Your IT team lives in Cursor. They are already asking the agent about tickets and [repositories](/blog/github-mcp-server-for-a-company-with-sso/). The next question is the obvious one. Can it look up who is in the Finance group, or whether a new hire landed in the right app? Okta is right there behind an API. The reason you hesitate is simple. The same API that lists a user can deactivate one. The same credential that reads group membership can add somebody to a group that grants production access.

That is the shape of Okta MCP access for IT team rollouts. Reads are useful every day. Writes are rare, consequential and hard to undo. The answer is not to pick one. Let the reads through and stop the writes before they leave Elaichi. MCP, the Model Context Protocol, is the standard an AI client uses to list and call tools. Elaichi serves it at one address for the whole organization. Every call is checked against the caller's role before the credential is used.

This post is about the governance shape, not about typing a URL into Cursor. For the connection steps, read the walkthrough on [connecting Elaichi to Cursor for a whole team](/blog/cursor-mcp-one-endpoint-vs-per-developer/).

## How do you set up Okta MCP access for IT team members?

Write block rules on the IT role naming every Okta tool that is not a read. Then have each IT member connect Cursor once with their own sign-in. Elaichi enforces the rule on every call, whatever client sent it. Cursor supports OAuth for MCP servers that require it, and reads a remote server from a `url` entry in its own `mcp.json` ([Cursor's MCP docs](https://cursor.com/docs/mcp), checked October 2026).

The order matters. Restrictions first, connection second. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. An IT persona role is where the rule belongs, and an unconfigured role is an open role.

Block rules alone have a gap. A layer with only block rules has no allowlist, so everything it does not block passes it. Block three obvious write tools on the Okta connector and every write tool you did not name stays reachable. Two ways out:

- **Allow rules naming the read tools.** Once a role carries any allow rule, every connector and tool that none of its allow rules names is blocked for that role. That holds across the whole catalog. So if you allow eight Okta read tools, add whole-connector allow rules for every other app that role uses. Otherwise you have cut IT off from Jira and Slack by accident.
- **Block rules naming every tool that is not a read.** More typing up front, no collateral damage elsewhere.

For a team that already reaches several apps through one endpoint, the block list is usually the smaller change. For the reasoning behind picking one or the other, see [restrict one AI tool or the whole app](/blog/per-tool-vs-per-app-restrictions/). The [Okta connector page](/connectors/okta/) lists the tools you will be naming.

## Which Okta tools should IT not reach from an AI client?

Anything that deactivates a user, changes group membership, or assigns or unassigns an application. Those are the shapes that turn a lookup question into an access change.

When you save a rule, Elaichi looks each named connector and tool up in the organization's catalog. A name it cannot find is refused. Each tool's operation is stored beside its name. A block rule then matches by name or by operation, so renaming a tool cannot slip it past a block. An allow rule matches only by the stored operation, never the name, because a tool's name is set by whoever edits the connector. That asymmetry is deliberate; [why blocks match tool names but allows do not](/blog/block-matches-name-allow-matches-operation/) covers it properly.

A block rule reaches one more thing. A block on a connector also blocks every fork that declares descent from it. Elaichi walks the lineage toward its root for up to eight hops. A chain that is longer, loops or is broken is refused outright rather than checked partially. So somebody forking the Okta connector to make a tidier version does not escape the block.

## Why is connector:create high trust for this team?

Because a restriction binds a connector's identity: its slug and its declared fork lineage. It deliberately does not bind the host the connector calls. A member with connector:create can build a new connector aimed at the same API. Your block on the old connector will not catch it.

This is the one permission Elaichi flags as high trust. The role editor shows a "High trust" tag on it. Its description warns that connector governance binds the connector, not the host it calls. Elaichi checks a custom connector's config for shape, not for where it points, and the permission text says a connector can be pointed at any destination.

For an IT team this cuts closer than for most. IT is the group that knows the Okta API and holds the credentials. It would reasonably want a connector that does the one thing the catalog connector does not. Among the system roles, connector:create and connector:manage sit only with Org Owner and Org Admin. If you are authoring a custom IT role, leave both out. Route the genuine need through whoever holds them.

One related limit on custom roles catches people. A custom role may include only permissions its author currently holds. So an Org Admin cannot grant a role something they do not hold. Editing or deleting a custom role also requires holding every permission that role currently has.

## What does the IT role actually look like?

One role, not two. A member holds exactly one role in an organization, and role writes refuse zero roles or more than one. Each role is meant to be a complete persona. To combine two personas you author a custom role rather than stacking them.

For a help desk persona that reads Okta from Cursor, three permissions matter:

- **tool:execute.** Without it the member's tool list over MCP is empty. Every call is refused in-band, with a message saying re-authorizing cannot help.
- **connection:create**, so each person connects their own Okta account rather than inheriting somebody else's.
- **connector:view**, to browse the catalog.

Leave out connector:create, connector:manage, restriction:manage and restriction:override. A member who can edit restrictions can edit their own way out of them. Elaichi enforces one exception here. An admin cannot create, edit or delete a restriction aimed at themselves while someone else's rule restricts them. They also cannot write one aimed at a role whose permissions exactly match their own. Both are refused, with a message asking another admin to make the change.

If you are designing this role from scratch, [designing roles for AI agents](/blog/designing-roles-for-ai-agents/) walks the one-role-each constraint in more detail.

## How does a member see that a tool is blocked?

They see the tool's name, flagged as restricted, with no description, no input schema and no way to call it. Elaichi does not hide a restricted tool. It names it and refuses it.

When somebody searches for a tool, Elaichi searches the tools they may run. It then ranks their restricted tools separately against the same query and returns those matches by name, flagged restricted, with a count. A connector blocked whole shows as one row for the connector. Calling a restricted tool's exact name returns a restriction refusal rather than "Unknown tool". The refusal says whether the block comes from their role or from their own account, and that an admin can lift it through an access request. It does not name the rule, who wrote it, why, or what else it covers.

That design decision keeps the help desk from filing a ticket about a broken AI. They can see that the deactivation tool exists and is not theirs, which is the correct mental model.

From the client, a member can file their own access request. Any member can file one, filing needs no permission, and a request is always for the caller themselves. An admin resolves it in the console under Governance, then Access requests. That needs member:manage and a step-up confirmation. No AI surface can approve or deny a request, denials included.

## Connecting the account: whose Okta sign-in?

Each IT member's own, not one shared service account, where Okta supports per-person sign-in. Every call through a connection fetches credentials from that one connection's bound account. The caller's own identity plays no part in whose credential is used.

That last sentence is the one people misread. A shared connection runs every caller's call as its owner. Say one person connects Okta with a broad admin account and shares the connection with the team at use level. Every member then reaches Okta as that admin, and only Elaichi's restrictions hold them back. The restrictions do hold, on every call, for the person calling rather than the connection's owner. But you have removed a layer you did not need to remove.

Where per-person connections are possible, have each member connect their own. Restrictions in Elaichi then narrow what each of them can do through it. Where only one credential exists, connect it with the narrowest account that covers the reads, and lean on the block rules. Either way, the credential never reaches the AI client. Elaichi's credential service holds every connected account's secrets encrypted, and fetches them into memory only for the call that needs them.

## When you do not need any of this

If one IT person wants Okta lookups in their own Cursor and nobody else is asking, a narrow read-only credential against Okta's own API is a smaller thing to maintain. You get no shared audit trail and no role rules, and you do the offboarding by hand. For one person that may be the honest trade. [When you do not need an MCP gateway yet](/blog/when-you-dont-need-an-mcp-gateway/) argues the threshold.

The case for routing it through Elaichi starts when there are several IT people, several apps, and somebody who will eventually leave. Then one address, one set of role rules and one audit log across apps is worth the setup. The audit log records each connected-tool call with the acting person, the connector, the connection the call reached, the tool's classification and the surface it came from. Over MCP it also records the client's id. Elaichi keeps 90 days of audit history.

When someone leaves, removing the member revokes every live MCP grant they hold in that organization. That happens inside the same call that deletes the membership, so their clients fail on the next request rather than after a cache window. Role and restriction changes are slower. They take about two minutes, because resolved permissions and restrictions are cached per point of presence.

## The order to do it in

Restrictions, then connections, then clients. If you connect first, there is a window where the role has no rules and therefore no limits.

Distribution is the client's business, not Elaichi's. On Enterprise, Cursor's MCP Allowlist is configured in the team dashboard under MCP Configuration, and adding a server there approves a configuration rather than pushing it to anyone's machine ([Cursor's model and integration management docs](https://cursor.com/docs/enterprise/model-and-integration-management), checked October 2026). Local servers are a separate inventory: the MCP project's own guide has each person list them in a config file on their own machine ([Connect to local MCP servers](https://modelcontextprotocol.io/docs/2026-07-28/develop/connect-local-servers), checked October 2026). One hosted endpoint spares you both.

For the whole-company view, [MCP governance](/blog/mcp-governance/) is the pillar. To compare this against an app vendor's own MCP server, [vendor MCP servers through Elaichi](/blog/vendor-mcp-servers-through-elaichi/) sets out the difference, and the [connector catalog](/connectors/) shows what is already there.

## FAQ

### Can an AI client deactivate a user in Okta through Elaichi?

Not if an admin has blocked the deactivation tools for that person's role. In Elaichi a restriction targets a role or one individual member. A block rule naming a tool stops every call to it before the connection's credential is used, whatever AI client sent the call. Blocks match a tool by its name or by the operation it performs, so renaming the tool does not slip it past the block. If no restriction rule reaches a member at all, nothing is restricted for them, so an unconfigured role is an open role.

### Why does blocking a few write tools leave other writes reachable?

Because a layer with only block rules has no allowlist, so everything it does not block passes it. Blocking three write tools on a connector leaves every write tool the rules do not name reachable. To hold a role to reads, write block rules naming every tool on that connector that is not a read. The alternative is an allow rule naming the read tools, plus whole-connector allow rules for every other app that role uses. That second route is needed because once a role carries any allow rule, every connector and tool none of its allow rules names is blocked for it.

### Why is connector:create called high trust in Elaichi?

Because restrictions bind a connector's identity, meaning its slug and its declared fork lineage, and deliberately not the host it calls. Someone who can create a connector can build a new one aimed at the same API, and a block on the original connector will not catch it. connector:create is the only permission Elaichi flags as high trust, the role editor shows a "High trust" tag on it, and its description warns that a connector can be pointed at any destination. Among Elaichi's built-in roles, only Org Owner and Org Admin hold it.

### Does a restricted tool disappear from the AI client's tool list?

No. Elaichi names a restricted tool and refuses it rather than hiding it. A tool search returns restricted matches by name, flagged as restricted, with no description or input schema and no way to call them, plus a count of how many were restricted. Calling a restricted tool's exact name returns a restriction refusal rather than "Unknown tool". That refusal says whether the block comes from the person's role or their own account, and that an admin can lift it through an access request. It does not name the rule, who wrote it, or what else it covers.

### How fast does a restriction change reach an AI client?

Within about two minutes. A member's roles, teams, permissions and resolved restrictions are cached for a short period. A change reaches every surface only once each point of presence sees the new state. Some changes are faster. Removing or suspending a member revokes their MCP grants in that organization, so their clients fail on the next call. Revoking a share or disconnecting an account also takes effect on the next call.

## Read next

- [Outreach MCP access for sales team in Cursor](/blog/sales-team-cursor-outreach-sequences/) — Outreach MCP access for sales team work in Cursor: allow sequence reads, block bulk enrollment and mailbox sends, and freeze the sequence owner.
- [GitHub MCP server for a company with SSO](/blog/github-mcp-server-for-a-company-with-sso/) — A GitHub MCP server for a company with SSO has two sign-ins to settle: your identity provider, and whose GitHub account the tool call actually runs as.
- [Linear MCP server for our engineering team](/blog/linear-mcp-server-for-our-engineering-team/) — A Linear MCP server for our engineering team changes whose account each call runs as, which tools stay on, and what the audit log keeps.
