Skip to content

test(e2e): Add MCP auto-instrumentation e2e apps - #24531

Merged
mydea merged 4 commits into
feat/mcp-server-auto-instrumentationfrom
feat/mcp-server-auto-instrumentation-e2e
Sep 28, 2026
Merged

mydea merged 4 commits into
feat/mcp-server-auto-instrumentationfrom
feat/mcp-server-auto-instrumentation-e2e

Conversation

@mydea

@mydea mydea commented Sep 21, 2026 •

Copy link
Copy Markdown
Member

Stacked on #24529.

Adds two Express e2e apps that construct an McpServer without calling wrapMcpServerWithSentry, so the mcpServer integration from #24529 is the only thing producing spans — over a real streamable-HTTP transport rather than the in-memory one used by the node-integration-tests:

  • node-express-mcp-v1 — @modelcontextprotocol/sdk (v1)
  • node-express-mcp-v2 — @modelcontextprotocol/server (v2)

Each asserts the expected mcp.server spans (initialize, tool call, resource read, error status) still appear with no manual wrap. Express is the existing convention for the sibling MCP e2e apps; MCP itself doesn't require it.

node-express-mcp-v2 replaces the previous manual-wrap app of that name — now that auto-instrumentation is the default path, these apps drop the interim -auto suffix and exercise the default. Manual-wrap e2e coverage remains via cloudflare-mcp (v2), cloudflare-mcp-agent (v1), and the v1 node-express* apps.

Bun/Deno/Cloudflare variants (hono-4 multi-entry style) are intentionally deferred to a follow-up — this PR keeps the auto-instrumentation e2e coverage node-only.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

size-limit report 📦

⚠️ Warning: Base artifact is not the latest one, because the latest workflow run is not done yet. This may lead to incorrect results. Try to re-run all tests to get up to date results.

Path Size % Change Change
@sentry/browser 29.24 kB - -
@sentry/browser - with treeshaking flags 27.5 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 27.4 kB - -
@sentry/browser (incl. Tracing) 51.15 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 51.17 kB - -
@sentry/browser (incl. Tracing, Profiling) 54.18 kB - -
@sentry/browser (incl. Tracing, Replay) 90.76 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 79.86 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 95.46 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 108.41 kB - -
@sentry/browser (incl. Feedback) 46.76 kB - -
@sentry/browser (incl. sendFeedback) 34.3 kB - -
@sentry/browser (incl. FeedbackAsync) 39.41 kB - -
@sentry/browser (incl. Metrics) 30.25 kB - -
@sentry/browser (incl. Logs) 30.51 kB - -
@sentry/browser (incl. Metrics & Logs) 31.18 kB - -
@sentry/react 31 kB - -
@sentry/react (incl. Tracing) 53.45 kB - -
@sentry/vue 36.74 kB - -
@sentry/vue (incl. Tracing) 53.7 kB - -
@sentry/svelte 29.26 kB - -
CDN Bundle 30.93 kB - -
CDN Bundle (incl. Tracing) 51.69 kB - -
CDN Bundle (incl. Logs, Metrics) 33.2 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 53.66 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 73.92 kB - -
CDN Bundle (incl. Tracing, Replay) 89.28 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 91.25 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 95.45 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 97.42 kB - -
CDN Bundle - uncompressed 91.4 kB - -
CDN Bundle (incl. Tracing) - uncompressed 153.77 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 97.97 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 159.73 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 227.54 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 273.5 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 279.44 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 287.2 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 293.13 kB - -
@sentry/nextjs (client) 55.77 kB - -
@sentry/sveltekit (client) 51.59 kB - -
@sentry/core/server 39.99 kB +0.12% +44 B 🔺
@sentry/core/browser 13.63 kB - -
@sentry/node 141.46 kB +3.17% +4.34 kB 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 82.83 kB +0.04% +31 B 🔺
@sentry/node - without tracing 90.76 kB +0.04% +35 B 🔺
@sentry/node - without channel injection 119.86 kB +3.79% +4.37 kB 🔺
@sentry/aws-serverless 99.02 kB +0.04% +36 B 🔺
@sentry/cloudflare (withSentry) - minified 206.62 kB - -
@sentry/cloudflare (withSentry) 514.02 kB - -

View base workflow run

@mydea
mydea added this pull request to stack #24534 September 21, 2026 08:30
@mydea
mydea force-pushed the feat/mcp-server-auto-instrumentation-e2e branch 2 times, most recently from ea8d457 to 59cc528 Compare September 21, 2026 08:58
@mydea mydea changed the title test(e2e): Add MCP auto-instrumentation e2e apps (node) test(e2e): Add MCP auto-instrumentation e2e apps Sep 21, 2026
@mydea
mydea marked this pull request as ready for review September 21, 2026 09:05

@betegon betegon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

