Repository navigation
Show and tell: Hardening Custom TypeScript MCP Tools Alongside Chrome DevTools MCP — Stdio Isolation & Read-Only SQL Guardrails #3359
Replies: 3 comments 3 replies
|
For the stdio question, I'd test the actual launch entry point, not only the logger class: capture stdout and stderr separately during startup, tool discovery, a tool error, and shutdown. Include a dependency that emits a harmless diagnostic during import. Validate stdout as newline-delimited MCP messages; the transport contract permits ordinary diagnostics on stderr. I'd also keep a healthy second server running during that fixture. If noise from one process disrupts both sessions, inspect the wrapper/client's stream routing rather than treating multiple MCP servers as inherently sharing stdout. Record the exact launcher, package revision and selected config bytes for each result, using dummy environment values. I maintain AEGIS at Escape Studio. Its offline review and saved inventory comparison of selected project MCP configuration files and optional tools/list exports can help track changes to those inputs. That is separate from testing runtime framing. It is an MIT Windows-first beta. Local security UI: 27 October 2026 source UI with simulated data; no live blocking test. |
|
On question 1, one convention that has held up for us in Mars (the browser we are building in Rust, with its own MCP surface): the rule is not "log to stderr", it is "stdout is the protocol and nothing else", and the thing that keeps it true is a test, not the logger. Our CLI tests run the binary, assert The other half for us was that On question 3, we went the other way from a text filter. Reads (summary, find, diff, screenshot, network) need no grant at all. Anything that changes a page takes a control grant from the person, and the call carries the grant epoch, so a revoked grant fails the step in flight with a code and the rest of the batch never runs. The guard lives in the process that owns the resource and checks a fact it holds, not the shape of the request. Your regex layer is doing the right job for SQL, where the request text is all you have; I would just not let it be the only layer, as you say yourself with |
|
@rhkiswani Thank you for sharing these insights from Mars — this is one of the most practical real-world architectural perspectives on MCP transports I've seen. 1. "stdout is the protocol and nothing else"Your phrasing captures the principle perfectly: the guarantee cannot be a convention or a logger abstraction; it has to be enforced by a process-level integration test. Following @antropos17's advice earlier in this thread, we implemented an end-to-end integration test harness ( 2. The Bridge Pattern (Decoupling Transport from Business Logic)Your approach in Mars of keeping 3. State-Held Grants vs. Request Shape InspectionYour point on capability epochs is spot on: for application-owned resources, the guard should live where the state lives, checking an authoritative grant rather than parsing request text. For SQL databases, where the tool interface gives an LLM expressive query power over an entire schema, application-level text inspection is only an operational tripwire (e.g. blocking multi-statement semicolon attacks or catching accidental mutation keywords before spending a database connection). As you noted, the real authority must remain the database engine itself: combining least-privilege roles ( Really appreciate you sharing how Mars handles this in Rust! |
Uh oh!
There was an error while loading. Please reload this page.
Context: Multi-Server MCP Stacks in Coding Agent Workflows
In modern AI-assisted engineering workflows (with Claude Code, Cursor, or Codex), developers frequently pair the official Chrome DevTools MCP Server with custom TypeScript backend servers and database tools in their workspace
mcpServersconfiguration.When running multiple MCP servers concurrently over standard I/O (stdio), two subtle stability risks emerge:
Stdio Stream Corruption Breaking JSON-RPC Framing:
Desktop and CLI agents communicate with MCP servers using
process.stdoutstrictly reserved for JSON-RPC 2.0 frames. If custom TypeScript tools or third-party dependencies log internal diagnostics viaconsole.log(),stdoutis corrupted, causing host parsers to drop the session or fail tool discovery across all active servers.Accidental Mutations During Automated Agent Debugging:
When coding agents inspect frontend DOM states via Chrome DevTools and cross-reference records against local or staging databases, prompt loops or unexpected LLM responses can attempt mutating queries (
DROP TABLE,ALTER, multi-statement injections).Production Hardening Patterns
The open-source MCP Production Kit demonstrates two architectural patterns designed to maintain rock-solid stability in multi-server development environments:
1. Dual-Stream Stdio Logging
Redirects all diagnostic, audit, and operational logging strictly to
process.stderr, keepingprocess.stdoutdedicated exclusively to JSON-RPC 2.0 protocol communication:2. Application-Level Token & Regex SQL Inspection
Before an agent-generated SQL query reaches a persistent database pool, a token-based guardrail inspects the input:
--and/* */SQL comments commonly used to mask injection payloads.status = 'DROP_PENDING') don't trigger false alarms.SELECTorWITH, and validates against 16 mutation keywords (DROP,DELETE,TRUNCATE,ALTER,UPDATE,INSERT,CREATE,REPLACE, etc.).(Note: This application-level guardrail uses token & regex sanitization, not a full SQL AST compiler, and is engineered to work in tandem with database-level read-only permissions like
GRANT SELECT).Architecture Comparison: Open-Source Core vs. Pro Pack ($19 USD)
USER nodeMaintainer Disclosure & Community Discussion
Disclosure: I am the maintainer of MCP Production Kit and author of the commercial Pro Pack add-on on Whop.
We'd love feedback from the Chrome DevTools MCP community:
All reactions