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

productboard-mcp-oauth

v1.2.0

Published

MCP server for ProductBoard API v2

Readme

productboard-mcp-oauth

A TypeScript Model Context Protocol server for the ProductBoard API v2. Manage features, releases, notes, and workspace configuration through natural language conversation in Claude Desktop or Claude Code.

Features

  • 66 MCP tools across features, products, components, subfeatures, releases, release groups, notes, strategy, entity operations, search, configuration, and ADO push/link
  • OAuth 2.0 + PKCE authentication with automatic token refresh
  • Rate limiting with exponential backoff
  • Cursor-based pagination for all list endpoints
  • Full CRUD for features, releases, and notes
  • ADO integration — push or link features to Azure DevOps work items via browser automation

Setup

There are two ways to authenticate: direct mode (you hold the OAuth credentials) and broker mode (credentials live in a shared Azure Function — recommended for team installs).


Direct mode

Use this when you are setting up the integration for yourself and are happy to store the OAuth client secret in your MCP config.

Step 1 — Create an OAuth app in ProductBoard

  1. Go to https://app.productboard.com/oauth2/applications
  2. Click Create OAuth App
  3. Set the redirect URI to http://localhost:3000/callback
  4. Select scopes: entities:read, entities:write, entities:delete, notes:read, notes:write, notes:delete
  5. Save your Client ID and Client Secret

Step 2 — Configure your MCP client

Claude Desktop — add to claude_desktop_config.json (Settings > Developer > Edit Config):

{
  "mcpServers": {
    "productboard": {
      "command": "npx",
      "args": ["-y", "productboard-mcp-oauth"],
      "env": {
        "PRODUCTBOARD_OAUTH_CLIENT_ID": "your-client-id",
        "PRODUCTBOARD_OAUTH_CLIENT_SECRET": "your-client-secret",
        "PRODUCTBOARD_WORKSPACE_URL": "https://yourcompany.productboard.com",
        "PRODUCTBOARD_ADO_INTEGRATION_NAME": "ADO Integration OAUTH 2.0"
      }
    }
  }
}

Claude Code — run once from any directory:

claude mcp add productboard npx -- -y productboard-mcp-oauth \
  -e PRODUCTBOARD_OAUTH_CLIENT_ID=your-client-id \
  -e PRODUCTBOARD_OAUTH_CLIENT_SECRET=your-client-secret \
  -e PRODUCTBOARD_WORKSPACE_URL=https://yourcompany.productboard.com \
  -e PRODUCTBOARD_ADO_INTEGRATION_NAME="ADO Integration OAUTH 2.0"

Step 3 — Authorize (one-time)

  1. Restart Claude Desktop or start a new Claude Code session
  2. A browser window opens to ProductBoard's OAuth consent page
  3. Sign in and authorize the application
  4. The browser shows "Authorization Successful" — you can close the tab

Tokens are saved to ~/.productboard-mcp/tokens.json and refresh automatically.


Broker mode

Use this for team installs where you want users to authenticate with their own ProductBoard account without distributing the OAuth client secret to every machine. A shared Azure Function holds the credentials; each user gets a broker URL and host key instead.

How it works: the broker acts as the OAuth redirect URI. When a user authorizes, ProductBoard redirects to the broker, which bounces the browser to a temporary local port (auto-selected from 50000+). Tokens are then stored locally on each user's machine — the broker is only involved during initial authorization and token refresh, not during normal API calls.

Step 1 — Deploy the broker

See broker/README.md for full Azure deployment instructions. Once deployed you will have:

  • A broker URL: https://<function-app-name>.azurewebsites.net/api
  • A host key to share with users

Step 2 — Register the broker callback in ProductBoard

  1. Go to https://app.productboard.com/oauth2/applications
  2. Open your OAuth app
  3. Add the redirect URI: https://<function-app-name>.azurewebsites.net/api/callback
  4. Select scopes: entities:read, entities:write, entities:delete, notes:read, notes:write, notes:delete

Step 3 — Configure each user's MCP client

Claude Desktop — add to claude_desktop_config.json:

{
  "mcpServers": {
    "productboard": {
      "command": "npx",
      "args": ["-y", "productboard-mcp-oauth"],
      "env": {
        "PRODUCTBOARD_BROKER_URL": "https://<function-app-name>.azurewebsites.net/api",
        "PRODUCTBOARD_BROKER_KEY": "your-host-key",
        "PRODUCTBOARD_WORKSPACE_URL": "https://yourcompany.productboard.com",
        "PRODUCTBOARD_ADO_INTEGRATION_NAME": "ADO Integration OAUTH 2.0"
      }
    }
  }
}

