npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@warnyin/zitadel-mcp

v0.2.0

Published

MCP (Model Context Protocol) server for ZITADEL identity & access management. Exposes ZITADEL v2 + management APIs as tools usable from any MCP-compatible client (Claude Desktop, Claude Code, Cursor, etc.).

Readme

@warnyin/zitadel-mcp

npm version license

MCP (Model Context Protocol) server that exposes the ZITADEL identity & access management API as tools you can call from any MCP-compatible client — Claude Desktop, Claude Code, Cursor, Continue, etc.

  • Built against ZITADEL's v2 APIs (users, sessions, organizations) plus the v1 management API for projects, applications, roles, and tokens.
  • Authenticates with a service-account Personal Access Token (PAT).
  • Ships as a zero-config CLI; run it via npx @warnyin/zitadel-mcp — no global install required.

Quick start

1. Provision a service account & PAT in ZITADEL

In the ZITADEL console:

  1. Create (or reuse) an organization that the server will manage.
  2. Create a Service User (Console → Users → Service Users → New). Pick Access Token Type = Bearer.
  3. Grant it the roles you need (IAM_OWNER for instance-wide, or ORG_OWNER, ORG_USER_MANAGER, PROJECT_OWNER, … for narrower scopes).
  4. Open the service user → Personal Access TokensNew and copy the token. It is shown only once.

2. Configure your MCP client

Add a server entry pointing at npx zitadel-mcp. For example, Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

{
  "mcpServers": {
    "zitadel": {
      "command": "npx",
      "args": ["-y", "@warnyin/zitadel-mcp"],
      "env": {
        "ZITADEL_INSTANCE_URL": "https://your-instance.zitadel.cloud",
        "ZITADEL_PERSONAL_ACCESS_TOKEN": "pat_xxxxxxxxxxxxxxxxx",
        "ZITADEL_DEFAULT_ORG_ID": "344648897353810062"
      }
    }
  }
}

Claude Code (~/.claude/mcp.json or .mcp.json at the project root) follows the same shape. Cursor uses the same JSON under Settings → MCP.

Restart the client and the zitadel tools should appear in the tool list.

3. (Optional) Try it locally

export ZITADEL_INSTANCE_URL=https://your-instance.zitadel.cloud
export ZITADEL_PERSONAL_ACCESS_TOKEN=pat_xxxxxxxxxxxxxxxxx
npx @warnyin/zitadel-mcp --help
npx -y @modelcontextprotocol/inspector npx -y @warnyin/zitadel-mcp

The MCP Inspector opens a web UI where you can introspect every tool, see its Zod schema, and call it with sample arguments.


Environment variables

| Variable | Required | Description | | --- | --- | --- | | ZITADEL_INSTANCE_URL | ✅ | Base URL of your ZITADEL instance, no trailing slash. e.g. https://acme-abc123.zitadel.cloud | | ZITADEL_PERSONAL_ACCESS_TOKEN | ✅ | Bearer PAT issued to a service account that holds the roles your tools need. | | ZITADEL_DEFAULT_ORG_ID | ⛔ optional | Default organization ID sent as the x-zitadel-orgid header for management calls. Each tool can override with its own organizationId argument. | | ZITADEL_TIMEOUT_MS | ⛔ optional | HTTP timeout per request in ms. Default 30000. |

The server prints fatal config errors to stderr and exits — your MCP client surface will show the error in its log.


Tool catalog (37 tools)

Users (v2)

  • zitadel_create_human_user — create an interactive (human) user with profile + email (+ optional password/phone/metadata)
  • zitadel_create_machine_user — create a service-account user (bearer or JWT access tokens)
  • zitadel_get_user — fetch a user by ID
  • zitadel_search_users — paginated search; accepts raw ZITADEL queries for any combination of filters
  • zitadel_set_user_password — admin reset or self-service (with currentPassword verification)
  • zitadel_deactivate_user / zitadel_reactivate_user
  • zitadel_lock_user / zitadel_unlock_user
  • zitadel_delete_user (destructive)

Organizations

  • zitadel_create_organization — create an org (v2)
  • zitadel_setup_organization_setup admin endpoint: create org + initial admin in one call (needs IAM_OWNER)
  • zitadel_search_organizations
  • zitadel_get_my_organization — metadata for the caller's org

