Skip to content

fix(mcp): preserve cached workspace arguments across schema upgrades - #375

Open
JunkaiWang-TheoPhy wants to merge 2 commits into
Waishnav:mainfrom
JunkaiWang-TheoPhy:codex/cached-workspace-arguments
Open

JunkaiWang-TheoPhy wants to merge 2 commits into
Waishnav:mainfrom
JunkaiWang-TheoPhy:codex/cached-workspace-arguments

Conversation

@JunkaiWang-TheoPhy

@JunkaiWang-TheoPhy JunkaiWang-TheoPhy commented Sep 27, 2026 •

Copy link
Copy Markdown

A ChatGPT connector created against v1.0.8 can retain workspaceId in cached tool calls after the server starts advertising workspace_id. The authenticated workspace and canonical read still work, but the old call fails input validation. #339 documents this upgrade boundary, and #373 narrows the proposed transition behavior.

This adds one compatibility step at the authenticated HTTP edge: normalize an own tools/call.arguments.workspaceId property before existing tool validation. Public schemas continue to advertise snake_case. Identical old/new values are accepted; contradictory values return Invalid params with the original JSON-RPC request ID. Notifications receive an empty HTTP 202 response. Invalid workspace values still reach the existing schema checks, and OAuth and filesystem authorization are unchanged.

The HTTP regression fails on the original implementation with workspace_id: Invalid input: expected string, received undefined, then passes after the change. Retaining the new tests while reverting the ID fix also reproduced expected: 'cached-request' / actual: null and the notification-status mismatch. All 31 server tests and TypeScript typecheck passed locally after restoration. Tests cover canonical schemas, both aliases, conflicts, invalid values, authentication, outside-root reads, response IDs, and notifications. Live ChatGPT error presentation and packaged installation were not tested.

#303 intentionally added no compatibility aliases. This proposal is limited to the observed cached workspace argument and its refresh path; other legacy field names still require the host to refresh descriptors. It does not extend aliases through the domain model. The two touched files contain the HTTP edge change and its regression coverage. External research references do not apply to this maintenance change.

Closes #373. Related to #339 and #303.

Summary by CodeRabbit

  • Bug Fixes
    • Workspace read requests using workspaceId are now handled consistently with workspace_id. Requests that provide conflicting values receive an HTTP 400 error.
    • Invalid notifications with conflicting workspace identifiers now receive an empty HTTP 202 response, while requests retain their JSON-RPC ID in the error response.

ChatGPT can retain the former workspaceId argument after schemas migrate to workspace_id. Normalize only that alias at the authenticated HTTP edge and reject contradictory handles before tool validation, while keeping the advertised schema canonical.

Constraint: Preserve OAuth and workspace containment boundaries
Confidence: high
Scope-risk: narrow
Tested: HTTP regression fails with original server and passes with compatibility adapter; all 26 server tests; TypeScript typecheck
Not-tested: Live ChatGPT cached session and packaged installation
Related: Waishnav#373
Alias conflicts must remain recognizable to MCP clients: retain string, numeric and null request IDs and accept notifications without sending JSON-RPC responses. Existing generic error responses retain their default null ID.

Confidence: high
Scope-risk: narrow
Tested: Original conflict handler fails string and numeric ID plus notification regressions; all 31 server tests pass after repair; TypeScript typecheck
Not-tested: Live ChatGPT error presentation
@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 75f27a54-bf0e-4591-b6d7-fd6eaa044296

📥 Commits

Reviewing files that changed from the base of the PR and between 531d3f9 and 6c5fc8f.

📒 Files selected for processing (2)
  • src/server.test.ts
  • src/server.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review.


📝 Walkthrough

Walkthrough

The /mcp handler now normalizes cached workspaceId arguments to workspace_id before dispatch. It rejects conflicting aliases with a JSON-RPC invalid-params error for requests and an empty HTTP 202 response for notifications. Tests cover these responses and related read request behavior.

Changes

Cached workspace argument compatibility

Layer / File(s) Summary
HTTP-boundary normalization and response handling
src/server.ts, src/server.test.ts
The server maps workspaceId to workspace_id when the canonical key is absent and rejects unequal values. Tests cover accepted and conflicting aliases, request IDs, notifications, and related read behavior. The published read schema remains canonical.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: waishnav

