Featured

Deploy OpenClaw in 60 seconds — 20% off logoDeploy OpenClaw in 60 seconds — 20% off

Launch OpenClaw on Hostinger in about 60 seconds and keep your agent live 24/7. Our referral link gives you 20% off, no coupon code needed.

Launch on Hostinger
Run your Hermes agent on Hostinger, fully managed logoRun your Hermes agent on Hostinger, fully managed

Launch Hermes on Hostinger in one click, fully managed, no VPS knowledge needed. Use code ZACAARON10 for 10% off.

Launch on Hostinger
Crawl and scrape any site into clean data, 10% off logoCrawl and scrape any site into clean data, 10% off

Firecrawl crawls and scrapes any site into clean markdown for your agent. Get 1,000 free credits, and new users get 10% off their first purchase.

Try Firecrawl free
6,000+ web scrapers for your AI agent, start free logo6,000+ web scrapers for your AI agent, start free

Apify gives your agent live web data: 6,000+ prebuilt scrapers and actors, MCP-ready. Sign up free with $5 in usage credits.

Try Apify free
One API to scrape, enrich, and extract the internet. logoOne API to scrape, enrich, and extract the internet.

Context.dev gives your agents a single API to scrape, enrich, and extract live web data — no proxies, no parsers, no maintenance.

Start building free
SetupClaw: done-for-you OpenClaw for founders & exec teams logoSetupClaw: done-for-you OpenClaw for founders & exec teams

White-glove OpenClaw for founders and exec teams (4–50+ employees): we install, harden, integrate your tools, and maintain it — secured from day one.

Get it set up for you
SEO data APIs for your agent, $1 free credit logoSEO data APIs for your agent, $1 free credit

DataForSEO gives your agent live access to SERP results, keyword data, backlinks, and on-page SEO data through one API. New accounts get a $1 credit, good for up to 20,000 keyword or backlink lookups.

Try DataForSEO free
Reach 48,000+ AI builders

A flat monthly placement in front of developers actively installing AI tools. No lock-in, cancel anytime.

Advertise here

Works with

Claude CodeClaude DesktopCursorVS CodeClineCodex CLIOpenClaw+ any MCP client

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

Enables AI assistants to securely access Okta Identity Governance APIs for managing users, groups, apps, access requests, and certifications with configurable deployment modes and safety controls.

README.md

Test - Governance MCP Server for OIG

Disclaimer: This project is a test/proof of concept developed using publicly available Okta APIs. This MCP server implementation is not affiliated with Okta, its official MCP servers, or its developer tools. This was developed on a personal device without any use of Okta (Okta, Inc.) resources or information outside of what is available to the public.

A Model Context Protocol (MCP) server that provides AI assistants with secure, structured access to Okta Identity Governance (OIG) APIs.

Built with TypeScript on Node.js, this server exposes 28 tools (19 admin + 9 end-user) that let LLMs query users, groups, apps, entitlements, access requests, certification campaigns, and more — with built-in safety controls for write operations.

Features

  • 28 tools — 19 admin tools for Okta core + OIG governance APIs, plus 9 end-user tools for delegated mode
  • Four deployment modesread-only, governance-admin, full-admin for admin use; delegated for end-user access via their own Okta login
  • End-user authentication — OAuth2 Authorization Code + PKCE flow lets users sign in with their own Okta credentials; the AI agent acts within their permissions
  • Confirmation protocol — write/destructive actions in admin modes require a two-step confirmation with HMAC-signed tokens
  • Intelligent rate limiting — tracks Okta's per-endpoint rate limits and backs off proactively
  • Response caching — LRU cache reduces redundant API calls (disabled in delegated mode to prevent cross-user data leaks)
  • Full audit trail — every tool invocation logged to stderr; mutations logged to SQLite
  • Two transports — stdio (for Claude Desktop, CLI tools) or HTTP (for web integrations and delegated mode)
  • Auto-detection — probes your Okta org at startup to determine if OIG is enabled (admin modes)

Prerequisites

  • Node.js >= 20
  • An Okta org with API access
  • Okta Identity Governance license (for governance tools; core user/group/app tools work without it)

Installation

git clone https://github.com/kaivalyapowale/test-governance-mcp.git
cd test-governance-mcp
npm install
npm run build

Configuration

All configuration is via environment variables. Copy .env.example to .env and fill in your values:

cp .env.example .env

Required

