Textcharts MCP surface boundary decision
Status: Accepted (separate-client)
Date: 2026-08-08
Decision scope: Whether BenchBox should bundle or proxy the external textcharts-mcp server versus keeping it as a separate client
Context
BenchBox publishes result-aware visualization tools (suggest_charts, generate_chart) that render from typed BenchBox result bundles via the internal semantic chart registry (benchbox/core/visualization). The external textcharts-mcp server provides raw textcharts primitives (bar, line, etc.) that accept arbitrary data arrays. Both surfaces exist on the same MCP server list for local stdio clients, but they are different trust and product boundaries.
The three candidate shapes were:
- Separate-client — textcharts-mcp runs as its own MCP server entry, configured by the user alongside
benchbox-mcp. No code, packaging, or runtime import connects them. - Bundled deployment —
benchboxwheels vendors textcharts-mcp code or declares it as a dependency, starts it in-process or as a child process, and re-exposes its tools. - Server-side proxying —
benchbox-mcpregisters textcharts tools on behalf of the external server, forwards calls, and returns results as if they were native BenchBox tools.
Decision
Keep separate-client configuration. Do not bundle or proxy textcharts-mcp in this product boundary.
Selected option
- Users configure textcharts-mcp separately when they need raw chart primitives (e.g.,
claudeMCP config with two entries:benchboxandtextcharts). BenchBox documentation points to the external repository for install and versioning. No import, subprocess spawn, or tool registration for textcharts occurs inbenchbox/mcporbenchbox/core/visualization. The existing result-aware chart contract (docs/reference/mcp.mdVisualization) remains the only chart surface BenchBox publishes.
Rejected alternatives
-
Bundled — rejected for namespace, tenant, and lifecycle reasons:
- Tool namespace collisions (
generate_chartvs textcharts primitives) require prefixing or aliasing that breaks the result-aware contract. - Tenant isolation: a bundled server would share the same process or workspace root, widening the blast radius for raw renderer input limits (unbounded data arrays, SVG injection) beyond BenchBox’s bounded visualization registry.
- Package/licensing/support ownership: textcharts-mcp is an external package with its own release cadence and license; vendoring locks BenchBox wheels to that cadence and makes security updates a BenchBox release.
- Rollback: a bundled chart bug forces a BenchBox release to roll back visualization, even when core benchmark logic is unaffected.
- Tool namespace collisions (
-
Proxying — rejected for the same reasons plus sessionless HTTP behavior:
- A server-side proxy would re-expose external tool schemas as BenchBox tools, mixing the product boundary and requiring BenchBox to validate and bound arbitrary textcharts payloads.
- Sessionless HTTP (
streamable-http) has no sticky session; proxy state, progress notifications, and error mapping would be reimplemented in BenchBox rather than delegated to the external server. - The proxy would need to handle textcharts-specific resource and prompt lifecycles that BenchBox does not own.
Consequences
- BenchBox MCP continues to publish only
suggest_chartsandgenerate_chart(result-aware) until a later decision changes the surface. Nobenchbox.mcpcode, visualization registry, ortextcharts/directory changes are made in this decision. - Documentation (
docs/reference/mcp.md,docs/reference/public-contracts.md) records the separate-client posture and the rejected bundle/proxy alternatives. - If demand for bundled or proxied textcharts emerges, the follow-on implementation must provide: (1) a namespaced tool prefix, (2) tenant and workspace isolation tests, (3) raw input bounds and SVG sanitization, (4) pinned version and license audit, (5) sessionless HTTP compatibility verification, and (6) a rollback plan that does not require a BenchBox core release.
Acceptance criteria for any future implementation
- No widening of the BenchBox visualization registry beyond the semantic, result-aware IDs without a contract-map update.
- All textcharts payloads bounded at the MCP admission layer (array length, string length, numeric ranges) with explicit
MCPValidationErrorcases. - Integration tests proving separate-client, bundled, and proxied shapes behave correctly under
benchbox-mcp --transport streamable-http(different workers, shared storage). - Release notes and support docs updated to reflect the new surface ownership and upgrade/rollback path.
Related
benchbox/core/visualization/*— result-aware chart registry and ASCII runtime (intentionally narrow).textcharts/— external dependency boundary, not vendored.benchbox/mcp/tools— tool registration boundary for BenchBox’s own 12 local tools.