Skip to content

feat(shared): add 12 net-new DCR MCP catalog entries fixes NV-7959#11437

Merged
djabarovgeorge merged 16 commits into
nextfrom
feat/mcp-dcr-catalog-net-new-twelve
Jun 3, 2026
Merged

feat(shared): add 12 net-new DCR MCP catalog entries fixes NV-7959#11437
djabarovgeorge merged 16 commits into
nextfrom
feat/mcp-dcr-catalog-net-new-twelve

Conversation

@djabarovgeorge
Copy link
Copy Markdown
Contributor

@djabarovgeorge djabarovgeorge commented Jun 3, 2026

New DCR MCP servers (12)

Stacked on #11435 (fix/mcp-oauth-dcr-polish) — catalog-only follow-up after OAuth discovery polish lands.

Name Catalog ID
Axiom axiom
Better Stack better-stack
Buildkite buildkite
GitLab gitlab
Grafana Cloud grafana
LaunchDarkly launchdarkly
New Relic new-relic
Pulumi pulumi
Railway railway
Replicate replicate
Semgrep semgrep
Sourcegraph sourcegraph

Summary

Linear: NV-7959

Test plan

Made with Cursor

What changed

This PR adds 12 new MCP catalog entries with Dynamic Client Registration (DCR) authentication support. The entries are for Axiom, Better Stack, Buildkite, GitLab, Grafana Cloud, LaunchDarkly, New Relic, Pulumi, Railway, Replicate, Semgrep, and Sourcegraph. Each entry includes the provider's name, description, URL, and DCR oauth configuration. The changes build on PR #11435, which introduced issuer-relaxation and DCR flow improvements required for these providers.

Affected areas

shared: The mcp-servers.ts catalog was extended with 12 new McpServer entries configured for DCR authentication, adding them to both popular and "all others" sections.

api: Two test suites were enhanced. The mcp-oauth-discovery.service.spec.ts now includes tests validating issuer pattern scenarios (delegated-issuer, parent-domain, sibling-subdomain, MCP gateway patterns), plus a test confirming issuer normalization with trailing slashes. The mcp-oauth-issuer-match.spec.ts adds negative test cases verifying that issuer-relaxation patterns are rejected when the OAuth token endpoint moves to an unauthorized domain.

Testing

New unit tests were added to validate issuer-discovery edge cases: delegated issuer on product origin, parent-domain issuers, sibling-subdomain acceptance, MCP gateway patterns, and trailing-slash normalization. Tests also verify that invalid endpoint-to-domain binding is rejected. Manual verification is planned for staging to confirm OAuth connect works for GitLab, New Relic, and one additional provider after PR #11435 is deployed, and to verify all 12 entries appear in the agent MCP picker with correct DCR wiring.

Greptile Summary

This PR adds 12 net-new MCP catalog entries with oauth.mode: dcr (Dynamic Client Registration) to mcp-servers.ts, covering providers like GitLab, Grafana Cloud, New Relic, LaunchDarkly, Axiom, and others. Accompanying tests extend the OAuth discovery and issuer-match specs with acceptance and rejection scenarios for delegated-issuer, parent-domain, sibling-subdomain, and MCP gateway patterns.

  • Catalog additions (mcp-servers.ts): 12 new McpServer entries spread across the popular and all-others sections, each with a vetted DCR OAuth config.
  • Discovery service tests (mcp-oauth-discovery.service.spec.ts): New positive tests validate the service processes Clerk delegated-issuer, Vercel parent-domain, PlanetScale MCP gateway, New Relic sibling-subdomain, and Monte Carlo trailing-slash patterns; one new rejection test verifies the service throws mcp_no_as_metadata when an OAuth endpoint moves to an unauthorized domain.
  • Issuer-match tests (mcp-oauth-issuer-match.spec.ts): Three new negative cases confirm isAcceptableIssuerMatch rejects each pattern variant when the token endpoint is swapped to evil.example.

Confidence Score: 5/5

Safe to merge; purely additive catalog entries and tests with no changes to runtime logic.

