# MCP Server

# ThunderID MCP Server

ThunderID provides a Model Context Protocol (MCP) server that lets AI assistants and MCP clients manage applications, authentication flows, users, and themes directly.

## Overview

The MCP server is available through the `/mcp` endpoint of your ThunderID instance (default: `https://localhost:8090/mcp`). MCP clients discover the available tools automatically through the protocol.

### Authentication

The endpoint follows the [MCP Authorization Specification](https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization). The MCP server publishes protected resource metadata at `/.well-known/oauth-protected-resource`, advertising ThunderID as the OAuth authorization server. If a [trusted issuer](https://thunderid.dev/guides/trusted-issuer.md) is configured, the metadata advertises that issuer instead. Spec-compliant MCP clients discover this automatically and run an OAuth authorization code + PKCE flow: you sign in through the browser, and the client obtains and refreshes tokens on its own. There is no manual token handling.

> [!NOTE]
> **Available from 1.0.2**
>
> Advertising the trusted issuer in the protected resource metadata is available from the 1.0.2 patch release. If you are using an earlier version, please upgrade to 1.0.2 or later to access this feature.

Access requires the `system` scope, and permissions come from the signed-in user, so sign in with an administrator account.

## Prerequisites

- ThunderID server running (default: `https://localhost:8090`)
- Access to the ThunderID Console with an administrator account
- Node.js and npm installed (to run MCP Inspector via `npx`)
- Claude Code CLI installed (only for the Claude Code option)

## Setup

Pick your MCP client below. MCP Inspector and Claude Code work with a local ThunderID instance today, and guides for more clients are on the way.

**MCP Inspector**

### Register an MCP Client

In the ThunderID Console, register an application for MCP Inspector.

1. Go to **Applications** and click **Add Application**.
2. Select **MCP Client**.
3. Enter a name (for example, `MCP Inspector`).
4. If prompted, select an organization unit.
5. On the **Client type** step, select **On behalf of a user**. This configures the Authorization Code flow with PKCE as a public client.
6. Under **Redirect URIs**, add `http://localhost:6274/oauth/callback`. The wizard shows this exact URI as a copyable hint for MCP Inspector.
7. Click **Finish**.
8. From the completion screen, copy the **Client ID**. You need it when connecting from MCP Inspector. No client secret is required because this is a public client.

### Allow the MCP Inspector Origin

MCP Inspector runs in the browser at `http://localhost:6274` and calls ThunderID cross-origin, so its origin must be allowed in the CORS configuration.

Create or update `config/resources/server_configs/cors.yaml` in your ThunderID distribution, or use `PUT /server-config/cors` after startup:

```yaml
name: cors
value:
  allowedOrigins:
    - "http://localhost:6274"
```

If the file already exists, append the origin to the existing `allowedOrigins` list instead of replacing it. Restart ThunderID after editing the file so the change takes effect.

### Trust the ThunderID Certificate

MCP Inspector's proxy runs on Node.js. Point Node.js at the ThunderID self-signed certificate so TLS connections to `https://localhost:8090` are trusted, without adding anything to your system trust store:

```bash
export NODE_EXTRA_CA_CERTS=<THUNDERID_HOME>/config/certs/server.cert
```

`<THUNDERID_HOME>` is the directory of your ThunderID distribution. The certificate generated during setup includes subject alternative names for `localhost` and `127.0.0.1`, so modern TLS clients accept it once it is trusted. Run the export in the same terminal session you launch MCP Inspector from.

### Launch MCP Inspector

```bash
npx @modelcontextprotocol/inspector
```

The Inspector UI opens at `http://localhost:6274`.

### Connect to the MCP Server

1. Set **Transport Type** to **Streamable HTTP**.
2. Set **URL** to `https://localhost:8090/mcp`.
3. Expand the **Authentication** section and select **OAuth**.
4. Enter the **Client ID** you copied earlier. Leave **Client Secret** empty.
5. Set **Scope** to `system`.
6. Click **Connect**.
7. A browser tab opens with the ThunderID sign-in page. Sign in with your administrator account.
8. Review and approve the requested permissions on the consent screen.
9. You are redirected back to MCP Inspector, now connected. Tokens are obtained and refreshed automatically from here on.

### Verify the Connection

1. In MCP Inspector, open the **Tools** tab and click **List Tools**.
2. Select a tool such as `list_applications` and run it.
3. The response lists the applications registered in ThunderID, including the MCP Inspector application you just created.

If the connection fails, see the [Troubleshooting](#troubleshooting) section below.

**Claude Code**

Claude Code connects to the MCP server over OAuth using Dynamic Client Registration. It registers its own OAuth client automatically, so you do not create an application in the Console for it.

#### Enable Dynamic Client Registration

Claude Code registers its own OAuth client through Dynamic Client Registration and cannot use a pre-registered client ID, so enable it for local development. Add the following to `deployment.yaml` in your ThunderID distribution:

```yaml
oauth:
  dcr:
    insecure: true
```

> [!WARNING]
> This setting is for local development only. It lets any client register with ThunderID without authentication. Do not enable it in production.

Restart ThunderID after saving the file.

#### Trust the Certificate for Claude Code

Claude Code runs on Node.js. Point it at the ThunderID self-signed certificate so TLS connections to `https://localhost:8090` are trusted, without adding anything to your system trust store:

```bash
export NODE_EXTRA_CA_CERTS=<THUNDERID_HOME>/config/certs/server.cert
```

`<THUNDERID_HOME>` is the directory of your ThunderID distribution. The certificate generated during setup includes subject alternative names for `localhost` and `127.0.0.1`, so modern TLS clients accept it once it is trusted. Run the export in the same terminal session you launch `claude` from.

#### Add the MCP Server to Claude Code

```bash
claude mcp add --transport http thunderid-mcp https://localhost:8090/mcp
```

Verify it was added:

```bash
claude mcp list
```

You should see `thunderid-mcp` in the list.

#### Authenticate with ThunderID

1. Start Claude Code from the same terminal where you exported `NODE_EXTRA_CA_CERTS`:
   ```bash
   claude
   ```
2. Run `/mcp` inside the Claude Code prompt.
3. Select `thunderid-mcp` and choose the authenticate option.
4. A browser tab opens with the ThunderID sign-in page. Sign in with your administrator account.
5. Review and approve the requested permissions on the consent screen.

Claude Code obtains and refreshes tokens automatically from here on. It discovers the required `system` scope from the server's metadata, so there is nothing else to configure.

#### Verify Claude Code Access

Ask Claude Code to use a tool, for example:

> "List the applications registered in ThunderID"

Claude Code calls the matching tool and returns the list of registered applications. To remove the server later, run `claude mcp remove "thunderid-mcp" -s local`.

**Claude Desktop**

> [!NOTE]
> **Coming soon**
>
> A step-by-step guide for connecting Claude Desktop to the ThunderID MCP server is on the way. Any MCP client that supports the MCP Authorization Specification with OAuth can connect today using the same application registered in the MCP Inspector guide above.

**GitHub Copilot**

> [!NOTE]
> **Coming soon**
>
> A step-by-step guide for connecting GitHub Copilot to the ThunderID MCP server is on the way. Any MCP client that supports the MCP Authorization Specification with OAuth can connect today using the same application registered in the MCP Inspector guide above.

## What You Can Do

Once connected, your AI assistant can work with ThunderID resources directly. MCP clients discover the available tools automatically, you just describe what you need in natural language.

| Toolset | Description |
|---------|-------------|
| `applications` | Create, configure, and manage OAuth applications with pre-built templates for SPA, Mobile, Server, and M2M |
| `flows` | Design and modify authentication and registration flows |
| `themes` | Browse and inspect login page themes, colors, and typography |
| `organization_units` | List organization units |
| `user_types` | List user types and self-registration settings |
| `react_sdk` | Get tailored integration code for the ThunderID React SDK |

**Example prompts:**

- "Create a new single-page application for my React project"
- "Show me the current authentication flow"
- "Add a second factor step to the default login flow"
- "What colors and typography does the default theme use?"
- "Integrate authentication with ThunderID for this application"

## Use Cases

### Scaffold a React App with Login

Ask the assistant to create a new React application with authentication wired up end-to-end:

> "Create a new React application with authentication using ThunderID"

The assistant scaffolds a React project using Vite, installs the ThunderID React SDK, and wires up the auth provider with the correct `clientId` and server URL from the application registered in ThunderID. By the end you have a running app with a working sign-in button backed by ThunderID.

To add authentication to an existing React application instead:

> "Integrate authentication with ThunderID for this application"

The assistant installs the SDK, configures the auth provider, and adds sign-in and sign-out components without scaffolding a new project.

### Add Signup to a React App

After integrating login, add a registration page:

> "Integrate a signup page in the application and enable signup"

The assistant enables self-registration on your ThunderID application and generates a signup page wired to the registration flow. New users can register directly from your application and appear in the ThunderID Console under **User Management**.

## Troubleshooting

### Browser shows a CORS error or the connection hangs

The Inspector origin is missing from the CORS configuration.

1. Re-check the `cors.yaml` step under [Allow the MCP Inspector Origin](#allow-the-mcp-inspector-origin).
2. Restart ThunderID after saving the change.

### Certificate or TLS errors

`NODE_EXTRA_CA_CERTS` was not set in the terminal that launched Inspector, or it points to the wrong path.

1. Export it again in the same terminal: `export NODE_EXTRA_CA_CERTS=<THUNDERID_HOME>/config/certs/server.cert`.
2. Relaunch MCP Inspector from that terminal.

### Claude Code cannot authenticate or reports it does not support dynamic client registration

Dynamic Client Registration is not enabled.

1. Set `oauth.dcr.insecure: true` in `deployment.yaml` (local development only) and restart ThunderID.
2. Confirm `NODE_EXTRA_CA_CERTS` is exported in the same terminal that launched `claude`.

### Claude Code authentication fails with "An application with the same name already exists"

Claude Code registers its OAuth client through Dynamic Client Registration each time it authenticates. If a previous registration already created an application with the same name, the new registration is rejected.

1. In the ThunderID Console, go to **Applications**.
2. Find the application named **Claude Code (thunderid-mcp)** (or similar) from the previous session and delete it.
3. Re-authenticate from Claude Code by running `/mcp` and selecting the authenticate option.

### Redirect URI error during sign-in

The redirect URI on the application does not exactly match `http://localhost:6274/oauth/callback`.

1. Edit the application in the Console.
2. Correct the redirect URI under **Redirect URIs** and save.

### 403 or insufficient scope after connecting

The signed-in user lacks administrator permissions, or the scope was not set to `system`.

1. Sign in with an administrator account.
2. Confirm the **Scope** field in MCP Inspector is set to `system`.

### MCP server not responding

Verify ThunderID is running and the endpoint is reachable:

```bash
curl -k https://localhost:8090/mcp
```

A `401 Unauthorized` response with a `WWW-Authenticate` header confirms the endpoint is up and secured. Any other error indicates the server is not running or the URL is incorrect.

## Related Documentation

- [API Reference](https://thunderid.dev/apis.md) - Application and Flow Management REST APIs
- [React SDK](https://thunderid.dev/sdks-and-tools/react/overview.md) - ThunderID React SDK documentation
- [Securing MCP](https://thunderid.dev/use-cases/ai-agents/mcp-authorization/overview.md) - governing MCP clients and protecting MCP servers with ThunderID
- [MCP Authorization Specification](https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization) - MCP auth protocol details
