Skip to main content
Glama
kaivalyapowale

Test-Governance MCP Server

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)

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 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

F
license - not found
-
quality - not tested
D
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

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