Skip to content

Trim MCP E2E coverage - #160

Merged
kentcdodds merged 3 commits into
mainfrom
cursor/trim-mcp-e2e-a5e6
Apr 13, 2026
Merged

kentcdodds merged 3 commits into
mainfrom
cursor/trim-mcp-e2e-a5e6

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Apr 13, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • reduce the MCP end-to-end suite to three high-signal journeys
  • remove niche scheduler, connector, skill, and structured-error scenarios from slow E2E coverage
  • keep coverage for auth gating, authenticated MCP search/execute flow, and generated UI persistence/session flow
  • strengthen the retained tests by pinning the bearer auth challenge shape and proving app-session state survives across separate execute requests

Testing

  • npm run test:mcp
  • node tools/prepare-e2e-env.ts && npm run build:mcp-apps && npx vitest run --project mcp-e2e
  • reliability log artifact: mcp-e2e-feedback-fix.log
Open in Web Open in Cursor 

Summary by CodeRabbit

  • Tests
    • Strengthened authentication checks for MCP endpoint responses.
    • Broadened tool coverage to require execute, UI-opening, and search capabilities.
    • Clarified memory and search behaviors, including structured memory fields and retrieval query verification.
    • Consolidated many feature scenarios into an end-to-end flow: generate/open a UI session with a token, run session-scoped value set/get, save a persistent UI, search for it, and reopen via its hosted URL.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@coderabbitai

coderabbitai Bot commented Apr 13, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Consolidates and simplifies MCP server end-to-end tests: removes many small, brittle tests, updates unauthenticated GET /mcp expectation to 401 with a Bearer-style WWW-Authenticate header, reshapes authenticated assertions, and adds a single generated-UI end-to-end flow using bearer tokens and execute/ui_save_app/search/open_generated_ui.

Changes

Cohort / File(s) Summary
MCP E2E Test Refactor
packages/worker/src/mcp/mcp-server.mcp-e2e.test.ts
Removed local getTextContent helper and many specific feature tests. Replaced unauthenticated GET /mcp checks to assert 401 + WWW-Authenticate: Bearer ... resource_metadata="<server_origin>/.well-known/oauth-protected-resource". Updated authenticated tool assertions (require execute, open_generated_ui, search). Renamed/normalized structured memory fields to searchStructured / memorySearchStructured and assert result.memory.id on upsert. Narrowed memory fallback assertions. Added a combined generated-UI E2E flow: obtain appSession.token via open_generated_ui, call execute with bearer token for session-scoped codemode value_set/value_get, save app via codemode.ui_save_app, discover via search, and reopen via open_generated_ui verifying hostedUrl.

Sequence Diagram(s)

sequenceDiagram
  participant TestRunner
  participant MCPServer
  participant AppSessionService
  participant ExecuteEndpoint

  TestRunner->>MCPServer: GET /mcp (unauthenticated)
  MCPServer-->>TestRunner: 401 + WWW-Authenticate: Bearer resource_metadata="<origin>/.well-known/oauth-protected-resource"

  TestRunner->>MCPServer: Authenticated request -> list tools
  MCPServer-->>TestRunner: tools include execute, open_generated_ui, search

  TestRunner->>MCPServer: POST open_generated_ui
  MCPServer->>AppSessionService: create session
  AppSessionService-->>MCPServer: { appSession.token, endpoints.execute }
  MCPServer-->>TestRunner: return appSession.token + execute endpoint

  TestRunner->>ExecuteEndpoint: POST codemode.value_set (Authorization: Bearer <token>)
  ExecuteEndpoint-->>TestRunner: { ok: true }

  TestRunner->>ExecuteEndpoint: POST codemode.value_get (Authorization: Bearer <token>)
  ExecuteEndpoint-->>TestRunner: { name: "example", value: "value" }

  TestRunner->>MCPServer: POST codemode.ui_save_app (persist app)
  MCPServer-->>TestRunner: { app_id }

  TestRunner->>MCPServer: POST search (find saved app)
  MCPServer-->>TestRunner: { results including saved app_id }

  TestRunner->>MCPServer: POST open_generated_ui (reopen saved app)
  MCPServer-->>TestRunner: { hostedUrl: "<origin>/ui/<savedAppId>" }
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐇 Hop, hop — tests leap, old bits set free,

