grafana-unified-mcp
grafana-unified-mcp
하나의 MCP 서버로 여러 Grafana 인스턴스를 관리합니다. 표준 Grafana MCP 서버의 모든 도구를 제공하며, instance라는 추가 인수를 통해 실행할 Grafana를 지정할 수 있습니다.
query_prometheus(instance="tenant-a", expr="up", datasourceUid="...")
search_dashboards(instance="tenant-b", query="login latency")존재 이유
상위 프로젝트 grafana/mcp-grafana는 프로세스 시작 시 GRAFANA_URL을 한 번만 바인딩합니다. 요청마다 X-Grafana-Service-Account-Token을 읽지만 URL은 고정되어 있으며, 이를 재정의하는 데 사용되던 헤더는 이제 명시적으로 비활성화되었습니다. 상위 프로젝트의 validate_url.go에서:
Deprecated: X-Grafana-URL은 더 이상 Grafana 클라이언트를 구성하지 않습니다. 이 미들웨어는 잘못된 형식의 헤더 처리를 유지하기 위해 임시로 보관됩니다.
따라서 하나의 mcp-grafana 프로세스는 오직 하나의 Grafana와만 통신할 수 있습니다. 10개의 Grafana가 있다면 10개의 서버, 모든 클라이언트 설정에 10개의 항목, 그리고 모델이 구분해야 하는 동일한 이름의 10개 도구 세트가 필요합니다.
이 서버는 인스턴스별로 하나의 상위 프로세스를 실행하고 instance 인수에 따라 각 호출을 올바른 프로세스로 라우팅하여 이 문제를 해결합니다. 도구는 런타임에 실제 바이너리에서 검색되므로, 현재 65개의 도구를 포함하여 상위 프로젝트가 노출하는 모든 도구를 사용할 수 있으며, 여기에는 도구별 코드가 없고 상위 프로젝트가 새 도구를 추가할 때 업데이트할 필요가 없습니다.
Related MCP server: mcphub
작동 방식
┌──────────────────────────────────┐
Claude Code / routines / │ grafana-unified-mcp │
cloud sessions │ │
│ │ ┌────────────────────────────┐ │
│ streamable-HTTP │ │ bearer auth │ │
│ Authorization: Bearer … │ │ → Principal(instances, │ │
├──────────────────────────────►│ │ read-only|read-write) │ │
│ │ └────────────┬───────────────┘ │
│ │ │ │
│ │ ┌────────────▼───────────────┐ │
│ │ │ catalog: inject `instance` │ │
│ │ │ filter by caller's grant │ │
│ │ └────────────┬───────────────┘ │
│ │ │ route on │
│ │ │ instance=… │
│ │ ┌────────────▼───────────────┐ │
│ │ │ child pool (lazy, reaped) │ │
│ │ └──┬──────────┬──────────┬───┘ │
└───────────────────────────────┴─────┼──────────┼──────────┼──────┘
│ stdio │ stdio │ stdio
┌─────▼────┐ ┌───▼──────┐ ┌▼─────────┐
│mcp-grafana│ │mcp-grafana│ │mcp-grafana│
│ tenant-a │ │ tenant-b │ │ … │
└─────┬────┘ └───┬──────┘ └┬─────────┘
▼ ▼ ▼
tenant-a tenant-b …Grafana자식 프로세스는 첫 사용 시 시작되고, 활성 상태를 유지하며, 유휴 시간(--idle-timeout, 기본값 15분)이 지나면 종료되고, 죽으면 투명하게 다시 생성됩니다. 연결할 수 없는 Grafana는 해당 인스턴스에만 영향을 미칩니다.
설치
두 가지 구성 요소가 필요합니다: 상위 바이너리와 이 패키지입니다.
# 1. the upstream mcp-grafana binary (needs Go 1.26+; GOTOOLCHAIN=auto fetches it)
deploy/install-mcp-grafana.sh /usr/local/bin
# 2. this server
python3 -m venv /opt/grafana-unified-mcp/.venv
/opt/grafana-unified-mcp/.venv/bin/pip install 'grafana-unified-mcp[aws] @ .'이미 바이너리가 있다면 MCP_GRAFANA_BINARY=/path/to/mcp-grafana 또는 --mcp-grafana-binary로 경로를 지정하세요.
설정
엔드포인트
예상되는 형태 그대로입니다 — 인스턴스 이름을 상위 환경 변수에 매핑합니다:
{
"tenant-a": {
"GRAFANA_URL": "https://tenant-a.example.cloud/grafana",
"GRAFANA_SERVICE_ACCOUNT_TOKEN": "glsa_…"
},
"tenant-b": {
"GRAFANA_URL": "https://tenant-b.example.cloud/grafana",
"GRAFANA_SERVICE_ACCOUNT_TOKEN": "glsa_…",
"description": "Tenant B production"
}
}인스턴스별 선택적 키: GRAFANA_ORG_ID, GRAFANA_USERNAME / GRAFANA_PASSWORD, description, extra_env, extra_args. 문서 자체에서 비밀 정보를 보호하려면 GRAFANA_SERVICE_ACCOUNT_TOKEN_ENV (이 프로세스의 환경 변수에서 읽음) 또는 GRAFANA_SERVICE_ACCOUNT_TOKEN_FILE (자식 프로세스가 읽는 파일 경로)을 사용하세요.
인증
{
"clients": [
{
"name": "claude-routines",
"token_sha256": "3f786850e387550fdab836ed7e6dc881de23001b…",
"instances": ["tenant-a", "tenant-b"],
"scope": "read-only"
},
{
"name": "platform-oncall",
"token_sha256": "…",
"instances": ["*"],
"scope": "read-write"
}
]
}토큰과 그 해시를 생성합니다:
grafana-unified-mcp --hash-token # generates one
grafana-unified-mcp --hash-token 'my-existing-token'클라이언트에 token을 제공하고, 문서에 token_sha256을 넣습니다. 토큰은 hmac.compare_digest를 사용해 다이제스트로 비교되며, 모든 클라이언트는 매 시도마다 확인되므로 일치 위치가 타이밍을 통해 유출되지 않습니다.
호출자별로 두 가지가 적용됩니다:
instances— 호출자가 볼 수 있는instance열거형은 부여된 범위로 제한되며, 범위 밖의 인스턴스를 호출하면 존재하지 않는 인스턴스와 동일한 메시지로 거부되므로 토큰이 접근할 수 없는 인스턴스를 열거할 수 없습니다.scope—read-only호출자는 변형 도구를 볼 수조차 없습니다. 이 구분은 여기서 유지 관리하는 목록이 아닌 상위 프로젝트 자체의readOnlyHint어노테이션(현재 65개 도구 중 49개가 읽기 전용)에서 비롯되므로, 상위 프로젝트에서 추가된 도구는 코드 변경 없이 분류됩니다. 어노테이션이 없는 것은 읽기 전용이 아닌 것으로 처리됩니다.
이중 안전 장치로 --child-arg=--disable-write를 추가하면 모든 호출자에 대해 소스에서 쓰기 도구를 제거합니다.
인증 없이 실행
--auth-mode none은 포트에 접근할 수 있는 모든 호출자에게 읽기 전용으로 서비스를 제공합니다. 인스턴스를 범위 지정할 신원이 없으므로 모든 설정된 인스턴스는 읽을 수 있지만, 열린 포트가 대시보드를 수정하거나 스냅샷을 삭제할 수 없어야 하므로 아무것도 쓸 수 없습니다. 이는 세 가지 계층에서 적용됩니다:
게시된 카탈로그에서 모든 변형 도구를 생략합니다;
인증 검사가 클라이언트가 직접 도구를 호출하더라도 거부합니다;
자식 프로세스는
--disable-write로 시작되어 상위 프로젝트도 거부합니다.
세 번째 계층이 단순한 필터 이상으로 만듭니다. 상위 프로젝트는 grafana_api_request를 별도의 GET 전용 등록으로 교체합니다 — body 매개변수 없음, method가 GET으로 제한됨, GET이 아닌 요청은 런타임에 거부됨 — 따라서 계층 1과 2에 버그가 있더라도 쓰기 작업으로 이어질 수 없습니다.
stdio는 다릅니다: 로컬 호출자는 이미 엔드포인트 문서와 모든 토큰을 보유하고 있으므로 제한하는 것은 무의미합니다. stdio는 전체 액세스 권한을 얻습니다.
HTTP를 통해 쓰기 작업이 필요하다면, 열린 포트 대신 read-write 클라이언트와 함께 베어러 토큰을 사용하세요.
설정 출처
--endpoints와 --auth 모두에 대해 다음 중 하나를 사용할 수 있습니다:
출처 | 예시 |
파일 |
|
인라인 환경 변수 |
|
AWS Secrets Manager |
|
AWS SSM Parameter Store |
|
두 문서 모두 --config-refresh-seconds(기본값 300)마다 다시 읽힙니다. 새로고침 실패 시 로그를 남기고 마지막 유효한 값을 유지하므로, 일시적인 AWS 오류나 불완전하게 작성된 파일이 서버를 중단시키지 않습니다. 인스턴스 추가는 재시작이 필요 없으며, 제거는 해당 자식 프로세스를 중지합니다.
시작 전에 검증:
grafana-unified-mcp --endpoints … --auth … --check-config실행
# local, over stdio (no auth — the local caller already holds the config)
grafana-unified-mcp --endpoints ./examples/endpoints.json
# deployed, over streamable-HTTP behind a reverse proxy
grafana-unified-mcp \
--transport streamable-http \
--address 127.0.0.1:8900 \
--endpoints aws-secrets:prod/grafana/endpoints?region=us-west-2 \
--auth aws-secrets:prod/grafana/mcp-auth?region=us-west-2 \
--public-url https://grafana-mcp.example.com
--public-url이 중요합니다. SDK는Host헤더를 기반으로 DNS-리바인딩 보호를 적용합니다. 공개 호스트 이름을 전달하는 프록시 뒤에서는 해당 호스트가 허용되어야 하며, 그렇지 않으면 모든 요청이 거부됩니다.--public-url이 이를 허용하고(RFC 9728 리소스 메타데이터에 사용됨),--allowed-host가 더 많은 호스트를 추가합니다.
GET /healthz는 Grafana에 접촉하지 않고 프로세스 상태, 활성 자식 프로세스, 카탈로그 상태를 보고합니다.
클라이언트 연결
로컬 stdio 사용을 위한 .mcp.json:
{
"mcpServers": {
"grafana": {
"command": "/opt/grafana-unified-mcp/.venv/bin/grafana-unified-mcp",
"args": ["--endpoints", "/etc/grafana-unified-mcp/endpoints.json"]
}
}
}배포된 서버의 경우 — Claude Code 루틴 및 클라우드 세션 포함, 이것이 베어러 토큰이 존재하는 이유입니다:
{
"mcpServers": {
"grafana": {
"type": "http",
"url": "https://grafana-mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer ${GRAFANA_UNIFIED_MCP_TOKEN}"
}
}
}
}세션이 실행되는 환경에 GRAFANA_UNIFIED_MCP_TOKEN을 설정하세요 — 웹의 Claude Code의 경우 환경 변수이므로, 예약된 루틴과 클라우드 세션이 비밀 정보를 저장소에 저장하지 않고도 이를 사용할 수 있습니다. 루틴에는 read-only 클라이언트를 부여하고, read-write는 사람을 위해 유지하세요.
systemd 서비스로 배포
deploy/를 참조하세요. 간단히:
sudo deploy/install.sh # user, dirs, venv, unit file
sudo systemctl edit grafana-unified-mcp # set the source URIs / region
sudo systemctl enable --now grafana-unified-mcp
curl -s localhost:8900/healthz | jq유닛은 전용 권한 없는 사용자로 실행되며 ProtectSystem=strict, PrivateTmp, NoNewPrivileges가 적용됩니다. TLS는 앞단의 nginx 또는 ALB에서 종료됩니다 — deploy/nginx.conf.example을 참조하세요. 응답 버퍼링을 비활성화합니다(SSE 스트리밍에 필요).
사용 방법
먼저 모델을 list_grafana_instances로 안내하세요:
list_grafana_instances()
→ { "instances": [ {"name": "tenant-a", "url": "…", "connection": "live"}, … ],
"routing_argument": "instance",
"access": { "client": "claude-routines", "scope": "read-only" } }그런 다음 다른 모든 도구는 해당 이름을 사용합니다:
search_dashboards(instance="tenant-a", query="latency")check_health=true를 전달하면 각 Grafana를 추가로 프로빙합니다 — 모든 인스턴스에 연결을 열어야 하므로 더 느립니다.
이름 관련 주의사항
상위 프로젝트의 grafana_api_request에는 이미 endpoint(API 경로)라는 필수 매개변수가 있습니다. 이 이름으로 라우팅 인수를 주입하면 조용히 가려지므로, 기본적으로 라우팅 인수는 instance입니다. --routing-param endpoint로 이름을 변경하면 해당 도구의 자체 매개변수가 자동으로 api_path로 다시 게시되고 통과 시 다시 매핑되므로, 어떤 이름을 선택하든 도구가 충돌로 인해 손상되지 않습니다.
개발
uv venv && uv pip install -e '.[dev,aws]'
uv run pytest # unit + integration통합 테스트는 실제 mcp-grafana 자식 프로세스를 연결할 수 없는 Grafana에 대해 구동합니다: 카탈로그 검색, instance 주입 및 제거, 라우팅, 인증 필터링을 증명하기에 충분하며, 실제 자격 증명이 필요하지 않습니다. MCP_GRAFANA_BINARY를 바이너리 경로로 설정하세요. 그렇지 않으면 테스트가 건너뜁니다.
로드맵
OAuth 2.1 — 인증 계층은 이미 인터페이스이며, SDK는 이미 토큰 검증기와 함께 OAuth 제공자를 받습니다.
OAuth2Provider.verify_token을 구현하는 것이 전부입니다;auth/oauth.py는 세 단계를 문서화합니다. IdP 그룹을 기존grafana:read/grafana:write/instance:<name>범위에 매핑하면 모든 인증 검사가 변경 없이 계속 작동합니다.Fan-out —
instance: "*"로 모든 인스턴스에 대해 하나의 읽기 전용 쿼리를 실행하고 결과를 병합합니다. "어느 것이 알림을 보내고 있나요?"와 같은 경우에 유용합니다. 결과 병합은 자체 설계가 필요하므로 현재는 제외되었습니다.
This server cannot be deployed
Maintenance
Related MCP Connectors
An MCP server giving access to Grafana dashboards, data and more.
Stateless MCP gateway and OTel span-streaming bridge for hosted MCP servers.
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
MCP-first control plane for ProAgentStore agents and private instances.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProxy that aggregates multiple MCP servers and presents them as a unified interface, allowing clients to access resources from multiple servers transparently.4-
- AlicenseNot gradedqualityAmaintenanceA unified hub for centrally managing and dynamically orchestrating multiple MCP servers/APIs into separate endpoints with flexible routing strategies.846 npm2,488Apache 2.0
- AlicenseNot gradedqualityDmaintenanceEnables MCP-compatible agents to interact with Grafana instances for searching, creating, and updating dashboards, exploring logs via Loki, querying datasources, managing alerts, incidents, and on-call shifts, and accessing observability data.8Apache 2.0
- FlicenseNot gradedqualityDmaintenanceEnables interaction with multiple Jenkins instances from a single MCP server, using header-based authentication for multi-tenancy.1-