Identity for AI

Secure a Cloudflare Workers MCP Server with PingOne

In this configuration, the Cloudflare Workers Model Context Protocol (MCP) server uses the Cloudflare Workers OAuth Provider, which delegates authentication to PingOne. This enables clients, such as AI agents, to call a protected API on behalf of an authenticated end user.

While serving as a resource server for MCP clients, this MCP server also fulfills two distinct OAuth roles:

  • An OAuth server to your MCP clients

  • An OpenID Connect (OIDC) client for your PingOne environment

This configuration uses Cloudflare to manage consent. To use this configuration with PingOne DaVinci-managed consent, see Secure a Cloudflare Workers MCP Server with PingOne DaVinci.

Before you begin

Refer to the remote-mcp-pingone/mcp directory in Ping Identity’s cloudflare-mcp Git repository.

Stack

Role Name Description

Platform

Serverless execution

Framework

Lightweight API endpoints

Agent Execution

Base class for implementing the stateful MCP server

Session State

Provides stateful, isolated storage for each MCP connection

OAuth Core

Orchestrates the OAuth flow, delegating authentication to PingOne

Ephemeral State

Stores OAuth state required by the workers oauth provider

Requirements

Structure

mcp/
├── package.json                     # Dependencies and scripts
├── tsconfig.json                    # TypeScript compiler settings
│── wrangler.jsonc                   # Worker configuration
└── src/
    ├── index.ts                     # OAuth server flow and MCP server routing
    ├── mcp.ts                       # Stateful MCP server as a Cloudflare McpAgent (durable object)
    ├── config.ts                    # Worker bindings and Cloudflare durable object session data
    ├── todoApi.client.ts            # HTTP client to the downstream Todo API
    └── auth/
        ├── workers-oauth-utils.ts   # Cloudflare OAuth utility functions
        ├── ping-handler.ts          # Endpoints that connect the auth flow between OAuth provider and PingOne
        ├── ping-utils.ts            # PingOne OAuth utility functions
        └── ping-types.ts            # PingOne OAuth types

Tasks

Configure the MCP server as an OIDC Client in PingOne

This step enables the Cloudflare worker to exchange authorization codes on behalf of the end user. Note that the MCP server, not the MCP client, receives the PingOne access token. The MCP server then issues a separate reference token to the MCP client for session lookups. This distinction ensures proper audience scoping: the MCP client token is intended for the MCP server, while the MCP server token is intended for the target API.

  1. In the PingOne admin console, go to Applications and click the icon to add a new application.

  2. Select OIDC Web App and click Save.

  3. In the Configuration tab of the application, ensure that:

    1. Grant Type is set to Authorization Code.

    2. PKCE Enforcement is set to S256_REQUIRED.

    3. Redirect URI is set to your Cloudflare worker’s callback endpoint, for example <mcp_server>/callback.
      If the worker is not yet deployed, use a placeholder and update it later.

  4. In the Resources tab of the application, allow the standard OIDC scopes, openid and profile, and the Todo API scopes, todo_api:read and tode_api:write.

  5. In the Policies tab of the application, enable Single_Factor or your preferred policy.

Deploy to Cloudflare

  1. In your terminal, install dependencies and build.

    npm install
    npm run build
  2. Use the Wrangler CLI to set the following remote environment variables:

    Name Description Example

    PINGONE_ISSUER

    PingOne environment domain

    https://auth.pingone.<REGION>/<ENV_ID>/as

    MCP_SERVER_CLIENT_ID

    ID of the MCP server client

    0c24f3a0-0522-4f76-9bcf-89643029e3e0

    MCP_SERVER_CLIENT_SECRET

    Secret of the MCP server client

    [A long, random, alphanumeric string]

    API_IDENTIFIER

    ID of the downstream Todo API resource

    https://todo.api.com

    API_URL

    URL of the downstream Todo API

    https://todo-api-ping-aic.<ENV>.workers.dev

    COOKIE_ENCRYPTION_KEY

    Key used to sign browser cookies

    [A long, random, base64 string]

    wrangler secret put PINGONE_ISSUER
    wrangler secret put MCP_SERVER_CLIENT_ID
    wrangler secret put MCP_SERVER_CLIENT_SECRET
    wrangler secret put API_IDENTIFIER
    wrangler secret put API_URL
    wrangler secret put COOKIE_ENCRYPTION_KEY
  3. Configure remote KV storage.

    wrangler kv namespace create OAUTH_KV
    After running this command, update wrangler.jsonc with the generated KV namespace ID.
  4. Deploy to Cloudflare.

    npm run deploy

Test the MCP Server with the MCP Inspector

The MCP Inspector is a developer tool that allows you to test and debug MCP servers by simulating a client connection. This enables you to validate the authentication flow and tool execution interactively. It confirms that the Cloudflare OAuth Provider successfully captures user consent locally before delegating identity verification to PingOne.

  1. Launch the Inspector.

    npx @modelcontextprotocol/inspector

    The Inspector starts on port 6277 and initiates the authentication flow. No CORS rules are needed because authentication occurs server-to-server (MCP server to PingOne), bypassing browser restrictions.

    Authentication flow
    1. The Inspector initiates a request to the MCP endpoint (<mcp_server>/mcp).

    2. The MCP server intercepts the request and presents the local, worker-hosted consent dialog.

    3. Upon approval, the MCP server redirects the user to PingOne for authentication.

    4. The MCP server exchanges the returned authorization code for an downstream access token.

    5. The server binds this downstream token to a new, isolated client session.

    6. The server establishes the connection and issues a session handle to the Inspector.

  2. Verify that the MCP server is working properly by using the Inspector to confirm the following behaviour:

    1. Connection initiates the full Cloudflare consent and PingOne login sequence.

    2. Reconnecting (without clearing cookies and using the same MCP client ID) recovers the existing session silently.

    3. Clearing browser cookies forces a new consent and authentication cycle upon reconnect.

    4. The server correctly populates the tool list in the Inspector.

    5. The whoAmI tool returns the PingOne access token audienced for the Todo API.

    6. Downstream API actions (adding/deleting todos) complete successfully.

Access the remote MCP server from Claude Desktop

  1. In Claude Desktop, click your profile icon, and then click Settings.

  2. Go to Connectors and then click Add Custom Connector.

  3. In the Remote MCP server URL field, enter the URL in this format: https://remote-mcp-ping-federate.<ENV>.workers.dev/mcp

    No OAuth Client ID or Secret is required since Claude will perform Dynamic Client Registration.

  4. Click Save.

  5. Connect to the MCP server and authenticate with PingFederate.

  6. Once connected, you can ask Claude: "Can you tell me what is in my Todo list?"

  7. Claude sees the connected tools and calls the appropriate tool after asking for consent.