Merge Risk: ⚪ Minimal · up to 6c5fc

The compatibility change appears ready to merge after normal checks; no concrete blocking risk remains.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 6c5fc

The endpoint accepts one legacy workspace argument after authentication and keeps the existing workspace and file-access checks. No bypass was found, but the available coverage does not establish that every client behavior has been exercised.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The additional accepted input is limited to an own workspaceId property on HTTP tools/call arguments. It does not add an unauthenticated route or itself select a workspace or access a file.

Trust Boundaries and Controls

  • observed — Attacker-supplied HTTP arguments encounter bearer and resource authorization before alias handling. Conflicting aliases stop before dispatch; accepted or invalid values continue through the downstream tool path.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: preserving cached workspace arguments across schema upgrades through an MCP compatibility fix.
Linked Issues check ✅ Passed The PR implements the coding requirements in [#373]. The HTTP-edge normalizer maps cached workspaceId to workspace_id before MCP dispatch and removes the alias. It rejects unequal aliases with JSO…
Out of Scope Changes check ✅ Passed The changed server code is limited to HTTP-edge alias normalization and JSON-RPC error ID handling. The added tests directly verify the transition behavior, error behavior, notification behavior, and …
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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

A rabbit taps the fields in line
Old names meet the new design
Conflicts earn a clear reply
Requests keep their IDs nearby
The schema stays snake_case
Soft paws leave a tidy trace

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

@greptile-apps

greptile-apps Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

[Medium risk] Normalizes workspace argument names in cached tool calls.

The test-coverage gap is non-blocking; the PR can merge with this concern outstanding.

Findings

  1. P2 Invalid-value test misses schema regressions ▶

Summary

This PR translates cached workspaceId tool arguments to workspace_id at the authenticated HTTP endpoint and adds regression tests. The invalid-value test remains green even when non-string IDs bypass schema validation and fail later during workspace handling.

Reviews (1) · Last reviewed commit: "Keep compatibility errors correlated wit..."

Comment thread src/server.test.ts
Comment on lines +503 to +509
for (const workspaceId of [null, 42, {}, []]) {
const invalid = await postModernMcp(localBaseUrl, accessToken, "tools/call", {
name: "read", arguments: { workspaceId, path: "note.txt" },
});
const body = await invalid.json();
assert.ok(body.error || body.result?.isError, JSON.stringify(body));
assert.notEqual(invalid.status, 500);

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.

P2 Invalid-value test misses schema regressions

The assertions accept any tool error for a non-string workspaceId. They still pass when schema validation is bypassed and the value fails later during workspace handling, so a validation regression could go unnoticed. Assert that the response specifically reports invalid workspace_id input.

Artifacts

HTTP probe source for non-string workspace IDs

  • The executed probe authenticates, sends four non-string IDs to the read endpoint, and applies the test's exact two assertions.

HTTP responses with string schema validation enabled

  • The command and captured responses show HTTP 200 OK validation errors for all four inputs, with both original assertions passing.

HTTP responses with string schema validation bypassed

  • The command and captured responses show HTTP 200 OK non-validation errors for the same inputs, yet both original assertions still pass.

View artifacts

T-Rex Ran code and verified through T-Rex

@greptile-apps

greptile-apps Bot commented Sep 27, 2026

Copy link
Copy Markdown
Contributor

Comments Outside Diff

These findings sit on lines the diff does not cover, so they could not be posted inline. Each one leaves this list once its file changes.

  • P2 Non-string workspace ID test accepts errors unrelated to schema validation ▶

    • Bug
      • The test at src/server.test.ts:503-509 stays green when non-string IDs reach workspace handling instead of being rejected by the input schema. The mutation produced unknown-workspace and downstream errors without failing either assertion.
    • Cause
      • The assertions check only for any error and a status other than 500, not the validation error's type or message.
    • Fix
      • Assert result.isError === true and that the returned text identifies input validation for workspace_id with an expected string; retain the status check as a separate assertion.

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.

Transition handling for cached workspaceId arguments after the snake_case schema migration

1 participant