| Variable | Description | |---|---| | OKTA_ORG_URL | Your Okta org URL (e.g., https://your-org.okta.com) |

Authentication (choose one)

Option 1: SSWS API Token (simpler, good for development)

| Variable | Description | |---|---| | OKTA_API_TOKEN | Okta API token (created in Admin > Security > API > Tokens) |

Option 2: OAuth2 Client Credentials (recommended for production)

| Variable | Description | |---|---| | OKTA_CLIENT_ID | OAuth2 service app client ID | | OKTA_PRIVATE_KEY_PATH | Path to RS256 private key PEM file | | OKTA_SCOPES | Comma-separated OAuth2 scopes (see Scopes below) |

OAuth2 Scopes

The default scopes (okta.users.read, okta.groups.read, okta.apps.read, okta.logs.read) only cover core Okta APIs. If your org has OIG enabled, you will need additional governance scopes for the OIG tools to work. The exact scope names depend on your Okta org configuration — check your Okta Admin console under Security > API > Authorization Servers for available governance scopes (e.g., okta.governance.accessRequests.read, okta.governance.campaigns.read, etc.).

Alternatively, using an SSWS API token with sufficient admin permissions avoids scope configuration entirely, as SSWS tokens inherit the permissions of the admin user who created them.

Optional

| Variable | Default | Description | |---|---|---| | MCP_DEPLOYMENT_MODE | read-only | read-only, governance-admin, full-admin, or delegated | | MCP_CLIENT_SECRET | — | Required for governance-admin and full-admin modes. Used to sign confirmation tokens. | | MCP_STATE_DB_PATH | ./data/state.db | SQLite database path for audit log and token tracking | | MCP_TRANSPORT | stdio | stdio or http | | MCP_HTTP_PORT | 3000 | HTTP server port (when transport is http) | | MCP_HTTP_HOST | 127.0.0.1 | HTTP server bind address | | MCP_LOG_LEVEL | info | debug, info, warn, or error |

Delegated Mode Configuration

Delegated mode requires additional configuration for the OAuth2 Authorization Code flow with PKCE. This mode requires HTTP transport.

| Variable | Description | |---|---| | OKTA_DELEGATED_CLIENT_ID | Client ID of an Okta app configured for Authorization Code + PKCE (SPA or Native type) | | OKTA_DELEGATED_REDIRECT_URI | Redirect URI registered in the Okta app (e.g., http://localhost:3000/auth/callback) | | OKTA_DELEGATED_SCOPES | Comma-separated scopes (defaults to openid,profile,email,okta.users.read,okta.groups.read,okta.apps.read) | | MCP_SESSION_SECRET | Secret key for signing session cookies (use a random 32+ character string) |

Usage

Stdio transport (Claude Desktop, CLI)

npm start

Add to your Claude Desktop config (claude_desktop_config.json):

{
  "mcpServers": {
    "okta-governance": {
      "command": "node",
      "args": ["/absolute/path/to/oig-mcp-server/dist/index.js"],
      "env": {
        "OKTA_ORG_URL": "https://your-org.okta.com",
        "OKTA_API_TOKEN": "your-token",
        "MCP_DEPLOYMENT_MODE": "read-only"
      }
    }
  }
}

HTTP transport (admin modes)

MCP_TRANSPORT=http MCP_HTTP_PORT=3000 npm start

Endpoints:

  • POST /mcp — MCP JSON-RPC endpoint
  • GET /health — Health check (returns tool count and deployment mode)

Delegated mode (end-user access)

Delegated mode lets end users authenticate with their own Okta credentials. The server uses their access token for all API calls, so responses are naturally scoped to their permissions — no admin privileges required.

MCP_DEPLOYMENT_MODE=delegated \
MCP_TRANSPORT=http \
OKTA_ORG_URL=https://your-org.okta.com \
OKTA_DELEGATED_CLIENT_ID=your_spa_client_id \
OKTA_DELEGATED_REDIRECT_URI=http://localhost:3000/auth/callback \
MCP_SESSION_SECRET=$(openssl rand -hex 32) \
npm start

Auth flow (browser — cookie-based):

  1. User visits GET /auth/login → redirected to Okta sign-in page
  2. After login, Okta redirects to GET /auth/callback → session cookie is set
  3. All subsequent POST /mcp requests use the user's own access token
  4. GET /auth/status — check if authenticated
  5. POST /auth/logout — end session

Auth flow (CLI / non-browser — Bearer token):

For non-browser MCP clients (Claude Code CLI, MCP Inspector, custom scripts), you can pass a user's Okta access token directly via the Authorization header instead of using cookies:

curl -X POST http://localhost:3000/mcp \
  -H "Authorization: Bearer <user's Okta access token>" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"okta_my_profile","arguments":{}},"id":1}'