Tokens fetched from open_generated_ui,
Values saved and fetched in session's light,
Search finds the app, reopen — hosted right,
The warren's tidy, end-to-end and spry.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly summarizes the main change: trimming/reducing the MCP E2E test coverage from extensive scenarios to three high-signal journeys, removing 716 lines.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/trim-mcp-e2e-a5e6

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.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@kentcdodds
kentcdodds marked this pull request as ready for review April 13, 2026 05:39
@github-actions

github-actions Bot commented Apr 13, 2026 •

Copy link
Copy Markdown
Contributor

🔎 Preview deployed: https://kody-pr-160.kentcdodds.workers.dev

Worker: kody-pr-160
D1: kody-pr-160-db
KV: kody-pr-160-oauth-kv

Mocks:

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/worker/src/mcp/mcp-server.mcp-e2e.test.ts (1)

19-22: Tighten this WWW-Authenticate assertion.

This only proves the header contains resource_metadata=. A malformed challenge like a missing Bearer scheme or the wrong metadata URL would still pass, and this is now the only unauthenticated MCP probe left in the suite. I’d pin at least the scheme and the server.origin-derived URL here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/worker/src/mcp/mcp-server.mcp-e2e.test.ts` around lines 19 - 22, The
current assertion only checks for 'resource_metadata='; tighten it by asserting
the WWW-Authenticate header begins with the Bearer scheme and that the
resource_metadata value includes the expected server origin: read the header via
response.headers.get('WWW-Authenticate'), assert it startsWith('Bearer ') (or
matches /^Bearer\s+/), and assert it contains the server.origin-derived URL
(e.g. contains server.origin or an encoded form of it) so both the scheme and
the metadata URL are validated (use the same server.origin symbol used in the
test to build the expected substring).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/worker/src/mcp/mcp-server.mcp-e2e.test.ts`:
- Around line 126-159: The test currently performs codemode.value_set and
value_get in the same POST, so it only proves intra-execution visibility; change
it to two separate app-session requests: send one fetch to executeEndpoint
(using executeToken, same headers) whose body runs only codemode.value_set and
assert that executeResponse.ok and executePayload.ok are true, then send a
second fetch to executeEndpoint that runs only codemode.value_get and assert
that its executeResponse.ok/executePayload.ok are true and that
executePayload.result?.result matches { name: 'example', value: 'value' };
reference the existing variables executeEndpoint, executeToken,
codemode.value_set, codemode.value_get, executeResponse and executePayload when
making the split and asserting both responses.

---

Nitpick comments:
In `@packages/worker/src/mcp/mcp-server.mcp-e2e.test.ts`:
- Around line 19-22: The current assertion only checks for 'resource_metadata=';
tighten it by asserting the WWW-Authenticate header begins with the Bearer
scheme and that the resource_metadata value includes the expected server origin:
read the header via response.headers.get('WWW-Authenticate'), assert it
startsWith('Bearer ') (or matches /^Bearer\s+/), and assert it contains the
server.origin-derived URL (e.g. contains server.origin or an encoded form of it)
so both the scheme and the metadata URL are validated (use the same
server.origin symbol used in the test to build the expected substring).
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: ce301754-a116-4f7d-8bcc-a549f00daf47

📥 Commits

Reviewing files that changed from the base of the PR and between 164f3bf and 4ba7c74.

📒 Files selected for processing (1)
  • packages/worker/src/mcp/mcp-server.mcp-e2e.test.ts

