|
1 | 1 | import { z } from "zod"; |
2 | 2 | import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; |
3 | 3 | import { execSSH, errorResponse } from "../utils/ssh-api.js"; |
| 4 | +import { CommandFailedError } from "../utils/errors.js"; |
| 5 | + |
| 6 | +const DEFAULT_PORT = 3000; |
| 7 | +const SERVICE_NAME = "Grafana"; |
4 | 8 |
|
5 | 9 | const inputSchema = { |
6 | 10 | dashboard: z.string().min(1).describe("Dashboard UID to export"), |
7 | 11 | }; |
8 | 12 |
|
| 13 | +function getPort(): number { |
| 14 | + const override = process.env.HOMELAB_GRAFANA_PORT; |
| 15 | + return override ? parseInt(override, 10) : DEFAULT_PORT; |
| 16 | +} |
| 17 | + |
| 18 | +function buildAuthHeader(): string { |
| 19 | + const token = process.env.HOMELAB_GRAFANA_TOKEN; |
| 20 | + if (token) { |
| 21 | + return `-H 'Authorization: Bearer ${token}'`; |
| 22 | + } |
| 23 | + const user = process.env.HOMELAB_GRAFANA_USER || "admin"; |
| 24 | + const password = process.env.HOMELAB_GRAFANA_PASSWORD; |
| 25 | + if (password) { |
| 26 | + return `-u '${user}:${password}'`; |
| 27 | + } |
| 28 | + return `-u 'admin:admin'`; |
| 29 | +} |
| 30 | + |
9 | 31 | export function register(server: McpServer): void { |
10 | 32 | server.tool( |
11 | 33 | "homelab_grafanaSnapshot", |
12 | 34 | "Export a Grafana dashboard configuration by UID", |
13 | 35 | inputSchema, |
14 | 36 | async (args) => { |
| 37 | + const port = getPort(); |
15 | 38 | try { |
| 39 | + const auth = buildAuthHeader(); |
16 | 40 | const output = await execSSH( |
17 | | - `curl -sf 'http://localhost:3000/api/dashboards/uid/${args.dashboard}'`, |
| 41 | + `curl -sf ${auth} 'http://localhost:${port}/api/dashboards/uid/${args.dashboard}'`, |
18 | 42 | ); |
19 | 43 |
|
20 | 44 | return { content: [{ type: "text" as const, text: output }] }; |
21 | 45 | } catch (error) { |
| 46 | + if (error instanceof CommandFailedError) { |
| 47 | + if (error.exitCode === 7) { |
| 48 | + return errorResponse( |
| 49 | + new Error( |
| 50 | + `Could not reach ${SERVICE_NAME} API on port ${port}. Is it running? ` + |
| 51 | + `Set HOMELAB_GRAFANA_PORT if using a non-default port.`, |
| 52 | + ), |
| 53 | + ); |
| 54 | + } |
| 55 | + if (error.exitCode === 22) { |
| 56 | + return errorResponse( |
| 57 | + new Error( |
| 58 | + `${SERVICE_NAME} returned an HTTP error. Check authentication -- ` + |
| 59 | + `set HOMELAB_GRAFANA_TOKEN (API key) or HOMELAB_GRAFANA_USER/HOMELAB_GRAFANA_PASSWORD. ` + |
| 60 | + `Also verify the dashboard UID "${args.dashboard}" exists.`, |
| 61 | + ), |
| 62 | + ); |
| 63 | + } |
| 64 | + } |
22 | 65 | return errorResponse(error); |
23 | 66 | } |
24 | 67 | }, |
|
0 commit comments