Skip to main content
Glama
infamousjoeg

idira-disco-mcp

by infamousjoeg

idira-disco-mcp

An MCP server for the Idira (CyberArk) Discovery & Context GraphQL API. It lets an AI agent such as Claude Code query the inventory and send what it discovers — secrets, machine identities (workloads) and AI agents — to the Idira platform.

The server is a remote (Streamable HTTP) MCP server and an OAuth 2.1 protected resource, so it can be registered behind the Idira Agent Identity Broker: the agent authenticates to the broker, the broker obtains a token for this server, and every tool call is authorized and audited.

Status. All 9 operations of the public schema are implemented and covered by 177 automated tests, including a test that compares the server with the documented schema field by field, and a run with a real Claude Code client. It has not yet been run against a live Idira tenant or a live Identity Broker — see What is and is not verified.

Tools

One tool per GraphQL root field — 100% of the documented schema.

Tool

GraphQL operation

Kind

disco_query_secrets

Query.secrets

read

disco_query_workloads

Query.workloads

read

disco_query_ai_agents

Query.aiAgents

read

disco_add_replace_secrets

Mutation.addReplaceExternalSecrets

write (idempotent upsert by originId)

disco_add_replace_workloads

Mutation.addReplaceExternalWorkloads

write (idempotent upsert by originId)

disco_add_replace_ai_agents

Mutation.addReplaceExternalAiAgents

write (idempotent upsert by originId)

disco_delete_secrets

Mutation.deleteExternalSecrets

destructive

disco_delete_workloads

Mutation.deleteExternalWorkloads

destructive

disco_delete_ai_agents

Mutation.deleteExternalAiAgents

destructive

  • Query tools take filter (every documented filter field, with nested and / or / not), sort (every sortable field), limit / offset, and an optional fields list. They return totalCount, hasMore and nextOffset.

  • Add/replace tools take up to 500 entities per call with every documented input field. They are forwarded upstream in batches (DISCO_BATCH_SIZE, default 100).

  • Delete tools take a filter and refuse one without a condition. dryRun: true reports how many entries match, and a sample, without deleting.

Related MCP server: Entra Permissions MCP Server

How it fits together

Claude Code ──OAuth 2.1──▶ Idira Agent Identity Broker ──bearer token──▶ idira-disco-mcp ──platform token──▶ Discovery & Context
 (MCP client)              https://<gateway>/mcp/<name>                  (this server)      (service user)     GraphQL API
                           authenticates the agent + user,               validates the token:
                           enforces access policy, audits                signature, issuer, expiry,
                                                                         audience, scopes

Two separate credentials are involved, on purpose:

  1. Inbound — an OAuth 2.1 access token (a JWT) issued by your authorization server for this server. The server checks its signature against the issuer's JWKS, its issuer, expiry and audience (RFC 8707), and optional scopes. It publishes RFC 9728 protected resource metadata and answers 401 with a WWW-Authenticate challenge, which is what MCP clients and the broker's "Discover" step use.

  2. Upstream — a short-lived Idira platform token the server obtains itself as a service user (client_credentials against /oauth2/platformtoken), cached and renewed automatically.

The inbound token is never forwarded to Idira. The MCP authorization spec forbids token passthrough, and the Discovery & Context API expects a platform token anyway.

Try it locally (no tenant needed)

Requires Node.js 22 or newer.

npm install
npm run demo

This starts a mock Idira tenant (it executes requests against the real documented schema), a mock authorization server and the built MCP server, and writes .demo/mcp.json with a valid bearer token. In a second terminal:

claude --mcp-config .demo/mcp.json --strict-mcp-config

Then ask Claude to, for example, "list the secrets in the inventory, then register this Claude Code install as an AI agent".

Configuration

All configuration is by environment variable; see .env.example. The server fails fast and lists every problem at once.

Variable

Required

Purpose

IDIRA_SUBDOMAIN

yes¹

Tenant subdomain; the API URL becomes https://<subdomain>.inventory.cyberark.cloud/api/graphql

IDIRA_IDENTITY_URL

yes¹

