feat(mcp): add cross-platform pack workspace - #2631
Conversation
|
Warning Review limit reached
Next review available in: 54 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
WalkthroughAdds a versioned MCP Apps pack workspace widget, bounded structured ChangesPack workspace MCP App
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant ChatGPT
participant MCPWorker
participant PackRatAPI
participant PackWorkspaceWidget
ChatGPT->>MCPWorker: call get_pack
MCPWorker->>PackRatAPI: request pack data
PackRatAPI-->>MCPWorker: return pack response
MCPWorker->>MCPWorker: normalize bounded PackSnapshot
MCPWorker-->>ChatGPT: structuredContent and text fallback
ChatGPT->>PackWorkspaceWidget: render structured content
PackWorkspaceWidget-->>ChatGPT: send initialization and resize messages
Suggested labels: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Coverage Report for packages/units (./packages/units)
File CoverageNo changed files found. |
Coverage Report for packages/mcp (./packages/mcp)
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||
Coverage Report for apps/expo (./apps/expo)
File CoverageNo changed files found. |
Coverage Report for packages/overpass (./packages/overpass)
File CoverageNo changed files found. |
Coverage Report for packages/api (./packages/api)
File CoverageNo changed files found. |
Coverage Report for packages/analytics (./packages/analytics)
File CoverageNo changed files found. |
There was a problem hiding this comment.
Actionable comments posted: 8
🤖 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 `@docs/plans/2026-07-17-001-feat-chatgpt-pack-app-plan.md`:
- Line 54: Remove the unsupported serialized-size bound claim from the plan and
its associated test claim, unless implementing enforcement in the pack-widget
normalization and client serialization flow. Keep only bounds that are actually
enforced by the normalization logic, including field lengths, row counts, and
categories.
- Line 45: Update the documented MCP fallback contract to match client.ts:
describe content as the complete structured snapshot serialized as formatted
JSON rather than “terse.” In
docs/plans/2026-07-17-001-feat-chatgpt-pack-app-plan.md at line 45, update R3
and its acceptance wording; in packages/mcp/README.md at lines 75-76, update the
Inspector validation expectation accordingly.
In `@packages/mcp/README.md`:
- Line 150: Update the health-check checklist entry in the README to distinguish
protocols: specify that local checks use an HTTP origin, while tunneled and
deployed checks use HTTPS. Keep the existing health-check success requirement
unchanged.
In `@packages/mcp/src/__tests__/apps.test.ts`:
- Around line 247-264: Replace the source-string assertions in the “uses
parent-only bridge messages and safe text DOM APIs for API-derived values” test
with execution in a DOM harness using the generated resource HTML. Dispatch
representative host messages and assert observable rendered text plus emitted
protocol messages, including initialization, tool results, and size changes;
retain coverage for parent-origin filtering and safe API-derived text without
checking implementation strings.
- Around line 183-201: Update the normalizePackSnapshot overflow test fixture to
use weight and quantity values that each satisfy their individual schema limits
while their product exceeds the aggregate derived-weight bound. Keep the
existing item structure and null expectation unchanged.
In `@packages/mcp/src/apps/pack-widget.ts`:
- Line 23: Update the weight-unit conversion logic to explicitly support only g,
kg, oz, lb, and lbs, preserving each unit’s existing conversion behavior. In the
relevant conversion and calculation paths around weightUnit, ensure unsupported
values such as "stone" return null rather than defaulting to factor 1 or being
treated as grams.
- Line 36: Bound the input array before Zod parsing and downstream aggregation
in the pack-widget flow. Add a documented maximum item-count check around the
schema containing items and reject or truncate oversized API responses before
safeParse(), category aggregation, and sorting; preserve the existing 50-row
display cap for output rendering.
In `@packages/mcp/src/tools/packs.ts`:
- Around line 52-61: The get_pack handler currently uses the bounded
normalizePackSnapshot result for both response channels. In
packages/mcp/src/tools/packs.ts lines 52-61, update the onSuccess path to
preserve the original API data as text while attaching the bounded snapshot only
as structuredContent. In packages/mcp/src/__tests__/apps.test.ts lines 47-98,
extend the fixture with data beyond the snapshot boundary and assert text
includes it while structured content remains bounded.
🪄 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: ASSERTIVE
Plan: Pro
Run ID: 585d858c-9edb-4c7e-a20a-e6b03260400e
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock,!bun.lock
📒 Files selected for processing (8)
docs/plans/2026-07-17-001-feat-chatgpt-pack-app-plan.mdpackages/mcp/README.mdpackages/mcp/package.jsonpackages/mcp/src/__tests__/apps.test.tspackages/mcp/src/apps/pack-widget.tspackages/mcp/src/client.tspackages/mcp/src/index.tspackages/mcp/src/tools/packs.ts
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/plans/2026-07-17-001-feat-chatgpt-pack-app-plan.md (1)
204-204: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winNarrow the payload-bound guarantee.
okStructuredpreserves the complete Eden response in textcontent(packages/mcp/src/client.ts), while onlystructuredContentis bounded. This DoD item currently implies that the entire model/widget payload is bounded. Restrict the claim to the structured widget snapshot, or add a cap to the intentional text fallback.Proposed wording
- oversized packs cannot create an unbounded model/widget payload. + oversized packs cannot create an unbounded structured widget snapshot.🤖 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 `@docs/plans/2026-07-17-001-feat-chatgpt-pack-app-plan.md` at line 204, Update the payload-bound guarantee in the plan to apply only to the bounded structured widget snapshot, unless the intentional text fallback in okStructured is also capped. Align the wording with the behavior of structuredContent and avoid claiming that the complete Eden response text content is bounded.
🤖 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 `@docs/plans/2026-07-17-001-feat-chatgpt-pack-app-plan.md`:
- Line 54: Clarify the serialized-size guarantee across the plan and README: at
docs/plans/2026-07-17-001-feat-chatgpt-pack-app-plan.md:54, either specify and
enforce a UTF-8 byte ceiling or limit the claim to structural/character bounds;
at docs/plans/2026-07-17-001-feat-chatgpt-pack-app-plan.md:167, align the test
requirement with that guarantee, including non-ASCII inputs if validating bytes;
and at packages/mcp/README.md:216-217, remove any implication that the
32,000-character repository test proves Claude’s external host limit.
---
Outside diff comments:
In `@docs/plans/2026-07-17-001-feat-chatgpt-pack-app-plan.md`:
- Line 204: Update the payload-bound guarantee in the plan to apply only to the
bounded structured widget snapshot, unless the intentional text fallback in
okStructured is also capped. Align the wording with the behavior of
structuredContent and avoid claiming that the complete Eden response text
content is bounded.
🪄 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: ASSERTIVE
Plan: Pro
Run ID: d83752fc-0fbb-4e7d-aae4-cc6b4cb73002
📒 Files selected for processing (6)
docs/plans/2026-07-17-001-feat-chatgpt-pack-app-plan.mdpackages/mcp/README.mdpackages/mcp/src/__tests__/apps.test.tspackages/mcp/src/apps/pack-widget.tspackages/mcp/src/client.tspackages/mcp/src/tools/packs.ts
Description
PackRat packs can now open as the same native workspace in ChatGPT and Claude while the existing
MCP endpoint remains fully usable by generic clients. Both hosts share one portable MCP Apps UI,
one OAuth flow, and the same thin Eden Treaty-backed tool layer—there is no provider-specific
backend or second data path to maintain.
The first workspace is read-only.
get_packretains its complete text fallback for clients thatignore UI metadata while supplying a bounded structured snapshot to the sandboxed widget. The UI
uses the standard MCP Apps initialization lifecycle, renders untrusted values with safe DOM APIs,
reports dynamic size changes, and has no network access in its CSP.
Session-settled decision carried from planning: extend the existing MCP Worker and preserve Eden
Treaty as the sole business-data boundary (user-directed).
Type of change
Area(s) affected
apps/expo)packages/mcp)apps/landing)apps/guides).github/)Testing
tool-result rendering, unit conversion, and sizing
bindings before the recovery update
The pre-crash branch also passed
bun run check, the repository custom lint suite, packageordering/catalog checks, and clean-tree hooks. After recovery,
git diff --checkpasses and thenew commit hook completed, but the local dependency tree remained too slow to collect Vitest after
the crash; CI is the authoritative rerun for the final head. Live ChatGPT and Claude Team
registration require a public Worker with deployed KV bindings and were not exercised locally.
Screenshots / recordings
No artifact attached; the browser-host validation was local and is summarized above.
New concepts
MCP Apps as a presentation profile
MCP Apps is not a competing data protocol beside MCP. It is an MCP resource profile that lets a
tool result point at a sandboxed HTML view while retaining ordinary
contentfor clients that donot render apps.
This keeps authorization and business behavior in the API instead of duplicating them in each AI
surface. A provider-specific backend would make sense only if a host required behavior outside the
portable MCP contract.
Pre-merge checklist
bun check-typespasses with no errors — MCP stricttscis repo-disabled; Wrangler deploydry-run is the package type/bundle gate
get_packmetadataand generic MCP behavior is preserved
feat:,fix:,chore:, etc.)Summary by CodeRabbit
get_packtool to return structured pack snapshots plus readable text fallback for broader MCP client support./mcpdocumentation, including setup, health checks, Inspector validation, and live dev verification steps.