Claude Code — run once from any directory:

claude mcp add productboard npx -- -y productboard-mcp-oauth \
  -e PRODUCTBOARD_BROKER_URL=https://<function-app-name>.azurewebsites.net/api \
  -e PRODUCTBOARD_BROKER_KEY=your-host-key \
  -e PRODUCTBOARD_WORKSPACE_URL=https://yourcompany.productboard.com \
  -e PRODUCTBOARD_ADO_INTEGRATION_NAME="ADO Integration OAUTH 2.0"

Step 4 — Each user authorizes (one-time)

  1. Restart Claude Desktop or start a new Claude Code session
  2. A browser window opens to ProductBoard's OAuth consent page
  3. Sign in and authorize with their own ProductBoard account
  4. The browser shows "Authorization Successful" — they can close the tab

Each user's tokens are stored at ~/.productboard-mcp/tokens.json on their machine and refresh automatically. The broker is not involved after initial authorization until the refresh token expires (~90 days of inactivity).


Environment Variables

Two auth modes are supported — configure one or the other, not both.

Direct mode

| Variable | Required | Default | Description | |----------|----------|---------|-------------| | PRODUCTBOARD_OAUTH_CLIENT_ID | Yes | — | OAuth 2.0 client ID | | PRODUCTBOARD_OAUTH_CLIENT_SECRET | Yes | — | OAuth 2.0 client secret | | PRODUCTBOARD_CALLBACK_PORT | No | 3000 | Local port for the OAuth callback server — change if port 3000 is already in use |

Broker mode

