refactor(mcp-server): replace SDK with xmcp framework and dual-runtime sandbox#34904
Conversation
…mework Replace the MCP server implementation with xmcp-based architecture featuring sandbox-isolated code execution, OpenAPI spec exploration, and build-time spec processing. Two tools: search (explore API spec) and execute (make authenticated API calls). - Switch build from @nx/esbuild to nx:run-commands + xmcp build (rspack) - Add bundler config to output directly to dist/apps/mcp-server - Add generate-spec target to process openapi.json at build time - Add xmcp, @apidevtools/swagger-parser, tsx dependencies - Update env vars: DOTCMS_BASE_URL, DOTCMS_API_TOKEN, SANDBOX_TIMEOUT Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… support The sandbox previously only worked with Bun Web Workers. Add a NodeWorkerSandbox using worker_threads so the server runs on both Node.js and Bun. Runtime is detected automatically via globalThis.Bun. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Paths now reference ./stdio.js instead of ./dist/stdio.js since the published package has files at the root. Remove xmcp and zod from dependencies since they are fully bundled by rspack. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… beta Update all setup examples to use @dotcms/mcp-server@beta tag. Fix TypeScript error in sandbox runtime detection. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Claude finished @fmontes's task in 2m 38s —— View job Rollback Safety Analysis
Result: Pull Request Unsafe to RollbackCategory: M-3 — REST / GraphQL / Headless API Contract Change The MCP server rewrite itself (frontend/TypeScript) introduces no rollback risk. The Java-side changes in this PR carry three breaking-on-rollback API contract changes:
The rollback-unsafe comment was posted directly on the PR and the label |
… file Remove the 762KB openapi.json from the repo. The generate-spec script now requires a URL or local file path as an argument and fails with clear usage instructions if none is provided. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Claude finished @fmontes's task —— View job Code Review CompleteReviewed this MCP server rewrite for potential issues, security concerns, and design problems. Review Checklist
Critical Issues Found🔴 CRITICAL: Code Injection Vulnerability
🟡 Security & Design Concerns
🟢 Architecture Positives
Recommendations
The architectural changes are sound, but the code injection vulnerability makes this unsuitable for production without fixes. |
There was a problem hiding this comment.
Pull request overview
Rewrites the core-web/apps/mcp-server application to replace the @modelcontextprotocol/sdk + esbuild-based implementation with the xmcp framework, introducing a worker-based sandbox for tool execution and a build-time OpenAPI spec processing step.
Changes:
- Migrates MCP server runtime to
xmcpwith auto-discovered tools (search,execute) and rspack bundling. - Adds a dual-runtime sandbox (Node
worker_threads+ Bun Web Workers) with an adapter bridge for authenticated HTTP calls. - Adds build-time OpenAPI processing (
scripts/generate-spec.ts) and updates Nx targets/build packaging docs.
Reviewed changes
Copilot reviewed 65 out of 67 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| core-web/yarn.lock | Adds lock entries for xmcp/rspack and spec tooling dependencies. |
| core-web/package.json | Adds xmcp dependency plus dev deps for spec generation (swagger-parser, tsx). |
| core-web/apps/mcp-server/xmcp.config.ts | New xmcp configuration with custom bundler output path into Nx dist/. |
| core-web/apps/mcp-server/tsconfig.json | Updates TS config to include sources and adjust compiler options for the new build approach. |
| core-web/apps/mcp-server/tsconfig.app.json | Removes esbuild app tsconfig (no longer used with xmcp build). |
| core-web/apps/mcp-server/src/utils/schema-helpers.ts | Removes legacy MCP SDK zod-compat helper. |
| core-web/apps/mcp-server/src/utils/schema-helpers.spec.ts | Removes tests tied to legacy MCP SDK schema compatibility. |
| core-web/apps/mcp-server/src/utils/response.ts | Removes legacy MCP response formatting utilities. |
| core-web/apps/mcp-server/src/utils/response.spec.ts | Removes tests for legacy response utilities. |
| core-web/apps/mcp-server/src/utils/logger.ts | Removes custom logger used by the previous implementation. |
| core-web/apps/mcp-server/src/utils/logger.spec.ts | Removes tests for the legacy logger. |
| core-web/apps/mcp-server/src/utils/context-store.ts | Removes legacy initialization state singleton. |
| core-web/apps/mcp-server/src/utils/context-store.spec.ts | Removes tests for the legacy context store. |
| core-web/apps/mcp-server/src/utils/context-checking-server.ts | Removes legacy MCP SDK middleware/proxy enforcing initialization. |
| core-web/apps/mcp-server/src/utils/context-checking-server.spec.ts | Removes tests for the legacy context-checking proxy. |
| core-web/apps/mcp-server/src/types/workflow.ts | Removes legacy workflow-related Zod schemas/types. |
| core-web/apps/mcp-server/src/types/site.ts | Removes legacy site schemas/types. |
| core-web/apps/mcp-server/src/types/search.ts | Removes legacy search schemas/types. |
| core-web/apps/mcp-server/src/types/contentype.ts | Removes legacy content type schemas/types. |
| core-web/apps/mcp-server/src/tools/workflow/utils.ts | Removes legacy workflow tool utilities. |
| core-web/apps/mcp-server/src/tools/workflow/index.ts | Removes legacy workflow tool registration. |
| core-web/apps/mcp-server/src/tools/workflow/handlers.ts | Removes legacy workflow handlers. |
| core-web/apps/mcp-server/src/tools/workflow/constants.ts | Removes legacy workflow constants. |
| core-web/apps/mcp-server/src/tools/search/index.ts | Removes legacy search tool registration module. |
| core-web/apps/mcp-server/src/tools/search/handlers.ts | Removes legacy content search handler. |
| core-web/apps/mcp-server/src/tools/search/description.ts | Removes long-form legacy Lucene search description text. |
| core-web/apps/mcp-server/src/tools/search.ts | Adds xmcp search tool executing sandboxed JS over generated OpenAPI spec. |
| core-web/apps/mcp-server/src/tools/execute.ts | Adds xmcp execute tool executing sandboxed JS with an authenticated api adapter. |
| core-web/apps/mcp-server/src/tools/context/index.ts | Removes legacy context_initialization tool registration. |
| core-web/apps/mcp-server/src/tools/context/handlers.ts | Removes legacy context init implementation/caching. |
| core-web/apps/mcp-server/src/tools/context/formatters.ts | Removes legacy context formatters. |
| core-web/apps/mcp-server/src/tools/context/cache.ts | Removes legacy context caching module. |
| core-web/apps/mcp-server/src/tools/content-types/index.ts | Removes legacy content type tools registration. |
| core-web/apps/mcp-server/src/tools/content-types/handlers.ts | Removes legacy content type handlers. |
| core-web/apps/mcp-server/src/tools/content-types/formatters.ts | Removes legacy content type text formatting. |
| core-web/apps/mcp-server/src/tools/_example-tool/index.ts | Removes legacy example tool template. |
| core-web/apps/mcp-server/src/tools/_example-tool/handlers.ts | Removes legacy example tool handler template. |
| core-web/apps/mcp-server/src/tools/_example-tool/formatters.ts | Removes legacy example tool formatter template. |
| core-web/apps/mcp-server/src/test-setup.ts | Strips legacy Jest setup/mocks used by removed services/tools. |
| core-web/apps/mcp-server/src/services/workflow.ts | Removes legacy workflow service client. |
| core-web/apps/mcp-server/src/services/workflow.spec.ts | Removes tests for legacy workflow service. |
| core-web/apps/mcp-server/src/services/site.ts | Removes legacy site service client. |
| core-web/apps/mcp-server/src/services/site.spec.ts | Removes tests for legacy site service. |
| core-web/apps/mcp-server/src/services/search.ts | Removes legacy search service client. |
| core-web/apps/mcp-server/src/services/search.spec.ts | Removes tests for legacy search service. |
| core-web/apps/mcp-server/src/services/contentype.spec.ts | Removes tests for legacy content type service. |
| core-web/apps/mcp-server/src/services/contentType.ts | Removes legacy content type service implementation. |
| core-web/apps/mcp-server/src/services/client.ts | Removes legacy base authenticated HTTP client. |
| core-web/apps/mcp-server/src/main.ts | Removes manual MCP SDK server entrypoint (xmcp generates entrypoint at build time). |
| core-web/apps/mcp-server/src/lib/types.ts | Adds core interfaces for adapters, sandbox config, and execution context. |
| core-web/apps/mcp-server/src/lib/spec.ts | Adds loader for generated OpenAPI spec JSON. |
| core-web/apps/mcp-server/src/lib/sandbox/interface.ts | Adds sandbox interface contract. |
| core-web/apps/mcp-server/src/lib/sandbox/index.ts | Adds runtime detection/factory for Bun vs Node sandbox. |
| core-web/apps/mcp-server/src/lib/sandbox/node-worker.ts | Adds Node worker_threads sandbox implementation. |
| core-web/apps/mcp-server/src/lib/sandbox/bun-worker.ts | Adds Bun Web Worker sandbox implementation. |
| core-web/apps/mcp-server/src/lib/http-client.ts | Adds authenticated HTTP adapter (api.request) for sandboxed execution. |
| core-web/apps/mcp-server/src/lib/executor.ts | Adds executor orchestrating sandbox creation and adapter injection. |
| core-web/apps/mcp-server/scripts/generate-spec.ts | Adds build-time OpenAPI dereference/filter/compaction step. |
| core-web/apps/mcp-server/project.json | Replaces esbuild targets with run-commands for xmcp build/dev + spec generation. |
| core-web/apps/mcp-server/package.json | Updates published package metadata to ship stdio.js (xmcp output) and raise Node engine. |
| core-web/apps/mcp-server/jest.config.ts | Updates Jest config for JSON modules and new matching behavior. |
| core-web/apps/mcp-server/README.md | Updates documentation for new tool model, env vars, packaging, and usage examples. |
| core-web/apps/mcp-server/CLAUDE.md | Updates internal architecture notes and developer commands to reflect xmcp/sandbox. |
| core-web/apps/mcp-server/.gitignore | Adds ignores for xmcp artifacts and generated spec/env files. |
| core-web/apps/mcp-server/.env.example | Adds example env file for the new DOTCMS_* variables and sandbox timeout. |
- Block direct network access (fetch, XMLHttpRequest, WebSocket, EventSource) in both sandbox runtimes - Block require() and clean process.env in Node.js worker; pass empty env to Worker constructor - Protect Authorization header from override by placing it after user header spread - Add 100KB code size limit via Zod .max(100_000) on both tools - Remove unenforceable memoryLimit and allowAsync from SandboxConfig - Fix dev → serve in docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Claude finished @fmontes's task —— View job Code Review CompleteReviewed this MCP server rewrite for potential issues, security concerns, and design problems. Review Checklist
Critical Issues Found🔴 CRITICAL: Code Injection Vulnerability
🟡 Security & Design Concerns
🟢 Architecture Positives
Recommendations
The architectural changes are sound, but the code injection vulnerability makes this unsuitable for production without fixes. |
Security Remediation — PR Review FindingsAddressed the legitimate security findings from the automated reviews. Fixed
Not changed (with reasoning)
|
…-reversible Replace simple `undefined` assignments with Object.defineProperty using writable: false, configurable: false so sandbox code cannot restore fetch/WebSocket/etc. Also covers navigator.sendBeacon and freezes require in the Node worker. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Claude finished @fmontes's task —— View job Code Review CompleteReviewed this MCP server rewrite for potential issues, security concerns, and design problems. Review Checklist
Critical Issues Found🔴 CRITICAL: Code Injection Vulnerability
🟡 Security & Design Concerns
🟢 Architecture Positives
Recommendations
The architectural changes are sound and show good security awareness, but the code injection vulnerability makes this unsuitable for production without fixes. |
…OTCMS_API_TOKEN → AUTH_TOKEN Shorter, cleaner names that align with existing conventions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Claude finished @fmontes's task —— View job Code Review CompleteReviewed this MCP server rewrite for potential issues, security concerns, and design problems. Review Checklist
Critical Issues Found🔴 CRITICAL: Code Injection Vulnerability
🟡 Security & Design Concerns
🟢 Architecture Positives
Recommendations
The architectural changes are sound and show good security awareness, but the code injection vulnerability makes this unsuitable for production without fixes. |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Inline generate-spec as the first build step so the OpenAPI spec URL can be passed directly via --specUrl instead of requiring a separate generate-spec run. Update CLAUDE.md and README accordingly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove /api/v1/content, /api/v1/es, and /api/es from allowed prefixes. Add /api/es/search as the sole Elasticsearch endpoint. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Pull Request Unsafe to Rollback!!!
|
resolveFileDescriptor fetched an arbitrary, sandbox-supplied desc.url on the host. Validate the URL first: require http(s), block loopback/private/ link-local IPv4 and IPv6 (incl. cloud metadata 169.254.169.254), refuse redirects, and cap size + add a fetch timeout. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Pull Request Unsafe to Rollback!!!
|
1 similar comment
|
Pull Request Unsafe to Rollback!!!
|
Story Block field values can be sent as an HTML or Markdown string to the workflow fire endpoints; dotCMS stores the string as-is and converts it to the Block Editor structure when opened in the editor. Add this to the shared fire-endpoint @operation notes and regenerate openapi.yaml. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ields Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Pull Request Unsafe to Rollback!!!
|
|
Pull Request Unsafe to Rollback!!!
|
Address unresolved PR review findings on the sandbox runtime: - Bun worker: clear inherited process.env and block require before running user code, mirroring the Node worker. Closes a token-leak path where sandboxed code could read AUTH_TOKEN/DOTCMS_URL. - Both workers: guard adapter_call postMessage with the resolved flag and try/catch so a timeout-terminated worker cannot raise an unhandled rejection that crashes the host process. - search tool: guard against a missing/empty OpenAPI spec and return a clear handler-level error instead of failing inside the sandbox. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Pull Request Unsafe to Rollback!!!
|
The ai-evals harness intentionally uses the Vercel AI SDK (tool/ generateText) to drive LLM evaluation runs. It is internal tooling, not shipped runtime code, so the four blocking detect-vercelai findings are false positives in this context. Add inline nosemgrep comments with justification, matching the repo's existing nosemgrep convention. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Pull Request Unsafe to Rollback!!!
|
Summary
Complete rewrite of the MCP server replacing
@modelcontextprotocol/sdk+ esbuild with the xmcp framework (rspack-based).Why?
Because Anthropic demostrate that models are better writing code that calling tools and Cloudfare had a similar problem that us... too many endpoints:
New Architecture
xmcp framework — Tools auto-discovered from
src/tools/, each exportsschema,metadata, and a handler. No manual server wiring. Seexmcp.config.ts.Sandbox isolation — AI-generated code runs in isolated Workers. API tokens never enter the sandbox; an adapter pattern bridges sandbox↔main thread for authenticated HTTP calls. See
src/lib/sandbox/andsrc/lib/http-client.ts.Dual-runtime support — Sandbox works on both Node.js (
worker_threads) and Bun (Web Workers), detected automatically at startup. Seesrc/lib/sandbox/index.ts.Build-time spec processing — OpenAPI spec is dereferenced, filtered, and compacted at build time. See
scripts/generate-spec.ts.Two tools —
search(explore API spec) andexecute(make API calls), both via sandboxed JS execution. Seesrc/tools/.Key Files
src/tools/search.tssrc/tools/execute.tssrc/lib/executor.tssrc/lib/http-client.tssrc/lib/sandbox/bun-worker.tssrc/lib/sandbox/node-worker.tsCLAUDE.mdTest plan
yarn nx build mcp-server— producesdist/apps/mcp-server/stdio.js+ chunksyarn nx test mcp-server— passesyarn nx lint mcp-server— passesnpm pack --dry-run— 5 files, 167KB, correct pathsnode dist/apps/mcp-server/stdio.js— runs without missing dependency errors🤖 Generated with Claude Code
Note
High Risk
High risk due to a full rewrite of the MCP server runtime/build pipeline and removal of prior tool/service implementations, plus introduction of sandboxed code execution and HTTP adapter behavior that directly affects authenticated API calls.
Overview
Replaces the
@modelcontextprotocol/sdk-based MCP server (manual tool registration + service layer) with anxmcp-based build that auto-discovers tools and outputs a new entrypointdist/apps/mcp-server/stdio.js.Introduces two sandboxed JS tools:
search(runs code against a build-time processed OpenAPIspec) andexecute(runs code that calls an injectedapi.requestadapter), including a dual-runtime Worker sandbox (Nodeworker_threadsvs Bun Web Workers), sandbox timeouts (SANDBOX_TIMEOUT), blocked direct network access inside the sandbox, and a new authenticated HTTP adapter with path validation and multipartformDatasupport.Adds an OpenAPI spec generation step (
scripts/generate-spec.ts) wired into Nx targets (generate-spec, newbuild/serveviaxmcp), updates Jest/NPM packaging metadata for the new entrypoint/version, and refreshes docs/examples (README.md,CLAUDE.md,.env.example,.gitignore) accordingly.Reviewed by Cursor Bugbot for commit a5fb0b0. Bugbot is set up for automated code reviews on this repo. Configure here.
This PR fixes: #35978