The server validates the token against Okta (GET /api/v1/users/me), extracts the user identity, and runs the tool as that user. This is stateless — no session is stored. Bearer tokens take priority over cookies if both are present.

Okta app setup: Create a SPA or Native application in Okta Admin (Applications > Create App Integration). Set the Sign-in redirect URI to match OKTA_DELEGATED_REDIRECT_URI. Enable Authorization Code grant type with PKCE. No client secret is needed.

Deployment Modes

The server supports four deployment modes. The first three are admin modes that use a service-level API token or OAuth2 client credentials. The fourth is delegated mode where each end user authenticates individually.

Admin Modes

| Mode | Access | Use Case | |---|---|---| | read-only | Query users, groups, apps, entitlements, grants, campaigns, etc. | Safe exploration and reporting | | governance-admin | Read + create access requests, launch campaigns, submit decisions, assign group/app membership | Day-to-day governance operations | | full-admin | All actions including revoke grants, remove memberships, user lifecycle (suspend/deactivate) | Full administrative control |

Write and destructive actions use a two-step confirmation protocol: the first call returns a preview and a signed token; the second call with that token executes the action. Tokens are single-use and expire after 5 minutes.

Delegated Mode

| Mode | Access | Use Case | |---|---|---| | delegated | End-user tools only: view own profile/groups/apps, browse catalog, request access, review certifications | AI-assisted end-user experience (e.g., chatbot, help desk) |

In delegated mode:

  • The user logs in with their own Okta credentials via OAuth2 Authorization Code + PKCE
  • All API calls use the user's own access token — no admin privileges
  • The user's userId is automatically injected into all tool calls (they can't query other users)
  • No confirmation tokens are needed — the user IS the actor
  • Admin tools are completely hidden; only end-user tools are available

Integrating with AI Agents (Delegated Mode)

Delegated mode is designed for building AI-powered end-user experiences — chatbots, help desk agents, or self-service portals where users interact with an AI assistant to manage their own access.

Architecture

