Added
alerting_manage_silencestool (opt-in, read/write-gated) to list, create, and expire Grafana alert silences (#991)update_incidenttool to update fields on an existing incident (#1080)update_alert_grouptool to acknowledge and resolve Grafana OnCall alert groups (#1083)get_alert_groupnow returns the last alert payload for the group, so callers can inspect the triggering alert without a second lookup (#1081)- Agent Observability
agento11y_manage_experimentsandagento11y_manage_test_suitestools, in the opt-inagento11ycategory (#1062) - Compact output format for
query_loki_logs, reducing token usage for large log result sets (#990) - Opt-in Loki query cost guardrail for
query_loki_logs(--loki-guardrail-mode/GRAFANA_LOKI_GUARDRAIL_MODE,offby default, withshadowandenforcemodes). Because Loki query cost is bytes scanned — determined only by the stream selector and time range, not line filters — the guardrail requires a selective stream selector, caps the time range (--loki-guardrail-max-range, default 24h), and pre-checks Loki'sindex/statsbyte estimate against a budget (--loki-guardrail-max-bytes, default 100GiB). Blocked queries return an MCP tool error with rewrite guidance; unparseable queries fail open (#1031) - OpenTelemetry counters recording Loki cost-guardrail decisions (allowed, blocked, failed-open), so operators can observe the guardrail's impact (#1095)
run_panel_querynow supports PostgreSQL (#1112) and MSSQL (#1042) datasources- Datasource resolution falls back to
/api/frontend/settingswhen the datasource metadata API is forbidden, so tools keep working on instances that restrict it (#1015) GrafanaVersion(ctx)exposes the targeted Grafana version to tools, so they can gate behaviour on it instead of inferring capability from API versions (#1091)- Optional
orgIdparameter onget_panel_imageto render a panel for a specific organisation (#903) list_datasourcesnow supports filtering by name (#973)--server-nameflag (andGRAFANA_MCP_SERVER_NAMEenv var) to set a custom MCP server name in the handshake and OTelservice.name, so operators can distinguish multiple instances (#1011)- Scoped SOCKS5 egress proxy via
GRAFANA_SOCKS5_PROXY, routing outbound Grafana traffic through a SOCKS5 proxy (#1119) - An MCP Bundle (
.mcpb) for Claude Desktop is now built and attached on release (#1077)
Changed
- Bumped
mcp-gofrom v0.55.0 to v0.58.0, picking up fixes for tool-filter scans on thetools/callhot path, raw JSON preservation for tool arguments andstructuredContent, schema tags on nested fields, multi-line SSEdatafields, and HEAD requests returning 200. This also inherits mcp-go's new default-on DNS rebinding protection, which returns 403 when a request arrives over a loopback connection with a non-loopbackHostheader — a second check underneathDNSRebindingProtectionMiddlewarethat--allowed-hostscannot loosen. Default deployments are unaffected, sinceDefaultAllowedHostsalready restrictsHostto loopback variants; operators who widen--allowed-hostswhile a same-host reverse proxy forwards over loopback preserving a non-localhostHostshould configure the proxy to rewriteHostto localhost (#1097) tools.Stats.Bytesis nowint64(wasint) so index/stats byte counts cannot overflow on 32-bit platforms; Go API consumers of the exported struct may need a cast (#1031)/api/frontend/settingsis now fetched once per Grafana instance instead of up to three times. The public URL, the Grafana version and the dashboard namespace previously each fetched that endpoint behind a cache of their own, even though a single response carries all three fields.mcpgrafana.GrafanaClientgains aVersionfield populated by the same request that populatesPublicURL, andmcpgrafana.GrafanaVersionprefers it, so a tool holding a client reads the version with no HTTP request at all — previously it cost a blocking round trip on a detached context the caller could not cancel. The namespace keeps a separate org-keyed cache, because Grafana computes it for the requesting org and a URL-keyed entry would serve one org another org's namespace. Failed fetches are still retried rather than cached, but a successful fetch that simply omitsbuildInfois now cached instead of being refetched on every call (#1115)
Fixed
- Closed two gaps in the
GRAFANA_SOCKS5_PROXYegress guarantee. Theinstall_pluginandsearch_plugin_informationtools reached the grafana.com plugin catalog viahttp.DefaultClient, bypassing the configured SOCKS5 proxy entirely; these requests now route through the proxy (carrying no Grafana credentials or forwarded headers) and fail closed when it is misconfigured.NewGrafanaClientnow installs a fail-closed transport instead of panicking when the proxy cannot be applied, matching the OnCall and incident paths, and the per-call fail-closed logic is centralised in one helper (#1121) observability.ToolMetricDimensionsnow bounds themcp.tool.phasemetric label against thetoolMetricDimsallowlist, likemcp.tool.operationandmcp.tool.resource_type. Phase is read from a tool result's_meta, and results proxied from an MCP-enabled datasource come from a remote server rather than from this repo, so the label was unbounded-cardinality in the general case. A tool that does not opt intophasesnow contributes no phase, and an opted-in tool reporting an unexpected value reportsother. Behaviour is unchanged for every in-tree tool:create_datasourceis the only producer, withschemaandcreated(#1094)- Distributed traces are no longer broken over the HTTP transports: the server now installs a global OTel
TextMapPropagator(viaautoprop, honouringOTEL_PROPAGATORS, defaulttracecontext,baggage), so an inboundtraceparentcontinues the caller's trace and outbound Grafana API requests carry one of their own. Previously every hop started a disconnected trace. Trace context forwarded viaGRAFANA_FORWARD_HEADERSno longer overrides the propagated value, which would have cut mcp-grafana out of the middle of the trace (#1084) - Grafana-managed alert rule UIDs are recovered from the internal
__alert_rule_uid__/__alert_rule_namespace_uid__labels when older Grafana responses omit the top-level UID fields; those internal labels are stripped from the returned summary so they don't surface as user labels (#968) - Alert rule matchers are now encoded in the JSON shape Grafana expects, fixing rule create/update requests that Grafana previously rejected (#1111)
run_panel_querynow resolves constant and textbox dashboard variables from their query field, so panels using them return correct results (#1041)- Datasource queries fall back to the legacy proxy on a
401, restoring queries against datasources the metadata proxy rejects (#1022) - URL shortening for navigation deeplinks now sends a relative path, fixing link generation on some deployments (#974)
GRAFANA_URLis normalized where it enters the process (trailing slash trimmed, missing scheme supplied), so the config, API client, and client-cache key all agree on the target. Previously a schemeless value such as127.0.0.1:3000could panic at startup or produce hostless requests (#1034)- Proxied tools auto-wire
SetToolManagerand report a clearer error when the tool manager is nil (#1102) - The session wait when building a proxied tool set is now bounded, so a slow or unavailable datasource can no longer hang tool discovery (#1087)
- Transient proxied-tool discovery/connect failures are retried and connections are established in parallel, making proxied tool startup faster and more resilient (#1071)
- The client cache and session OTel meters are now injectable, so embedders can supply their own instrumentation (#1073)