grafana-mcp-server
Allows running SQL queries against ClickHouse datasources through Grafana and retrieving the resulting rows.
Provides read-only access to a Grafana instance, including listing datasources, searching and fetching dashboards, and running queries through Grafana's HTTP API.
Allows running SQL queries against MySQL datasources through Grafana and retrieving the resulting rows.
Allows running PromQL queries against Prometheus metrics through Grafana, including range and instant queries.
Click on "Install 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., "@grafana-mcp-serverwhat's the average request latency for the checkout service in the last hour?"
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.
Grafana MCP Server
A Model Context Protocol (MCP) server that gives AI assistants read-only access to everything your Grafana can already see — Prometheus/Loki metrics, ClickHouse/Postgres/MySQL datasources, and the dashboards your team has already built. Ask questions in natural language and get answers backed by real data.
Works with Claude Code, Claude Desktop, and any MCP-compatible client. Your project can be in any language — this server runs independently.
How It Works
Your project (any language) grafana-mcp-server Grafana Datasources
┌───────────────────┐ ┌──────────────────┐ ┌──────────┐ ┌────────────┐
│ Claude Code or │ stdio │ Builds the │ HTTPS │ /api/ds/ │──────>│ Prometheus │
│ Claude Desktop │────MCP──>│ per-plugin │────────->│ query │──────>│ ClickHouse │
│ │<─────────│ query model │<─────────│ │──────>│ Postgres … │
└───────────────────┘ └──────────────────┘ └──────────┘ └────────────┘The server talks only to Grafana's HTTP API. Grafana proxies the query to the datasource with its credentials, so the assistant never holds a database password, and whatever the Grafana user can see is exactly what the assistant can see — no more. All requests are read-only (use a Viewer credential to make that a guarantee).
Related MCP server: Grafana MCP Server
Requirements
Node.js >= 18 or Docker (only for running this MCP server)
A Grafana account you can sign in with — Google / SSO / password, whatever your Grafana uses. No admin rights, no service account, no API token required:
grafana-mcp-server loginsigns you in in a browser and hands the session to the server (see Authentication). A service-account token works too if you have one.Chrome or Edge installed (used only as the sign-in window; your daily browser can be anything). If neither is present,
loginfalls back to a guided cookie copy in your default browser.
Quick Start
Option A: Node.js
1. Clone and build
git clone https://github.com/stonoyan04/grafana-mcp-server.git
cd grafana-mcp-server
npm install
npm run buildThis creates the compiled server at dist/main.js.
2. Sign in
GRAFANA_URL=https://grafana.example.com npm run loginIf Chrome or Edge is installed (as the default browser, or just present on the machine — that covers almost everyone, whatever their daily browser), login opens a dedicated window of it — its own throwaway profile, not your everyday one — on the Grafana login page. Sign in exactly as you always do. The moment Grafana issues a session, the command stores it, removes it from that profile, verifies it, and prints:
[grafana-mcp-server] ✓ signed in as jane <jane@example.com>No pasting, no token, nothing secret in a config file. If Grafana is behind Cloudflare Access you sign in to that in the same window, and its cookie is captured too. Don't close the window until you see the ✓. The session is stored at ~/.grafana-mcp/sessions/<host>.json (mode 600).
Playwright can only drive Chrome and Edge (Arc, for one, can't be automated at all), so
loginuses one of those as the sign-in window regardless of your default browser — your default browser is never touched. Only if neither Chrome nor Edge is installed doesloginfall back to opening Grafana in your default browser and guiding a one-timegrafana_sessioncopy from DevTools.
Why a dedicated window and not my open tab? A browser never hands its cookies to a command-line tool — that isolation is the point of a browser — so
logindrives an instance it controls, in a separate profile, and takes the session out of it.
Force a specific browser:
npm run login -- --browser chrome(ormsedge,chromiumafternpx playwright install chromium, or a path to a Chromium binary).npm run login -- --pastereads a cookie from stdin with no browser opened.
3. Configure
Claude Code — one command, or the equivalent .mcp.json block:
claude mcp add grafana --scope user --env GRAFANA_URL=https://grafana.example.com -- node /home/john/grafana-mcp-server/dist/main.js{
"mcpServers": {
"grafana": {
"command": "node",
"args": ["/home/john/grafana-mcp-server/dist/main.js"],
"env": {
"GRAFANA_URL": "https://grafana.example.com"
}
}
}
}Claude Desktop — same block in the config file:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
Note: Replace
/home/john/grafana-mcp-serverwith the actual path where you cloned this repo. The only required setting isGRAFANA_URL— the credential comes from the sessionloginstored. Restart the client after adding the server.
Have a service-account token instead? Add
"GRAFANA_TOKEN": "glsa_…"toenvand skiplogin. Or pointGRAFANA_CREDENTIAL_FILEat a0600file holding it, or inject it from a secret manager at launch (e.g.charter secret exec … --exec -- node dist/main.js).
Option B: Docker
git clone https://github.com/stonoyan04/grafana-mcp-server.git
cd grafana-mcp-server
docker build -t grafana-mcp-server .{
"mcpServers": {
"grafana": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-v", "/home/john/.grafana-mcp:/root/.grafana-mcp",
"-e", "GRAFANA_URL=https://grafana.example.com",
"grafana-mcp-server"
]
}
}
}Run login on the host (GRAFANA_URL=… npm run login from a Node checkout, since the container has no browser) and mount ~/.grafana-mcp read-write as shown — the container needs to write rotated sessions back. Or skip the mount and pass -e GRAFANA_TOKEN=glsa_… if you have a service-account token.
Why
-iand no-t? MCP speaks JSON over stdin/stdout.-ikeeps stdin open; a TTY (-t) would corrupt the stream.
If Grafana is behind Cloudflare Access, mount your host's token cache read-only — -v /home/john/.cloudflared:/root/.cloudflared:ro — and run cloudflared access login https://grafana.example.com on the host first. The container cannot run cloudflared itself, so it reads the mounted cache (or a CF_ACCESS_TOKEN); when the token expires, re-run the login on the host.
4. Discover your datasources
List the Grafana datasourcesEvery query tool needs a datasource uid, and the datasource type decides which tool to use — query_sql for ClickHouse/Postgres/MySQL, query_metrics for Prometheus/Loki. list_datasources tells you both.
5. Start asking questions
How many messages per Kafka topic were produced in the last 7 days? → query_metrics on Prometheus
Which dashboards mention "kafka"? → search_dashboards
Show me the panel queries in that dashboard → get_dashboard
Run: SELECT count() FROM events WHERE created > now() - INTERVAL 1 DAY → query_sql on ClickHouseTip:
get_dashboardreturns the raw SQL / PromQL behind each panel. Reusing a query a human already wrote and trusts beats writing one from scratch.
Tools
The server exposes 6 read-only tools:
list_datasources
List datasources with uid, name, type, and which query tool applies. No parameters.
query_sql
Run raw SQL against a SQL-family datasource through Grafana and get rows back.
Parameter | Type | Default | Description |
| string | Datasource uid or exact name | |
| string | The SQL to run | |
| string |
| Range start (for |
| string |
| Range end |
The query object sent to /api/ds/query is built per plugin — grafana-clickhouse-datasource, vertamedia-clickhouse-datasource, and the built-in Postgres/MySQL/MSSQL all want different shapes.
query_metrics
Run a PromQL or LogQL expression. Omit from for an instant query.
Parameter | Type | Default | Description |
| string | Datasource uid or exact name | |
| string | PromQL / LogQL expression | |
| string | Range start, e.g. | |
| string |
| Range end / evaluation time |
| number |
| Range-query step |
| number |
| Points per series cap |
search_dashboards
Parameter | Type | Default | Description |
| string | Title substring | |
| string | Dashboard tag | |
| number |
| Max results |
get_dashboard
Parameter | Type | Description |
| string | Dashboard uid from |
Returns the panels (rows flattened) with each panel's datasource and raw queries, plus the dashboard's template variables and default time range.
health
Checks connectivity and tells the two auth layers apart: failingLayer: "cloudflare" means run cloudflared access login (or login again); failingLayer: "grafana" means the stored session/credential is dead or under-privileged — run grafana-mcp-server login. Reports who the credential authenticates as and how many datasources it can see. No parameters. Call it first whenever another tool fails.
Data frames are flattened into plain rows keyed by field name (Prometheus series are disambiguated by their labels), capped at GRAFANA_MAX_ROWS.
Commands
Command | What it does |
| Run the MCP server on stdio — this is what the MCP client launches |
| Open your default browser (dedicated profile), sign in to Grafana as usual, store the session for the server |
| Force |
| Store a |
| Delete the stored session |
npm run login / npm run logout are shortcuts for the same thing from a checkout.
Configuration
All configuration is via environment variables. With login, only GRAFANA_URL is needed.
Variable | Required | Default | Description |
| Yes | Grafana base URL | |
| No | Service-account token ( | |
| No | Basic auth | |
| No | A | |
| No | File holding any one of the above; shape inferred, re-read per request, rotated sessions written back | |
| No |
| Where |
| No |
| How long |
| No |
|
|
| No | auto | Cloudflare Access JWT fallback |
| No | (all) | Comma-separated allowlist of datasource uids or names |
| No |
| Rows returned per frame |
| No |
| Request timeout in milliseconds |
Credential precedence: GRAFANA_TOKEN → GRAFANA_USERNAME+PASSWORD → GRAFANA_SESSION → GRAFANA_CREDENTIAL_FILE → the session stored by login → ~/.grafana-mcp-token if it exists.
Datasource allowlist
"ALLOWED_DATASOURCES": "OsirT4Bnz,Prometheus"list_datasources hides everything else and the query tools refuse it.
Authentication
Grafana: sign in with your own account (login)
grafana-mcp-server login gets you signed in and hands the session to the server. It drives Chrome or Edge — whichever is installed, used only as the sign-in window regardless of your default browser — through Playwright in a dedicated profile under ~/.grafana-mcp/browser, opens GRAFANA_URL/login, and waits while you sign in — Google, GitHub, SAML, LDAP, or a plain password; the tool never sees or types your credentials. When Grafana sets its grafana_session cookie the tool:
copies the session (and the
CF_Authorizationcookie, if Cloudflare Access is in front) into~/.grafana-mcp/sessions/<host>.json(0600),deletes Grafana's cookies from that browser profile, so the server is the session's only holder,
calls
/api/userthrough the server's own code path and prints who you are.
Playwright can drive only Chrome and Edge, and Arc can't be automated at all — so the sign-in window is always Chrome/Edge, never your default browser (which is left untouched). Only if neither Chrome nor Edge is installed does login fall back to opening Grafana in your default browser and walking you through copying the grafana_session cookie from DevTools once; that path also asks you to sign out of the tab afterwards so it stops competing for session rotations.
From then on the server keeps the session alive itself: Grafana answers a stale session with 401 session.token.rotate, the server calls POST /api/user/auth-tokens/rotate, persists the new cookie atomically, and retries. The session therefore lasts for Grafana's login lifetime (30 days by default, 7 days idle) — re-run login when health says failingLayer: "grafana".
Why this is the recommended path: it needs no Grafana admin. Everyone who can open Grafana in a browser can use the server, with exactly their own permissions, and revoking access is the same as for any user.
Why a pasted cookie normally dies in minutes
Grafana ≥ 10 rotates a session token every few minutes, and only one client gets the new one. If you copy grafana_session from DevTools while the tab stays open, the browser rotates it first and the copy is dead within minutes — that is the classic "the cookie stopped working" experience. login avoids it by taking the session out of the browser; login --paste works too as long as you then sign out (or clear the cookie) in the tab you copied from, because the server persists its own rotations.
Grafana: other credentials
Credential | Notes |
Service-account token ( | Never rotates. Needs a Grafana admin to create it (Administration → Service accounts, role Viewer) — |
Basic auth | Only if the login form is enabled — instances on Google/GitHub OAuth usually have no password to give. |
| A session value straight from env. Works, but rotations cannot be written back, so it dies with the first rotation after a restart. Prefer |
scripts/verify.sh checks both layers and reports what the credential can see — without ever printing it.
Cloudflare Access (optional)
If Grafana sits behind Cloudflare Zero Trust, every request also needs a cf-access-token header or the edge redirects to its login page before Grafana sees the call. The server handles that automatically:
Read the cached JWT from
~/.cloudflared/<hostname>-<audience>-token(written bycloudflared access login)If missing or expired, run
cloudflared access token --app=<GRAFANA_URL>(non-interactive)Use the
CF_Authorizationcookie captured bylogin(if not expired)Fall back to
CF_ACCESS_TOKENOn a 302 from the edge, drop the cached token and retry once with a fresh one
The token is resolved lazily, per request — never once at startup — so an expiring token heals itself instead of failing every call until the client restarts. Installing cloudflared is optional but recommended: its token refreshes itself for as long as your Cloudflare login lasts, whereas the cookie captured by login expires with Cloudflare's session policy (typically 24h) and then needs login again.
brew install cloudflared # macOS; see Cloudflare's docs for Linux
cloudflared access login https://grafana.example.comCloudflare does not log you into Grafana. The CF JWT proves you may reach the host; Grafana then wants its own credential. A 302 / HTML response is Cloudflare; a JSON 401 is Grafana. health reports which.
Not behind Cloudflare? Set GRAFANA_CF_ACCESS=off, or just don't install cloudflared — the server skips the layer when no token can be found.
Project Structure
src/
main.ts # Entry point — `login` / `logout` commands, or the stdio MCP server
login.ts # Browser sign-in (Playwright over your default Chromium-based browser) → session store
default-browser.ts # Detect the default browser (macOS LaunchServices / xdg) and whether it can be driven
session-store.ts # ~/.grafana-mcp/sessions/<host>.json, 0600, atomic writes
grafana-client.ts # Grafana HTTP client: two auth layers, CF retry, session rotation, datasource cache
auth.ts # Grafana credential resolution (token / basic / session / file / login store)
cf-token.ts # Cloudflare Access token: cache → cloudflared → login cookie → env, lazy + retry
query-model.ts # Per-plugin /api/ds/query bodies (ClickHouse, SQL, PromQL/LogQL)
allowed-datasources.ts # Datasource allowlist
utils/
frames.ts # Data frames → rows
format-response.ts # Truncation, error results
tools/
list-datasources.tool.ts # list_datasources
query-sql.tool.ts # query_sql
query-metrics.tool.ts # query_metrics
search-dashboards.tool.ts # search_dashboards
get-dashboard.tool.ts # get_dashboard
health.tool.ts # health
scripts/
verify.sh # Check both auth layers; list what the credential can see
mint-token.sh # Turn a fresh admin browser session into a service-account tokenLicense
MIT
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseCqualityDmaintenanceEnables AI-powered integration with Grafana instances through 52 MCP tools for dashboard management, Prometheus/Loki queries, alerting, and administrative functions. Supports complete Grafana functionality including metrics exploration, log analysis, and incident response through natural language.801
- AlicenseBqualityBmaintenanceEnables AI assistants to interact with Grafana dashboards, datasources, alerts, incidents, and monitoring data through 43 comprehensive tools. Supports querying Prometheus metrics, Loki logs, managing incidents, and dashboard operations with full authentication support.437623MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to query Prometheus metrics, monitor alerts, and analyze system health through read-only access to your Prometheus server with built-in query safety and optional AI-powered metric analysis.MIT
- AlicenseNot gradedqualityDmaintenanceQuery Grafana logs, metrics, and dashboards from Cursor. Enables the AI to call your Grafana instance via tools without leaving the editor.84Apache 2.0
Related MCP Connectors
Renders interactive Chart.js charts and dashboards inline in AI conversations.
Provide real-time data querying and visualization by integrating Tako with your agents. Generate o…
Connect AI assistants to your GitHub-hosted Obsidian vault to seamlessly access, search, and analy…
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/stonoyan04/grafana-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server