Provider REST API

Security

Connect Claude to Okta

Read an Okta org's users, groups, applications, MFA enrolment and system log. Toolspoke puts 12 of its actions behind one MCP endpoint that Claude, Cursor, and Codex all speak.

Connection
Provider REST API
Authentication
API token (SSWS)
Actions exposed
12
Cost per call (typical)
1 credit
Adapter
Maintained by Toolspoke

Connected in three steps

  1. 1

    Install Okta

    Open the marketplace in your workspace, add Okta to the project your agents work in, and it appears on the gateway immediately.

  2. 2

    Connect the credential

    Authenticate with api token (ssws). Where to get one, and what it has to be able to reach, is the next section.

  3. 3

    Point your agent at the gateway

    Give your client one address, https://toolspoke.com/mcp. Claude Code takes it as a command, Claude and Claude Desktop add it as a custom connector, and Cursor, Codex and VS Code each read it from a config file of their own.

.mcp.json
{
  "mcpServers": {
    "toolspoke": {
      "type": "http",
      "url": "https://toolspoke.com/mcp"
    }
  }
}

One block covers every tool you have installed. Okta shows up in the client as soon as your policy allows it, and so does everything else you install later.

Where the address goes, per client

Claude Code

Run it in your project, then /mcp to sign in

claude mcp add --transport http toolspoke https://toolspoke.com/mcp
Claude and Claude Desktop

Settings, then Connectors, then Add custom connector

https://toolspoke.com/mcp
Cursor

~/.cursor/mcp.json, or .cursor/mcp.json for one project

{ "mcpServers": { "toolspoke": { "url": "https://toolspoke.com/mcp" } } }
Codex

~/.codex/config.toml

[mcp_servers.toolspoke]
url = "https://toolspoke.com/mcp"
VS Code

.vscode/mcp.json, or the MCP: Add Server command

{ "servers": { "toolspoke": { "type": "http", "url": "https://toolspoke.com/mcp" } } }

What Okta asks for

API token (SSWS). You provide it once, when you install the connector. Toolspoke encrypts it at rest and decrypts it only for the length of a single call, and the gateway attaches it to the outbound request itself, so it is never part of the arguments an agent sends.

Okta org domainRequired
The hostname only - no https://, no trailing slash, no /api/v1. For example acme.okta.com, acme.oktapreview.com, or a custom domain such as id.acme.com.
acme.okta.com
API tokenRequired
Okta Admin Console → Security → API → Tokens → Create token. The token inherits the permissions of the administrator who created it, so create it while signed in as a read-only administrator: every action in this connector is a read, and a token with more than that is more blast radius than anything here can use. Okta expires a token that goes 30 days without being used.
Paste the token

What Claude can do in Okta

12 actions, each one declared and named by the connector rather than discovered at runtime. A workspace policy grants a person all of them, a hand-picked selection, everything on the read side, everything on the write side, or none.

Reads
12Reads
Writes
0Writes
Destructive
0Destructive

Reads

12

Fetches data and changes nothing.

  • list_users

    List the people in the org, newest first, with each one's id, status, profile and sign-in timestamps. This is the entry point for the user side: get_user, list_user_app_assignments and list_user_factors all take the id returned here. Use `filter` for an exact, indexed expression over status, id, type.id, and the profile's firstName, lastName, login and email - for example "status eq \"ACTIVE\"" or "profile.email eq \"[email protected]\"". Use search_users instead for a broader expression that covers custom profile attributes. Paging is by the `after` cursor Okta returns in its Link header, not by an offset.

  • get_user

    Fetch one person by id, login, or login shortname, with their full profile, status and sign-in timestamps. Okta accepts an email address here as well as an id, so this is the way to answer "who is [email protected]" without a search first. The status values that matter are ACTIVE, PROVISIONED, STAGED, RECOVERY, PASSWORD_EXPIRED, LOCKED_OUT, SUSPENDED and DEPROVISIONED.

  • search_users

    Search people with an expression that reaches custom profile attributes and supports sorting, which the plain `filter` on list_users does not. `search` takes an SCIM-style expression such as "profile.department eq \"Engineering\"", "profile.lastName sw \"Do\"" or "status eq \"ACTIVE\" and lastUpdated gt \"2026-01-01T00:00:00.000Z\""; `q` is the simpler alternative that matches the beginning of firstName, lastName or email. Give one or the other, not both. Search results in Okta are eventually consistent, so a person created seconds ago may not appear yet - use get_user when the id or login is already known.

  • list_groups

    List the org's groups with each one's id, name, description, type and member count. Groups are how application access is handed out in bulk, so this is the map of who can reach what before any individual person is looked at. `type` is OKTA_GROUP for groups managed in Okta, APP_GROUP for groups imported from an application, and BUILT_IN for Everyone. Narrow with `q` (starts-with on the group name), `filter` (indexed properties) or `search`; pass expand=stats to include the member count.

  • get_group

    Fetch one group by id, with its name, description and type. Read it to confirm which group an id refers to before calling list_group_members, which returns the people in it.

  • list_group_members

    List the people in one group, with each one's id, status and profile. This is the answer to "who can reach the applications this group grants". Paging is by the `after` cursor from the previous response's Link header; a large group needs several calls.

  • list_applications

    List the applications configured in the org, with each one's id, label, sign-on mode and status. This is the inventory of what Okta federates into - the SAML and OIDC integrations, the SWA apps, and the bookmarks. Use `filter` for the indexed properties, which are the only ones Okta will filter on here: "status eq \"ACTIVE\"", "user.id eq \"00u...\"", "group.id eq \"00g...\"" and "credentials.signing.kid eq \"...\"". Filtering by group id is how to answer "what does this group actually grant".

  • get_application

    Fetch one application by id, with its sign-on mode, settings and lifecycle state. Use it after list_applications to read how a single integration is configured - the SAML assertion settings, the OIDC redirect URIs, the visibility rules. Client secrets are not returned by this endpoint and this connector exposes no operation that returns one.

  • list_user_app_assignments

    List the applications one person can actually reach - the tiles on their Okta dashboard - with the application id, label and sign-on URL of each. This is the per-person answer to "what does this account have access to", and it is the call to make when reviewing a leaver or an escalation. It resolves both direct assignments and the ones inherited from a group, which list_applications filtered by group.id cannot do on its own.

  • list_system_log_events

    Read the org's System Log - who signed in from where, what failed, which admin changed what, and when. This is the operation to reach for after a suspicious sign-in or an unexplained configuration change. `filter` is Okta's indexed SCIM expression over eventType, target.id, actor.id and outcome.result, e.g. "eventType eq \"user.session.start\" and outcome.result eq \"FAILURE\""; `q` is a plain keyword match across the record. Always give `since` - without it Okta returns the last seven days and pages forever. Timestamps are ISO 8601 with milliseconds, e.g. 2026-08-01T00:00:00.000Z.

  • list_user_factors

    List one person's enrolled authentication factors, with the type, provider and status of each. This answers "does this account have a second factor, and what kind" - the question behind most access reviews and most compromised-account triage. The factor's `profile` is deliberately not returned: it holds the enrolled phone number or email address, and the answer to the question does not need it. Nothing here can enrol, reset or unenrol a factor; this connector has no writes at all.

  • get_org_settings

    Read the org's own settings - company name, subdomain, status, support contact and creation date. It is the cheapest call an API token can make and takes no arguments, which is why it is what an install runs to prove the token and the org domain are both right. It returns the account's own configuration and no personal data, so unlike most reads here its response is kept in the audit log.

