Skip to main content
Glama
fso-datawarrior

lab-mcp-identity-server


🎯 The 60-second version

  • An AI assistant is given five tools that operate a real Okta directory: look up, create, grant, revoke, deactivate.

  • The destructive tools (revoke, deactivate) cannot execute in the model's turn. They write a durable pending request and stop. Release happens on a separate local channel, behind a secret the model never sees. There is no approve, confirm, or resolve tool anywhere on the model's surface, and a test fails the build if one ever appears.

  • The design was built to make one bounded claim true by construction, then attacked on purpose (three adversarial probes) to see whether the claim held.

  • The whole 115-test suite runs with zero credentials (108 at publish, then 115 after concurrency hardening), so you can clone it and inspect the exact seam where the destructive branch stops, without an Okta account.

The claim. For the five enumerated identity tools, even a fully compromised model cannot execute a destructive action alone, because the control lives in the server and the out-of-band approval channel and not in the model's behavior. This holds while the server and that channel are uncompromised and the approver cannot be spoofed. The model can still be hijacked, and can still make the call. The gate constrains the outcome, not the model.

Read the full write-up: Even a Fully Compromised Model Cannot Deprovision a User Alone and its appendices. This repository is a learning artifact, not production software.


Related MCP server: gov-mcp

πŸ” Why this exists

The failure mode of AI governance is rarely a missing control. It is a control that exists in name and not in mechanism. A "separate" confirm tool the model could still call. An "append-only" log anyone could edit. A "read" that wrote instructions into the model's context. An "additive" grant that escalated a user to admin. Each named a safe idea while its enforcement lived in a convention the constrained thing could reach.

This lab is a documented case study of catching that gap before shipping: an independent blind review before any code, validation against what is actually on disk during the build, one live run against a real directory, and a deliberate adversarial pass, each stage leaving evidence you can re-check. The full story is in the methodology docs and the whitepaper.

🧱 Architecture: where the control actually lives

flowchart LR
  subgraph outside["OUTSIDE the trust boundary"]
    M["AI model / MCP client<br/>(assume fully compromised)"]
  end

  subgraph inside["INSIDE the trust boundary"]
    S["MCP server<br/>5 tools, no resolver tool"]
    P[("Durable pending store<br/>single-use, TTL")]
    CLI["Out-of-band approver<br/>separate process + secret<br/>the model never holds"]
    LOG[("Hash-chained, signed<br/>audit log")]
  end

  OKTA[("Real Okta directory")]
  LAB1[("Lab 1 SCIM server<br/>downstream system")]

  M -->|"Tier 1-2: get_user, grant, provision (execute + audit)"| S
  M -->|"Tier 3: revoke, deactivate"| S
  S -->|"write pending, return only an id"| P
  S -. "NO approve / confirm / resolve tool exists" .-> M
  CLI -->|"approve or deny with the secret"| P
  P -->|"approved: precondition re-check, then execute"| S
  S -->|"read / write"| OKTA
  S --> LOG
  OKTA -->|"group removal cascades via SCIM (~2.8s)"| LAB1

The destructive branch of every gated action terminates in the pending store and can only be released by the out-of-band approver, which runs in a separate process behind a secret the model never sees. A test pins the registered tool set to exactly the five operational tools and fails the build if a resolver ever appears. Two independent layers make the claim true: the resolver fails closed by construction, and the model has no tool that reaches it.

πŸ› οΈ The five tools

Tool

Kind

Tier

Gated

get_user

read

1

no (audited)

provision_user

additive

2

no (audited)

grant_access

additive

2 or 3

Tier 3 when the target group is protected

revoke_access

destructive

3

yes, out-of-band approval

deactivate_user

destructive

3

yes, out-of-band approval

Tier is a function of the target, not the verb: a grant into an ordinary group flows and is audited, a grant into a protected group is gated exactly like a removal, because adding a user to an administrative group escalates privilege as surely as any removal. delete_user was cut, because in Okta a delete requires a prior deactivation and is irreversible.

⚑ Quickstart (zero credentials)

git clone https://github.com/fso-datawarrior/lab-mcp-identity-server
cd lab-mcp-identity-server
pnpm install
pnpm test        # 115 tests, all green, no Okta account required

The whole suite runs against an in-memory mock directory, so a stranger can clone it, inspect the exact seam where the destructive branch stops, and run every test without any secret. That zero-credential path is a first-class property of the design: a control a stranger cannot inspect and exercise is a control a stranger has no reason to trust.

πŸ”Œ Running against real Okta (optional)

cp .env.example .env       # add your Okta org, service-app key, demo group id
pnpm seed:demo             # creates the demo group and users
pnpm smoke:okta            # 5/5 fixture check
pnpm start:real            # or register scripts/start-desktop.mjs in your MCP client

The go/no-go checklist (docs/MCP-SERVER-CHECKLIST.md) and the recovery runbook (docs/BREAK-GLASS.md) are the operator surface. pnpm approve <id> / pnpm deny <id> is the out-of-band channel. Point the real-mode path only at a throwaway developer org with the demo fixture.

πŸ“Š What we found (the honest part)

This lab scores its own gaps down, not up. A five-category agent-governance self-assessment, conservative and carrying no external audit:

Category

Score

The named gap

Audit trail

74

deletion-evidence is verify-time, not caller-independent; in-process signing key

Policy enforcement

71

code-enforced, not a policy engine

Human oversight

70

single approver, and in the demo a single shared secret, not an authenticated approver

Error handling

66

fails closed, but the mock is synchronously consistent while a real directory is not

Revocation capability

58

the service credential is scoped organization-wide (Okta scopes are org-wide)

Three adversarial probes, with honest denominators:

  • Probe A (gate bypass): 11 of 12 held. The one gap, a blank justification satisfying "justification required," was closed the same session.

  • Probe B (audit integrity): 7 of 10 held. The deletion-evidence family was closed with a named boundary via ADR-0003.

  • Probe C (live hostile-profile injection): one witnessed run where a poisoned read created nothing.

Full write-up in docs/PENTEST-FINDINGS.md.

One approved revoke removes an Okta group membership and, about 2.8 seconds later, deprovisions the same user in a second system entirely, through Okta's own provisioning, verified at the far end. One approval, two systems.

πŸ“– The methodology (how it was built and checked)

The most transferable thing here is not the server, it is the pipeline that produced it. Three curated records tell that story:

  • Assumption and Discovery Ledger, every design assumption the build walked in with, the point it broke, and what the design does instead. The reversals are the primary finding.

  • Build Evidence, what the code actually proved, milestone by milestone, with the monotonic test spine (7 to 115) and commit hashes.

  • Prompt Archive, how the build was driven, the one-unit-of-work-with-acceptance-criteria loop, and two representative verbatim prompts.

The portable heuristic: put the control where the constrained thing cannot reach it, then try to break it from the outside.

πŸ—ΊοΈ Repository map

Path

What it is

docs/whitepaper/

The whitepaper body and appendices

docs/methodology/

The ledger, build evidence, and prompt archive

ADR/

ADR-0001 (out-of-band gate), ADR-0002 (audit fidelity), ADR-0003 (deletion-evidence)

docs/PENTEST-FINDINGS.md

Probes A / B / C, held and gaps

docs/BREAK-GLASS.md

Recovery runbook (kill-switch, restore)

docs/MCP-SERVER-CHECKLIST.md

Live-demo go/no-go

src/

The server, the out-of-band approver, the audit chain, the Okta clients

test/, tests/

The 115-case zero-credential suite

πŸ§ͺ Try to break it

The invitation is the whole point. Clone it, read the architecture, and try to make a destructive action complete without the out-of-band approval. If you find a way, that is a finding worth more than the demo. The probes we already ran, and the gaps we already found and named, are in docs/PENTEST-FINDINGS.md.

πŸ”— The Identity Lab series

  • Lab 1: lab-okta-scim-server, the downstream SCIM target this lab cascades into.

  • Lab 3 (this repo), the AI-directed identity operations server with the out-of-band gate.

A LinkedIn series ("Building the Gate," three parts) and a Dev.to series ("Lab 3 Engineering Notes") tell the story for a general engineering audience.

πŸ–ΌοΈ Visual summary

βš–οΈ License and disclaimer

MIT. This is a demonstration build for learning, not production software. It performs real, destructive identity operations against whatever Okta org you point it at, so run the real-mode path only against a throwaway developer org with the demo fixture. Nothing here should be read as a claim that any system is production-ready, tamper-proof, injection-proof, or secure by default. The one thing it demonstrates is bounded, stated above, and scored openly with its residuals.

Install Server
A
license - permissive license
A
quality
B
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.

Related MCP Servers

  • A
    license
    -
    quality
    C
    maintenance
    An MCP server that enforces runtime governance on AI agent actions β€” file access, command execution, delegation chains, and permission escalation.
    Last updated
    MIT
  • F
    license
    -
    quality
    D
    maintenance
    An MCP server for managing Okta users (CRUD operations) with full OAuth 2.1 compliance, enabling secure integration with Claude Desktop and other MCP clients.
    Last updated
  • F
    license
    -
    quality
    D
    maintenance
    A production-ready MCP server for Identity and Access Management with Okta integration, providing user and group management, audit logging, and permission guardrails.
    Last updated

View all related MCP servers

Related MCP Connectors

  • MCP server for Argo RPG Platform β€” connects AI assistants to campaign data via OAuth2

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

  • Personal assistant MCP server with search, execute, packages, jobs, secrets, and integrations.

View all MCP Connectors

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/fso-datawarrior/lab-mcp-identity-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server