Passer au contenu principal
L

dsh-tool-grafana

leoswing/dsh-tool-grafana

Grafana capability for DeepSeek Harness: composes the community mcp-grafana server with Grafana-specific prompt guidance and a troubleshooting skill

Installer

dsh plugin --profile web add github:leoswing/dsh-tool-grafana

README

dsh-tool-grafana

English | 简体中文

Grafana capability for DeepSeek Harness (dsh).

This plugin owns no Grafana tool logic. It composes the community mcp-grafana server as a child @deepseek-ai/dsh-mcp-client plugin — the model sees mcp__grafana__* tools exactly as in any MCP-aware agent — and layers on what a plain MCP bridge cannot provide:

  1. One config owner for connection material (URL, service-account token, tool-category selection, read-only mode) instead of raw env passthrough.
  2. A standing system-prompt section (grafana:workflow, order 115) encoding the upstream context-window discipline: summary before full JSON, JSONPath for partial reads, datasource discovery before querying.
  3. An embedded runtime skill (grafana-troubleshooting) teaching a systematic alert → dashboard → metrics → logs → incident workflow, invocable on both model and user surfaces.
┌─ dsh-tool-grafana (this plugin) ─────────────┐
│  config validation · prompt section · skill       │
└──────────────┬─────────────────────────────────────┘
               │ ctx.plugin(dsh-mcp-client, plan)
               ▼
┌─ mcp-grafana (community Go binary, stdio) ────────┐
│  mcp__grafana__search_dashboards                  │
│  mcp__grafana__query_prometheus / loki / ...      │
└───────────────────────────────────────────────────┘

The same mcp-grafana binary remains directly usable by Cursor, Claude Code, OpenClaw, etc. — one core, both ecosystems.

Install into a profile

dsh plugin --profile web add /path/to/dsh-grafana   # or a published name

Then wire it in ~/.dsh/profiles/web/cordis.patch.yml:

- insert:
    - id: grafana
      name: 'dsh-tool-grafana'
      config:
        url: https://myinstance.grafana.net   # default; the settings card can override
        # The token is resolved through the DSH credential store under this
        # reference — never inline in this file:
        tokenCredentialRef: GRAFANA_SERVICE_ACCOUNT_TOKEN
        readOnly: true
        categories: [search, datasource, dashboard, prometheus, loki, alerting]
        launcher:
          kind: uvx
          version: '0.7.9'   # pin the upstream release; omit to track latest
        # kind: binary
        # path: /usr/local/bin/mcp-grafana   # go install github.com/grafana/mcp-grafana/cmd/mcp-grafana@vX.Y.Z

Under the web profile you can skip the YAML entirely except for the insert row: open Settings → Plugins → Grafana observability and enter the URL and service-account token in the card. Card values are stored in the DSH settings document / credential store and override the patch config per field; the patch url remains the fallback default.

Config

FieldDefaultMeaning
url''Default Grafana base URL; the settings card value (web) overrides it. Both empty fails activation with guidance
tokenCredentialRefGRAFANA_SERVICE_ACCOUNT_TOKENCredential reference resolved through ctx.credentials (see below). No inline token field exists, by design
categoriesupstream default set*mcp-grafana --enabled-tools categories
readOnlytrueDefault for --disable-write; the settings card toggle overrides it (web)
launcher{kind: 'uvx', version: ''}How to start the server process; pin version (uvx) or use a versioned binary/docker tag to avoid upstream drift
env{}Extra env merged into the server process
toolCallTimeoutMs60000Per-tool-call timeout (dsh-mcp-client)

* search, datasource, dashboard, folder, prometheus, loki, alerting, incident, oncall, sift, navigation, annotations. Heavy backends (clickhouse, cloudwatch, snowflake, athena, elasticsearch, quickwit, graphite, influxdb) and the runpanelquery/examples/ agento11y/assistant groups stay opt-in.

Credentials

The token is resolved through the DSH credential seam (ctx.credentials), not read from a plugin-owned env var. With the default local provider (dsh-credentials-local), the first configured source wins:

  1. Launching environmentGRAFANA_SERVICE_ACCOUNT_TOKEN=… dsh web
  2. Managed store$DSH_HOME/.credentials.yaml (what the Web Models page writes; writable from inside DSH)
  3. Project .env in the invocation directory
  4. User .env at $DSH_HOME/.env

There is no inline token config field, so the token can never be committed into cordis.patch.yml or leak through --dump-config output.

Connection changes take effect on profile restart. The token and URL are resolved once at activation and handed to the mcp-grafana process environment; stdio MCP servers cannot receive env updates after spawn. (Native-tool plugins like the dsh-grafana dashboard editor resolve per tool call and pick up changes live — that is the trade-off of composition over re-implementation.)

Web settings card

The package ships a dsh.client entry (client.js) that mounts a card under Settings → Plugins → Grafana observability:

  • Service Account Token — written to the credential store (write-only; the card shows a mask, never the value)
  • Grafana URL — stored in the grafana settings namespace, shown verbatim after saving
  • Read-only toggle — stored in the same namespace

Precedence is card value > patch config > activation error, per field.

Development

npm install
npm run build   # tsc → lib/
npm test        # node --test (unit + real-Cordis integration)

The integration test boots the plugin under a real Cordis context with the real dsh-system-prompt and dsh-skill services, stubbing only the child mcp-client mount so no Grafana is needed.

Design notes

  • Why not re-implement the tools natively? The community server ships 60+ tools with per-category flags, auth handling, and active upstream maintenance. Re-implementing buys nothing and forks the maintenance burden.
  • Why not just dsh-mcp-client directly? You can — one YAML row works. This plugin exists for the delta MCP can't express: validated config, prompt-level usage discipline, and bundled workflow knowledge.
  • Token hygiene: the token only ever travels into the child process env, never into prompts, tool output, or logs (declared as this package's invariant in ./invariant).

License

MIT

Plugins associés