
A Model Context Protocol (MCP) server for Grafana.
A Model Context Protocol (MCP) server for Grafana.
·
A Model Context Protocol (MCP) server for Grafana.
This provides access to your Grafana instance and the surrounding ecosystem.
Requires uv. Add the following to your MCP client configuration (e.g. Claude Desktop, Cursor):
{
"mcpServers": {
"grafana": {
"command": "uvx",
"args": ["mcp-grafana"],
"env": {
"GRAFANA_URL": "http://localhost:3000",
"GRAFANA_SERVICE_ACCOUNT_TOKEN": "<your service account token>"
}
}
}
}For Grafana Cloud, replace GRAFANA_URL with your instance URL (e.g. https://myinstance.grafana.net). See Usage for more installation options including Docker, binary, and Helm.
The following features are currently available in MCP server. This list is for informational purposes only and does not represent a roadmap or commitment to future features.
version to load a saved snapshot instead of the current dashboard. Warning: Large dashboards can consume significant context window space.$.title, $.panels[*].title) to fetch only needed data and reduce context window consumptionNote: Run panel query tools are disabled by default. To enable them, add
runpanelqueryto your--enabled-toolsflag.
backend or jq-backend parser (Google Sheets queries always do); the default simple parser and the UQL and GROQ parsers work only in the browser.The dashboard tools now include several strategies to manage context window usage effectively (issue #101):
get_dashboard_summary for dashboard overview and planning modificationsget_dashboard_property with JSONPath when you only need specific dashboard partsget_dashboard_by_uid unless you specifically need the complete dashboard JSONNote: Query examples tools are disabled by default. To enable them, add
examplesto your--enabled-toolsflag.
Note: InfluxDB tools are disabled by default. To enable them, add
influxdbto your--enabled-toolsflag.
dialect parameter.Note: SQL tools are disabled by default. To enable them, add
sqlto your--enabled-toolsflag. Back-compat aliasesclickhouse,snowflake, andathenaalso work.
Unified SQL tools support ClickHouse, Snowflake, Athena, MySQL, PostgreSQL, and MSSQL through a single set of tools. Queries go through Grafana's datasource plugins, so authentication is handled by datasource configuration — credentials are never seen by the MCP server.
$__timeFilter(col), $__from/$__to, $__interval, ${varname}), automatic limit enforcement, and template variable support.Note: CloudWatch tools are disabled by default. To enable them, add
cloudwatchto your--enabled-toolsflag.
Note: Google Cloud Logging tools are disabled by default. To enable them, add
cloudloggingto your--enabled-toolsflag. Requires the Google Cloud Logging datasource plugin (googlecloud-logging-datasource) version 1.8.0 or later, which needs Grafana 11.2+. Older plugin versions return a different response layout andquery_cloud_loggingreports an error asking for an upgrade.
resource.type="k8s_container" AND severity>=ERROR) with time range and limit; returns entries newest-first with severity, body, labels, and trace ID. GCP authentication is handled by the datasource configuration.Note: Graphite tools are disabled by default. To enable them, add
graphiteto your--enabled-toolsflag.
Note: Elasticsearch/OpenSearch tools are disabled by default. To enable them, add
elasticsearchto your--enabled-toolsflag.
Note: Quickwit tools are disabled by default. To enable them, add
quickwitto your--enabled-toolsflag.
Note: Agent Observability tools are disabled by default and work only in Grafana Cloud. To enable them, add
agento11yto your--enabled-toolsflag.
sha256: hashes that a tool change never affects; for an agent that reports no version of its own they hash the system prompt, so a prompt edit mints a new version. Catalog and version rows carry a token_estimate, which is worth checking before fetching a full prompt.preview_rule and test_evaluator operations need the grafana-agento11y-app.eval:write permission, granted by the Agento11y Admin role.grafana-agento11y-app.eval:write permission.grafana-agento11y-app.eval:write.grafana-agento11y-app.eval:write. Experiments are created by SDK runners, not by this tool.Note: Assistant tools are disabled by default and require the Grafana Assistant plugin (
grafana-assistant-app) to be installed on the target Grafana instance. They are also write tools (the assistant may mutate stack state), so they are skipped when--disable-writeis set. To enable them, addassistantto your--enabled-toolsflag.
contextId back in a follow-up call to continue the same conversation. Complex tasks can take several minutes; the call blocks until the reply is done or the request times out (5 minutes).Note: Admin tools are disabled by default. To enable them, include
adminin your--enabled-toolsflag.
orgId values for multi-organization requests.http://localhost:3000/d/dashboard-uid)http://localhost:3000/d/dashboard-uid?viewPanel=5)http://localhost:3000/explore?schemaVersion=1&panes={"a":{"datasource":"prometheus-uid"}}). Grafana below 10.2 does not understand panes, so the legacy ?left={...} format is emitted for those versions instead.from=now-1h&to=now)what, when, tags, data).provisioningPreview parameter.
The list of tools is configurable, so you can choose which tools you want to make available to the MCP client.
This is useful if you don't use certain functionality or if you don't want to take up too much of the context window.
To disable a category of tools, use the --disable-<category> flag when starting the server. For example, to disable
the OnCall tools, use --disable-oncall, or to disable navigation deeplink generation, use --disable-navigation.
Each tool requires specific RBAC permissions to function properly. When creating a service account for the MCP server, ensure it has the necessary permissions based on which tools you plan to use. The permissions listed are the minimum required actions - you may also need appropriate scopes (e.g., datasources:*, dashboards:*, folders:*) depending on your use case.
Tip: If you're not familiar with Grafana RBAC or you want a quicker, simpler setup instead of configuring many granular scopes, you can assign a built-in role such as Editor to the service account. The Editor role grants broad read/write access that will allow most MCP server operations; it is less granular (and therefore less restrictive) than manually-applied scopes, so use it only when convenience is more important than strict least-privilege access.
Note: OnCall and other plugin-backed tools are authorized by plugin actions such as grafana-irm-app.schedules:read. The basic Viewer role includes the read actions and Editor the write actions. Incident tools need only plugins.app:access; IRM authorizes incident actions by basic role.
Actions in group/resource:verb form, such as dashboard.grafana.app/dashboards:get, apply only to on-behalf-of access tokens. A service account needs only the other actions listed.
For more information about Grafana RBAC, see the official documentation.
Scopes define the specific resources that permissions apply to. Each action requires both the appropriate permission and scope combination.
Common Scope Patterns:
Broad access: Use * wildcards for organization-wide access
datasources:* - Access to all datasourcesdashboards:* - Access to all dashboardsfolders:* - Access to all foldersteams:* - Access to all teamsLimited access: Use specific UIDs or IDs to restrict access to individual resources
datasources:uid:prometheus-uid - Access only to a specific Prometheus datasourcedashboards:uid:abc123 - Access only to dashboard with UID abc123folders:uid:xyz789 - Access only to folder with UID xyz789teams:id:5 - Access only to team with ID 5global.users:id:123 - Access only to user with ID 123Examples:
Full MCP server access: Grant broad permissions for all tools
datasources:* (datasources:read, datasources:query)
dashboards:* (dashboards:read, dashboards:create, dashboards:write)
folders:* (for dashboard creation and alert rules)
teams:* (teams:read)
global.users:* (users:read)Limited datasource access: Only query specific Prometheus and Loki instances
datasources:uid:prometheus-prod (datasources:query)
datasources:uid:loki-prod (datasources:query)Dashboard-specific access: Read only specific dashboards
dashboards:uid:monitoring-dashboard (dashboards:read)
dashboards:uid:alerts-dashboard (dashboards:read)| Tool | Category | Description | Required RBAC Permissions | Required Scopes |
|---|---|---|---|---|
list_teams | Admin* | List all teams | teams:read | teams:* or teams:id:1 |
list_users_by_org | Admin* | List users in an organization, with search and pagination | org.users:read | global.users:* or global.users:id:123 |
list_all_roles | Admin* | List all Grafana roles | roles:read | roles:* |
get_role_details | Admin* | Get details for a Grafana role | roles:read | roles:uid:editor |
get_role_assignments | Admin* | List assignments for a role | roles:read, teams.roles:read, users.roles:read | roles:uid:editor |
list_user_roles | Admin* | List roles for users | users.roles:read | global.users:id:123 |
list_team_roles | Admin* | List roles for teams | teams.roles:read | teams:id:7 |
get_resource_permissions | Admin* | List permissions for a resource | dashboards.permissions:read, datasources.permissions:read, folders.permissions:read, serviceaccounts.permissions:read, teams.permissions:read, users.permissions:read | dashboards:uid:abcd1234 |
get_resource_description | Admin* | Describe a Grafana resource type | dashboards.permissions:read, datasources.permissions:read, folders.permissions:read, serviceaccounts.permissions:read, teams.permissions:read, users.permissions:read | dashboards:* |
user_info | User | Current identity, capabilities, and accessible organizations | None | — |
search_dashboards | Search | Search for dashboards by query, folder UID, tag, or starred | dashboards:read, folders:read | dashboards:* or dashboards:uid:abc123 |
search_folders | Search | Search for folders by title | folders:read | folders:* or folders:uid:xyz789 |
get_dashboard_by_uid | Dashboard | Get a dashboard by uid, optionally a saved version | dashboard.grafana.app/dashboards:get, dashboards:read, dashboards:write | dashboards:uid:abc123 |
list_dashboard_versions | Dashboard | List saved versions of a dashboard (version, author, time, message) | dashboards:read, dashboards:write | dashboards:uid:abc123 |
update_dashboard | Dashboard | Update or create a new dashboard | dashboard.grafana.app/dashboards:create, dashboard.grafana.app/dashboards:get, dashboard.grafana.app/dashboards:update, dashboards:create, dashboards:read, dashboards:write, folders:read | dashboards:*, folders:* or folders:uid:xyz789 |
get_dashboard_panel_queries | Dashboard | Get panel title, queries, datasource UID and type from a dashboard | dashboard.grafana.app/dashboards:get, dashboards:read | dashboards:uid:abc123 |
run_panel_query | RunPanelQuery* | Execute one or more dashboard panel queries | dashboard.grafana.app/dashboards:get, dashboards:read, datasources:query, datasources:read | dashboards:uid:*, datasources:uid:* |
get_dashboard_property | Dashboard | Extract specific parts of a dashboard using JSONPath expressions | dashboard.grafana.app/dashboards:get, dashboards:read | dashboards:uid:abc123 |
get_dashboard_summary | Dashboard | Get a compact summary of a dashboard without full JSON | dashboard.grafana.app/dashboards:get, dashboards:read | dashboards:uid:abc123 |
create_folder | Dashboard | Create a folder | folders:create, folders:read, folders:write | folders:* |
list_datasources | Datasources | List datasources | datasources:read | datasources:* |
get_datasource | Datasources | Get a datasource by UID or name | datasources:read | datasources:uid:prometheus-uid |
check_datasources_health | Datasources | Check the health of one or more datasources | datasources:query, datasources:read | datasources:uid:* |
create_datasource | Datasources | Create a datasource | datasources:create, datasources:read | datasources:* |
update_datasource | Datasources | Update a datasource | datasources:read, datasources:write | datasources:* or datasources:uid:abc123 |
get_query_examples | Examples* | Get example queries for a datasource type | None | datasources:* |
query_prometheus | Prometheus | Execute a query against a Prometheus datasource | datasources:query, datasources:read | datasources:uid:prometheus-uid |
list_prometheus_metric_metadata | Prometheus | List metric metadata | datasources:query, datasources:read | datasources:uid:prometheus-uid |
list_prometheus_metric_names | Prometheus | List available metric names | datasources:query, datasources:read | datasources:uid:prometheus-uid |
list_prometheus_label_names | Prometheus | List label names matching a selector | datasources:query, datasources:read | datasources:uid:prometheus-uid |
list_prometheus_label_values | Prometheus | List values for a specific label | datasources:query, datasources:read | datasources:uid:prometheus-uid |
query_prometheus_histogram | Prometheus | Calculate histogram percentile values | datasources:query, datasources:read | datasources:uid:prometheus-uid |
list_incidents | Incident | List incidents in Grafana Incident, optionally with their custom field values | plugins.app:access | N/A |
create_incident | Incident | Create an incident in Grafana Incident, optionally setting custom fields | plugins.app:access | N/A |
add_activity_to_incident | Incident | Add an activity item to an incident in Grafana Incident | plugins.app:access | N/A |
update_incident | Incident | Update an incident in Grafana Incident (status, severity, title, or custom fields) | plugins.app:access | N/A |
get_incident | Incident | Get a single incident by ID, including its custom fields | plugins.app:access | N/A |
list_incident_custom_fields | Incident | List the custom fields configured for incidents, with their types and select options | plugins.app:access | N/A |
query_loki_logs | Loki | Query and retrieve logs using LogQL (either log or metric queries) | datasources:query, datasources:read | datasources:uid:loki-uid |
list_loki_label_names | Loki | List all available label names in logs | datasources:query, datasources:read | datasources:uid:loki-uid |
list_loki_label_values | Loki | List values for a specific log label | datasources:query, datasources:read | datasources:uid:loki-uid |
query_loki_stats | Loki | Get statistics about log streams | datasources:query, datasources:read | datasources:uid:loki-uid |
query_loki_patterns | Loki | Query detected log patterns to identify common structures | datasources:query, datasources:read | datasources:uid:loki-uid |
analyze_loki_labels | Loki | Audit a Loki label strategy (live or static) and optionally diagnose query performance | datasources:query, datasources:read | datasources:uid:loki-uid |
suggest_loki_alloy_label_config | Config | Generate an Alloy loki.process snippet enforcing approved labels | None | N/A |
query_influxdb | InfluxDB* | Query InfluxDB using InfluxQL (v1) or Flux (v2) | datasources:query, datasources:read | datasources:uid:influxdb-uid |
list_sql_databases | SQL* | List databases, schemas, or catalogs from a SQL datasource | datasources:query, datasources:read | datasources:uid:* |
list_sql_tables | SQL* | List tables in a SQL datasource | datasources:query, datasources:read | datasources:uid:* |
describe_sql_table | SQL* | Get column schema for a table | datasources:query, datasources:read | datasources:uid:* |
query_sql | SQL* | Execute SQL queries with macro substitution | datasources:query, datasources:read | datasources:uid:* |
list_cloudwatch_namespaces | CloudWatch* | List available AWS CloudWatch namespaces | datasources:query, datasources:read | datasources:uid:* |
list_cloudwatch_metrics | CloudWatch* | List metrics in a namespace | datasources:query, datasources:read | datasources:uid:* |
list_cloudwatch_dimensions | CloudWatch* | List dimensions for a metric | datasources:query, datasources:read | datasources:uid:* |
list_cloudwatch_dimension_values | CloudWatch* | List values for a dimension key | datasources:query, datasources:read | datasources:uid:* |
query_cloudwatch | CloudWatch* | Execute CloudWatch metric queries | datasources:query, datasources:read | datasources:uid:* |
list_cloud_logging_projects | Cloud Logging* | List GCP projects readable by a Google Cloud Logging datasource | datasources:query, datasources:read | datasources:uid:* |
list_cloud_logging_buckets | Cloud Logging* | List log buckets in a GCP project | datasources:query, datasources:read | datasources:uid:* |
list_cloud_logging_views | Cloud Logging* | List log views in a log bucket | datasources:query, datasources:read | datasources:uid:* |
query_cloud_logging | Cloud Logging* | Query logs with the Cloud Logging query language | datasources:query, datasources:read | datasources:uid:* |
query_elasticsearch | Elasticsearch/OpenSearch* | Query Elasticsearch or OpenSearch using Lucene syntax or Query DSL | datasources:query, datasources:read | datasources:uid:datasource-uid |
query_quickwit | Quickwit* | Query Quickwit using Lucene syntax or Query DSL | datasources:query, datasources:read | datasources:uid:quickwit-uid |
alerting_rules_read | Alerting | List and inspect alert rules (list, get, versions) | alert.rules.external:read, alert.rules:read, datasources:read, folders:read | folders:* or folders:uid:alerts-folder |
alerting_rules_write | Alerting | Create, update and delete Grafana-managed rules, or explicitly create datasource-managed rules | alert.provisioning.provenance:write, alert.rules.external:read, alert.rules.external:write, alert.rules:create, alert.rules:delete, alert.rules:read, alert.rules:write, datasources:read, folders:read | folders:*, or datasources:uid:<uid> for external creation |
alerting_manage_routing | Alerting | Manage notification policies, contact points, and time intervals | alert.notifications.external:read, alert.notifications.receivers:read, alert.notifications.routes:read, alert.notifications.time-intervals:read, alert.notifications:read, datasources:query, datasources:read, notifications.alerting.grafana.app/routingtrees:get | Global scope |
alerting_routing_write | Alerting | Create Grafana-managed contact points by default, or explicitly create external Alertmanager receivers | alert.notifications.external:read, alert.notifications.external:write, alert.notifications.receivers:create, alert.provisioning.provenance:write, datasources:read | Global, or datasources:uid:<uid> for external creation |
alerting_silences_read | Alerting | List and inspect alerting silences (list, get) | alert.instances:read, alert.silences:read | Global scope |
alerting_silences_write | Alerting | Create, update, and expire alerting silences | alert.instances:create, alert.instances:read, alert.instances:write, alert.silences:create, alert.silences:read, alert.silences:write | Global scope |
list_oncall_schedules | OnCall | List schedules from Grafana OnCall | grafana-irm-app.schedules:read, plugins.app:access | Plugin-specific scopes |
get_oncall_shift | OnCall | Get details for a specific OnCall shift | grafana-irm-app.schedules:read, plugins.app:access | Plugin-specific scopes |
get_current_oncall_users | OnCall | Get users currently on-call for a specific schedule | grafana-irm-app.schedules:read, grafana-irm-app.user-settings:read, plugins.app:access | Plugin-specific scopes |
list_oncall_teams | OnCall | List teams from Grafana OnCall | grafana-irm-app.user-settings:read, plugins.app:access | Plugin-specific scopes |
list_oncall_users | OnCall | List users from Grafana OnCall | grafana-irm-app.user-settings:read, plugins.app:access | Plugin-specific scopes |
list_alert_groups | OnCall | List alert groups from Grafana OnCall with filtering options | grafana-irm-app.alert-groups:read, plugins.app:access | Plugin-specific scopes |
get_alert_group | OnCall | Get a specific alert group from Grafana OnCall by its ID | grafana-irm-app.alert-groups:read, plugins.app:access | Plugin-specific scopes |
update_alert_group | OnCall | Acknowledge, unacknowledge, resolve, or unresolve an alert group | grafana-irm-app.alert-groups:read, grafana-irm-app.alert-groups:write, plugins.app:access | Plugin-specific scopes |
list_pyroscope_label_names | Pyroscope | List label names matching a selector | datasources:query, datasources:read | datasources:uid:pyroscope-uid |
list_pyroscope_label_values | Pyroscope | List label values matching a selector for a label name | datasources:query, datasources:read | datasources:uid:pyroscope-uid |
list_pyroscope_profile_types | Pyroscope | List available profile types | datasources:query, datasources:read | datasources:uid:pyroscope-uid |
query_pyroscope | Pyroscope | Query profiles, metrics, or both from Pyroscope | datasources:query, datasources:read | datasources:uid:pyroscope-uid |
get_assertions | Asserts | Get assertion summary for a given entity | plugins.app:access | Plugin-specific scopes |
agento11y_manage_conversations | Agent Observability* | List, search, and fetch LLM conversations from Grafana Agent Observability | grafana-agento11y-app.conversations:read, grafana-agento11y-app.data:read, plugins.app:access | N/A |
agento11y_manage_generations | Agent Observability* | Fetch LLM generation details and evaluation scores from Grafana Agent Observability | grafana-agento11y-app.conversations:read, grafana-agento11y-app.data:read, plugins.app:access | N/A |
agento11y_manage_agents | Agent Observability* | Read the agent catalog: list agents, get one agent version in full, list version history, and per-version score aggregates | grafana-agento11y-app.conversations:read, grafana-agento11y-app.data:read, plugins.app:access | N/A |
agento11y_manage_evaluators | Agent Observability* | Manage evaluators, evaluator templates, and the judge catalog (list, get, upsert, fork, test, delete) | grafana-agento11y-app.conversations:read, grafana-agento11y-app.data:read, plugins.app:access; with writes enabled also grafana-agento11y-app.eval:write | N/A |
agento11y_manage_eval_rules | Agent Observability* | Manage eval rules and guards (list, get, create, update, preview, delete) | grafana-agento11y-app.conversations:read, grafana-agento11y-app.data:read, plugins.app:access; with writes enabled also grafana-agento11y-app.eval:write | N/A |
agento11y_manage_eval_collections | Agent Observability* | Manage saved conversations and the collections that group them (list, get, save, create, update, delete, add and remove members) | grafana-agento11y-app.conversations:read, grafana-agento11y-app.data:read, plugins.app:access; with writes enabled also grafana-agento11y-app.eval:write | N/A |
agento11y_manage_experiments | Agent Observability* | Read offline experiments, their trials, scores, artifact metadata, and filter facets; update and cancel an experiment | grafana-agento11y-app.conversations:read, grafana-agento11y-app.data:read, plugins.app:access; with writes enabled also grafana-agento11y-app.eval:write | N/A |
agento11y_manage_test_suites | Agent Observability* | Manage the test suites that offline experiments run against, their versions, and their test cases (list, get, create, update, draft, publish, upsert, delete) | grafana-agento11y-app.conversations:read, grafana-agento11y-app.data:read, plugins.app:access; with writes enabled also grafana-agento11y-app.eval:write | N/A |
ask_assistant | Assistant* | Send a prompt to Grafana Assistant and return the full text reply (multi-turn via contextId) | grafana-assistant-app.chats:access, plugins.app:access | Plugin-specific scopes |
generate_deeplink | Navigation | Generate accurate deeplink URLs for Grafana resources | None | N/A |
get_annotations | Annotations | Fetch annotations with filters | annotations:read | annotations:* or annotations:id:123 |
create_annotation | Annotations | Create a new annotation (standard or Graphite format) | annotations:create | annotations:* |
update_annotation | Annotations | Update specific fields of an annotation (partial update) | annotations:read, annotations:write | annotations:* |
delete_annotation | Annotations | Delete an annotation by ID | annotations:delete | annotations:* |
get_annotation_tags | Annotations | List annotation tags with optional filtering | annotations:read | annotations:* |
list_snapshots | Snapshot | List dashboard snapshots with optional query and limit filters | snapshots:read | N/A |
get_snapshot | Snapshot | Get snapshot metadata and dashboard payload by snapshot key | None | N/A |
create_snapshot | Snapshot | Create a dashboard snapshot from a full dashboard payload | dashboards:read, snapshots:create | dashboards:uid:abc123 |
delete_snapshot | Snapshot | Delete a dashboard snapshot by snapshot key | dashboards:write, snapshots:delete | dashboards:uid:abc123 |
get_panel_image | Rendering | Render a stored dashboard or panel, a provisioning preview, or an ad-hoc Explore view as a PNG image | dashboards:read, datasources:explore, datasources:query, datasources:read, provisioning.repositories:read | dashboards:uid:abc123 |
list_provisioning_repositories | Provisioning | List provisioning repositories (e.g. git-sync sources) with their source URL, branch, sync state, and health | provisioning.grafana.app/repositories:list, provisioning.repositories:read | N/A |
validate_provisioning_file | Provisioning | Dry-run-apply a file from a provisioning repository and report admission validation errors | dashboard.grafana.app/dashboards:get, dashboards:read, folder.grafana.app/folders:get, folders:read, provisioning.grafana.app/repositories:get, provisioning.repositories:read | N/A |
search_docs | Docs | Search Grafana documentation or list product groups (omit query to list products) | None | N/A |
get_doc | Docs | Fetch a documentation page; set outline_only for headings, or section for bounded retrieval | None | N/A |
search_tempo_traces | Tempo | Search traces with TraceQL | datasources:query, datasources:read | datasources:uid:tempo-uid |
query_tempo_metrics | Tempo | Compute metrics from traces with TraceQL | datasources:query, datasources:read | datasources:uid:tempo-uid |
get_tempo_trace | Tempo | Fetch a trace by ID | datasources:query, datasources:read | datasources:uid:tempo-uid |
diff_tempo_traces | Tempo | Compare two traces | datasources:query, datasources:read | datasources:uid:tempo-uid |
list_tempo_attribute_names | Tempo | List span and resource attribute names | datasources:query, datasources:read | datasources:uid:tempo-uid |
list_tempo_attribute_values | Tempo | List values for a trace attribute | datasources:query, datasources:read | datasources:uid:tempo-uid |
get_tempo_traceql_docs | Tempo | Get TraceQL documentation | None | N/A |
query_graphite | Graphite* | Query Graphite metrics | datasources:query, datasources:read | datasources:uid:graphite-uid |
query_graphite_density | Graphite* | Query Graphite metric density | datasources:query, datasources:read | datasources:uid:graphite-uid |
list_graphite_metrics | Graphite* | List Graphite metrics | datasources:query, datasources:read | datasources:uid:graphite-uid |
list_graphite_tags | Graphite* | List Graphite tags | datasources:query, datasources:read | datasources:uid:graphite-uid |
get_plugin | Plugins | Get an installed plugin | plugins.app:access | N/A |
search_plugin_information | Plugins | Search the grafana.com plugin catalog | None | N/A |
install_plugin | Plugins | Install a plugin | plugins:install | N/A |
grafana_api_request | API | Call a Grafana HTTP API endpoint | None | Depends on the endpoint |
* Disabled by default. Add category to --enabled-tools to enable.
The get_tempo_trace tool displays an interactive trace viewer in compatible MCP hosts whenever Tempo query tools are enabled. Its existing text output remains available. See MCP Apps for setup and library embedding.
The mcp-grafana binary supports various command-line flags for configuration:
Transport Options:
-t, --transport: Transport type (stdio, sse, or streamable-http) - default: stdio--address: The host and port for SSE/streamable-http server - default: localhost:8000--base-path: Base path for the SSE/streamable-http server. /healthz and /metrics are always served at the server root, not under this prefix — they're internal-only endpoints for probes and scrapers, and keeping them off the application prefix makes it easier to expose the API through a reverse proxy without also exposing them--endpoint-path: Endpoint path for the streamable-http server, appended to --base-path - default: /mcp--server-name: Server name used in the MCP handshake and OTel service.name - default: mcp-grafana. Overrides GRAFANA_MCP_SERVER_NAME env var--instructions-append: Text appended to the server instructions returned to MCP clients on initialize, so every connecting agent sees it[!NOTE] Over SSE, per-request headers do not reach tool calls:
X-Grafana-Service-Account-Token/X-Grafana-API-Key,X-Grafana-Org-Id, and headers listed inGRAFANA_FORWARD_HEADERShave no effect, tool calls use the server's environment credentials, andX-Grafana-URLoverrides do not work. Use streamable-http when each caller needs its own Grafana URL, credentials, or organization.
HTTP Transport Security (SSE / streamable-http only):
Host/Origin validation is enforced on every route on the MCP listener — /sse, /mcp, and /healthz / /metrics when they share that listener — so a DNS-rebinding browser cannot reach any of them. Stdio transport is unaffected. --healthz-address and --metrics-address start a separate listener that is not wrapped.
--allowed-hosts: Comma-separated allowlist of Host header values. Defaults to loopback variants of --address (e.g. localhost:8000,127.0.0.1:8000,[::1]:8000). A value that parses to empty (unset, ,, ,, etc.) also falls back to the defaults so a typo cannot silently disable the check. Requests with a Host header outside the allowlist are rejected with 403. Pass * to disable Host validation — only safe when a trusted reverse proxy validates Host. K8s httpGet probes and external /metrics scrapes will need either an explicit hostname in this list, *, a tcpSocket probe, or a separate port (--healthz-address / --metrics-address).--allowed-origins: Comma-separated allowlist of Origin header values. Empty by default — any request that carries an Origin header is rejected (browsers always send one for cross-origin requests, and no browser should be calling this server directly). Set to an explicit list to permit browser-based clients, or * to disable the check.--allow-grafana-url-override: Enable X-Grafana-URL selection. Falls back to GRAFANA_ALLOW_URL_OVERRIDE; disabled by default. Without an allowlist, callers can select any HTTP(S) URL the server can reach.--allowed-grafana-urls: Optional comma-separated exact Grafana base URL allowlist for URL overrides. Falls back to GRAFANA_ALLOWED_URLS. Requires --allow-grafana-url-override; an explicit empty flag disables an inherited list.Caller Authentication (SSE / streamable-http only):
Optionally require MCP clients to authenticate to the server. This is separate from the credentials the server uses to reach Grafana. Stdio is unaffected.
--server-auth-token: Bearer token callers must send as Authorization: Bearer <token>. Falls back to the MCP_GRAFANA_SERVER_TOKEN environment variable. When set, requests without a valid token are rejected with 401 before any tool runs. Prefer the env var so the secret isn't visible in the process arguments.Caller authentication is enforced only when --server-auth-token is set. When it isn't and the server binds a non-loopback address, the server starts but logs a security error — emitted at the error log level so it isn't hidden by --log-level (loopback and stdio are unaffected); a future major release will make that a startup error. Use TLS (or TLS termination) whenever caller auth is enabled on a non-loopback address. When caller auth is enabled, the validated Authorization header is stripped before requests reach Grafana; combining --server-auth-token with GRAFANA_FORWARD_HEADERS=Authorization is rejected at startup.
Grafana URL overrides (streamable-http only):
[!WARNING] URL overrides let MCP callers select outbound HTTP(S) destinations. An allowlist limits URLs but does not authenticate callers or bind tokens to targets.
Deploy behind an authenticating proxy that authorizes each target, replaces client-supplied URL and token headers, and supplies the matching token. Restrict the server's outbound network access to approved destinations.
Without an allowlist, a fake request token can cause requests to any reachable HTTP(S) service, including internal and metadata services.
Set GRAFANA_ALLOW_URL_OVERRIDE=true (or --allow-grafana-url-override) to enable selection for a large fleet. To restrict destinations, also set GRAFANA_ALLOWED_URLS=https://one.example.com,https://two.example.com/grafana (or --allowed-grafana-urls).
Send these headers on each MCP request that selects a target:
X-Grafana-URL: https://one.example.com
X-Grafana-Service-Account-Token: <token for one.example.com>If --server-auth-token is configured, also send Authorization: Bearer <MCP caller token>. This authenticates to the MCP server and is separate from X-Grafana-Service-Account-Token, which is for the selected Grafana instance. Your proxy can send a different Grafana token for each instance; the server never shares one configured token across them. The deprecated X-Grafana-API-Key header also works. A URL header without a request Grafana token is rejected. Use TLS for incoming requests because they carry tokens.
The allowlist matches exact base URLs, including scheme, port, and path; wildcards are not supported. Grafana authentication is not an SSRF defense.
For a selected URL, the server does not use GRAFANA_SERVICE_ACCOUNT_TOKEN, GRAFANA_SERVICE_ACCOUNT_TOKEN_FILE, GRAFANA_API_KEY, environment basic authentication, GRAFANA_EXTRA_HEADERS, or client certificates. TLS verification remains enabled even if --tls-skip-verify is set; a configured CA file still applies. Headers explicitly forwarded from that request still apply. Redirects and other Grafana API requests outside the selected base URL are blocked. Requests without X-Grafana-URL retain the usual GRAFANA_URL and environment credential behavior. This option applies to streamable HTTP only. It does not work over SSE, which does not pass per-request headers to tool calls; a selected URL there is used without the caller's token, so the calls fail.
Debug and Logging:
--debug: Enable debug mode for detailed HTTP request/response logging--log-level: Log level (debug, info, warn, error) - default: infoGrafana Client Options:
--grafana-timeout: Time limit for requests made by the Grafana client. Accepts Go duration strings (e.g., 10s, 500ms) - default: 10s--allow-cross-origin-redirects: Allow outbound Grafana clients to follow redirects to a different scheme, host, or port. Defaults to false; GRAFANA_ALLOW_CROSS_ORIGIN_REDIRECTS is the environment fallback. Enabling this can send Grafana credentials to the redirect target. Request-selected Grafana URLs remain pinned to their selected target.--include-args-in-spans: Include tool call arguments in OpenTelemetry spans. Only enable in non-production environments or when arguments are known not to contain PII - default: falseObservability:
--metrics: Enable Prometheus metrics endpoint at /metrics--metrics-address: Separate address for metrics server (e.g., :9090). If empty, metrics are served on the main server--healthz-address: Separate address for /healthz (e.g., :8080). If empty, /healthz is served on the main server. Shares a listener with --metrics-address when the two addresses match. Side listeners skip Host/Origin validation.--slow-request-threshold: Log an event when any MCP request (tool invocation, list, resource read, etc.) takes longer than this duration. Accepts Go duration strings (e.g., 500ms, 5s). Default 0 disables slow-request logging. See the Slow-request logging section.--slow-request-log-level: Log level for slow-request events (info or warn) - default: warn.Anonymous Usage Statistics:
--usage-stats: Anonymous usage statistics reporting: enabled, disabled, or log (print the report that would be sent to stderr and send nothing). Overrides the GRAFANA_USAGE_STATS env var, which in turn overrides DO_NOT_TRACK; any unrecognised value disables reporting. See the Anonymous usage statistics section.Tool Configuration:
--enabled-tools: Comma-separated list of enabled categories - default: all categories except admin, agento11y, assistant, athena, clickhouse, cloudlogging, cloudwatch, elasticsearch, examples, graphite, quickwit, runpanelquery, and snowflake. To enable disabled categories, add them to the list (e.g., "search,datasource,...,snowflake")--max-loki-log-limit: Maximum number of log lines returned per query_loki_logs call - default: 100. Note: Set this at least 1 below Loki's server-side max_entries_limit_per_query to allow truncation detection (the tool requests limit+1 internally to detect if more data exists).--loki-guardrail-mode: Loki query cost guardrail for query_loki_logs - default: off. Loki does not enforce max_query_bytes_read on log queries without a line filter, so a broad selector over a wide range can scan terabytes; the guardrail requires a selective stream selector, caps the effective time range (including range-vector durations like [30d]), and pre-checks Loki's index/stats byte estimate before running the query. shadow logs queries that would be blocked but lets them run (it still pays the index/stats round trip); enforce rejects them with rewrite guidance the LLM can act on. On VictoriaLogs the guardrail applies only to selector-shaped ({...}) queries — when no selector parses (the normal brace-less LogsQL shape), the query passes through entirely, and the byte-budget check never applies (no cheap index estimate). Env fallback: GRAFANA_LOKI_GUARDRAIL_MODE.--loki-guardrail-max-bytes: Maximum bytes a single query_loki_logs call may scan, estimated via Loki's index/stats API - default: 107374182400 (100 GiB). 0 disables the byte-budget check. Env fallback: GRAFANA_LOKI_GUARDRAIL_MAX_BYTES.--loki-guardrail-max-range: Maximum effective time range for a single query_loki_logs call, including range-vector durations - default: 24h. Accepts Go duration strings. 0 disables the range check. Env fallback: GRAFANA_LOKI_GUARDRAIL_MAX_RANGE.--loki-enforced-matchers: LogQL label matchers AND-ed into every native-Loki query to restrict which log streams can be read (e.g. environment=~"prod|staging"). Requires --disable-api. See Loki query enforcement.--loki-label-enumeration-fallback: What the label-enumeration tools do when negative enforced matchers can't scope them: reject (default) or unfiltered. See Loki query enforcement.--disable-search: Disable search tools--disable-datasource: Disable datasource tools--disable-incident: Disable incident tools--disable-prometheus: Disable prometheus tools--disable-write: Disable write tools (create/update operations)--disable-query: Disable query tools (tools that execute a query against a datasource); metadata and discovery tools stay available--enable-query: Keep the raw-SQL query tools (query_sql, query_influxdb) registered even under --disable-write. Equivalent to --enable-write-tools=query_sql,query_influxdb; kept as a shorthand for that common case.--enable-write-tools: Comma separated list of individual tool names to keep registered even under --disable-write, for tools whose write behavior is scoped enough to opt back in independently. Has no effect on a tool whose whole category is disabled. For example, --enable-write-tools=generate_deeplink keeps URL shortening (shorten=true) working under --disable-write.--disable-loki: Disable loki tools--disable-elasticsearch: Disable elasticsearch and opensearch tools--disable-quickwit: Disable quickwit tools--disable-influxdb: Disable InfluxDB tools--disable-alerting: Disable alerting tools--disable-dashboard: Disable dashboard tools--disable-oncall: Disable oncall tools--disable-asserts: Disable asserts tools--disable-admin: Disable admin tools--disable-pyroscope: Disable pyroscope tools--disable-navigation: Disable navigation tools--disable-rendering: Disable rendering tools (panel/dashboard image export)--disable-snapshot: Disable snapshot tools--disable-cloudwatch: Disable CloudWatch tools--disable-cloudlogging: Disable Google Cloud Logging tools--disable-examples: Disable query examples tools--disable-sql: Disable SQL datasource tools (ClickHouse, Snowflake, Athena, MySQL, PostgreSQL, MSSQL). Aliases --disable-clickhouse, --disable-snowflake, --disable-athena also work.--disable-runpanelquery: Disable run panel query tools--disable-graphite: Disable Graphite tools--disable-provisioning: Disable provisioning tools--disable-agento11y: Disable Agent Observability tools--disable-assistant: Disable Grafana Assistant tools--disable-docs: Disable documentation toolsThe --disable-write flag provides a way to run the MCP server in read-only mode, preventing any write operations to your Grafana instance. This is useful for scenarios where you want to provide safe, read-only access such as:
When --disable-write is enabled, the following write operations are disabled:
Dashboard Tools:
update_dashboardFolder Tools:
create_folderIncident Tools:
create_incidentadd_activity_to_incidentupdate_incidentAlerting Tools:
alerting_rules_write (create, update, delete operations)alerting_silences_write (create, update, delete operations)alerting_routing_write (create_contact_point operation)OnCall Tools:
update_alert_groupAnnotation Tools:
create_annotationupdate_annotationdelete_annotationSnapshot Tools:
create_snapshotdelete_snapshotNavigation Tools:
generate_deeplink (shorten=true is ignored and the full URL is returned; pass --enable-write-tools=generate_deeplink to keep URL shortening)Raw-SQL Query Tools:
These execute whatever query you give them without inspecting it, so they can write when the datasource credentials permit it — query_sql will run a DROP TABLE, query_influxdb will run a DELETE. Read-only mode therefore removes them. Pass --enable-query to keep them when the datasource credentials are known to be read-only.
query_sqlquery_influxdbAgent Observability Tools:
agento11y_manage_evaluators (upsert, delete, fork, test evaluator operations)agento11y_manage_eval_rules (create, update, delete, preview rule and guard operations)agento11y_manage_eval_collections (save and delete saved conversations; create, update, delete collections; add and remove collection members)agento11y_manage_experiments (update and cancel experiment operations)agento11y_manage_test_suites (create and update test suites; create and publish versions; upsert and delete test cases)All read operations remain available, allowing you to query dashboards, run PromQL/LogQL queries, list resources, and retrieve data. The query languages that cannot express a write — PromQL, LogQL, TraceQL, the Elasticsearch DSL, Graphite, CloudWatch — keep their query tools in read-only mode; only the raw-SQL ones listed above are removed.
The --disable-query flag removes every tool that executes a query against a datasource, while leaving the metadata and discovery tools in place. This is useful when you want an assistant that can explore what exists — datasources, dashboards, metric names, labels, table schemas — without running potentially expensive or data-revealing queries, for example when the service account has datasources:read but not datasources:query.
It is the strongest of the three query settings, and it wins over --enable-query:
| Flags | Safe query tools (query_prometheus, query_loki_logs, run_panel_query, …) | Raw-SQL query tools (query_sql, query_influxdb) |
|---|---|---|
| (none) | registered | registered |
--disable-write | registered | not registered |
--disable-write --enable-query | registered | registered |
--disable-query | not registered | not registered |
--disable-query --enable-query | not registered | not registered |
When --disable-query is enabled, the following tools are not registered:
Prometheus Tools:
query_prometheusquery_prometheus_histogramLoki Tools:
query_loki_logsquery_loki_patternsquery_loki_stats and analyze_loki_labels stay registered: both send a selector to the datasource, but they read the index and return stream, chunk, and byte counts rather than log content.
Elasticsearch/OpenSearch and Quickwit Tools:
query_elasticsearchquery_quickwitInfluxDB Tools (also removed by --disable-write, see above):
query_influxdbSQL Datasource Tools (also removed by --disable-write, see above):
query_sqlGraphite Tools:
query_graphitequery_graphite_densityCloudWatch Tools:
query_cloudwatchGoogle Cloud Logging Tools:
query_cloud_loggingPyroscope Tools:
query_pyroscopeRun Panel Query Tools:
run_panel_queryThe elasticsearch, quickwit, influxdb, and runpanelquery categories contain nothing else, so they register no tools at all when queries are disabled. The sibling tools in every other category — list_prometheus_metric_names, list_loki_label_values, describe_sql_table, list_cloudwatch_metrics, list_cloud_logging_projects, and so on — remain available.
Note that --disable-query gates the query tools and the grafana_api_request POST-to-/api/ds/query path, but does not police every route to a datasource. In read-only mode, grafana_api_request allows POST to /api/ds/query only when query tools are enabled (same gate as the raw-SQL tools — blocked by --disable-write unless --enable-query overrides). get_panel_image, which renders a panel server-side, is unaffected.
Client TLS Configuration (for Grafana connections):
--tls-cert-file: Path to TLS certificate file for client authentication--tls-key-file: Path to TLS private key file for client authentication--tls-ca-file: Path to TLS CA certificate file for server verification--tls-skip-verify: Skip TLS certificate verification (insecure)Server TLS Configuration (streamable-http transport only):
--server.tls-cert-file: Path to TLS certificate file for server HTTPS--server.tls-key-file: Path to TLS private key file for server HTTPSThis MCP server works with both local Grafana instances and Grafana Cloud. For Grafana Cloud, use your instance URL (e.g., https://myinstance.grafana.net) instead of http://localhost:3000 in the configuration examples below.
If using service account token authentication, create a service account in Grafana with enough permissions to use the tools you want to use,
generate a service account token, and copy it to the clipboard for use in the configuration file.
Follow the Grafana service account documentation for details on creating service account tokens.
Tip: If you're not comfortable configuring fine-grained RBAC scopes, a simpler (but less restrictive) option is to assign the built-in Editor role to the service account. This grants broad read/write access that covers most MCP server operations — use it when convenience outweighs strict least-privilege requirements.
Note: The environment variable
GRAFANA_API_KEYis deprecated and will be removed in a future version. Please migrate to usingGRAFANA_SERVICE_ACCOUNT_TOKENinstead. The old variable name will continue to work for backward compatibility but will show deprecation warnings.
Instead of passing the token inline via GRAFANA_SERVICE_ACCOUNT_TOKEN, you can point GRAFANA_SERVICE_ACCOUNT_TOKEN_FILE at a file path that contains the token. The file is read fresh on every request, so rotated tokens are picked up automatically without restarting the server.
This is particularly useful in Kubernetes, where a Secret mounted as a volume is updated in place when the underlying Secret changes (typically within ~1 minute). Combined with the per-request client cache — which is keyed on the token value — a rotated token transparently produces a new client with no pod restart and no downtime:
env:
- name: GRAFANA_SERVICE_ACCOUNT_TOKEN_FILE
value: /var/run/secrets/grafana/token
volumeMounts:
- name: grafana-token
mountPath: /var/run/secrets/grafana
readOnly: true
volumes:
- name: grafana-token
secret:
secretName: grafana-mcp-tokenSurrounding whitespace (including a trailing newline) is trimmed from the file contents. If both GRAFANA_SERVICE_ACCOUNT_TOKEN and GRAFANA_SERVICE_ACCOUNT_TOKEN_FILE are set, the inline token takes precedence.
You can specify which organization to interact with using either:
GRAFANA_ORG_ID to the numeric organization IDX-Grafana-Org-Id when using the streamable HTTP transport (header takes precedence over environment variable - meaning you can set a default org as well).When an organization ID is provided, the MCP server will set the X-Grafana-Org-Id header on all requests to Grafana, ensuring that operations are performed within the specified organization context.
The options above fix the organization for the whole connection. To let a single connection target different organizations per tool call, start the server with the --dynamic-multi-org flag. This is off by default.
When enabled, every tool accepts an optional orgId argument that overrides the connection's organization for that call (driving both the X-Grafana-Org-Id header and, for app-platform APIs, the resolved Kubernetes namespace). Proxied datasource tools are additionally discovered across every organization the credential can access. Calls that omit orgId use the connection's default organization.
This only works for credentials that belong to more than one organization (e.g. a user or on-behalf-of identity); a service-account token remains bound to its single organization. Use the user_info tool to discover which orgId values are valid.
Example with organization ID:
{
"mcpServers": {
"grafana": {
"command": "mcp-grafana",
"args": [],
"env": {
"GRAFANA_URL": "http://localhost:3000",
"GRAFANA_USERNAME": "<your username>",
"GRAFANA_PASSWORD": "<your password>",
"GRAFANA_ORG_ID": "2"
}
}
}
}You can add arbitrary HTTP headers to all Grafana API requests using the GRAFANA_EXTRA_HEADERS environment variable. The value should be a JSON object mapping header names to values.
Example with custom headers:
{
"mcpServers": {
"grafana": {
"command": "mcp-grafana",
"args": [],
"env": {
"GRAFANA_URL": "http://localhost:3000",
"GRAFANA_SERVICE_ACCOUNT_TOKEN": "<your token>",
"GRAFANA_EXTRA_HEADERS": "{\"X-Custom-Header\": \"custom-value\", \"X-Tenant-ID\": \"tenant-123\"}"
}
}
}
}You can route all requests this server makes to Grafana through a SOCKS5 proxy using the GRAFANA_SOCKS5_PROXY environment variable. The proxy is scoped to this server's Grafana traffic: it does not modify the global HTTP_PROXY/HTTPS_PROXY variables, and when set it overrides their proxy selection for Grafana transports only, without affecting other MCP servers or your shell session. When unset, behavior is unchanged.
The URL must use the socks5:// or socks5h:// scheme (Go treats them identically: hostname resolution is delegated to the proxy) and may include credentials, e.g. socks5://user:[email protected]:1080.
Example:
{
"mcpServers": {
"grafana": {
"command": "mcp-grafana",
"args": [],
"env": {
"GRAFANA_URL": "http://localhost:3000",
"GRAFANA_SERVICE_ACCOUNT_TOKEN": "<your token>",
"GRAFANA_SOCKS5_PROXY": "socks5://127.0.0.1:1080"
}
}
}
}An invalid proxy URL is a startup error, and if building a proxied connection fails at runtime the server fails closed rather than silently sending Grafana traffic directly.
When the MCP server runs behind a gateway or reverse proxy that handles SSO (e.g. an AWS ALB with OIDC), each user's session cookie must reach Grafana so it can associate the request with the authenticated user. The GRAFANA_FORWARD_HEADERS environment variable enables this by specifying a comma-separated allowlist of header names to copy from the incoming HTTP request to every outbound Grafana API request.
This only applies when using the streamable-http (-t streamable-http) transport. It has no effect in stdio or SSE mode.
Example: forward the session cookie
{
"env": {
"GRAFANA_URL": "https://grafana.internal",
"GRAFANA_SERVICE_ACCOUNT_TOKEN": "<your token>",
"GRAFANA_FORWARD_HEADERS": "Cookie"
}
}You can forward multiple headers by separating them with commas:
GRAFANA_FORWARD_HEADERS=Cookie,X-Session-IdForwarded headers are merged with any headers defined in GRAFANA_EXTRA_HEADERS. If a header name appears in both, the value from the incoming request takes precedence for that request.
Trace context headers (traceparent, tracestate, baggage) are the exception: the server propagates trace context itself, so a forwarded value never overrides the one it injects. See observability.
You have several options to install mcp-grafana:
uvx (recommended): If you have uv installed, no extra setup is needed — uvx will automatically download and run the server:
uvx mcp-grafanaDocker image: Use the pre-built Docker image from Docker Hub.
Important: The Docker image's entrypoint is configured to run the MCP server in SSE mode by default, but most users will want to use STDIO mode for direct integration with AI assistants like Claude Desktop:
-t stdio and include the -i flag to keep stdin open:docker pull grafana/mcp-grafana
# For local Grafana:
docker run --rm -i -e GRAFANA_URL=http://localhost:3000 -e GRAFANA_SERVICE_ACCOUNT_TOKEN=<your service account token> grafana/mcp-grafana -t stdio
# For Grafana Cloud:
docker run --rm -i -e GRAFANA_URL=https://myinstance.grafana.net -e GRAFANA_SERVICE_ACCOUNT_TOKEN=<your service account token> grafana/mcp-grafana -t stdioNote — secure the networked modes: In SSE and streamable-http modes the container binds a non-loopback address (
0.0.0.0:8000). Without a caller token the server starts but logs a security error (at theerrorlog level, so it isn't hidden by--log-level; and it will refuse to start in a future major release). SetMCP_GRAFANA_SERVER_TOKENto require anAuthorization: Bearer <token>from clients (recommended). STDIO mode is unaffected. See Caller Authentication.
-p flag:docker pull grafana/mcp-grafana
docker run --rm -p 8000:8000 -e GRAFANA_URL=http://localhost:3000 -e GRAFANA_SERVICE_ACCOUNT_TOKEN=<your service account token> -e MCP_GRAFANA_SERVER_TOKEN=<caller auth token> grafana/mcp-grafana-p flag: For this mode you must explicitly override the default with -t streamable-httpdocker pull grafana/mcp-grafana
docker run --rm -p 8000:8000 -e GRAFANA_URL=http://localhost:3000 -e GRAFANA_SERVICE_ACCOUNT_TOKEN=<your service account token> -e MCP_GRAFANA_SERVER_TOKEN=<caller auth token> grafana/mcp-grafana -t streamable-httpFor HTTPS streamable HTTP mode with server TLS certificates:
docker pull grafana/mcp-grafana
docker run --rm -p 8443:8443 \
-v /path/to/certs:/certs:ro \
-e GRAFANA_URL=http://localhost:3000 \
-e GRAFANA_SERVICE_ACCOUNT_TOKEN=<your service account token> \
-e MCP_GRAFANA_SERVER_TOKEN=<caller auth token> \
grafana/mcp-grafana \
-t streamable-http \
-addr :8443 \
--server.tls-cert-file /certs/server.crt \
--server.tls-key-file /certs/server.keyDownload binary: Download the latest release of mcp-grafana from the releases page and place it in your $PATH.
Build from source: If you have a Go toolchain installed you can also build and install it from source, using the GOBIN environment variable
to specify the directory where the binary should be installed. This should also be in your $PATH.
GOBIN="$HOME/go/bin" go install github.com/grafana/mcp-grafana/v2/cmd/mcp-grafana@latestDeploy to Kubernetes using Helm: use the Helm chart from the Grafana helm-charts repository
helm repo add grafana https://grafana.github.io/helm-charts
helm install --set grafana.apiKey=<Grafana_ApiKey> --set grafana.url=<GrafanaUrl> my-release grafana/grafana-mcpAdd the server configuration to your client configuration file. For example, for Claude Desktop:
If using uvx:
{
"mcpServers": {
"grafana": {
"command": "uvx",
"args": ["mcp-grafana"],
"env": {
"GRAFANA_URL": "http://localhost:3000",
"GRAFANA_SERVICE_ACCOUNT_TOKEN": "<your service account token>"
}
}
}
}If using the binary:
{
"mcpServers": {
"grafana": {
"command": "mcp-grafana",
"args": [],
"env": {
"GRAFANA_URL": "http://localhost:3000", // Or "https://myinstance.grafana.net" for Grafana Cloud
"GRAFANA_SERVICE_ACCOUNT_TOKEN": "<your service account token>",
// If using username/password authentication
"GRAFANA_USERNAME": "<your username>",
"GRAFANA_PASSWORD": "<your password>",
// Optional: specify organization ID for multi-org support
"GRAFANA_ORG_ID": "1"
}
}
}
}Note: if you see
Error: spawn mcp-grafana ENOENTin Claude Desktop, you need to specify the full path tomcp-grafana.
If using Docker:
{
"mcpServers": {
"grafana": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-e",
"GRAFANA_URL",
"-e",
"GRAFANA_SERVICE_ACCOUNT_TOKEN",
"grafana/mcp-grafana",
"-t",
"stdio"
],
"env": {
"GRAFANA_URL": "http://localhost:3000", // Or "https://myinstance.grafana.net" for Grafana Cloud
"GRAFANA_SERVICE_ACCOUNT_TOKEN": "<your service account token>",
// If using username/password authentication
"GRAFANA_USERNAME": "<your username>",
"GRAFANA_PASSWORD": "<your password>",
// Optional: specify organization ID for multi-org support
"GRAFANA_ORG_ID": "1"
}
}
}
}Note: The
-t stdioargument is essential here because it overrides the default SSE mode in the Docker image.
Using VSCode with remote MCP server
If you're using VSCode and running the MCP server in SSE mode (which is the default when using the Docker image without overriding the transport), make sure your .vscode/settings.json includes the following:
"mcp": {
"servers": {
"grafana": {
"type": "sse",
"url": "http://localhost:8000/sse"
}
}
}For HTTPS streamable HTTP mode with server TLS certificates:
"mcp": {
"servers": {
"grafana": {
"type": "sse",
"url": "https://localhost:8443/sse"
}
}
}You can enable debug mode for the Grafana transport by adding the -debug flag to the command. This will provide detailed logging of HTTP requests and responses between the MCP server and the Grafana API, which can be helpful for troubleshooting.
To use debug mode with the Claude Desktop configuration, update your config as follows:
If using the binary:
{
"mcpServers": {
"grafana": {
"command": "mcp-grafana",
"args": ["-debug"],
"env": {
"GRAFANA_URL": "http://localhost:3000", // Or "https://myinstance.grafana.net" for Grafana Cloud
"GRAFANA_SERVICE_ACCOUNT_TOKEN": "<your service account token>"
}
}
}
}If using Docker:
{
"mcpServers": {
"grafana": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-e",
"GRAFANA_URL",
"-e",
"GRAFANA_SERVICE_ACCOUNT_TOKEN",
"grafana/mcp-grafana",
"-t",
"stdio",
"-debug"
],
"env": {
"GRAFANA_URL": "http://localhost:3000", // Or "https://myinstance.grafana.net" for Grafana Cloud
"GRAFANA_SERVICE_ACCOUNT_TOKEN": "<your service account token>"
}
}
}
}Note: As with the standard configuration, the
-t stdioargument is required to override the default SSE mode in the Docker image.
If your Grafana instance is behind mTLS or requires custom TLS certificates, you can configure the MCP server to use custom certificates. The server supports the following TLS configuration options:
--tls-cert-file: Path to TLS certificate file for client authentication--tls-key-file: Path to TLS private key file for client authentication--tls-ca-file: Path to TLS CA certificate file for server verification--tls-skip-verify: Skip TLS certificate verification (insecure, use only for testing)Example with client certificate authentication:
{
"mcpServers": {
"grafana": {
"command": "mcp-grafana",
"args": [
"--tls-cert-file",
"/path/to/client.crt",
"--tls-key-file",
"/path/to/client.key",
"--tls-ca-file",
"/path/to/ca.crt"
],
"env": {
"GRAFANA_URL": "https://secure-grafana.example.com",
"GRAFANA_SERVICE_ACCOUNT_TOKEN": "<your service account token>"
}
}
}
}Example with Docker:
{
"mcpServers": {
"grafana": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-v",
"/path/to/certs:/certs:ro",
"-e",
"GRAFANA_URL",
"-e",
"GRAFANA_SERVICE_ACCOUNT_TOKEN",
"grafana/mcp-grafana",
"-t",
"stdio",
"--tls-cert-file",
"/certs/client.crt",
"--tls-key-file",
"/certs/client.key",
"--tls-ca-file",
"/certs/ca.crt"
],
"env": {
"GRAFANA_URL": "https://secure-grafana.example.com",
"GRAFANA_SERVICE_ACCOUNT_TOKEN": "<your service account token>"
}
}
}
}The TLS configuration is applied to all HTTP clients used by the MCP server, including:
Direct CLI Usage Examples:
For testing with self-signed certificates:
./mcp-grafana --tls-skip-verify -debugWith client certificate authentication:
./mcp-grafana \
--tls-cert-file /path/to/client.crt \
--tls-key-file /path/to/client.key \
--tls-ca-file /path/to/ca.crt \
-debugWith custom CA certificate only:
./mcp-grafana --tls-ca-file /path/to/ca.crtProgrammatic Usage:
If you're using this library programmatically, you can also create TLS-enabled context functions:
// Using struct literals
tlsConfig := &mcpgrafana.TLSConfig{
CertFile: "/path/to/client.crt",
KeyFile: "/path/to/client.key",
CAFile: "/path/to/ca.crt",
}
grafanaConfig := mcpgrafana.GrafanaConfig{
Debug: true,
TLSConfig: tlsConfig,
}
contextFunc := mcpgrafana.ComposedStdioContextFunc(grafanaConfig)
// Or inline
grafanaConfig := mcpgrafana.GrafanaConfig{
Debug: true,
TLSConfig: &mcpgrafana.TLSConfig{
CertFile: "/path/to/client.crt",
KeyFile: "/path/to/client.key",
CAFile: "/path/to/ca.crt",
},
}
contextFunc := mcpgrafana.ComposedStdioContextFunc(grafanaConfig)URL validation:
When calling NewGrafanaClient directly (stdio or programmatic construction), pre-validate URLs to avoid a reachable panic:
if err := mcpgrafana.ValidateGrafanaURL(urlFromHeader); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
client := mcpgrafana.NewGrafanaClient(ctx, urlFromHeader, apiKey, nil)When using the streamable HTTP transport (-t streamable-http), you can configure the MCP server to serve HTTPS instead of HTTP. This is useful when you need to secure the connection between your MCP client and the server itself.
The server supports the following TLS configuration options for the streamable HTTP transport:
--server.tls-cert-file: Path to TLS certificate file for server HTTPS (required for TLS)--server.tls-key-file: Path to TLS private key file for server HTTPS (required for TLS)Note: These flags are completely separate from the client TLS flags documented above. The client TLS flags configure how the MCP server connects to Grafana, while these server TLS flags configure how clients connect to the MCP server when using streamable HTTP transport.
Example with HTTPS streamable HTTP server:
./mcp-grafana \
-t streamable-http \
--server.tls-cert-file /path/to/server.crt \
--server.tls-key-file /path/to/server.key \
-addr :8443This would start the MCP server on HTTPS port 8443. Clients would then connect to https://localhost:8443/ instead of http://localhost:8000/.
Docker example with server TLS:
docker run --rm -p 8443:8443 \
-v /path/to/certs:/certs:ro \
-e GRAFANA_URL=http://localhost:3000 \
-e GRAFANA_SERVICE_ACCOUNT_TOKEN=<your service account token> \
grafana/mcp-grafana \
-t streamable-http \
-addr :8443 \
--server.tls-cert-file /certs/server.crt \
--server.tls-key-file /certs/server.keyWhen using the SSE (-t sse) or streamable HTTP (-t streamable-http) transports, the MCP server exposes a health check endpoint at /healthz. This endpoint can be used by load balancers, monitoring systems, or orchestration platforms to verify that the server is running and accepting connections.
Endpoint: GET /healthz
Response:
200 OKokExample usage:
# For streamable HTTP or SSE transport on default port
curl http://localhost:8000/healthz
# Probe a side listener while MCP stays on loopback (Kubernetes + sidecar)
./mcp-grafana -t streamable-http --address 127.0.0.1:8000 --healthz-address :8080
curl http://127.0.0.1:8080/healthz
# With --base-path /my-base the MCP routes move under the prefix
# (/my-base/sse, /my-base/mcp), but healthz does not:
curl http://localhost:8000/healthz # 200 ok
curl http://localhost:8000/my-base/healthz # 404Note: The health check endpoint is only available when using SSE or streamable HTTP transports. It is not available when using the stdio transport (-t stdio), as stdio does not expose an HTTP server.
The server can report anonymous usage statistics about itself to Grafana Labs: which tools were called, how many of those calls failed, and how the server is configured. One report covers one server process — not one user and not one conversation — and is sent every 4h plus once on shutdown. Reporting is enabled by default. To opt out, set --usage-stats=disabled, GRAFANA_USAGE_STATS=disabled, or DO_NOT_TRACK=1.
Tool arguments, resource names, queries, log lines, error messages and credentials are never sent. Flags are recorded by name only, never by value, and the Grafana instance is described only as cloud or self_hosted — never by URL, hostname, stack slug or org. Nothing is per user, per session or per client: there is no session identifier on the wire and no way to attribute a tool call to a particular client.
# Turn reporting on
mcp-grafana --usage-stats=enabled
# Turn it off (or GRAFANA_USAGE_STATS=disabled)
mcp-grafana --usage-stats=disabled
# Print what would be sent, to stderr, and send nothing
GRAFANA_USAGE_STATS=log mcp-grafanaDO_NOT_TRACK=1 also disables reporting, following the cross-tool DO_NOT_TRACK convention. Only 1 has any effect, it can only disable, and both --usage-stats and GRAFANA_USAGE_STATS override it, so a host that sets it globally can still opt one server back in.
GRAFANA_USAGE_STATS_ENDPOINT changes the destination. It is not an opt-out.
For the full field list, what is never sent, how to read the data and its limitations, see Anonymous usage statistics.
The MCP server supports Prometheus metrics, OpenTelemetry distributed tracing, and OpenTelemetry log export, following the OTel MCP semantic conventions. Tracing and log export are configured via standard OTEL_* environment variables and work with any transport.
Note: mcp-grafana currently only supports the OTLP/gRPC transport for both traces and logs. OTEL_EXPORTER_OTLP_PROTOCOL (and its _TRACES_PROTOCOL / _LOGS_PROTOCOL variants) are not honored — gRPC is used regardless.
When using the SSE or streamable HTTP transports, enable Prometheus metrics with the --metrics flag:
# Metrics served on the main server at /metrics
./mcp-grafana -t streamable-http --metrics
# Metrics served on a separate address
./mcp-grafana -t streamable-http --metrics --metrics-address :9090Available Metrics:
| Metric | Type | Description |
|---|---|---|
mcp_server_operation_duration_seconds | Histogram | Duration of MCP operations (labels: mcp_method_name, gen_ai_tool_name, error_type, network_transport, mcp_protocol_version) |
http_server_request_duration_seconds | Histogram | Duration of HTTP server requests (from otelhttp) |
Note: Metrics are only available when using SSE or streamable HTTP transports. They are not available with the stdio transport.
When the Loki cost guardrail (--loki-guardrail-mode) is enabled, four more counters record its decisions:
| Metric | Type | Description |
|---|---|---|
mcp_loki_guardrail_admitted_total | Counter | Queries that passed every enabled check (labels: backend) |
mcp_loki_guardrail_would_block_total | Counter | Queries that failed a check in shadow mode and ran anyway (labels: backend, reason) |
mcp_loki_guardrail_blocked_total | Counter | Queries rejected in enforce mode (labels: backend, reason) |
mcp_loki_guardrail_fail_open_total | Counter | Queries the guardrail could not evaluate and admitted (labels: backend, cause) |
reason is one of selector, range, bytes; cause is one of unparseable, estimate_failed; backend is one of loki, victorialogs, unknown. A query that trips several checks is counted once, labelled with the check that ran first (selector, then range, then bytes), so the four counters partition the guarded population. See Observability for how to read them during a shadow → enforce rollout.
Library embedders should set GrafanaConfig.MeterProvider (the metrics counterpart of GrafanaConfig.Logger): the guardrail runs inside a tool handler, so it has no constructor option, and a process that installs a noop global MeterProvider would otherwise drop every recording.
The --slow-request-threshold flag emits a structured log event whenever an MCP request (tool invocation, list, resource read, etc.) exceeds the given duration. It is useful for diagnosing slow queries and tool calls without drowning in the full debug log.
# Warn on any request slower than 500ms (works on all transports)
./mcp-grafana -t streamable-http --slow-request-threshold 500ms
# Same thing on stdio (the feature is transport-agnostic, unlike --metrics)
./mcp-grafana -t stdio --slow-request-threshold 500ms
# Log at INFO level instead of WARN (useful during investigation)
./mcp-grafana -t streamable-http --slow-request-threshold 500ms --slow-request-log-level infoThe log event carries these structured attributes:
| Attribute | Description |
|---|---|
mcp.method | The MCP method (e.g., tools/call, tools/list, resources/read) |
duration | Observed request duration |
threshold | Configured threshold |
tool | Tool name (only present for tools/call methods) |
error | Error value, when the request failed (best-effort context; content is controlled by upstream error wrapping) |
error.type | Bounded-cardinality error classification (_OTHER for untyped errors) |
Slow-request logging works on all transports (including stdio) and does not require --metrics. The default threshold of 0 disables it entirely. Proxied tools flow through tools/call and are covered automatically.
Distributed tracing is configured via standard OTEL_* environment variables and works independently of the --metrics flag. When OTEL_EXPORTER_OTLP_ENDPOINT (or the signal-specific OTEL_EXPORTER_OTLP_TRACES_ENDPOINT) is set, the server exports traces via OTLP/gRPC:
# Send traces to a local Tempo instance
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 \
OTEL_EXPORTER_OTLP_INSECURE=true \
./mcp-grafana -t streamable-http
# Send traces to Grafana Cloud with authentication
OTEL_EXPORTER_OTLP_ENDPOINT=https://tempo-us-central1.grafana.net:443 \
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic ..." \
./mcp-grafana -t streamable-httpTool call spans follow semconv naming (tools/call <tool_name>) and include attributes like gen_ai.tool.name, mcp.method.name, and mcp.session.id. The server also supports W3C trace context propagation from the _meta field of tool call requests.
When OTEL_EXPORTER_OTLP_ENDPOINT (or the signal-specific OTEL_EXPORTER_OTLP_LOGS_ENDPOINT) is set, the server also exports structured logs via OTLP/gRPC in addition to the existing plain-text stderr output. The otelslog bridge automatically attaches trace_id and span_id from the active span, so log records correlate with the traces the server already emits.
Traces and logs resolve their endpoints independently, so the two signals can be enabled separately: setting only OTEL_EXPORTER_OTLP_TRACES_ENDPOINT enables tracing without log export, setting only OTEL_EXPORTER_OTLP_LOGS_ENDPOINT enables log export without tracing, and the generic OTEL_EXPORTER_OTLP_ENDPOINT enables both.
If you use the generic OTEL_EXPORTER_OTLP_ENDPOINT but want to disable log export (e.g. your backend does not support the LogsService), set:
OTEL_LOGS_EXPORTER=noneThis prevents the server from creating an OTLP logs exporter regardless of the endpoint configuration, avoiding errors like unknown service opentelemetry.proto.collector.logs.v1.LogsService.
Stderr logging is unchanged when OTLP logging is enabled; you can continue to rely on container logs or pipe stderr to /dev/null if you prefer.
# Send both logs and traces to a local OTel collector
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 \
OTEL_EXPORTER_OTLP_INSECURE=true \
./mcp-grafana -t streamable-httpThe transport is OTLP/gRPC (default port 4317). Logs can be sent directly to any managed backend that accepts OTLP/gRPC — for example, Grafana Cloud — by pointing OTEL_EXPORTER_OTLP_LOGS_ENDPOINT (or the generic OTEL_EXPORTER_OTLP_ENDPOINT) at the remote gRPC endpoint and supplying auth via OTEL_EXPORTER_OTLP_LOGS_HEADERS (or OTEL_EXPORTER_OTLP_HEADERS), mirroring the tracing example above. A local OTel collector is optional — useful for fan-out, batching, or multi-backend routing, but not required.
The signal-specific variants OTEL_EXPORTER_OTLP_LOGS_ENDPOINT, OTEL_EXPORTER_OTLP_LOGS_HEADERS, OTEL_EXPORTER_OTLP_LOGS_INSECURE, OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE, OTEL_EXPORTER_OTLP_LOGS_TIMEOUT, and OTEL_EXPORTER_OTLP_LOGS_COMPRESSION are honored and override their generic OTEL_EXPORTER_OTLP_* counterparts — see the OTel exporter spec for the full list and precedence rules.
If the configured collector is unreachable, log records are buffered in memory (default queue: 2048) and the oldest records are dropped once the queue fills. The process continues without blocking the service. Configure a local OTel collector if you need lossless buffering during outages.
Logs are also exported under the stdio transport, which makes it easy to centralize logs from local mcp-grafana instances invoked by IDE clients.
Docker example with metrics, tracing, and logs:
docker run --rm -p 8000:8000 \
-e GRAFANA_URL=http://localhost:3000 \
-e GRAFANA_SERVICE_ACCOUNT_TOKEN=<your token> \
-e OTEL_EXPORTER_OTLP_ENDPOINT=http://tempo:4317 \
-e OTEL_EXPORTER_OTLP_INSECURE=true \
grafana/mcp-grafana \
-t streamable-http --metrics--loki-enforced-matchers lets an operator restrict which Loki log streams the
server can ever read, by AND-ing a fixed set of LogQL label matchers into every
native-Loki query the server issues. This is useful when a datasource contains
streams that must not be exposed (e.g. logs that may carry sensitive
information) but you cannot restrict access at the Grafana or Loki layer (OSS has
no per-datasource or per-user label access control).
# Only ever read prod/staging environments (allowlist)
./mcp-grafana --loki-enforced-matchers 'environment=~"prod|staging"' --disable-api
# Never read the vault or payments namespaces (exclusion)
./mcp-grafana --loki-enforced-matchers 'namespace!~"vault|payments"' --disable-apiHow it works:
{namespace="vault"} under an exclusion) simply
returns nothing.query_loki_logs, query_loki_stats, query_loki_patterns,
list_loki_label_names, and list_loki_label_values.--loki-label-enumeration-fallback (reject by default, or unfiltered
to allow unscoped enumeration of label metadata — log lines are never
exposed). Positive/allowlist matchers are not affected.[!IMPORTANT] Enforcement only applies to the Loki query tools. Other tools can reach Loki log data through paths that never touch the enforced backend, so for the restriction to actually hold you must also disable them:
--disable-api—grafana_api_requestcan query the Loki datasource proxy directly (full bypass).--disable-rendering—get_panel_imagerenders Loki panels server-side, producing images with unrestricted log lines.--disable-assistant—ask_assistantdelegates to Grafana Assistant, which reads Loki server-side across all streams. Only registered when write tools are enabled, so--disable-writecloses it too.The server logs a warning at startup naming each of these that is still enabled.
run_panel_queryis safe (it reuses the enforced query path). Tempo tools query traces, not Loki logs, so they are not a bypass. Dashboard snapshots (--disable-snapshot) can also embed log-panel data captured outside enforcement.
If you encounter the following error when using datasource-related tools:
get datasource by uid : [GET /datasources/uid/{uid}][400] getDataSourceByUidBadRequest {"message":"id is invalid"}This typically indicates that you are using a Grafana version earlier than 9.0. The /datasources/uid/{uid} API endpoint was introduced in Grafana 9.0, and datasource operations will fail on earlier versions.
Solution: Upgrade your Grafana instance to version 9.0 or later to resolve this issue.
Contributions are welcome! Please read CONTRIBUTING.md first — it covers what belongs in this server and how to propose it.
If you're adding a new tool, please open a tool proposal before writing the code. Every default-on tool is sent to the model on every request by every user, so we'd rather discuss the idea than decline a finished pull request. Bug fixes, docs, tests and new parameters on existing tools need no proposal — just send a PR.
This project is written in Go. Tool versions and dev tasks live in mise.toml: install mise, run mise install to get the pinned tools, and mise tasks to list the tasks.
To run the server locally in STDIO mode (which is the default for local development), use:
mise run runTo run the server locally in SSE mode, use:
go run ./cmd/mcp-grafana --transport sseYou can also run the server using the SSE transport inside a custom built Docker image. Just like the published Docker image, this custom image's entrypoint defaults to SSE mode. To build the image, use:
mise run build-imageAnd to run the image in SSE mode (the default), use:
docker run -it --rm -p 8000:8000 mcp-grafana:latestIf you need to run it in STDIO mode instead, override the transport setting:
docker run -it --rm mcp-grafana:latest -t stdioThere are three types of tests available:
mise run test-unitYou can also run unit tests with:
mise run testmise run test-integrationmise run test-cloudNote: Cloud tests are automatically configured in CI. For local development, you'll need to set up your own Grafana Cloud instance and credentials.
More comprehensive integration tests will require a Grafana instance to be running locally on port 3000; you can start one with Docker Compose:
docker-compose up -dIf you're adding more tools, please add integration tests for them. The existing tests should be a good starting point.
To lint the code, run:
mise run lintThis includes a custom linter that checks for unescaped commas in jsonschema struct tags. The commas in description fields must be escaped with \\, to prevent silent truncation. You can run just this linter with:
mise run lint-jsonschemaSee the JSONSchema Linter documentation for more details.
This project is licensed under the Apache License, Version 2.0.
Pick your client and paste the snippet. Each one is the same server, written the way that client expects it.
claude mcp add grafana -- uvx mcp-grafana{
"mcpServers": {
"grafana": {
"env": {
"GRAFANA_URL": "",
"GRAFANA_SERVICE_ACCOUNT_TOKEN": ""
},
"args": [
"mcp-grafana"
],
"command": "uvx"
}
}
}code --add-mcp '{"name":"grafana","env":{"GRAFANA_URL":"","GRAFANA_SERVICE_ACCOUNT_TOKEN":""},"args":["mcp-grafana"],"command":"uvx"}'[mcp_servers.grafana]
command = "uvx"
args = ["mcp-grafana"]Runs locally on your device. Your client starts the server itself, so nothing has to be hosted.
Paste this prompt into your agent. It reads this page and does the setup for you.
Read https://aiagentslisting.com/mcp/grafana-mcp-server to learn what the "Grafana MCP Server" MCP server does and how to install it. Add it to my coding agent's MCP configuration as documented on that page, then confirm the server connects and list the tools it exposes.Agents can also browse this directory over MCP at https://aiagentslisting.com/api/mcp
uvx mcp-grafanadocker run --rm -i -e GRAFANA_URL=http://localhost:3000 -e GRAFANA_SERVICE_ACCOUNT_TOKEN=<your service account token> grafana/mcp-grafana -t stdio
docker run --rm -i -e GRAFANA_URL=https://myinstance.grafana.net -e GRAFANA_SERVICE_ACCOUNT_TOKEN=<your service account token> grafana/mcp-grafana -t stdio
docker run --rm -p 8000:8000 -e GRAFANA_URL=http://localhost:3000 -e GRAFANA_SERVICE_ACCOUNT_TOKEN=<your service account token> -e MCP_GRAFANA_SERVER_TOKEN=<caller auth token> grafana/mcp-grafana
docker run --rm -p 8000:8000 -e GRAFANA_URL=http://localhost:3000 -e GRAFANA_SERVICE_ACCOUNT_TOKEN=<your service account token> -e MCP_GRAFANA_SERVER_TOKEN=<caller auth token> grafana/mcp-grafana -t streamable-http
docker run --rm -p 8443:8443This server runs locally, so we can't read its tool list over the web yet.
We could not run this server: it ships no npx package for our sandbox and no public endpoint. The four checks that need a live server are left out, and the grade tops out at B until one exists.
Maintain this server? Claiming proves you own the listing and earns the last 4 points.
Claim this listingPaste this line near the top of your repository's README. The badge always renders the current score.
[](https://aiagentslisting.com/mcp/grafana-mcp-server)Model Context Protocol (MCP) server for Opik, the open-source LLM observability and evaluation platf
Daily keyword rankings, installs, ratings, competitor data, and listing changes from Chrome Web Stor
WebScore is a free website scanner & checker — scan any site for SEO, performance, security and acce
No tagged releases on record.
Connect to the AI Agents Listing MCP server at https://aiagentslisting.com/api/mcp using the HTTP transport and complete the sign-in when it asks. Then call the submit_review tool for the listing "grafana-mcp-server" with a rating from 1 to 5 and a short note on what worked and what did not.No reviews yet
Be the first to share your experience with this tool.
Model Context Protocol (MCP) server for Opik, the open-source LLM observability and evaluation platf
AI & ML Services
Daily keyword rankings, installs, ratings, competitor data, and listing changes from Chrome Web Stor
AI & ML Services
WebScore is a free website scanner & checker — scan any site for SEO, performance, security and acce
AI & ML Services
One email a week. New agents, MCP servers and skills, and what is actually getting traction.