All 12 catalog additions follow the established McpServer schema, and the PR description notes each endpoint was vetted via live PRM/DCR probes. The new tests correctly exercise both acceptance and rejection paths for each issuer-relaxation pattern, and the negative cases in both spec files explicitly guard against adversarial token-endpoint substitution.

No files require special attention.

Important Files Changed

Filename Overview
packages/shared/src/consts/providers/mcp-servers.ts 12 new DCR MCP catalog entries added with correct structure; all entries follow the existing McpServer schema pattern.
apps/api/src/app/agents/mcp/oauth/mcp-oauth-discovery.service.spec.ts Six new test cases added covering acceptance and rejection of issuer-relaxation patterns; consistent with the existing try/catch test style used throughout the file.
apps/api/src/app/agents/mcp/oauth/mcp-oauth-issuer-match.spec.ts Three new negative test cases added verifying that delegated-issuer, parent-domain, and sibling-subdomain relaxations are rejected when the token endpoint moves to an untrusted domain.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User selects DCR MCP provider] --> B[Load catalog entry from mcp-servers.ts]
    B --> C[discoverAuthorizationServer\ncatalog URL]
    C --> D{PRM probe\n/.well-known/oauth-protected-resource}
    D -->|200 with authorization_servers| E[Fetch AS metadata]
    D -->|404 / no PRM| F[Try direct AS discovery\n/.well-known/oauth-authorization-server]
    E --> G[isAcceptableIssuerMatch\ndiscovery URL x issuer x endpoints]
    F --> G
    G -->|exact match| H[Proceed to DCR registration]
    G -->|relaxed match\nparent-domain / sibling / delegated| I{All OAuth endpoints\non trusted domain?}
    G -->|no match| J[throw mcp_no_as_metadata]
    I -->|yes| H
    I -->|evil.example in token endpoint| J
    H --> K[POST registration_endpoint\nDynamic Client Registration]
    K --> L[Store client_id + client_secret]
    L --> M[OAuth PKCE Authorization Code Flow]
Loading

Reviews (3): Last reviewed commit: "test(api): add off-domain rejection case..." | Re-trigger Greptile

djabarovgeorge and others added 13 commits June 2, 2026 14:13
Context7 PRM lists context7.com while AS metadata declares clerk.context7.com; allow that pattern when OAuth endpoints stay on the product host, and surface upstream DCR error_description for clearer failures.

Co-authored-by: Cursor <cursoragent@cursor.com>
…method

Added support for the `token_endpoint_auth_method` in the MCP OAuth discovery service. This includes parsing the method from the response and ensuring it is correctly returned in the registration response. Updated tests to verify the behavior when the authorization server downgrades to a public client.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Removed outdated comments in the MCP OAuth controller and updated the discovery service to better handle authorization server metadata. Enhanced the token exchange process to interpret error outcomes more effectively, ensuring clearer logging and error messages. Updated tests to validate new behaviors and ensure compliance with the latest OAuth standards.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
…entation vetting

Updated the onboarding process for DCR OAuth MCP catalog entries to include a documentation vetting step. Added criteria for aborting onboarding if providers require whitelist or manual approval. Adjusted descriptions and updated the MCP_SERVERS catalog to reflect changes in provider management for 'monday.com' and 'monday-com'.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Updated the MCP OAuth discovery service to support the well-known gateway pattern for PlanetScale and Monte Carlo, improving issuer validation. Enhanced onboarding documentation to include steps for appending blocked providers to the `blocked-mcp-servers.md` file. Adjusted MCP server configurations to reflect a shift from managed to DCR authentication mode for several providers.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Updated the GenerateMcpOAuthUrl use case to improve session rotation logic based on catalog scopes. Introduced new functions to resolve DCR authorize scopes and check scope matches, ensuring better handling of OAuth sessions. Modified the MCP_SERVERS configuration for PostHog to include curated OAuth scopes, optimizing authorize URL requests within Slack button limits.
Added new MCP server entries for GitLab, Grafana Cloud, New Relic, Buildkite, Axiom, Better Stack, LaunchDarkly, Pulumi, Railway, Replicate, and Semgrep, each supporting DCR OAuth mode. Enhanced the MCP OAuth discovery service to accept sibling-subdomain patterns for New Relic, improving issuer validation. Updated the GenerateMcpOAuthUrl use case to construct authorization URLs more effectively.
…mentation

