Test-Governance MCP Server
Provides tools for interacting with Okta Identity Governance APIs, enabling AI agents to manage users, groups, apps, entitlements, access requests, certification campaigns, and more with built-in safety controls.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Test-Governance MCP Servershow pending access requests for the marketing team"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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 modes —
read-only,governance-admin,full-adminfor admin use;delegatedfor end-user access via their own Okta loginEnd-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)
Related MCP server: TAKO MCP Server for Okta
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 buildConfiguration
All configuration is via environment variables. Copy .env.example to .env and fill in your values:
cp .env.example .envRequired
Variable | Description |
| Your Okta org URL (e.g., |
Authentication (choose one)
Option 1: SSWS API Token (simpler, good for development)
Variable | Description |
| Okta API token (created in Admin > Security > API > Tokens) |
Option 2: OAuth2 Client Credentials (recommended for production)
Variable | Description |
| OAuth2 service app client ID |
| Path to RS256 private key PEM file |
| 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 |
|
|
|
| — | Required for |
|
| SQLite database path for audit log and token tracking |
|
|
|
|
| HTTP server port (when transport is |
|
| HTTP server bind address |
|
|
|
Delegated Mode Configuration
Delegated mode requires additional configuration for the OAuth2 Authorization Code flow with PKCE. This mode requires HTTP transport.
Variable | Description |
| Client ID of an Okta app configured for Authorization Code + PKCE (SPA or Native type) |
| Redirect URI registered in the Okta app (e.g., |
| Comma-separated scopes (defaults to |
| Secret key for signing session cookies (use a random 32+ character string) |
Usage
Stdio transport (Claude Desktop, CLI)
npm startAdd 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 startEndpoints:
POST /mcp— MCP JSON-RPC endpointGET /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 startAuth flow (browser — cookie-based):
User visits
GET /auth/login→ redirected to Okta sign-in pageAfter login, Okta redirects to
GET /auth/callback→ session cookie is setAll subsequent
POST /mcprequests use the user's own access tokenGET /auth/status— check if authenticatedPOST /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 |
| Query users, groups, apps, entitlements, grants, campaigns, etc. | Safe exploration and reporting |
| Read + create access requests, launch campaigns, submit decisions, assign group/app membership | Day-to-day governance operations |
| 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 |
| 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
userIdis 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
User opens your app — the frontend checks
GET /auth/status. If not authenticated, it redirects the user toGET /auth/login.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.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.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?" |
| Returns user's groups, apps, and active grants in one call |
"Show me my groups" |
| Lists groups the user belongs to |
"What can I request access to?" |
| Browses the access catalog scoped to the user |
"Request access to Salesforce Admin role" |
| Submits an access request with the user as requester |
"What's the status of my requests?" |
| Lists the user's access requests with status |
"Do I have any reviews to complete?" |
| Lists pending certification items assigned to the user |
"Approve the review for Jane's access" |
| 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, origa_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
Go to Okta Admin Console → Applications → Create App Integration
Select OIDC - OpenID Connect → Single-Page Application (or Native)
Set Sign-in redirect URI to your
OKTA_DELEGATED_REDIRECT_URI(e.g.,http://localhost:3000/auth/callback)Set Sign-out redirect URI if needed
Under General Settings, ensure Authorization Code grant type is enabled (with PKCE — this is default for SPA apps)
No client secret is needed (PKCE replaces it)
Under Assignments, assign the users or groups who should have access
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 |
| View your own Okta profile |
| List groups you belong to |
| List applications assigned to you |
| Full summary of your access: profile, groups, apps, and active grants |
| Browse the access catalog to discover requestable entitlements |
| Submit an access request (requesterId auto-set to you) |
| List your own access requests and their status |
| List certification review items pending your 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 |
|
| Manage users and their memberships |
|
| Query groups and membership |
|
| Query application integrations |
OIG Governance Tools (require OIG license)
Tool | Actions | Description |
|
| Manage application entitlements |
|
| Entitlement bundles (access packages) |
|
| Resource collection groupings |
|
| Governance policies |
|
| Separation of duties rules and violation detection |
|
| Active entitlement grants |
|
| Certification campaigns |
|
| Access request workflows |
|
| Security review management |
| — | Browse the access catalog |
| — | 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 |
| Full picture of a user's access: profile, groups, apps, grants, pending requests, SoD violations. Supports |
| Timeline of governance-relevant changes for a user over a time range |
| Org-wide governance snapshot: active campaigns, pending requests, open reviews, SoD violations |
| Risk scoring for a user based on grant count, auth failures, login recency, and account status |
| 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 redactionSecurity
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, orclientSecretare replaced with[REDACTED]in logsResponse 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
HttpOnlyandSameSite=LaxNo 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;
userIdcomes from the session, not from parametersOkta-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 --noEmitDependencies
Package | Purpose | License |
MCP server SDK | MIT | |
SQLite for audit log and token tracking | MIT | |
JWT signing for OAuth2 client credentials | MIT | |
API response caching | ISC | |
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
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/kaivalyapowale/test-governance-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server