great one!

could we keep the existing legacy coverage and add a no-wrapper HTTP scenario pinned to protocol 2026-07-28, using createMcpHandler?

The current SDK 2 scenario still uses the legacy initialization/session path (there's no initialization in v2), so it doesn't verify auto-instrumentation through the v2 entry point

@github-actions

Copy link
Copy Markdown
Contributor

👋 @nicohrubec, @s1gr1d — Please review this PR when you get a chance!

@mydea
mydea force-pushed the feat/mcp-server-auto-instrumentation-e2e branch from 59cc528 to d4eaf18 Compare September 25, 2026 11:51
Comment on lines -10 to +14
const server = wrapMcpServerWithSentry(
new McpServer({
name: 'Echo-V2',
version: '2.0.0',
}),
);
// Intentionally NOT wrapped with `wrapMcpServerWithSentry`: the `mcpServer` integration
// auto-instruments the `McpServer` constructor, so spans must be produced anyway.
const server = new McpServer({
name: 'Echo-V2',
version: '2.0.0',
});

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this pr still just test, even though there are actual changes? I'll let you decide

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this is just changed based on the previous PR in the stack

mydea and others added 2 commits September 28, 2026 09:59
Add two Express e2e apps that construct an `McpServer` WITHOUT calling
`wrapMcpServerWithSentry`, exercising the `mcpServer` integration's
auto-wrapping over a real streamable-HTTP transport:

- `node-express-mcp-v1-auto` (`@modelcontextprotocol/sdk` v1)
- `node-express-mcp-v2-auto` (`@modelcontextprotocol/server` v2)

Both assert the expected `mcp.server` spans (initialize, tool call,
resource read, error status) still appear without a manual wrap.

Bun/Deno/Cloudflare variants are intentionally left as a follow-up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the `-auto` suffix now that auto-instrumentation is the default path:
- `node-express-mcp-v1-auto` -> `node-express-mcp-v1`
- `node-express-mcp-v2-auto` -> `node-express-mcp-v2`, replacing the previous
  manual-wrap app of that name (same assertions, now exercising the default
  auto path). Manual-wrap coverage remains via the cloudflare-mcp apps and the
  v1 `node-express*` apps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mydea
mydea force-pushed the feat/mcp-server-auto-instrumentation-e2e branch from d4eaf18 to c029964 Compare September 28, 2026 07:59
Comment on lines +9 to +14
// Intentionally NOT wrapped with `wrapMcpServerWithSentry`: the `mcpServer` integration
// auto-instruments the `McpServer` constructor, so spans must be produced anyway.
const server = new McpServer({
name: 'Echo-V2',
version: '2.0.0',
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bug: The E2E test's custom instrumentation script (instrument.mjs) calls Sentry.init() but fails to register the orchestrion runtime hook, preventing auto-instrumentation and causing the test to fail.
Severity: MEDIUM

Suggested Fix

Modify the test application's startup command to correctly register the orchestrion runtime hook. Instead of using a custom instrument.mjs file, the package.json should be updated to use --import @sentry/node/import. This ensures the hook is active before the application code runs, allowing mcpServerIntegration to function as expected.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: dev-packages/e2e-tests/test-applications/node-express-mcp-v2/src/mcp.ts#L9-L14

Potential issue: The E2E test application `node-express-mcp-v2` is configured to run
with a custom entry point (`--import ./instrument.mjs`) that calls `Sentry.init()`.
However, calling `Sentry.init()` alone does not register the orchestrion runtime hook,
which is required for the `mcpServerIntegration` to perform auto-instrumentation. The
hook is typically registered by using `--import @sentry/node/import`. Without the hook,
the `@modelcontextprotocol/server` module will not be instrumented, no spans will be
produced, and the test will fail because it explicitly waits for and asserts the
presence of these spans.

Did we get this right? 👍 / 👎 to inform future reviews.

The MCP server suites were restructured into `mcp-server/manual-instrumentation`,
`mcp-server/v1`, and `mcp-server/v2`, where v1/v2 rely on orchestrion
auto-instrumentation. `bun run` cannot inject the diagnostics channels, so those
suites produce no spans and fail. Replace the stale `mcp-server-streamed` exclude
with a `mcp-server/**` glob covering all three.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mydea
mydea requested a review from a team as a code owner September 28, 2026 08:34
@mydea
mydea requested review from andreiborza and isaacs and removed request for a team September 28, 2026 08:34
…egration

The default `mcpServer` integration pushed the main `@sentry/node` entry to
141.21 KB, over its 139 KB limit. Bump to 142 KB.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mydea
mydea merged commit 3030fde into develop Sep 28, 2026
8 of 9 checks passed
@mydea
mydea deleted the feat/mcp-server-auto-instrumentation-e2e branch September 28, 2026 08:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants