mcp-data-tools

mcp-data-tools

A governed MCP server enabling LLM agents to query BigQuery, inspect GCS, trigger Airflow DAGs, and run data-quality checks with built-in security guardrails like allow-lists, cost ceilings, and audit trails.

Category
Visit Server

README

mcp-data-tools

A governed Model Context Protocol (MCP) server for data-platform operations.

Give an LLM agent the ability to query BigQuery, inspect GCS, trigger Airflow DAGs, and run data-quality checks — without giving it the ability to scan an unbounded table, touch a dataset outside its remit, or run anything but a read-only query. Every tool call is dry-run estimated, checked against an explicit allow-list, capped by a cost/row ceiling, and written to an audit trail before it ever reaches a real backend.

Test Lint Security License: MIT Python 3.11+

Why this exists

Agentic data platforms (NL2SQL assistants, on-call/triage agents, data copilots) all eventually hit the same problem: an LLM agent that can call a real query engine is, by construction, an LLM agent that can be prompt-injected or simply mistaken into running a full-table scan, reading a dataset it shouldn't, or mutating data it was only supposed to read. Most MCP servers for data tools wrap the backend SDK directly and call it done. mcp-data-tools treats the guardrail layer as the actual product:

  • Allow-listed resources. BigQuery tables, GCS buckets, and Airflow DAGs are matched against explicit glob patterns. Nothing is reachable by default.
  • Enforced read-only SQL. A lexical check rejects anything that isn't a bare SELECT/WITH, with comments and string literals stripped first so neither can be used to smuggle a write statement past the check.
  • Two-phase table authorization. A cheap preflight check denies obviously out-of-policy queries before any backend call — so an agent can't even use a dry run to probe the existence/schema of a non-allow-listed table — followed by an authoritative check against the backend's own dry-run result. See docs/SECURITY.md.
  • Real, enforced cost ceilings. max_bytes_billed is passed straight through to the backend's execution API, so it holds even if a stale estimate undercounts a table that grew in the meantime.
  • A fail-closed audit trail. Every decision — allowed or denied — is logged. If the audit sink itself is unavailable, the request is denied rather than let through unaudited.

Architecture at a glance

flowchart LR
    Agent[LLM Agent] -->|MCP / JSON-RPC| Server[mcp-data-tools]
    Server --> Guardrails[GuardrailEngine]
    Guardrails --> Audit[(Audit Trail)]
    Server --> BigQuery[(BigQuery)]
    Server --> GCS[(GCS)]
    Server --> Airflow[(Airflow)]

Full component and sequence diagrams, plus the design decisions and trade-offs behind them, are in docs/ARCHITECTURE.md.

Tools exposed

Tool What it does Guarded by
bigquery_estimate_cost Dry-runs SQL, returns projected bytes/cost/tables — no data returned Read-only check, table allow-list
bigquery_query Executes a read-only SQL query Read-only check, table allow-list, byte/row ceiling
data_quality_check Runs null_rate / uniqueness / freshness / row_count checks against a table Same as bigquery_query, per check
gcs_inspect_object Fetches metadata for one GCS object Bucket allow-list
gcs_list_objects Lists objects under a prefix Bucket allow-list
airflow_trigger_dag Triggers a new Airflow DAG run DAG-id allow-list
airflow_get_dag_run_status Fetches a DAG run's status DAG-id allow-list

Quick start

No cloud credentials required — this runs entirely against in-memory mock adapters, the same ones the test suite uses:

git clone https://github.com/umamahesh-ade/mcp-data-tools.git
cd mcp-data-tools
python -m venv .venv && source .venv/bin/activate
pip install -e .
python examples/quickstart.py

You should see an allowed query, a data-quality report, a denied query (hitting a table outside the allow-list), and the resulting audit trail — all in a few dozen lines of output.

Installation

pip install -e ".[dev]"          # base + testing/linting
pip install -e ".[gcp]"          # + google-cloud-bigquery, google-cloud-storage
pip install -e ".[azure]"        # + Azure Key Vault secret resolution
pip install -e ".[all]"          # everything

Running the real MCP server