Identity tenant URL, e.g. https://abc1234.id.cyberark.cloud

IDIRA_CLIENT_ID / IDIRA_CLIENT_SECRET

yes

Login name and password of the service user

MCP_PUBLIC_URL

yes²

Public HTTPS URL of the MCP endpoint. It is the OAuth resource identifier, and its path is the path served

OAUTH_ISSUER_URL

yes

Issuer of the authorization server whose tokens are accepted

OAUTH_AUDIENCE

no

Accepted aud value(s). Defaults to MCP_PUBLIC_URL

OAUTH_JWKS_URI

no

Only if the issuer's metadata has no jwks_uri

OAUTH_REQUIRED_SCOPES

no

Scopes every request must carry

OAUTH_SCOPES_READ / _WRITE / _DELETE

no

Extra scopes per kind of tool (403 insufficient_scope challenge when missing)

MCP_HOST / MCP_PORT

no

Bind address (default 127.0.0.1:3000)

MCP_ALLOWED_HOSTS

no

Extra accepted Host header values

DISCO_BATCH_SIZE

no

Entities per upstream add/replace request (default 100)

DISCO_ALLOW_SECRET_VALUES

no

Accept the secretValue input field. Default false

MCP_AUTH_DISABLED

no

Serve without authentication. Local development only; refused unless bound to loopback

IDIRA_DISCO_GRAPHQL_URL, IDIRA_PLATFORM_TOKEN_URL, IDIRA_TIMEOUT_MS, LOG_LEVEL

no

Overrides and tuning

¹ Or the full-URL overrides IDIRA_DISCO_GRAPHQL_URL / IDIRA_PLATFORM_TOKEN_URL. ² Defaults to http://localhost:<port>/mcp for local use.