| Variable | Required | Default | Description | |----------|----------|---------|-------------| | PRODUCTBOARD_BROKER_URL | Yes | — | Azure Function base URL (e.g. https://my-fn.azurewebsites.net/api) | | PRODUCTBOARD_BROKER_KEY | Yes | — | Azure Function host key |

Common (both modes)

| Variable | Required | Default | Description | |----------|----------|---------|-------------| | PRODUCTBOARD_WORKSPACE_URL | No | — | Workspace URL (e.g. https://yourcompany.productboard.com) — required for ADO push/link tools | | PRODUCTBOARD_ADO_INTEGRATION_NAME | No | ADO Integration OAUTH 2.0 | Name of the ADO integration as shown in ProductBoard's Integrations section | | PRODUCTBOARD_TOKEN_PATH | No | ~/.productboard-mcp/tokens.json | Custom token storage path | | PRODUCTBOARD_API_BASE_URL | No | https://api.productboard.com | API base URL override |

Tool Reference

Health

| Tool | Description | |------|-------------| | pb_health_check | Verify API connectivity and authentication status |

Features (5 tools)

| Tool | Description | |------|-------------| | pb_feature_list | List features with optional filtering | | pb_feature_get | Get a feature by ID | | pb_feature_create | Create a new feature | | pb_feature_update | Update a feature's fields | | pb_feature_delete | Delete a feature |

Products (4 tools)

| Tool | Description | |------|-------------| | pb_product_list | List all products | | pb_product_get | Get a product by ID | | pb_product_create | Create a new product | | pb_product_update | Update a product's fields |

Components (4 tools)

| Tool | Description | |------|-------------| | pb_component_list | List all components | | pb_component_get | Get a component by ID | | pb_component_create | Create a new component | | pb_component_update | Update a component's fields |

Subfeatures (4 tools)

| Tool | Description | |------|-------------| | pb_subfeature_list | List subfeatures with optional parent filter | | pb_subfeature_get | Get a subfeature by ID | | pb_subfeature_create | Create a new subfeature (requires parent feature) | | pb_subfeature_update | Update a subfeature's fields |

Releases (5 tools)

| Tool | Description | |------|-------------| | pb_release_list | List releases | | pb_release_get | Get a release by ID | | pb_release_create | Create a new release (requires parent release group) | | pb_release_update | Update a release's fields | | pb_release_delete | Delete a release |

Release Groups (3 tools)

| Tool | Description | |------|-------------| | pb_release_group_list | List all release groups | | pb_release_group_get | Get a release group by ID | | pb_release_group_update | Update a release group's name or description |

Release Assignments (3 tools)

| Tool | Description | |------|-------------| | pb_release_assign_feature | Assign a feature to a release | | pb_release_list_features | List features assigned to a release | | pb_release_unassign_feature | Remove a feature from a release |

Entity Relationships (1 tool)

| Tool | Description | |------|-------------| | pb_entity_list_relationships | List parent/child, link, isBlockedBy/isBlocking relationships for any entity; filter by type, target type, or target ID |

Entity Operations (5 tools)

| Tool | Description | |------|-------------| | pb_entity_add_tag | Add a tag to any entity without overwriting existing tags | | pb_entity_remove_tag | Remove a tag from any entity | | pb_entity_replace_parent | Atomically move an entity to a new parent | | pb_entity_create_relationship | Create a link, isBlockedBy, or isBlocking relationship between two entities | | pb_entity_delete_relationship | Delete a relationship between two entities |

Strategy (12 tools)

| Tool | Description | |------|-------------| | pb_initiative_list | List initiatives | | pb_initiative_get | Get an initiative by ID | | pb_initiative_create | Create a new initiative | | pb_initiative_update | Update an initiative's fields | | pb_objective_list | List objectives | | pb_objective_get | Get an objective by ID | | pb_objective_create | Create a new objective | | pb_objective_update | Update an objective's fields | | pb_key_result_list | List key results | | pb_key_result_get | Get a key result by ID | | pb_key_result_create | Create a new key result | | pb_key_result_update | Update a key result's fields |

Notes (11 tools)

| Tool | Description | |------|-------------| | pb_note_list | List notes with optional filtering | | pb_note_get | Get a note by ID | | pb_note_create | Create a new note | | pb_note_update | Update a note's fields | | pb_note_delete | Delete a note | | pb_note_search | Search notes by structured filters | | pb_note_count | Count notes matching structured filters (paginates internally) | | pb_note_link_feature | Link a note to a feature | | pb_note_link_customer | Link a note to a customer/company | | pb_note_unlink | Remove a relationship from a note | | pb_note_list_relationships | List a note's relationships |

Search

| Tool | Description | |------|-------------| | pb_entity_search | Search entities by type and structured filters |

Configuration (3 tools)

| Tool | Description | |------|-------------| | pb_config_list | List all entity type configurations (fields, filters) | | pb_config_get | Get configuration for a specific entity type | | pb_config_notes | Get note field configuration |

ADO Push/Link (4 tools)

| Tool | Description | |------|-------------| | pb_ado_push_feature_auto | Push a PB feature to ADO — launches Chromium, fills the push dialog, returns the created work item URL | | pb_ado_link_feature_auto | Link a PB feature to an existing ADO work item by ID | | pb_build_detail_url | Encode a ProductBoard entity UUID into a detail page URL | | pb_decode_detail_url | Decode a ProductBoard detail URL back to entity UUID + workspace URL |

Troubleshooting

"Missing required environment variables" → Set PRODUCTBOARD_OAUTH_CLIENT_ID and PRODUCTBOARD_OAUTH_CLIENT_SECRET in your MCP client config.

"Token exchange failed" / "invalid_grant" → Authorization codes are short-lived. Restart the server to trigger a fresh OAuth flow.

Persistent 401 errors after token refresh → The refresh token may have expired. The server will automatically detect this, clear the stale token, and open a browser window to re-authorize.

EADDRINUSE: address already in use :::3000 on first run → A previous server instance is holding the callback port. Wait a few seconds and restart.

"Server disconnected" in Claude Desktop → Ensure console.log is not used in any server code — stdout is the MCP transport channel.

ADO push opens a browser login screen → The browser session (stored in ~/.productboard-mcp/browser-profile) has expired. Log in once and subsequent pushes will reuse the session.

Release Notes

1.1.0

  • Broker mode: zero-configuration OAuth callback — when using the Azure Function token broker, the local OAuth callback port is now auto-selected from the 50000+ range. No port needs to be pre-registered with ProductBoard, and PRODUCTBOARD_CALLBACK_PORT is not required. The broker's /api/callback endpoint acts as the registered redirect URI and bounces the browser to whichever local port was picked.
  • PRODUCTBOARD_CALLBACK_PORT now direct mode only — this variable is still supported for direct mode (default: 3000) but is ignored in broker mode.

1.0.8

  • Automatic re-authorization on expired refresh token — if the refresh token expires (e.g. after a period of inactivity), the server now detects the invalid_grant error, clears the stale credentials, and automatically opens a browser window to re-authorize. No manual intervention required.

1.0.7

  • PRODUCTBOARD_CALLBACK_PORT environment variable — allows configuring the local port used for the OAuth callback server (default: 3000). Useful if port 3000 is already in use on your machine.

License

MIT