cp configs/full-example.yaml configs/my-config.yaml
# edit configs/my-config.yaml: project ids, allow-list patterns, Airflow URL
cp .env.example .env
# fill in AIRFLOW_TOKEN, GOOGLE_APPLICATION_CREDENTIALS, etc.

mcp-data-tools validate-config --config configs/my-config.yaml
mcp-data-tools serve --config configs/my-config.yaml

The server speaks MCP over stdio, so it's meant to be launched by an MCP client host (Claude Desktop, an agent framework's MCP client, etc.), not run standalone as a long-lived network service. See docs/CONFIGURATION.md for every config field.

Wiring into an MCP client

Most MCP client hosts take a command + args:

{
  "mcpServers": {
    "data-tools": {
      "command": "mcp-data-tools",
      "args": ["serve", "--config", "/path/to/configs/my-config.yaml"],
      "env": { "AIRFLOW_TOKEN": "..." }
    }
  }
}

Docker

make docker-build
make docker-run          # docker compose run --rm mcp-data-tools

Testing

make test        # pytest
make test-cov     # pytest with coverage (fails under 85%)

The suite includes a real MCP-protocol integration test (tests/integration/test_mcp_server_e2e.py) built on the official mcp SDK's in-memory client/server harness — it exercises the exact list_tools/call_tool JSON-RPC path a real agent host uses, not a hand-rolled fake.

Examples

FAQ

Does this replace IAM? No. It's a fast, auditable policy layer in front of your backends; the service account/role this server runs as should still be scoped to least privilege. See docs/SECURITY.md for the full defense-in-depth argument.

Can it write data? No tool in this package can execute DDL/DML, delete/write a GCS object, or do anything to Airflow beyond triggering a run and reading status. guardrails.read_only: false is not currently a supported configuration surface for SQL tools.

Does it support Databricks/Snowflake instead of BigQuery? Not yet — the query engine is behind ports.QueryEnginePort, so adding one is a new adapter, not a rewrite. See "Extensibility" in docs/ARCHITECTURE.md.

Why do dry runs still get preflight-checked if they don't cost anything? Because a dry run against BigQuery still reveals whether a table exists and its schema/referenced-table list, which is itself information the allow-list is meant to gate. See docs/SECURITY.md.

Troubleshooting

Symptom Likely cause Fix
Server starts with zero tools registered No bigquery/gcs/airflow section in config Add the relevant section — see configs/full-example.yaml
ConfigurationError: Environment variable 'X' is not set A ${ENV:X} placeholder or SecretRef references an unset var Export it or add it to .env
Every query is denied with "not in the allow-list" guardrails.allowed_table_patterns doesn't match your tables Check the exact project.dataset.table string in the denial's audit event
BackendOperationError: google-cloud-bigquery is required... bigquery section configured but [gcp] extra not installed pip install -e ".[gcp]"
Docker build fails on pip install No network egress in your build environment Use docker build --network=host or a proxy-aware base image

Performance

  • Dry runs are always performed before execution (require_dry_run), so every query pays one extra round-trip to BigQuery — a deliberate trade-off of latency for cost/safety guarantees. See docs/ARCHITECTURE.md for why this isn't optional.
  • The regex-based preflight check (core/sql_tables.py) avoids that round-trip entirely for queries that are obviously out of policy.
  • All adapters use a bounded exponential-backoff retry (core/retry.py) with jitter, so a single transient failure doesn't multiply into a retry storm against the backend.
  • guardrails.max_rows_returned and max_bytes_billed bound both the memory footprint of a single tool call and the backend cost, regardless of how a caller phrases the query.

Security

See SECURITY.md for the threat model, the two-phase SQL authorization design, secret handling, and how to report a vulnerability.

Roadmap

See the [Unreleased] section of CHANGELOG.md: BigQuery-backed audit sink, a Databricks/Delta Lake query-engine adapter, and column/row-level masking policy.

Contributing

See CONTRIBUTING.md for the dev setup, the architecture ground rules new contributions are expected to follow, and the lint/type/security/test gate every PR must pass.

License

MIT

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured