MCP: export_query tool + guard rails for large results - #325
Merged
Merged
Conversation
run_sql inlines rows (capped) for previews; export_query instead returns a fetch recipe -- the exact /api/query request plus a ready-to-run Python snippet -- so a script pulls the Parquet/Arrow/CSV directly from /api/query and the bulk bytes never enter the model's context. Read-only (SELECT/WITH) guard; parquet default, arrow (IPC) and csv supported. Tests + docs (user guide + architecture).
run_sql is now explicitly a bounded preview; when a result exceeds the 1000-row cap the response carries truncated=true plus guidance instructing the model not to treat the preview as complete and to call export_query for the full result as a file. Tool description states the contract. Docs updated.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #325 +/- ##
==========================================
- Coverage 74.51% 74.50% -0.01%
==========================================
Files 290 290
Lines 38448 38566 +118
==========================================
+ Hits 28649 28735 +86
- Misses 9799 9831 +32
🚀 New features to boost your workflow:
|
Adds an optional free-form `guardrails` map to the mcp extension: arbitrary key/value hints that beacon surfaces to the agent (appended to the generated tool's description and returned by describe_table) but does NOT enforce. Admins can attach any keys. Enforcement of output size remains the separate built-in run_sql preview cap. Tests + docs.
Adds a versioned, canonical MCP Server guide at docs/docs/1.8.0/mcp.md (config, tools incl. export_query, exposing tables via the mcp/preset extensions, column descriptions, advisory guardrails, large-result export, per-user auth, connecting Claude, and a 'How it works' section) and wires it into the 1.8.0 sidebar between REST API and Connect. Removes the redundant top-level docs/mcp.md and docs/mcp-architecture.md (superseded by the versioned page).
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.
Follow-up to the MCP server (#323, now on
main). Adds a path for large query results so they don't get streamed through the model's context.export_querytoolMCP tool results are model-context text, so returning a big Parquet/Arrow blob inline is wrong.
export_queryinstead returns a fetch recipe — it does not run the query:sql(read-onlySELECT/WITH) +format(parquetdefault,arrowIPC,csv)./api/queryrequest (body withoutput.format) and a ready-to-run Python snippet./api/query, which streams the file in one response — bulk bytes flow script↔beacon, never through the model.No server-side changes — it reuses the existing
/api/queryfile download.Guard rail on
run_sqlrun_sqlis now explicitly a bounded preview (≤1000 rows). When a result exceeds the cap the response is marked"truncated": truewith aguidancefield telling the model not to treat the preview as complete and to callexport_queryfor the full result. The tool description states the contract too — so large queries are steered to the file path rather than silently returning partial data.This is a reactive guard (based on actual rows produced), which is reliable for beacon's streaming/external sources where planner row-count estimates are often absent.
Tests / docs
beacon-mcpunit test forexport_query(recipe shape, parquet/CTE, write-rejection); 7beacon-mcptests pass,beacon-apibuilds.docs/mcp.md(tools list + Large results section) anddocs/mcp-architecture.mdupdated.