cost-guard-mcp
Cost-guard-mcp is an MCP server that gives AI agents pre-flight cost and result-size guardrails for BigQuery, Snowflake, and Databricks queries before they run.
Check credentials and connectivity per engine without running real queries (
check_credentials).Describe each engine's exact vs. approximate cost signals (
describe_engine_capabilities).Estimate query cost before execution with accuracy tiers: PRECISE, UPPER_BOUND, or HEURISTIC (
estimate_query_cost).Run queries only if the estimate is within user-specified bounds for bytes billed, rows returned, or estimated cost in USD (
run_query_bounded).Refuse risky queries with a clear reason and hint instead of executing them.
Support optional warehouse, warehouse size, and Snowflake edition parameters to improve estimate accuracy.
Provide caveats on estimates, such as missing AI/remote function costs or row-level security effects.
Works as a lightweight local stdio process with structured logging and optional OpenTelemetry tracing.
Provides pre-flight cost estimation using BigQuery dryRun and bounded query execution for BigQuery, allowing AI agents to cap bytes billed, rows returned, and estimated cost before running queries.
Provides pre-flight query cost estimation using Snowflake EXPLAIN and bounded query execution for Snowflake, with per-call limits on bytes, rows, and estimated cost.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@cost-guard-mcpestimate the BigQuery cost of SELECT * FROM sales before I run it"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
cost-guard-mcp
Pre-flight query cost & result-size guardrails for AI agents, across BigQuery, Snowflake, and Databricks — before the query ever runs.
Why
An AI agent using a warehouse MCP can silently trigger a full-table scan that costs hundreds of dollars, or return millions of rows that flood its own context window. No existing warehouse MCP tells the agent "how much will this cost" or "how much data will this return" before running the query.
Related MCP server: BQ Agent Gateway
What makes this different
Every cost estimate discloses its accuracy tier —
PRECISE(BigQuerydryRun),UPPER_BOUND(SnowflakeEXPLAIN), orHEURISTIC(DatabricksEXPLAIN COST) — so your agent never over-trusts a heuristic number.Per-call bounds —
run_query_boundedtakesmax_bytes_billed/max_rows/max_estimated_cost_usdon each call; no shared session state required.Zero infrastructure — a single local stdio process. No database, no gateway, no Docker Compose.
Tools
check_credentials(engine, warehouse?)— verifies credentials/connectivity without running any real query; call this first after configuring a new engine. Supports BigQuery, Snowflake, and Databricks.describe_engine_capabilities(engine)— what's exact vs. approximate for this engine.estimate_query_cost(engine, sql, warehouse?, warehouse_size?, edition?)— pre-flight cost estimate, tagged with its accuracy tier. Supports BigQuery, Snowflake, and Databricks.warehouse_size(Snowflake/Databricks) andedition(Snowflake) default to the smallest/standard tier if omitted — set them to match the warehouse you actually run on, or the dollar figure understates cost on a larger one.run_query_bounded(engine, sql, max_bytes_billed?, max_rows?, max_estimated_cost_usd?, warehouse?, warehouse_size?, edition?)— refuses to run if the estimate exceeds your bound. Supports BigQuery, Snowflake, and Databricks.
Setup
BigQuery
Set GOOGLE_APPLICATION_CREDENTIALS to a service-account key file path (or run gcloud auth application-default login).
Snowflake
Set SNOWFLAKE_ACCOUNT, SNOWFLAKE_USER, SNOWFLAKE_ROLE (required — no default, never ACCOUNTADMIN), and either SNOWFLAKE_PRIVATE_KEY_PATH (preferred) or SNOWFLAKE_PASSWORD (discouraged).
Databricks
Set DATABRICKS_SERVER_HOSTNAME and DATABRICKS_HTTP_PATH (from the SQL warehouse's
Connection Details tab), and either DATABRICKS_TOKEN (a personal access token,
simplest) or DATABRICKS_CLIENT_ID + DATABRICKS_CLIENT_SECRET (OAuth machine-to-machine
via a service principal, preferred for automated use). Only Serverless SQL warehouses are
priced accurately — see Known Limitations.
A note on credentials with MCP hosts
Whatever MCP client/host you use (Claude Desktop, etc.) spawns this server as its own subprocess — it does not automatically inherit your shell's environment variables, even if they're set in your .zshrc/.bashrc. Put them directly in the host's server config instead — see .mcp.json.example for the exact block, and the "Use with other AI coding tools" section below for where each specific tool wants it.
Install
uvx cost-guard-mcpAlso published on the official MCP Registry as io.github.mcpsmiths/cost-guard-mcp.
For local development instead:
git clone https://github.com/mcpsmiths/cost-guard-mcp.git
cd cost-guard-mcp
uv sync
uv run cost-guard-mcpOr via Docker:
docker build -t cost-guard-mcp .
docker run -i --rm -e GOOGLE_APPLICATION_CREDENTIALS=/creds.json -v /path/to/service-account.json:/creds.json cost-guard-mcpQuickstart (~5 minutes to your first estimate)
This walks through the fastest path to a real tool call — no data of your own required (it uses a public BigQuery dataset), no Snowflake trial signup needed.
Get a GCP project with the BigQuery API enabled. Any project works, including the free-tier Sandbox mode (no billing card required to run
dryRun, which is allestimate_query_costdoes). Create one at console.cloud.google.com if you don't have one.Get Application Default Credentials: run
gcloud auth application-default loginlocally, or create a service-account key and pointGOOGLE_APPLICATION_CREDENTIALSat its JSON file.Add the server to your MCP client — see
.mcp.json.example, filling in onlyGOOGLE_APPLICATION_CREDENTIALS(leave the Snowflake vars out entirely for this quickstart).Restart your MCP client so it picks up the new server config, then ask your agent to call
check_credentialson bigquery. This confirms your setup without running any real query — you should get back"ok": trueand a detail line naming your project. If you get"ok": falseinstead, thedetailfield explains exactly what's missing (usuallyGOOGLE_APPLICATION_CREDENTIALSnot making it through to the server process — see the credentials note above, and double check the value is set inside the client's own server config block, not just your shell).Ask your agent to call
estimate_query_costagainst a public dataset — for example:Use cost-guard-mcp's estimate_query_cost tool on bigquery for this query:
SELECT name, SUM(number) AS total FROMbigquery-public-data.usa_names.usa_1910_2013GROUP BY name ORDER BY total DESC LIMIT 10You'll know it worked when the response looks like this — the exact numbers will differ, but
accuracy_tiershould readPRECISE:{ "engine": "bigquery", "accuracy_tier": "PRECISE", "estimated_bytes": 320866545, "estimated_cost_usd": 0.001842, "currency": "USD", "caveats": [] }
Use with other AI coding tools
cost-guard-mcp is a standard stdio MCP server — any MCP-compatible client works, not just Claude Desktop. Every client ultimately runs the same command/args/env; only the wrapping file format differs, so there's one canonical definition — .mcp.json.example — instead of a separately maintained copy per tool below.
There is no single file every tool reads automatically (each looks in its own location), but three of the four use the exact same mcpServers wrapper .mcp.json.example already has, so those need nothing more than copying it into place. Fill in your real credential values, then:
Client | Where it goes | Change needed from |
Claude Code |
| None — copy as-is, or |
Claude Desktop |
| None — copy as-is |
Cursor |
| Add |
GitHub Copilot (VS Code) |
| Rename top-level key |
OpenAI Codex CLI |
| Same fields, TOML syntax instead of JSON (below) — or |
Codex is the one genuine exception (TOML, not JSON), so it still needs its own block:
[mcp_servers.cost-guard-mcp]
command = "uvx"
args = ["cost-guard-mcp"]
[mcp_servers.cost-guard-mcp.env]
GOOGLE_APPLICATION_CREDENTIALS = "/path/to/service-account.json"
BIGQUERY_PROJECT = "your-project-id"
SNOWFLAKE_ACCOUNT = "your-account"
SNOWFLAKE_USER = "your-user"
SNOWFLAKE_ROLE = "your-role"
SNOWFLAKE_PRIVATE_KEY_PATH = "/path/to/rsa_key.p8"
DATABRICKS_SERVER_HOSTNAME = "your-workspace.cloud.databricks.com"
DATABRICKS_HTTP_PATH = "/sql/1.0/warehouses/your-warehouse-id"
DATABRICKS_TOKEN = "your-personal-access-token"Observability
Structured logging (always on, no configuration needed) — every tool call and warehouse-client failure is logged via Python's standard
loggingmodule. Since stdout is the MCP transport channel in stdio mode,logging's default (stderr) is what this server relies on — never redirect these loggers to stdout. What gets logged:Every tool call (
check_credentials,describe_engine_capabilities,estimate_query_cost,run_query_bounded) logs one INFO record on completion:tool=<name> outcome=<success|error> elapsed_ms=<n>.Every warehouse-client failure (BigQuery/Snowflake/Databricks) logs one WARNING record:
engine=<engine> warehouse_client_call_failed message=<redacted>—messageis always the same secret-redacted text the caller gets back, never the raw exception.Every
run_query_boundedrefusal logs one INFO record naming the engine and the specific refusal reason (cost_cap_exceeded,byte_cap_exceeded, orrow_cap_exceeded).Each engine's 120-second execution watchdog logs one WARNING record before cancelling a still-running query.
None of the above ever logs a credential, connection string, or raw (unredacted) warehouse-client exception message — the same
redact_secretshelper that sanitizes what a tool caller sees is applied before anything is logged.
OpenTelemetry tracing (opt-in, off by default) — the underlying
mcpSDK ships anOpenTelemetryMiddlewareon by default for every server, wrapping each inbound message in a SERVER span, but that middleware is a documented no-op until a real exporter is registered — this project registers none unless you ask for it. SetOTEL_EXPORTER_OTLP_ENDPOINTto your OTel Collector's endpoint (e.g.http://localhost:4317) to turn it on: at that pointcost-guard-mcpconstructs aTracerProviderwith a gRPC OTLP exporter pointed at that endpoint and registers it as the global tracer provider before the server starts running. Leave the env var unset and nothing changes — no exporter is constructed, and the two extra dependencies below never need to be installed. Requires theotelextra:uv sync --extra otel # or: pip install "cost-guard-mcp[otel]"
Known limitations
Snowflake cost estimates are calibrated from the caller's own recent query history (
INFORMATION_SCHEMA.QUERY_HISTORY, no elevated privilege required) when an exact repeat of the same SQL text has run before - falling back to a coarse byte-size-tier heuristic otherwise. This only fires on an exact repeated query; a genuinely novel query always uses the heuristic. Result-cache hits are deliberately excluded from the average (a cached, near-instant repeat would otherwise corrupt calibration toward underestimating future runtime). Query history ingestion has its own latency - a query run moments ago may not yet be visible to the lookup, in which case it safely falls back to the heuristic rather than erroring.Databricks calibration was investigated and found blocked: its Query History REST API returns the query text as
"<REDACTED>"unconditionally on the account tested, even for the caller's own queries and even withinclude_metrics=True- confirmed server-side via a direct SDK source read, not something a client-side parameter can bypass. Not implemented for Databricks as a result; may be revisited if a future paid workspace confirms this is a toggleable setting there.Databricks cost estimates are always
HEURISTIC(the least precise tier) - Databricks has no dry-run, andEXPLAIN COST's byte estimates are frequently unavailable.Databricks pricing only models Serverless SQL warehouses - Classic/Pro warehouses use different (lower) DBU rates plus a separate cloud VM cost not modeled here.
Databricks has no per-query warehouse override - the SQL warehouse is fixed by
DATABRICKS_HTTP_PATHat connect time.Snowflake's
UPPER_BOUNDestimate excludes Cortex AI Function ("AI Credits") cost.Snowflake warehouse generation (Gen1 vs. the newer, pricier Gen2) is detected on a best-effort basis via
SHOW WAREHOUSESandCURRENT_REGION()(both ordinary, non-privileged SQL) to pick the correct credit rate — Gen2 bills ~1.35x Gen1 on AWS/GCP and ~1.25x on Azure. Detection needs awarehouseto be specified; if it isn't, or the lookup fails for any reason (permission, timeout, unrecognized response shape), the estimate safely falls back to Gen1 rates with an explicit caveat rather than erroring — since Gen2 is now the default for new standard warehouses in most regions, an undetectable generation means the real cost may be higher than this estimate. This was implemented and unit-tested with mocked Snowflake responses only; live verification against a real Gen2 warehouse is still an open follow-up.BigQuery Editions/capacity-billed projects cannot get a dollar estimate — only a byte count (capacity billing has no fixed $/byte rate).
BigQuery dry runs always report 0 bytes processed for tables protected by row-level security, by design, to prevent a side-channel —
dry_runadds a caveat when it sees 0 bytes against a non-emptyreferenced_tableslist, but a $0.00 estimate on such a query must never be treated as proof the query is free to run.BigQuery remote functions and BigQuery ML remote-model inference (e.g.
ML.GENERATE_TEXT) incur separate Cloud Run/Vertex AI billing that this byte-based dollar estimate does not include —dry_runflags this with a conservative text-based heuristic (ML.GENERATE_TEXTorCREATE FUNCTION+REMOTEin the query text) rather than the dry-run response'sreferencedRoutinesfield, which would need live-credential verification not available at the time this caveat was added.run_query_boundedgives up on a still-running query after 120 seconds and cancels it (BigQuery:QueryJob.cancel(); Snowflake:SYSTEM$CANCEL_QUERY; Databricks:Cursor.cancel()from a watchdog thread) rather than waiting indefinitely — a query stuck behind slot contention or a cold/suspended warehouse would otherwise block the tool call, and keep burning warehouse-seconds the whole time, defeating the point of a "bounded" tool.The underlying
mcpSDK can drop an in-flight tool-call response if the client closes stdin before the tool finishes (upstream issue modelcontextprotocol/python-sdk#2678, open since 2026-05, unresolved after several attempted fixes) — no known real-world exposure for well-behaved clients that keep stdin open for the session, but worth knowing about given this server's tool calls can run up to 120 seconds.A client-sent MCP cancellation notification against an in-flight
run_query_boundedcall now detaches promptly at the MCP bookkeeping level, but the warehouse-side query itself keeps running in the abandoned background thread until the existing per-engine watchdog (~120s, see above) fires on its own — this fix does not by itself stop the warehouse from billing for that abandoned query any sooner.
More docs
ARCHITECTURE.md— component/data-flow mapDECISIONS.md— why the design looks the way it doesCONTEXT.md— terminology glossary (BigQuery/Snowflake concepts that sound alike but aren't)CHANGELOG.md— release historyCONTRIBUTING.md/AGENTS.md— contributing and build/test/lint commandsSECURITY.md— vulnerability reporting
License
MIT
Available Tools
4 toolscheck_credentialsARead-only
Verify credentials/connectivity for an engine without running any real query or dry-run estimate. Call this once after configuring a new engine (or when a real tool call fails) to get a fast, clear yes/no signal instead of debugging via trial queries.
| Name | Required | Description | Default |
|---|---|---|---|
| engine | Yes | ||
| warehouse | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| detail | Yes | |
| engine | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description adds meaningful behavioral context: no query or dry-run is executed, and the result is a fast yes/no signal. This goes beyond the structured annotation hints and does not contradict them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two concise sentences. The core distinguishing behavior is front-loaded, and every sentence earns its place without fluff or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple credential-check tool, the description covers purpose, usage triggers, and behavioral boundaries. The output schema and annotations handle return/safety expectations, so nothing essential is missing for an agent to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description provides no explanation of the engine or warehouse parameters. While the schema's enum and default offer structural clues, the description does not compensate for the missing semantic detail, such as why warehouse is optional or how it affects the check.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and object: 'Verify credentials/connectivity for an engine.' It also explicitly distinguishes itself by stating it does not run a real query or dry-run estimate, which separates it from sibling tools like estimate_query_cost and run_query_bounded.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit call triggers: after configuring a new engine or when a real tool call fails. It also clarifies the intended outcome ('fast, clear yes/no signal') and contrasts with debugging via trial queries, providing strong when-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
describe_engine_capabilitiesARead-only
Declare which cost signals are exact vs. approximate for the given warehouse engine.
Call this before estimate_query_cost or run_query_bounded to understand how much to
trust the accuracy_tier on their responses for this engine.
| Name | Required | Description | Default |
|---|---|---|---|
| engine | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| engine | Yes | |
| known_gaps | No | |
| default_accuracy_tier | Yes | |
| supports_precise_bytes | Yes | |
| supports_dollar_estimate | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish the tool as read-only and open-world, so the description is free to add value. It does so by disclosing that the output distinguishes exact vs. approximate cost signals and that this affects interpretation of downstream accuracy_tier values.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tightly scoped sentences, with the core purpose front-loaded and the usage guidance immediately following. No filler or repetition of schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the single enum parameter, the output schema presence, and annotations indicating a safe read operation, the description covers everything needed: what it does, when to use it, and how to interpret its result in context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter engine is clearly identified as the warehouse engine, and its enum values are self-describing. The description adds little beyond the schema, but for a one-parameter enum this is not a meaningful gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: declaring which cost signals are exact vs. approximate for a warehouse engine. It clearly differentiates itself from siblings like estimate_query_cost and run_query_bounded by framing itself as a prerequisite capability check.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly instructs the agent to call this before estimate_query_cost or run_query_bounded, and explains why: to calibrate trust in accuracy_tier. It does not explicitly state a when-not case, but the sequencing guidance is clear and actionable enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
estimate_query_costARead-only
Estimate the cost of a SQL query before running it. ALWAYS call this before running an expensive-looking query. The response's accuracy_tier tells you how much to trust the number: PRECISE (exact), UPPER_BOUND (real cap, may overstate), HEURISTIC (rough).
warehouse_size (Snowflake/Databricks only, e.g. "SMALL", "X-Large") and edition
(Snowflake only, e.g. "enterprise") default to the smallest/standard tier if omitted —
set them to match the warehouse you actually run this query on, or the dollar figure
will understate cost on a larger warehouse.| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | ||
| engine | Yes | ||
| edition | No | ||
| warehouse | No | ||
| warehouse_size | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| engine | Yes | |
| caveats | No | |
| currency | No | |
| accuracy_tier | Yes | |
| estimated_bytes | No | |
| estimated_cost_usd | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint, but the description goes well beyond by explaining the accuracy_tier semantics (PRECISE, UPPER_BOUND, HEURISTIC) and the impact of warehouse_size/edition defaults on cost understatement. This adds valuable behavioral context that annotations alone do not provide, such as the trustworthiness of the returned number and how to get a more accurate estimate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is relatively long but every sentence earns its place: purpose and usage directive are front-loaded, followed by the accuracy tiers, then the optional-parameter caveat. It is well-structured and information-dense without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a cost-estimation tool with an output schema, the description covers all aspects an agent needs: what to pass, accuracy tiers (likely an output field), and how to tune inputs for a reliable estimate. There are no obvious gaps in calling it correctly; even error conditions are implicitly covered by the accuracy-tier guidance.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden for parameters. It explicitly explains warehouse_size (engine-specific) and edition (engine-specific), their defaults, and the consequences of omission (understated cost). It also ties engine to available tiers. This fully compensates for the schema gap, leaving no parameter unaddressed beyond the obvious sql and engine.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Estimate') and resource ('cost of a SQL query'), and clearly frames it as a pre-run estimation. It distinguishes itself from siblings like run_query_bounded (which likely executes) and check_credentials (credential verification) by being strictly an estimation tool. No ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says 'ALWAYS call this before running an expensive-looking query', which is a clear directive for when to use. However, it does not mention when not to use or explicitly reference alternatives like run_query_bounded. It gives strong context but lacks the 'when-not' and alternative naming, so a 4 is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_query_boundedA
Run a query only if its pre-flight cost estimate is within your given bounds; refuses otherwise (check result.status — "refused" means it did NOT run and result.hint explains why). NOTE: unlike estimate_query_cost, a successful call here has a real monetary/quota side effect — don't call this repeatedly without inspecting the result of each call.
warehouse_size/edition (see estimate_query_cost) default to the smallest/standard tier
if omitted - set them to match the warehouse you actually run on, since max_estimated_cost_usd
is checked against the estimate they produce.| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | ||
| engine | Yes | ||
| edition | No | ||
| max_rows | No | ||
| warehouse | No | ||
| warehouse_size | No | ||
| max_bytes_billed | No | ||
| max_estimated_cost_usd | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| rows | No | |
| reason | No | |
| status | Yes | |
| estimate | No | |
| row_count | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only indicate readOnlyHint=false and openWorldHint=true. The description adds valuable behavioral context: it discloses the refusal behavior (result.status='refused') and the side-effect warning. It also explains the default behavior for warehouse_size and edition. This goes beyond annotations and provides the agent with essential operational expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured into three focused paragraphs: the core behavior, the side-effect warning, and the parameter defaults. Every sentence adds necessary information, with the primary purpose front-loaded. It is somewhat lengthy but justified given the tool's complexity; no redundant phrasing is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has 8 parameters and an output schema, so the description need not explain return values. It covers the key behavioral aspects (refusal, side effects, defaults) and gives enough context for safe usage. The main gap is the lack of detail for some parameters (e.g., max_rows, max_bytes_billed), but these are less critical than the cost-bound logic and are reasonably inferable from names. Overall, it is sufficiently complete for a complex tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explicitly explains warehouse_size and edition defaults and implies the role of max_estimated_cost_usd. However, it does not describe sql, engine, max_rows, max_bytes_billed, or the exact semantics of the bounds check. This is a partial compensation, leaving significant parameter meaning to be inferred by the agent.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb ('Run'), resource ('a query'), and the conditional constraint ('only if its pre-flight cost estimate is within your given bounds'). It explicitly distinguishes itself from the sibling tool estimate_query_cost by contrasting the side effect. This leaves no ambiguity about what the tool does or how it differs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage guidance: it warns that a successful call has a real monetary/quota side effect and advises against repeated calls without inspecting results, directly contrasting with estimate_query_cost. However, it does not mention when to use or avoid relative to other siblings like check_credentials or describe_engine_capabilities, though those are not directly competing. The guidance is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.1- Added
check_credentials - Changed
estimate_query_cost2 fields changed- added
Input schema / properties / editionAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Edition" +} - added
Input schema / properties / warehouse_sizeAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Warehouse Size" +}
- Changed
run_query_bounded2 fields changed- added
Input schema / properties / editionAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Edition" +} - added
Input schema / properties / warehouse_sizeAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Warehouse Size" +}
3 tool updates
v0.1.0- First observed
describe_engine_capabilities - First observed
estimate_query_cost - First observed
run_query_bounded
TDQS
Scored across 4 tools
Each tool targets a distinct stage: credential verification, capability/accuracy disclosure, cost estimation, and guarded execution. The overlap between estimate_query_cost and run_query_bounded is explicitly clarified by the side-effect warning.
All tool names use a consistent snake_case verb_noun pattern: check_, describe_, estimate_, run_. The slight grammatical extension in run_query_bounded does not break the overall naming consistency.
Four tools is well-scoped for a cost-guard MCP server. Each tool serves a necessary and non-redundant role in the pre-flight cost-protection workflow.
The core lifecycle is covered: verify connectivity, understand estimate reliability, estimate cost, and run only within bounds. A post-run actual-cost tracking or persistent budget management tool would be a minor enhancement, but agents can work around its absence for the stated use case.
Maintenance
Related MCP Connectors
Deterministic safety, correctness & cost gate that vets Postgres SQL before your AI agent runs it.
See, price, and control every tool call your AI agents make: policy checks, cost, and audit tools.
Budget & cost control for AI agents — per-agent spend caps + rate limits before each call.
AI agents need permission before production SQL writes. Pilot $100 · Gateway $299. Lint≠authorize.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI agents to securely query databases (PostgreSQL, SQLite, MySQL, DuckDB) with read-only defaults and multi-layer SQL injection prevention.81MIT
- FlicenseNot gradedqualityCmaintenanceEnables safe, read-only interaction with Google BigQuery through Claude, with layered guardrails preventing dangerous or expensive queries. Exposes tools for listing datasets, tables, estimating costs, and running queries.-
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to query business databases directly via natural language, with enforced read-only access and secure query limits. Supports SQLite and PostgreSQL, and works with any OpenAI-compatible model.0ISC
- AlicenseNot gradedqualityCmaintenanceEnforces safety and governance for SQL queries executed by AI agents, providing read-only enforcement, cost estimation, and audit trails.Apache 2.0