Projects

  • zitadel_create_project
  • zitadel_get_project
  • zitadel_list_projects
  • zitadel_deactivate_project / zitadel_reactivate_project
  • zitadel_delete_project (destructive)
  • zitadel_add_project_role / zitadel_bulk_add_project_roles
  • zitadel_list_project_roles

Applications

  • zitadel_create_oidc_app — full OIDC config (PKCE, auth method, response/grant types, app type, role assertions…)
  • zitadel_create_api_app — machine-to-machine API app
  • zitadel_list_apps, zitadel_get_app
  • zitadel_delete_app (destructive)
  • zitadel_regenerate_oidc_client_secret (destructive — rotates secret)

Sessions (v2)

  • zitadel_create_session — initiate session with optional user/password/totp/intent checks
  • zitadel_get_session
  • zitadel_update_session — add factor checks (requires sessionToken)
  • zitadel_delete_session

Service-account credentials

  • zitadel_add_personal_access_token — issue PAT for a machine user (token returned once)
  • zitadel_list_personal_access_tokens
  • zitadel_remove_personal_access_token
  • zitadel_add_machine_key — JSON key for JWT Profile auth

PKCE / OIDC example

For a Next.js (or any SPA/native) PKCE client without a static client secret:

// zitadel_create_oidc_app
{
  "projectId": "278123847301234567",
  "name": "Web App (PKCE)",
  "appType": "OIDC_APP_TYPE_USER_AGENT",
  "authMethodType": "OIDC_AUTH_METHOD_TYPE_NONE",
  "responseTypes": ["OIDC_RESPONSE_TYPE_CODE"],
  "grantTypes": [
    "OIDC_GRANT_TYPE_AUTHORIZATION_CODE",
    "OIDC_GRANT_TYPE_REFRESH_TOKEN"
  ],
  "redirectUris": ["https://app.example.com/api/auth/callback"],
  "postLogoutRedirectUris": ["https://app.example.com"],
  "accessTokenType": "OIDC_TOKEN_TYPE_BEARER"
}

This returns clientId plus clientSecret: "" (none for PKCE). Use clientId together with PKCE in your app.


Development

git clone <this-repo>
cd zitadel-mcp
npm install
npm run dev        # tsx watch — auto-restarts on edits

# build & sanity-check
npm run build
node dist/index.js --help

# inspect tools interactively
npx -y @modelcontextprotocol/inspector npx -y @warnyin/zitadel-mcp

Project layout

src/
├── index.ts               # entry point (#!/usr/bin/env node, stdio transport)
├── constants.ts           # env keys, limits, version
├── types.ts               # shared interfaces
├── schemas/
│   └── common.ts          # Zod schemas reused across tools (pagination, org header, response format)
├── services/
│   ├── config.ts          # env -> typed config + validation
│   ├── client.ts          # axios wrapper, injects x-zitadel-orgid for /management
│   ├── errors.ts          # ZITADEL → human messages
│   └── formatter.ts       # JSON/Markdown response formatting + CHARACTER_LIMIT
└── tools/
    ├── util.ts            # okJson / okFormatted / withErrorHandling
    ├── users.ts           # v2 users
    ├── organizations.ts   # v2 orgs + admin _setup
    ├── projects.ts        # /management/v1/projects
    ├── applications.ts    # OIDC/API apps
    ├── sessions.ts        # v2 sessions
    └── tokens.ts          # PATs + machine keys

Troubleshooting

| Symptom | Likely cause | Fix | | --- | --- | --- | | Error 401 (Unauthenticated) | PAT expired / revoked / wrong instance | Rotate the PAT in console and update the env var | | Error 403 (Permission denied) | Service account missing role | Grant the needed role (e.g. ORG_OWNER, IAM_OWNER) | | Error 404 (Not found) | Wrong ID or wrong org context | Pass organizationId explicitly or set ZITADEL_DEFAULT_ORG_ID | | Request to ZITADEL timed out | Slow network or instance | Increase ZITADEL_TIMEOUT_MS (e.g. 60000) | | DNS lookup failed | Typo in ZITADEL_INSTANCE_URL | Use the full URL incl. https:// |


License

MIT.