Drop stdio MCP; keep process spawning and eval out of the bundle - #467
Merged
Conversation
Contributor
Greptile SummaryThis PR removes stdio MCP support and keeps process-spawning and dynamic-code dependencies out of the production bundle.
Confidence Score: 5/5The PR appears safe to merge; no outstanding blocking or non-blocking code issue remains. No new actionable defects were established. The previous SSE finding was correctly withdrawn, the bundle-shim invariant is now enforced during production builds, and the credential-probe and save-gating findings were fully addressed in the current code. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Stored agent MCP configuration] --> B[v12 to v13 migration]
B --> C{Transport}
C -->|stdio| D[Remove server entry]
C -->|HTTP| E[Keep server entry]
E --> F[AgentManager]
F --> G[HTTP MCP client]
H[Vite dependency resolution] --> I[stdio transport shim]
H --> J[CFWorker schema validator shim]
H --> K[Anthropic toolset shim]
H --> L[Pixi no-eval shims]
I --> M[Production bundle]
J --> M
K --> M
L --> M
M --> N[Forbidden-pattern validation]
Reviews (8): Last reviewed commit: "MCP server modal: let untouched-connecti..." | Re-trigger Greptile |
MCP servers are HTTP-only now: the transport picker, command/args/env fields and stdio branches are gone from the server modal, agent editor, data store and types, and a v13 migration drops any stored stdio server. A resolved-path shim plugin in vite.config.ts then swaps the dependency modules that would still put shell access or dynamic code execution in the bundle: the MCP SDK's stdio transport (child_process), its ajv validator (new Function; replaced by the SDK's own cfworker provider), the Anthropic SDK's local agent toolset (bash/grep/skills via child_process, inlined through a dynamic import nothing here calls) and Pixi's code generators (pixi.js/unsafe-eval provides the runtime). The production bundle contains no child_process, spawn, execFile, eval or new Function, and is ~140 kB smaller.
…pattern returns Every shim pattern must match at least one resolved module, and the production chunk is scanned for child_process / spawn( / execFile / new Function( / eval( after minification. A dependency moving one of the shimmed files now breaks the build instead of quietly restoring the capability.
Core's .modal-button-container top margin stacked on the body's flex gap (and its bottom padding on the modal's own), leaving a hole between Test connection and the buttons. The flex gap now provides the spacing.
Mirrors the provider setup modal: no Test connection button. The URL and headers are probed (debounced) as they change, the verdict — idle, checking, connected with the tool count, or the failure cause — sits in the footer between Delete and Cancel/Save, and the discovered tools are listed once the probe connects. A result is only shown while the form still matches the config it was taken for. The URL field is bound so the probe tracks typing rather than waiting for blur.
…ep the confirm buttons together Probing per keystroke would send stored headers (a bearer token, say) to every host a half-typed URL happens to name, so the connection is now checked when the URL or headers field is left, and while editing a server it is held — with an inline "check now" — whenever the URL points at a different origin than the saved one and headers are set. Saving still sends them; the hold covers only the moment before. The footer status takes a zero flex basis and Cancel/Save sit in a non-shrinking group, so a long verdict wraps its own text instead of pushing the confirm pair onto a second line.
Same rule as the provider modal's Done: the confirm button is plain and disabled until the probe reports connected, so a server can't be saved on a URL that was never reached, and a held cross-origin probe has to be released explicitly before saving.
…r is down A rename of an existing server must not need a live probe of a host that may be unreachable. Save stays gated on a validated connection whenever the URL or headers differ from the saved ones; if they are untouched, the saved config is what gets written back, so nothing new is being trusted.
Leo310
force-pushed
the
feat/drop-stdio-mcp
branch
from
September 5, 2026 14:22
179766e to
c5469f8
Compare
Leo310
added a commit
that referenced
this pull request
Sep 5, 2026
The Obsidian plugin-review pass (#465) and the removal of the stdio MCP transport (#467). A minor bump, not a patch: a transport is gone (stored stdio servers are dropped by the v13 data migration) and the MCP server modal now checks the connection automatically and gates saving on it. minAppVersion is unchanged at 1.11.4. Nothing in this release touched PROVIDER_TEMPLATES, src/skills/defaults/, BUILT_IN_TOOL_IDS or CURATED_PLUGIN_INTEGRATIONS, so the site's enumerable facts need no refresh; the MCP docs were updated separately (s2b-dev/site#1).
Leo310
added a commit
that referenced
this pull request
Sep 5, 2026
Re-cut of 2.1.0 as a patch release: nothing was added — the plugin-review pass (#465) and the removal of the stdio MCP transport (#467) are cleanup and a removal, not a feature. The 2.1.0 tag and release were deleted; versions.json carries 2.0.3 in its place. minAppVersion unchanged at 1.11.4; site enumerable facts unchanged.
This was referenced Sep 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #465 for the two behaviour findings that came from bundled dependencies rather than our code: Shell Execution (
child_process) and Dynamic Code Execution (new Function). After this PR the production bundle contains nochild_process,spawn,execFile,eval(ornew Functionat all (verified by greppingbuild/prod/main.js), and it is ~140 kB smaller.MCP is HTTP-only
MCPTransportTypeis"http"only;MCPStdioServerConfigis gone. The agent editor, data store andAgentManager.loadMCPToolsdrop their stdio branches (MCP now loads identically on desktop and mobile).Build-time module shims (
vite.config.ts→src/lib/shims/)A small
shimModulesVite plugin matches on resolved module paths and swaps four dependency modules:@modelcontextprotocol/sdk/client/stdio.js→ throws if ever constructed (removeschild_process+ cross-spawn).@modelcontextprotocol/sdk/validation/ajv-provider.js→ the SDK's own@cfworker/json-schemaprovider, which interprets schemas instead of compiling them withnew Function. Tool-result validation still runs.@anthropic-ai/sdk/tools/agent-toolset/node.mjs→ a stub. This is the SDK's local bash/grep/skills toolset; its worker environment imports it dynamically, so Vite inlined it even though nothing here calls it. It was the lastchild_processuser.unsafeEvalSupported,createUboSyncFunction,generateShaderSyncCode,generateUniformsSync,generateParticleUpdateFunction) → stubs;pixiRenderer.tsimportspixi.js/unsafe-eval, Pixi's supported eval-free implementation, so the stubs are never reached.child_process.spawnwas a doc string in@langchain/mcp-adapters' stdio option schema; the plugin rewords it in that module only.Docs to update (site repo)
agents/mcp.mdandhelp/troubleshooting.mdon smartsecondbrain.dev still describe the stdio transport and its mobile caveat; both need trimming to HTTP-only.Test plan
bun run check,format,lint,test(1652 passing),bun run buildchild_process/spawn(/execFile/eval(/new Function