┌─────────────────────────────────────────────────────────┐
│  End User's Browser / App                               │
│                                                         │
│  ┌──────────────┐     ┌──────────────────────────────┐  │
│  │  Chat UI /   │────▶│  AI Agent Backend             │  │
│  │  Frontend    │◀────│  (Claude, GPT, custom LLM)    │  │
│  └──────────────┘     └──────────┬───────────────────┘  │
│                                  │ MCP JSON-RPC          │
│                                  ▼                       │
│                       ┌──────────────────────────────┐  │
│                       │  This MCP Server             │  │
│                       │  (delegated mode, HTTP)      │  │
│                       │                              │  │
│                       │  /auth/login  → Okta SSO     │  │
│                       │  /auth/callback ← token      │  │
│                       │  /mcp ← tools (user context) │  │
│                       └──────────┬───────────────────┘  │
│                                  │ Bearer {user token}   │
│                                  ▼                       │
│                       ┌──────────────────────────────┐  │
│                       │  Okta APIs                   │  │
│                       │  (scoped to user's perms)    │  │
│                       └──────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘

How it works

  1. User opens your app — the frontend checks GET /auth/status. If not authenticated, it redirects the user to GET /auth/login.
  2. User signs in via Okta — standard Okta login page (SSO, MFA, etc.). After authentication, Okta redirects back to /auth/callback, which sets a session cookie.
  3. AI agent calls tools — the agent backend sends MCP JSON-RPC requests to POST /mcp. The session cookie is included automatically. Every tool call runs under the user's own identity.
  4. User asks questions naturally — e.g., "What apps do I have access to?", "Request access to Salesforce", "Do I have any pending reviews?". The AI agent translates these into the appropriate tool calls.

What the AI agent can do for the user

| User intent | Tool used | What happens | |---|---|---| | "What's my access?" | iga_my_access | Returns user's groups, apps, and active grants in one call | | "Show me my groups" | okta_my_groups | Lists groups the user belongs to | | "What can I request access to?" | iga_catalog_browse | Browses the access catalog scoped to the user | | "Request access to Salesforce Admin role" | iga_request_access | Submits an access request with the user as requester | | "What's the status of my requests?" | iga_my_requests | Lists the user's access requests with status | | "Do I have any reviews to complete?" | iga_my_pending_reviews | Lists pending certification items assigned to the user | | "Approve the review for Jane's access" | iga_submit_review_decision | Submits APPROVE/REVOKE on a review item |

Key behaviors in delegated mode

  • No userId parameter — the user's identity is injected automatically from their session. They cannot query other users' data.
  • No confirmation tokens — unlike admin modes, delegated tools execute directly because the authenticated user IS the actor making the request.
  • Okta enforces permissions — if the user doesn't have permission for an action, Okta returns 403. The server doesn't need its own permission layer.
  • Session expiry — tokens refresh automatically. If the refresh token expires, the user is prompted to log in again.
  • Admin tools are hidden — the AI agent only sees the 9 delegated tools. It cannot access admin-level tools like okta_users, iga_campaigns, or iga_risk_assessment.

Example: connecting Claude as the AI agent

If you're using Claude (or another LLM) as the agent backend with an MCP client library:

import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';

// The MCP client connects to your delegated-mode server
// The session cookie from the user's browser must be forwarded
const transport = new StreamableHTTPClientTransport(
  new URL('http://localhost:3000/mcp'),
  {
    // Forward the user's session cookie from the browser request
    headers: { Cookie: `mcp_session=${userSessionCookie}` },
  },
);

const client = new Client({ name: 'my-agent', version: '1.0.0' });
await client.connect(transport);

// Now call tools — they execute as the authenticated user
const myAccess = await client.callTool('iga_my_access', {});

Okta app setup for delegated mode

  1. Go to Okta Admin ConsoleApplicationsCreate App Integration
  2. Select OIDC - OpenID ConnectSingle-Page Application (or Native)
  3. Set Sign-in redirect URI to your OKTA_DELEGATED_REDIRECT_URI (e.g., http://localhost:3000/auth/callback)
  4. Set Sign-out redirect URI if needed
  5. Under General Settings, ensure Authorization Code grant type is enabled (with PKCE — this is default for SPA apps)
  6. No client secret is needed (PKCE replaces it)
  7. Under Assignments, assign the users or groups who should have access
  8. Copy the Client ID and use it as OKTA_DELEGATED_CLIENT_ID

Tools

Delegated End-User Tools (delegated mode only)

These tools are available when the server runs in delegated mode. They operate under the authenticated user's identity — no userId parameter needed.

| Tool | Description | |---|---| | okta_my_profile | View your own Okta profile | | okta_my_groups | List groups you belong to | | okta_my_apps | List applications assigned to you | | iga_my_access | Full summary of your access: profile, groups, apps, and active grants | | iga_catalog_browse | Browse the access catalog to discover requestable entitlements | | iga_request_access | Submit an access request (requesterId auto-set to you) | | iga_my_requests | List your own access requests and their status | | iga_my_pending_reviews | List certification review items pending your decision | | iga_submit_review_decision | Submit APPROVE/REVOKE decision on a review item assigned to you |

Admin Tools (read-only / governance-admin / full-admin modes)

Core Okta Tools (always available)

| Tool | Actions | Description | |---|---|---| | okta_users | list, get, groups, apps, lifecycle, assign_to_group, remove_from_group, assign_to_app, remove_from_app | Manage users and their memberships | | okta_groups | list, get, members | Query groups and membership | | okta_apps | list, get | Query application integrations |

OIG Governance Tools (require OIG license)

| Tool | Actions | Description | |---|---|---| | iga_entitlements | list, get, search, set_owner | Manage application entitlements | | iga_bundles | list, get, create, update | Entitlement bundles (access packages) | | iga_resource_collections | list, get | Resource collection groupings | | iga_policies | list, get, create, update | Governance policies | | iga_sod | list, get, detect, create | Separation of duties rules and violation detection | | iga_grants | list, get, revoke | Active entitlement grants | | iga_campaigns | list, get, create, launch, list_items, submit_decision, close, archive | Certification campaigns | | iga_access_requests | list, get, create, decide | Access request workflows | | iga_security_reviews | list, get, submit_finding | Security review management | | iga_list_catalog_entries | — | Browse the access catalog | | iga_get_audit_log | — | Query local mutation audit log |

Intelligence Tools (require OIG license)

These tools fan out to multiple APIs in a single call to provide aggregated insights.

| Tool | Description | |---|---| | iga_investigate_user_access | Full picture of a user's access: profile, groups, apps, grants, pending requests, SoD violations. Supports summary, detailed, and full depth. | | iga_explain_access_changes | Timeline of governance-relevant changes for a user over a time range | | iga_governance_dashboard | Org-wide governance snapshot: active campaigns, pending requests, open reviews, SoD violations | | iga_risk_assessment | Risk scoring for a user based on grant count, auth failures, login recency, and account status | | iga_access_coverage_report | Per-app governance coverage: entitlement discovery, active policies, recent certifications |

Architecture

src/
├── index.ts                  # Server entry point, transport setup
├── config.ts                 # Zod-validated configuration from env vars
├── auth/
│   ├── token-manager.ts      # SSWS and OAuth2 (JWT client credentials) auth
│   ├── session-manager.ts    # OAuth2 Auth Code + PKCE flow, session storage (delegated mode)
│   └── session-context.ts    # AsyncLocalStorage for per-request session threading
├── api/
│   └── client.ts             # HTTP client with caching, rate limiting, retries
├── state/
│   ├── repository.ts         # State interface (audit log, token tracking)
│   └── sqlite.ts             # SQLite implementation (better-sqlite3, WAL mode)
├── tools/
│   ├── registry.ts           # Tool registry with deployment mode filtering
│   ├── delegated.ts          # End-user tools for delegated mode (9 tools)
│   ├── users.ts              # okta_users
│   ├── groups.ts             # okta_groups
│   ├── apps.ts               # okta_apps
│   ├── entitlements.ts       # iga_entitlements
│   ├── bundles.ts            # iga_bundles
│   ├── collections.ts        # iga_resource_collections
│   ├── policies.ts           # iga_policies
│   ├── sod.ts                # iga_sod
│   ├── grants.ts             # iga_grants
│   ├── campaigns.ts          # iga_campaigns
│   ├── access-requests.ts    # iga_access_requests
│   ├── security-reviews.ts   # iga_security_reviews
│   ├── catalog.ts            # iga_list_catalog_entries
│   ├── audit-log.ts          # iga_get_audit_log
│   ├── investigate.ts        # iga_investigate_user_access
│   ├── explain-changes.ts    # iga_explain_access_changes
│   ├── dashboard.ts          # iga_governance_dashboard
│   ├── risk.ts               # iga_risk_assessment
│   └── coverage.ts           # iga_access_coverage_report
└── util/
    ├── types.ts              # Shared types (ToolResponse, ToolError, etc.)
    ├── errors.ts             # Error classes and Okta error mapping
    ├── response.ts           # Response builder helpers
    ├── confirmation.ts       # HMAC-SHA256 confirmation token protocol
    ├── action-filter.ts      # Per-action deployment mode filtering
    └── audit.ts              # Audit logger (stderr + SQLite) with field redaction

Security

All modes

  • No credentials in code — all auth is via environment variables
  • Rate limit awareness — proactively backs off when Okta rate limit headers show remaining capacity below threshold
  • Concurrency control — configurable semaphore limits parallel API calls (default: 3)
  • Deployment mode gating — tools and actions are filtered at registration time so the LLM never sees unavailable operations

Admin modes (read-only / governance-admin / full-admin)

  • Confirmation tokens — write/destructive operations require HMAC-SHA256 signed, single-use tokens with 5-minute expiry
  • Audit logging — all tool invocations logged to stderr; all mutations logged to SQLite with Okta request IDs
  • Sensitive field redaction — fields named password, secret, token, apikey, credentials, privatekey, or clientSecret are replaced with [REDACTED] in logs
  • Response caching — LRU cache reduces redundant API calls

Delegated mode

  • OAuth2 PKCE — Authorization Code flow with Proof Key for Code Exchange; no client secret stored on the server
  • Signed session cookies — session IDs are HMAC-signed to prevent tampering; cookies are HttpOnly and SameSite=Lax
  • No cross-user data — cache is skipped for all delegated API calls; each request uses only the authenticated user's token
  • User identity auto-injected — tools cannot be tricked into querying other users; userId comes from the session, not from parameters
  • Okta-enforced permissions — the server does not maintain its own permission model; Okta returns 403 if the user lacks access
  • Session lifecycle — tokens refresh automatically; idle sessions expire after 24 hours; expired pending auth flows are cleaned up every 5 minutes

Development

# Watch mode (recompiles on change)
npm run dev

# Run tests
npm test

# Type check without emitting
npx tsc --noEmit

Dependencies

| Package | Purpose | License | |---|---|---| | @modelcontextprotocol/sdk | MCP server SDK | MIT | | better-sqlite3 | SQLite for audit log and token tracking | MIT | | jose | JWT signing for OAuth2 client credentials | MIT | | lru-cache | API response caching | ISC | | zod | Schema validation for config and tool inputs | MIT |

Disclaimer

This project is a test/proof of concept developed using publicly available Okta APIs. This MCP server implementation is not affiliated with Okta, its official MCP servers, or its developer tools. This was developed on a personal device without any use of Okta (Okta, Inc.) resources or information outside of what is available to the public.

License

MIT

See related servers & alternatives →

Related MCP servers

Browse all →

Related guides

Hand-picked reading to help you choose and use Cloud & DevOps servers.