Added new entries for Fly.io, Pylon, Omni Analytics, and Sourcegraph to the blocked MCP servers list, detailing their OAuth capabilities and reasons for blocking. Enhanced the onboarding documentation to clarify candidate selection criteria and re-probing conditions for DCR entries. Updated MCP server configurations to reflect a shift from managed to DCR authentication mode for Omni Analytics and Pylon.
…nd enhance descriptions

Modified several MCP server entries to transition from provider-managed to DCR authentication mode, including AirOps, Apollo.io, Bitly, CB Insights, Contentsquare, Day AI, and Scite. Updated descriptions for clarity on each service's capabilities and use cases.
Move GitLab, Grafana, New Relic, Buildkite, Axiom, Better Stack,
LaunchDarkly, Pulumi, Railway, Replicate, Semgrep, and Sourcegraph
to a stacked catalog-only PR for easier review.

fixes NV-7959

Co-authored-by: Cursor <cursoragent@cursor.com>
Onboard Axiom, Better Stack, Buildkite, GitLab, Grafana Cloud,
LaunchDarkly, New Relic, Pulumi, Railway, Replicate, Semgrep, and
Sourcegraph after live PRM/DCR probes.

Stacked on fix/mcp-oauth-dcr-polish for OAuth discovery polish.

fixes NV-7959

Co-authored-by: Cursor <cursoragent@cursor.com>
@linear-code
Copy link
Copy Markdown

linear-code Bot commented Jun 3, 2026

NV-7959

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds test coverage for MCP OAuth discovery and issuer-matching validation across delegated, parent-domain, and gateway issuer patterns, validates endpoint-domain binding constraints, and extends the MCP server catalog with 12 new DCR-enabled entries (GitLab, Grafana Cloud, New Relic, Buildkite, Axiom, Better Stack, LaunchDarkly, Pulumi, Railway, Replicate, Semgrep, and Sourcegraph).

Changes

OAuth Discovery and Validation Test Coverage

Layer / File(s) Summary
Discovery service issuer pattern acceptance tests
apps/api/src/app/agents/mcp/oauth/mcp-oauth-discovery.service.spec.ts
Adds six test cases validating discoverAuthorizationServer acceptance of delegated-issuer, parent-domain, and MCP gateway patterns (PlanetScale, New Relic), rejection of gateway patterns when OAuth endpoints leave the advertised domain, and normalization of issuer URLs with trailing slashes.
Issuer-match endpoint domain binding tests
apps/api/src/app/agents/mcp/oauth/mcp-oauth-issuer-match.spec.ts
Adds three test cases asserting that delegated-issuer, parent-domain, and sibling-subdomain issuer-relaxation patterns reject token endpoints configured to unauthorized domains.

MCP Catalog Extensions

Layer / File(s) Summary
New DCR-enabled server catalog entries
packages/shared/src/consts/providers/mcp-servers.ts
Adds 12 new McpServer entries (GitLab, Grafana Cloud, New Relic as popular; Buildkite, Axiom, Better Stack, LaunchDarkly, Pulumi, Railway, Replicate, Semgrep, Sourcegraph as standard), each configured with oauth.mode: 'Dcr' and categorized as code providers.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • novuhq/novu#11435: Implements mcp-oauth-issuer-match and OAuth discovery service foundation that these test cases directly validate and extend with new issuer pattern and endpoint-binding scenarios.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title follows Conventional Commits format with valid type and scope, includes Linear ticket reference, and is directly related to the main change (adding 12 new MCP catalog entries).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread packages/shared/src/consts/providers/mcp-servers.ts
Comment thread packages/shared/src/consts/providers/mcp-servers.ts
Base automatically changed from fix/mcp-oauth-dcr-polish to next June 3, 2026 15:43
Take next's issuer-match and token-exchange-outcome refactor while
keeping the 12 net-new DCR catalog entries from this branch.

