feat(server/mcp): add opt-in GCF response encoding for tool results - #3833
feat(server/mcp): add opt-in GCF response encoding for tool results#3833blackwell-systems wants to merge 2 commits into
Conversation
Adds a `--response-encoding` flag (`json` default / `gcf`) that, when set to `gcf`, returns each tool's result set as a single Graph Compact Format (https://gcformat.com) generic-profile block instead of one JSON block per row. The repeated field names of the uniform record arrays these tools return are factored into a single header, cutting token cost on large query results (~30% fewer o200k/Claude tokens on a 30-row instance list) with no per-tool changes. The substitution is conservative, so enabling it can only help: GCF is used at the shared per-row serialization point in the five protocol handlers only when it encodes without error, is strictly smaller than the JSON (never-grow), and decodes back to the same rows (lossless, verified against the input and order-aware on columns); otherwise the JSON is kept. Integers are preserved exactly via EncodeGenericChecked, and a column type GCF cannot round-trip (e.g. a byte blob) falls back to JSON rather than being altered. - `--response-encoding` is a validated enum, mirroring `--logging-format`. - Plumbing mirrors `--sql-commenter`: flag -> ServerConfig -> Server -> context. - internal/util/gcf.go: EncodeGCFToolResult converts orderedmap.Row -> gcf.OrderedMap (preserving column order) and applies the guards. - Dependency: github.com/blackwell-systems/gcf-go v1.7.1 (zero-dependency). - Tests: util round-trip / order / never-grow / int64 / byte-safety, config enum validation, and a handler-level json-vs-gcf gating test.
73fcad3 to
a267d80
Compare
There was a problem hiding this comment.
Code Review
This pull request introduces support for Graph Compact Format (GCF) response encoding via the --response-encoding=gcf flag, which reduces the token cost of large, uniform tool results by factoring repeated field names into a single header. The changes include CLI flag registration, documentation updates, MCP handler integrations across multiple protocol versions, and comprehensive unit and integration tests. Feedback on the implementation highlights a precision loss bug in scalarEqual when comparing large int64 values with float64 values, which could compromise the lossless round-trip validation. Additionally, it is recommended to normalize the response encoding string to lowercase during validation in the Set method to avoid potential comparison mismatches.
… guard Addresses review feedback on the response-encoding PR: - scalarEqual no longer collapses a large int64 to a lossy float64 when comparing mixed numeric types. A value beyond the +/-2^53 float-exact range can no longer be falsely reported equal to a rounded float64, which would let a lossy encoding slip past the losslessness guard. Integers compare exactly as int64; an integer and a float compare equal only when the float represents the integer exactly. - responseEncoding.Set stores the lowercased value, so a flag given as GCF matches the downstream "gcf" comparison directly rather than relying on String() to normalize it. Adds tests for both.
Description
Toolbox returns each tool's result set as one JSON object per row. For the uniform record arrays these tools return (query rows, table listings, schema descriptions), the field names repeat in full on every row, and that repetition dominates the token cost once the result crosses the LLM boundary.
This PR adds an opt-in
--response-encodingflag (jsondefault, orgcf). When set togcf, a result set is returned as a single Graph Compact Format generic-profile block instead of N JSON blocks: the repeated field names are factored into one header and the per-row framing is dropped. On a representative 30-row × 7-column result (a Cloud SQL instance listing) this is 30.1% fewer tokens (GPT-4o/o200k) and 31.3% fewer (Claude), losslessly.The change is at a single shared seam and covers every data-returning tool with no per-tool changes. JSON remains the default and is completely unaffected.
What this adds
--response-encodingflag — a validated enum (json/gcf) mirroring the existing--logging-formatflag, plumbed exactly like--sql-commenter(flag →ServerConfig→Server→ request context).internal/util/gcf.go—EncodeGCFToolResult, which converts eachorderedmap.Rowto a GCF ordered map (preserving query column order) and encodes the set.github.com/blackwell-systems/gcf-go— zero runtime dependencies, MIT-licensed.Conservative by construction — it can only help
GCF is offered only when all of the following hold; otherwise the original JSON is returned unchanged:
EncodeGenericChecked, which surfaces the numeric-domain error rather than panicking).So enabling
gcfcan never grow, drop, or garble a tool result. Integers beyond the float64-safe range round-trip exactly.Benchmark (honest floor and scale)
Measured on real result shapes, lossless in every case:
The saving grows with row count and column count (more repeated field names to factor). On tiny or high-entropy results GCF does not win, and the never-grow guard keeps the JSON — the feature has a floor of "no worse than today," not a regression.
About GCF
Graph Compact Format is a compact, lossless wire format for structured data crossing the model boundary. It is Apache-2.0/MIT-compatible (MIT), zero-dependency, and implemented across seven languages, all validated against a shared conformance suite (281 fixtures, 43B+ verified round-trips).
Comprehension, not just tokens. Fewer tokens only helps if the model reads the format at least as well. On the standard-workload comprehension study most relevant here — 500-order nested arrays (the shape of a tool result), 27 runs across 11 models / 4 providers, deterministic answers with no LLM judge — GCF's generic profile is read at 100% accuracy on every frontier model (Claude Opus/Sonnet/Haiku, GPT-5.5, Gemini 2.5/3.1/3.5), averages equal-or-better than JSON on every model, and pulls ahead of both JSON and TOON on smaller models (e.g. GCF 95% vs JSON 74% vs TOON 85% on Gemini 2.5 Flash). TOON is consistently the weakest. Full methodology and reproducible harness: gcformat.com/guide/benchmarks.
Grounded in original research. The format was derived from tokenization/attention research (Tokenizer–Attention Coupling and related work), then validated after the fact by controlled from-scratch training studies. See gcformat.com.
Already in adoption. GCF compresses LLM-bound output in a range of shipped MCP servers and gateways:
oq --format gcf, merged after a dependency audit.RESPONSE_FORMAT=gcf.Full list: gcformat.com/ecosystem/adopters.
Design notes
--response-encoding=gcfis set. The JSON path is byte-for-byte unchanged.Tests
internal/util/gcf_test.go— round-trip + header factoring + column-order preservation, the never-grow fallback, int64 > 2⁵³ exactness, and a byte-column fail-safe.internal/server/config_test.go— the--response-encodingenum (acceptsjson/gcfcase-insensitively, rejects invalid values, defaults tojson).internal/server/mcp/v20250618/method_test.go— handler-level gating: default encoding returns per-row JSON blocks;gcfreturns a single GCF block.tests/sqlite/sqlite_integration_test.go— an end-to-end integration test: boots the server with--response-encoding=gcfagainst a real SQLite source and asserts a query tool's result comes back as a single GCF block over the MCP transport.go build,go vet,gofmt, andgolangci-lintare clean; the affected test packages pass.Docs
--response-encodingadded to the CLI reference flags table.PR Checklist