feat(mcp): auto-traversal hint, wrong_dialect arm, JS-runtime wrapper note#584
Merged
amitdeshmukh merged 2 commits intomasterfrom Apr 29, 2026
Merged
feat(mcp): auto-traversal hint, wrong_dialect arm, JS-runtime wrapper note#584amitdeshmukh merged 2 commits intomasterfrom
amitdeshmukh merged 2 commits intomasterfrom
Conversation
GraphJin auto-traverses any single FK chain between two tables, so the
collapsed shape `{ <dim> { <fact> { sum(...) } } }` works even when the
underlying join is N hops. Surface this fact in the contract instead of
making every consumer (ax-crew, custom MCP clients, the CLI) repeat it
in their actor descriptions.
- get_query_syntax.patterns.metric_by_dimension gains an
`auto_traversal_note` that explains the collapsed form and tells
agents to call find_path first to confirm a single FK path exists.
- find_path now emits `collapsed_example_query`,
`collapsed_example_query_compiles`, an optional repair warning, and
a `collapsed_note` whenever the path has intermediates. Both example
queries run through validateExampleQuery so the response proves the
auto-traversal compiles on this schema rather than promising it.
CLI (`graphjin cli schema path`) inherits the new fields automatically
since it's a thin runToolCmd wrapper; MCP/CLI parity tests stay green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two follow-ups from the same multi-model agent test, reduced to the
items that survive the framework-generic / "teach DSL via contract"
filter:
- fix_query_error gains a `wrong_dialect` arm that catches the two
Hasura aggregate-leak shapes: the `aggregation:` argument
(`unknown argument 'aggregation'`) and the `<table>_aggregate` field
suffix (the source query carries the suffix and the error reports
the table missing). Repair shows GraphJin's leaf-field aggregate
shape — sum_<col> / sum(expr: { mul: [...] }) — with placeholder
column names so it stays generic across schemas.
- get_js_runtime_api adds one Notes entry distinguishing in-runtime
results (gj.tools.* returns decoded objects) from direct MCP-caller
results (use result.structuredContent or
JSON.parse(result.content[0].text)). One sentence at the wrapper
layer beats per-tool noise on every tool description.
Skipped from the same feedback round: per-table aggregate suggestions
and pre-substituted columns in aggregations.usage. Both cross from
teach-DSL into guess-business-logic / schema-shape inference, which
collides with the framework-generic rule.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
Three round-2 wins teaching GraphJin's DSL through structured contracts instead of per-consumer prompt prose.
find_path— auto-traversal hint (commit 6565d0d)get_query_syntax.patterns.metric_by_dimensiongains anauto_traversal_notethat teaches the collapsed shape ({ <dimension> { <fact> { sum(...) } } }) and tells agents to callfind_pathfirst to confirm a single FK path exists.find_pathemitscollapsed_example_query,collapsed_example_query_compiles, an optional repair warning, and acollapsed_notewhenever the path has intermediates. Both the full and collapsed examples run throughvalidateExampleQuery, so the response proves auto-traversal compiles on this schema instead of just claiming it.fix_query_error—wrong_dialectarm (commit 6ef6f7e)aggregation:argument and the<table>_aggregatefield suffix.sum_<col>/sum(expr: { mul: [...] })) with placeholder column names so it stays generic across schemas.kind: "generic"re-discovery loop that hit every model in our test except Pro.get_js_runtime_api— MCP wrapper one-liner (commit 6ef6f7e)gj.tools.*returns decoded objects) from direct MCP-caller results (result.structuredContentorJSON.parse(result.content[0].text)).Skipped from the same feedback round
suggested_aggregates[](mul: [unitprice, orderqty]etc.) — pattern-matches column names to guess business metrics; collides with the framework-generic rule and produces nonsense on non-ecommerce schemas.aggregations.usage— agent failures here are training-data priors winning at the substitution step, not missing data.CLI (
graphjin cli schema path,graphjin cli fix-query-error) inherits the new fields automatically since they're thinrunToolCmdwrappers; MCP/CLI parity tests stay green.Test plan
go test ./serv/...— full suite greengo test ./cmd/... -run TestMCPCLI— parity tests greenTestHandleFindPath_CollapsedExample— 2-hop chain (category → product → orderitem) yields a compiling collapsed query that names only the endpointsTestHandleFindPath_DirectRelationship— single-hop paths omit the collapsed fieldsTestCanonicalQueryPatterns— extended to assertmetric_by_dimension.AutoTraversalNotementions auto-traversal andfind_pathTestBuildFixQueryErrorRepair_Arms / wrong_dialect_argument—unknown argument 'aggregation'routes towrong_dialectwithsum(expr:)repairTestBuildFixQueryErrorRepair_Arms / wrong_dialect_aggregate_suffix—orders_aggregate { aggregate { count } }source +table not founderror routes towrong_dialectwithordersextracted🤖 Generated with Claude Code