Comment thread packages/worker/src/mcp/mcp-server.mcp-e2e.test.ts Outdated
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/worker/src/mcp/mcp-server.mcp-e2e.test.ts`:
- Around line 235-253: The test currently only verifies URL fields for the
reopened saved app after calling mcpClient.client.callTool with name
'open_generated_ui' (savedOpenResult / savedOpenStructured) but does not assert
that a usable app session is returned; update the test to assert the reopened
appSession fields (e.g., presence of appSession.id, token, or whatever the
session shape is returned in savedOpenStructured or savedOpenResult) and then
perform a simple smoke call against the saved app's execute endpoint (e.g., POST
to /ui/{savedAppId}/execute or use the client's execute helper) to confirm the
reopened UI can actually execute actions. Ensure you reference and validate the
exact session properties returned by 'open_generated_ui' (appSession or similar)
and check the /execute response for a successful status or expected result.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: ac8a9ae0-ea83-4b6a-bb1c-b63514146d0e

📥 Commits

Reviewing files that changed from the base of the PR and between 4ba7c74 and 8e5acaa.

📒 Files selected for processing (1)
  • packages/worker/src/mcp/mcp-server.mcp-e2e.test.ts

Comment on lines +235 to 253
const savedOpenResult = await mcpClient.client.callTool({
name: 'open_generated_ui',
arguments: {
app_id: savedAppId,
},
})
const savedOpenStructured = (savedAppOpenResult as CallToolResult)
const savedOpenStructured = (savedOpenResult as CallToolResult)
.structuredContent as
| {
renderSource?: string
appId?: string | null
hostedUrl?: string | null
renderSource?: string
}
| undefined
expect(savedOpenStructured?.renderSource).toBe('saved_app')
expect(savedOpenStructured?.appId).toBe(savedAppId)
expect(savedOpenStructured?.hostedUrl).toContain(`/ui/${savedAppId}`)
})

test('mcp endpoint requires OAuth bearer auth', async () => {
await using database = await createTestDatabase()
await using server = await startDevServer(database.persistDir)
const response = await fetch(new URL('/mcp', server.origin), {
headers: {
Accept: 'application/json, text/event-stream',
},
})
expect(response.status).toBe(401)
expect(response.headers.get('WWW-Authenticate') ?? '').toContain(
'resource_metadata=',
)
})

test('generated UI execute supports session storage context', async () => {
await using database = await createTestDatabase()
await using server = await startDevServer(database.persistDir)
await using mcpClient = await createMcpClient(server.origin, database.user)

const openResult = await mcpClient.client.callTool({
name: 'open_generated_ui',
arguments: {
code: '<main><h1>Storage Context</h1></main>',
},
})
const openStructured = (openResult as CallToolResult).structuredContent as
| {
appSession?: {
token?: string
endpoints?: { execute?: string }
} | null
}
| undefined
const executeEndpoint = openStructured?.appSession?.endpoints?.execute
const executeToken = openStructured?.appSession?.token
expect(typeof executeEndpoint).toBe('string')
expect(typeof executeToken).toBe('string')

const response = await fetch(executeEndpoint!, {
method: 'POST',
headers: {
Authorization: `Bearer ${executeToken}`,
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
code: `async () => {
await codemode.value_set({
name: 'example',
value: 'value',
scope: 'session',
})
const result = await codemode.value_get({
name: 'example',
scope: 'session',
})
return { result }
}`,
}),
})
expect(response.ok).toBe(true)
const payload = (await response.json()) as {
ok?: boolean
result?: { result?: { name?: string; value?: string } }
}
expect(payload.ok).toBe(true)
expect(payload.result?.result?.name).toBe('example')
expect(payload.result?.result?.value).toBe('value')
})

test('mcp server resolves host approval errors into structured guidance', async () => {
await using database = await createTestDatabase()
await using server = await startDevServer(database.persistDir)
await using mcpClient = await createMcpClient(server.origin, database.user)
const appCookieHeader = await loginToApp(server.origin, database.user)

const secretSaveResponse = await fetch(
new URL('/account/secrets.json', server.origin),
{
method: 'POST',
headers: {
Cookie: appCookieHeader,
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
action: 'save',
name: 'hostApprovalToken',
value: 'secret',
scope: 'user',
description: 'Host approval',
allowedHosts: [],
allowedCapabilities: ['fetch'],
}),
},
)
expect(secretSaveResponse.ok, await secretSaveResponse.text()).toBe(true)

const result = await mcpClient.client.callTool({
name: 'execute',
arguments: {
code: `async () => {
await fetch('https://example.com', {
headers: {
Authorization: 'Bearer {{secret:hostApprovalToken|scope=user}}',
},
})
return { ok: true }
}`,
},
})

const structuredResult = (result as CallToolResult).structuredContent as
| { errorDetails?: Record<string, unknown> }
| undefined
expect((result as CallToolResult).isError).toBe(true)
expect(structuredResult?.errorDetails?.kind).toBe(
'host_approval_required_batch',
)
})

test('mcp server exposes direct refreshAccessToken helper', async () => {
await using database = await createTestDatabase()
await using server = await startDevServer(database.persistDir)
await using mcpClient = await createMcpClient(server.origin, database.user)
const appCookieHeader = await loginToApp(server.origin, database.user)

const secretSaveResponse = await fetch(
new URL('/account/secrets.json', server.origin),
{
method: 'POST',
headers: {
Cookie: appCookieHeader,
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
action: 'save',
name: 'restrictedRefreshToken',
value: 'secret',
scope: 'user',
description: 'Restricted for helper',
allowedHosts: [],
allowedCapabilities: [],
}),
},
)
expect(secretSaveResponse.ok, await secretSaveResponse.text()).toBe(true)

const setupResult = await mcpClient.client.callTool({
name: 'execute',
arguments: {
code: `async () => {
await codemode.value_set({
name: 'spotify-client-id',
value: 'spotify-client-id-value',
scope: 'user',
description: 'Spotify OAuth client id',
})
await codemode.connector_save({
name: 'spotify',
tokenUrl: 'https://accounts.spotify.com/api/token',
apiBaseUrl: 'https://api.spotify.com/v1',
flow: 'pkce',
clientIdValueName: 'spotify-client-id',
clientSecretSecretName: null,
accessTokenSecretName: 'spotifyAccessToken',
refreshTokenSecretName: 'restrictedRefreshToken',
requiredHosts: ['accounts.spotify.com', 'api.spotify.com'],
})
return { ok: true }
}`,
},
})
if ((setupResult as CallToolResult).isError) {
throw new Error(
`Helper setup execute failed: ${getTextContent((setupResult as CallToolResult).content)}`,
)
}

const result = await mcpClient.client.callTool({
name: 'execute',
arguments: {
code: `async () => {
return await refreshAccessToken('spotify')
}`,
},
})

const structuredResult = (result as CallToolResult).structuredContent as
| { errorDetails?: Record<string, unknown> }
| undefined
expect((result as CallToolResult).isError).toBe(true)
expect(structuredResult?.errorDetails?.kind).toBe(
'host_approval_required_batch',
expect(savedOpenStructured?.hostedUrl).toBe(
`${server.origin}/ui/${savedAppId}`,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Reopened saved apps still need their own session check.

This branch now only proves that a saved app can be found and reopened by URL. If open_generated_ui stopped returning a usable appSession for app_id opens, this test would still pass even though the reopened UI could no longer execute anything. Please assert the reopened session fields here and ideally smoke the saved app's /execute endpoint too.

💡 Suggested tightening
 const savedOpenStructured = (savedOpenResult as CallToolResult)
 	.structuredContent as
 	| {
 			renderSource?: string
 			appId?: string | null
 			hostedUrl?: string | null
+			appSession?: {
+				token?: string
+				endpoints?: { execute?: string }
+			} | null
 	  }
 	| undefined
 expect(savedOpenStructured?.renderSource).toBe('saved_app')
 expect(savedOpenStructured?.appId).toBe(savedAppId)
 expect(savedOpenStructured?.hostedUrl).toBe(
 	`${server.origin}/ui/${savedAppId}`,
 )
+
+const reopenedExecuteEndpoint = savedOpenStructured?.appSession?.endpoints?.execute
+const reopenedExecuteToken = savedOpenStructured?.appSession?.token
+expect(typeof reopenedExecuteEndpoint).toBe('string')
+expect(typeof reopenedExecuteToken).toBe('string')
+
+const reopenedExecuteResponse = await fetch(reopenedExecuteEndpoint!, {
+	method: 'POST',
+	headers: {
+		Authorization: `Bearer ${reopenedExecuteToken}`,
+		'Content-Type': 'application/json',
+		Accept: 'application/json',
+	},
+	body: JSON.stringify({
+		code: `async () => ({ ok: true })`,
+	}),
+})
+expect(reopenedExecuteResponse.ok).toBe(true)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/worker/src/mcp/mcp-server.mcp-e2e.test.ts` around lines 235 - 253,
The test currently only verifies URL fields for the reopened saved app after
calling mcpClient.client.callTool with name 'open_generated_ui' (savedOpenResult
/ savedOpenStructured) but does not assert that a usable app session is
returned; update the test to assert the reopened appSession fields (e.g.,
presence of appSession.id, token, or whatever the session shape is returned in
savedOpenStructured or savedOpenResult) and then perform a simple smoke call
against the saved app's execute endpoint (e.g., POST to /ui/{savedAppId}/execute
or use the client's execute helper) to confirm the reopened UI can actually
execute actions. Ensure you reference and validate the exact session properties
returned by 'open_generated_ui' (appSession or similar) and check the /execute
response for a successful status or expected result.

@kentcdodds
kentcdodds merged commit f195eaf into main Apr 13, 2026
9 checks passed
@kentcdodds
kentcdodds deleted the cursor/trim-mcp-e2e-a5e6 branch April 17, 2026 01:00
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.

2 participants