Co-authored-by: Cursor <cursoragent@cursor.com>
@netlify
Copy link
Copy Markdown

netlify Bot commented Jun 3, 2026

Deploy Preview for dashboard-v2-novu-staging canceled.

Name Link
🔨 Latest commit 47e15d8
🔍 Latest deploy log https://app.netlify.com/projects/dashboard-v2-novu-staging/deploys/6a20514f633cfa00091530c3

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/__fixtures__/_shared/replay.ts (1)

44-61: ⚡ Quick win

Use interface for backend request/response contracts.

SafeJsonRequestArgs, SafeJsonResponse, and SafeRawResponse should be interface declarations in backend TS files per repository rule.

As per coding guidelines: "**/*.{ts,tsx}: On the backend: use interface for type definitions; on the frontend: use type for type definitions".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/__fixtures__/_shared/replay.ts`
around lines 44 - 61, Replace the three exported type aliases with exported
interface declarations: change SafeJsonRequestArgs, SafeJsonResponse<T>, and
SafeRawResponse from "export type" to "export interface" while preserving their
property names, optional modifiers (e.g., method?), generic parameter on
SafeJsonResponse<T>, and the exact property types (headers as Record<string,
string | string[] | undefined>, body Buffer for SafeRawResponse, etc.); keep the
exports and shapes identical so consumers are unaffected.
apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/__fixtures__/_shared/types.ts (1)

1-14: ⚡ Quick win

Use interface for backend type definitions.

These exported backend contracts are declared as type; convert them to interface to match project conventions.

As per coding guidelines: "**/*.{ts,tsx}: On the backend: use interface for type definitions; on the frontend: use type for type definitions".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/__fixtures__/_shared/types.ts`
around lines 1 - 14, Change the backend type aliases to interfaces: replace the
exported type declarations DcrFixtureManifest and DcrFixtureSet with exported
interface declarations that preserve the exact shape (fields mcpUrl, issuer,
optional registrationEndpoint, tokenEndpoint for DcrFixtureManifest; manifest,
prm, asMetadata, optional dcrRegisterResponse, tokenExchangeResponse for
DcrFixtureSet). Ensure the export names remain identical and keep the same
property types (string, optional string, and Record<string, unknown>) so callers
of DcrFixtureManifest and DcrFixtureSet continue to work.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/__fixtures__/_shared/replay.ts`:
- Around line 10-15: The helper readOptionalJsonFile currently swallows all
errors; change it to only return undefined for a missing-file error (errno/code
'ENOENT') and rethrow any other exceptions so parse/permission errors surface;
locate readOptionalJsonFile and its call to readJsonFile<T>(filePath) and wrap
the readJsonFile call in a try/catch that checks the error code (or errno) and
returns undefined only when it's ENOENT, otherwise rethrow the caught error.
- Around line 71-77: The urlMatches function is too permissive because the
reverse-prefix check candidate.startsWith(`${url}/`) causes broad issuer URLs to
match narrower endpoints; fix urlMatches by removing that reverse-prefix
condition and normalizing trailing slashes before comparison: trim any trailing
'/' from both url and candidate, then return true only when they are exactly
equal or when url is a longer path that starts with candidate + '/' (i.e., url
=== candidate || url.startsWith(candidate + '/')). Ensure this change is applied
inside the urlMatches function.

In
`@apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/resolve-default-dcr-token-exchange-outcome.ts`:
- Line 1: The default resolver resolveDefaultDcrTokenExchangeOutcome is applying
provider-specific remaps via mapTokenExchangeErrorCode without any
mcpId/provider context, causing GitHub-only codes (e.g.,
application_suspended/app_blocked → mcp_github_org_block) to leak to other
providers; change it so the default resolver is provider-agnostic by either
returning a generic fallback like mcp_token_exchange_failed (or another neutral
code) from resolveDefaultDcrTokenExchangeOutcome, or update the call sites to
pass mcpId/provider and move the GitHub-specific remapping into the GitHub DCR
strategy (not in resolveDefaultDcrTokenExchangeOutcome) so
mapTokenExchangeErrorCode is only used with provider-aware logic in the per-mcp
strategy.

In `@apps/api/src/app/agents/mcp/oauth/mcp-oauth-discovery.service.spec.ts`:
- Around line 270-347: Add negative tests for the delegated-issuer,
parent-domain, and sibling-subdomain relaxed-match patterns mirroring the
existing "MCP well-known gateway" off-domain rejection test: for each pattern
(delegated-issuer / Clerk, parent-domain / Vercel, sibling-subdomain / New
Relic) stub safeJsonStub to return metadata whose issuer is on a different
domain than the requested MCP host and assert that
service.discoverAuthorizationServer rejects or throws (i.e., does not accept the
off-domain issuer) — follow the same structure and assertions used by the
existing gateway negative test but applied to the test cases named
"delegated-issuer", "parent-domain", and "sibling-subdomain" to ensure
domain-boundary validation cannot regress.

---

Nitpick comments:
In
`@apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/__fixtures__/_shared/replay.ts`:
- Around line 44-61: Replace the three exported type aliases with exported
interface declarations: change SafeJsonRequestArgs, SafeJsonResponse<T>, and
SafeRawResponse from "export type" to "export interface" while preserving their
property names, optional modifiers (e.g., method?), generic parameter on
SafeJsonResponse<T>, and the exact property types (headers as Record<string,
string | string[] | undefined>, body Buffer for SafeRawResponse, etc.); keep the
exports and shapes identical so consumers are unaffected.

In
`@apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/__fixtures__/_shared/types.ts`:
- Around line 1-14: Change the backend type aliases to interfaces: replace the
exported type declarations DcrFixtureManifest and DcrFixtureSet with exported
interface declarations that preserve the exact shape (fields mcpUrl, issuer,
optional registrationEndpoint, tokenEndpoint for DcrFixtureManifest; manifest,
prm, asMetadata, optional dcrRegisterResponse, tokenExchangeResponse for
DcrFixtureSet). Ensure the export names remain identical and keep the same
property types (string, optional string, and Record<string, unknown>) so callers
of DcrFixtureManifest and DcrFixtureSet continue to work.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0842eac4-3407-4b4f-ba7d-1613f3e02ae9

📥 Commits

Reviewing files that changed from the base of the PR and between 590dff3 and 2c2c4b1.

📒 Files selected for processing (14)
  • apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/__fixtures__/_shared/replay.spec.ts
  • apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/__fixtures__/_shared/replay.ts
  • apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/__fixtures__/_shared/types.ts
  • apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/__fixtures__/example/as-metadata.json
  • apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/__fixtures__/example/dcr-register-response.json
  • apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/__fixtures__/example/manifest.json
  • apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/__fixtures__/example/prm.json
  • apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/__fixtures__/example/token-exchange-response.json
  • apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/dcr-provider-strategy-registry.ts
  • apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/dcr-provider-strategy.spec.ts
  • apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/dcr-provider-strategy.ts
  • apps/api/src/app/agents/mcp/oauth/dcr-provider-strategies/resolve-default-dcr-token-exchange-outcome.ts
  • apps/api/src/app/agents/mcp/oauth/mcp-oauth-discovery.service.spec.ts
  • packages/shared/src/consts/providers/mcp-servers.ts

Align with NV-7959 (#11435): issuer matching and token exchange now live
in mcp-oauth-issuer-match and token-exchange-outcome.

Co-authored-by: Cursor <cursoragent@cursor.com>
Cover delegated-issuer, parent-domain, and sibling-subdomain patterns
in mcp-oauth-issuer-match.spec.ts per security review feedback.

Co-authored-by: Cursor <cursoragent@cursor.com>
@djabarovgeorge djabarovgeorge merged commit d37e2c0 into next Jun 3, 2026
38 checks passed
@djabarovgeorge djabarovgeorge deleted the feat/mcp-dcr-catalog-net-new-twelve branch June 3, 2026 16:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant