An MCP server is the small adapter that lets a model actually do something with your data instead of just talking about it. For analytics, it's how Claude runs a query instead of asking you to.
What an MCP server actually is
It's a process that exposes tools and resources over the Model Context Protocol. The client, like Claude, discovers those tools at runtime and calls them.
The server does the real work, querying BigQuery or hitting an API, and returns the result. Because the interface is standard, any MCP client can use the same server without a custom integration.
Tools are actions the model can call. Resources are read-only context the model can pull in, like a table's schema. For analytics you'll lean on both.
What a useful analytics server exposes
Keep the surface small. A handful of tools covers most of the job: run_query with a byte cap, list_tables, and describe_schema.
Add get_metric_definition so the model uses your blessed definition of "revenue" or "active user" instead of inventing one. Narrow tools are far easier to make safe than a single do-anything endpoint.
Building a minimal one
Pick the SDK, TypeScript or Python, define a tool with a typed signature, and implement the handler. Here's a minimal run_query tool in Python:
from mcp.server.fastmcp import FastMCP
from google.cloud import bigquery
mcp = FastMCP("bigquery-analytics")
bq = bigquery.Client()
@mcp.tool()
def run_query(sql: str) -> list[dict]:
cfg = bigquery.QueryJobConfig(
maximum_bytes_billed=1_000_000_000)
job = bq.query(sql, job_config=cfg)
return [dict(row) for row in job.result()]
That's a working tool a client can discover and call. Add list_tables and describe_schema the same way, each a small function that returns plain data.
describe_schema is just as small: take a table name, return its columns and types so the model stops guessing. get_metric_definition takes a metric name and returns your one blessed SQL expression for it. Together, those read-only tools let the model answer real questions with no write path anywhere.
Wire it into the client
Register the server in your MCP client's config, point it at the script or command that runs it, and restart. The client lists the tools, and the model can start calling them in its next answer.
Then ask the client a question that should use run_query, and check the tool call to confirm it passed sensible SQL. If it did, the loop is closed. If a tool doesn't show up at all, the server failed to start, so check its logs before blaming the model.
When to build your own vs use an existing one
For plain BigQuery access, an existing server like Google's MCP Toolbox for Databases saves you the work. Build your own when you need tools specific to your business, like get_metric_definition that reads your semantic layer, or a tool that only exposes three approved views.
The value of a custom server isn't the query tool. It's the guardrails and the business logic you bake in that a generic server won't have.
The parts that matter more than the code
Least-privilege credentials, a byte cap on every query, input validation, and read-only by default. Consider allowlisting which datasets the server can touch, so a stray query can't wander into a table it shouldn't.
The server runs with your access, so treat it like an account, not a throwaway script. Log every tool call, too, because when someone asks why a number looks off, the query log is the first place you'll look.
An MCP server is a small adapter, but it's the piece that turns a model from something that talks about your data into something that touches it. Build it narrow, scope it tight, and it earns its place in the stack.
Want a stronger data analyst role or a raise? Grab the FREE Product Analyst Playbook and get the exact roadmap to your next offer.
