Quality & tooling

AI-assisted development (MCP)

The platform ships two MCP (Model Context Protocol) servers that connect your coding assistant (Claude Code, Cursor, or any MCP client) to the Okta standards and tooling — so your assistant follows the platform rules from the first line instead of discovering violations at PR review.

1) Local server — inside your repo (no account needed)

Every app repository scaffolded by the platform ships a ready local MCP server in scripts/mcp/ with a root .mcp.json:

  • Claude Code: auto-discovers it when you open the repo — zero setup.
  • Cursor: add to .cursor/mcp.json:
{ "mcpServers": { "okta-partner": { "command": "php", "args": ["scripts/mcp/server.php"] } } }

Requires only php on your PATH (no Composer, no network). Its tools wrap the exact CI scanners (scan_code, validate_manifest, lint_permission, component_catalog, feature_service, search_standards, list_scopes) — whatever passes locally passes the merge gate. See scripts/mcp/README.md in your repo.

The hosted server adds live, identity-bound tools on top of the standards: your apps and versions, the live scope catalog, monitoring (app health and webhook deliveries), the app-preview simulator, and control / app-control-panel tools.

Connect (one-time):

# Claude Code
claude mcp add --transport http okta-partner https://partners.getokta.io/mcp
// Cursor — .cursor/mcp.json
{ "mcpServers": { "okta-partner": { "url": "https://partners.getokta.io/mcp" } } }

The first use opens your browser on the partner platform's consent screen: sign in with your normal account, review what the tool will be able to do, and approve. No token is ever copied or pasted — the grant is full OAuth (PKCE).

Write access: by default the link is read-only (your apps + standards + monitoring). To enable the control tools (submit for review, create a version, edit the changelog and release channel, set the account types, program the app control panel and webhook settings) tick "Allow write (app control)" on the consent screen. All writes go through the same guards as the portal UI (no bypassing publish state, no writing to a published version).

Key live tools:

Tool Purpose
whoami / list_my_modules your identity and your tenant's apps
get_module / list_versions app details + built manifest + versions
module_health health report: status, versions, deployment checks, sandbox
webhook_deliveries / delivery_stats / replay_delivery External delivery history, stats and replay
notification_deliveries what became of your app's catalog notifications across every school that installed it: totals by status, channel and key, then the latest failures with their error text — the first place to look when a school says a notification never arrived
preview_module / store_listing store-card & dashboard-placement simulation + preview page URL
create_module create a new draft app — the first step, before create_version (write access required)
submit_module / create_version / update_changelog / set_release_channel / sync_from_manifest lifecycle control (write access required)
get/set_developer_ui / get/set_webhook_config program the app control panel & settings (write access required)
set_landing_widgets declare your embedded app's landing-page widgets directly — or as a per-version override — without going through manifest.json. The list you pass replaces what is stored; [] clears the declaration (on a version that drops the override, restoring inheritance). The rules are okta-web's own publish rules (write access required)
get/set_notification_config read and write the notification/payment provider block — at module level or as a per-version override (writing requires write access)
list_notifications / create_notification / update_notification / delete_notification the catalogue of notifications a version dispatches (writing requires write access)
discover_notifications / import_notifications scan the repo for undeclared notification keys and import them (importing requires write access)
list_account_types / get_account_types / set_account_types the account-type catalog, what your versions declare, and setting it (write access required)
list_shared_data what other apps share with other apps — the list you pick from before asking for access. Read from each app's latest published version, so anything still in a draft does not appear
list_app_links / request_app_access / answer_access_request / revoke_app_access cross-app links: list them in both directions, request access, answer a request, and revoke a grant you gave (writes require write access)
set_shared_data declare what your app shares with others, on an editable version — the first step, since nobody can request what you have not declared. Whole-list replace; [] clears it. Labels and descriptions are written for the school, not the developer (write access required)
get_app_dependencies / set_app_dependencies what your app needs from other apps: what it declares today, what it COULD declare (granted to you and still published), and setting it on an editable version. Whole-list replace, and no entry without a live grant behind it (setting requires write access)
get_org_profile / set_org_profile your organization and developer profile as the store shows it, plus your interface language. The account password is never readable or writable through MCP, and the logo is uploaded from the portal only (writing requires write access)
optimize_screenshots re-encode a version's stored screenshots as WebP and scale down anything wider than needed. New uploads are already converted, so this is for an older library (write access required)

Account types over MCP

The version editor's "Account types" tab is fully reachable from your assistant:

  • list_account_types — the live catalog (the same list the portal offers): each type has a key, a target (role = a tenant role, portal = a cross-tenant portal) and Arabic/English labels. A key outside the list is accepted as a custom tenant role; the portals are a closed set (student | guardian).
  • get_account_types — what your app actually declares. Account types are declared per version (there is no module-level value to inherit), so the report lists every version; pass {version} to narrow it.
  • set_account_types — a whole-list replace on an editable version, exactly like the version editor's save. Read the current list first and resend it complete with your edit; account_types: [] clears it.

Each entry: key (must equal the role name or the portal) + kind (primary | dependent) + exactly one target: roles (one role) or portal + at least one surface: web_route (a Laravel route name such as school-app.admin — not a URL and not a /path) and/or mobile_entry (in the shape the version's mobile mode requires) — and, on a native row with a mobile_entry, an optional min_contract (integer ≥ 1: this type's own host-contract floor; omit it to inherit the block default). This single declaration is what builds menu.audiences[] in okta-web and mobile.audiences[] in the Okta app, and the tool refuses up front whatever the publish-time validator would refuse.

Custom tenant roles. A role key outside the account-type catalog is allowed — tenants define their own roles — but it is declared explicitly: the audience it produces carries "custom": true in the manifest, and set_account_types warns you when it stores one. Publishing an out-of-catalog key without that marker is rejected, on purpose. The platform matches a role key as plain text against the roles users actually hold, so an invented or mistyped key matches nobody: the version publishes, the manifest looks healthy, and every page of that audience is then refused for every user by the deny-by-default audience guard. If you meant a known type, pick its exact key (list_account_types); if you really do mean a tenant-defined role, make sure the tenant has it under exactly that name. custom is never valid on a portal audience.

Security note: the token is bound to you and your tenant only — it can never see or touch another tenant's apps, and webhook secrets are never readable through any tool. You can re-link at any time; write consent is your call on every link.


View the whole guide on one page · ↧ Raw Markdown