What it will not do

Enforced by the gateway rather than left to convention, which is why each of these can be stated flatly.

It cannot call anything else
The 12 actions above are the whole of it. A call to any other name is refused before it reaches Okta rather than forwarded on, and connecting your account does not add to the list: it is fixed by the connector, not discovered at run time.
It only reads
Every action here reads. Nothing this connector can do changes anything in Okta.
It reaches no further than your credential
Toolspoke holds no access to Okta of its own. Every call carries the credential you stored and nothing besides, so whatever that credential cannot reach, this connector cannot reach either.
It never hears from Okta
Nothing is pushed to it. There is no webhook, no subscription and no polling, so this connector cannot notice by itself that something changed in Okta. An agent has to ask.
It does not smooth over provider limits
Toolspoke does not retry, queue or back off around Okta's own rate limits. A call that Okta refuses comes back to the agent as a failed call.

Before you connect it

What can Claude do in Okta?

12 named actions: 12 that only read. They include list_users, get_user and search_users. Nothing outside that list is reachable: the connector declares each operation by name rather than proxying whatever an agent asks for.

What credentials does the Okta connector need?

API token (SSWS). The connector asks for okta org domain and api token. Values are encrypted at rest and attached to the outbound request by the gateway, so they are never part of the arguments an agent sends and never reach the audit log.

Does the Okta connector work with Cursor and Codex, or only Claude?

Any client that speaks MCP, and every one of them gets the same 12 actions. There is a single address, https://toolspoke.com/mcp. Claude Code adds it with claude mcp add --transport http, Claude and Claude Desktop take it as a custom connector in settings, Cursor reads it from .cursor/mcp.json, Codex from ~/.codex/config.toml, and VS Code from .vscode/mcp.json. Each of them signs in to the gateway itself, so there is no key to paste.

What does the Okta connector not do?

The 12 actions above are the whole of it. A call to any other name is refused before it reaches Okta rather than forwarded on, and connecting your account does not add to the list: it is fixed by the connector, not discovered at run time. Every action here reads. Nothing this connector can do changes anything in Okta. Toolspoke holds no access to Okta of its own. Every call carries the credential you stored and nothing besides, so whatever that credential cannot reach, this connector cannot reach either. Nothing is pushed to it. There is no webhook, no subscription and no polling, so this connector cannot notice by itself that something changed in Okta. An agent has to ask. Toolspoke does not retry, queue or back off around Okta's own rate limits. A call that Okta refuses comes back to the agent as a failed call.

Can I limit which actions an agent can call?

Yes, in two places. The project switches Okta's actions on and off one at a time, for everyone in the project at once, and the screen groups them by read, write and destructive so turning off everything that deletes is one click. An individual agent key can then be narrowed further, to particular toolkits in a project and to particular actions in a toolkit. Whatever it was granted, a key never reaches a project its owner cannot.

What gets recorded when an agent calls Okta?

Every attempt, with the agent that made it and the person that agent belongs to, the full request payload, the response payload, the status, the duration, and the credits spent. Values whose key names a secret are masked out before the record is shown to anyone. An operation the connector marks as not retained never has its response body written at all, so the gateway keeps no second copy of what was read.