Deploying behind the Idira Agent Identity Broker

  1. Create the service user. In Idira: Manage > Inventory > Identities > Users > Add User, tick Is OAuth confidential client, then add the user to the Machines Admin role. Its login name and password are IDIRA_CLIENT_ID / IDIRA_CLIENT_SECRET. (Create an API token, Authenticate to the GraphQL API)

  2. Choose the authorization server that will issue tokens for this server. For Idira Identity, follow the step-by-step integration guide. Any OAuth 2.1 server works if it publishes RFC 8414 or OpenID Connect discovery metadata and issues JWT access tokens whose aud is MCP_PUBLIC_URL (or whatever you set in OAUTH_AUDIENCE). Set OAUTH_ISSUER_URL to its issuer.

  3. Run the server behind a TLS-terminating reverse proxy or ingress, reachable at MCP_PUBLIC_URL:

    npm ci && npm run build && npm start

    or with Docker:

    docker build -t idira-disco-mcp . && docker run --env-file .env -p 3000:3000 idira-disco-mcp
  4. Register it in Idira. Manage > Inventory > AI > MCP servers > Register custom MCP server, enter MCP_PUBLIC_URL, click Discover. Idira reads this server's well-known metadata and detects OAuth 2.1. Choose a connection mode (table below), then Register and enable the server. (Register MCP servers)

  5. Register the agent and connect it. Register Claude Code under Managed AI agents, then use Connect AI agent on the MCP server to get the Identity Broker URL (https://<tenant-gateway-host>/mcp/<serverName>) and client credentials. (Secure AI agents access, Connect MCP servers to AI agents)

    claude mcp add --transport http idira-disco https://<tenant-gateway-host>/mcp/<serverName> --client-id <client-id> --client-secret

Connection modes

Keep the OAuth app in Idira (recommended)

Passthrough

None

Who gets the token for this server

Idira, as OAuth client of your authorization server (automatic with DCR, otherwise you enter a client ID and secret)

The agent brings its own token

Nobody; Idira is the only gate

What this server validates

Signature, issuer, expiry, audience, scopes

Same

Nothing

Audit in Idira

Full: user, agent, tool, server

Limited: may not identify agent or user

Not stated in the docs

Agent holds a credential for this server

No

Yes

No

Supported by this server

Yes

Yes

No — the server would accept anything that can reach its URL directly. MCP_AUTH_DISABLED exists for loopback development only

Setup effort

Medium

Low

Lowest

Source: Understand Secure AI agents architecture.

Security notes

  • Audience binding. Tokens issued for any other resource are refused, so a token stolen from another service cannot be replayed here.

  • Asymmetric signatures only; unsigned and shared-secret tokens are rejected. Tokens without exp are rejected.

  • Least privilege. Use OAUTH_SCOPES_READ/WRITE/DELETE to give an agent read-only or no-delete access. The service user needs only the Machines Admin role.

  • Secret values stay out. The inventory needs metadata about secrets, not their values. The secretValue input field exists in the API and is implemented, but the server rejects it unless the operator sets DISCO_ALLOW_SECRET_VALUES=true. Values are never logged or echoed back.

  • Deletes are irreversible. Delete tools are annotated destructive, refuse empty filters, and offer dryRun. The dry run counts every entry matching the filter; the API's delete mutations are named deleteExternal*, so the real deletion may be limited to externally ingested entries.

  • Audit trail. Every tool call is logged as a JSON line (tool, OAuth client, subject, outcome, duration) to stderr. Tool arguments are never logged. Upstream, calls appear as the service user; the per-agent and per-user trail is the broker's.

  • Host header allow-list (DNS rebinding protection) is always on: the public hostname plus MCP_ALLOWED_HOSTS.

  • GET /healthz is unauthenticated and returns only a static status.

Development

npm test
npm run coverage
npm run schema:check

schema:check compares schema/disco.graphql with the schema currently published in the Idira docs (-- --write updates the local copy). If the published schema gains a field, test/schema-coverage.test.ts then fails until the server covers it.

Test file

What it proves

test/schema-coverage.test.ts

Tools, input schemas, selections and enums match the documented schema exactly, in both directions; every GraphQL document validates against it

test/e2e.test.ts

A real MCP client over HTTP: OAuth challenges and metadata, nine kinds of bad token, scopes, every tool, every input and filter field reaching the API, batching, pagination, error handling

test/client.test.ts

Platform token caching and renewal, retries and backoff, error mapping

test/auth.test.ts, test/config.test.ts

Authorization server discovery, JWT verification details, configuration validation

What is and is not verified

Verified here:

  • Every operation, argument, input field, output field and enum value matches the schema published at the docs URL above (checked by test, and the local schema copy is byte-identical to the published one).

  • Requests are executed by a mock tenant built from that schema, with AppSync's rules for AWSDateTime and AWSJSON inputs.

  • The OAuth 2.1 resource-server behaviour required by the MCP authorization spec (2026-07-28), using the official MCP TypeScript SDK v2.

  • Claude Code 2.1 connecting to the built server with a bearer token and calling the tools.

Not verified — needs a real tenant:

  • Live API behaviour beyond the published schema: page-size and batch-size limits, error formats, rate limits, and whether AWSJSON is enforced as assumed.

  • The Identity Broker end to end: the Discover step against this server, and the token it presents. In particular, confirm that your authorization server issues JWT access tokens with the right audience; opaque tokens are not supported (no RFC 7662 introspection).

  • Claude Code's redirect URL in agent registration. Claude Code uses a loopback callback (http://localhost:<port>/callback, fixable with --callback-port). The docs say custom agent redirect URLs must be HTTPS; whether the predefined Claude agent type accepts Claude Code's loopback callback needs checking in the tenant.

  • The public schema exposes no risk details (only a riskId filter), although the docs mention viewing risks; there is nothing to implement for that yet.

License

MIT

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Provides Microsoft Entra ID / Graph permissions data to AI agents, enabling search and retrieval of application and delegated permissions as well as Microsoft first-party app details.
    6
    8 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides AI agents with a DID-based identity, secure wallet, and cloud KMS-backed signing keys, enabling trusted interactions with persons, companies, and other agents via standards like OIDC4VCI, OIDC4VP, and SD-JWT.
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables autonomous AI agents to securely access and execute external tools, such as GitHub REST API operations, with per-user authentication, authorization, audit logging, and observability.
    MIT