@daanrongen/grafana-mcp 1.0.4 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.js +297 -213
  2. package/package.json +4 -2
package/dist/main.js CHANGED
@@ -36769,7 +36769,7 @@ class AlertInstance extends exports_Schema.Class("AlertInstance")({
36769
36769
  class Folder extends exports_Schema.Class("Folder")({
36770
36770
  uid: exports_Schema.String,
36771
36771
  title: exports_Schema.String,
36772
- url: exports_Schema.String
36772
+ url: exports_Schema.optional(exports_Schema.String)
36773
36773
  }) {
36774
36774
  }
36775
36775
 
@@ -36791,10 +36791,91 @@ class HealthStatus extends exports_Schema.Class("HealthStatus")({
36791
36791
  }
36792
36792
 
36793
36793
  // src/infra/GrafanaClientLive.ts
36794
+ var SearchItemSchema = exports_Schema.Struct({
36795
+ uid: exports_Schema.String,
36796
+ title: exports_Schema.String,
36797
+ url: exports_Schema.String,
36798
+ folderTitle: exports_Schema.optional(exports_Schema.String),
36799
+ tags: exports_Schema.Array(exports_Schema.String)
36800
+ });
36801
+ var DashboardEnvelopeSchema = exports_Schema.Struct({
36802
+ dashboard: exports_Schema.Record({ key: exports_Schema.String, value: exports_Schema.Unknown }),
36803
+ meta: exports_Schema.Struct({
36804
+ folderTitle: exports_Schema.optional(exports_Schema.String),
36805
+ version: exports_Schema.optional(exports_Schema.Number)
36806
+ })
36807
+ });
36808
+ var CreateDashboardResponseSchema = exports_Schema.Struct({
36809
+ uid: exports_Schema.String,
36810
+ version: exports_Schema.Number,
36811
+ url: exports_Schema.String
36812
+ });
36813
+ var UpdateDashboardResponseSchema = exports_Schema.Struct({
36814
+ uid: exports_Schema.String
36815
+ });
36816
+ var DatasourceSchema = exports_Schema.Struct({
36817
+ id: exports_Schema.Number,
36818
+ uid: exports_Schema.String,
36819
+ name: exports_Schema.String,
36820
+ type: exports_Schema.String,
36821
+ url: exports_Schema.String,
36822
+ isDefault: exports_Schema.Boolean
36823
+ });
36824
+ var CreateDatasourceResponseSchema = exports_Schema.Struct({
36825
+ datasource: DatasourceSchema
36826
+ });
36827
+ var AlertRuleSchema = exports_Schema.Struct({
36828
+ uid: exports_Schema.String,
36829
+ title: exports_Schema.String,
36830
+ condition: exports_Schema.String,
36831
+ folderUID: exports_Schema.String,
36832
+ ruleGroup: exports_Schema.String,
36833
+ noDataState: exports_Schema.String,
36834
+ execErrState: exports_Schema.String
36835
+ });
36836
+ var AlertInstanceSchema = exports_Schema.Struct({
36837
+ labels: exports_Schema.Record({ key: exports_Schema.String, value: exports_Schema.String }),
36838
+ status: exports_Schema.Struct({ state: exports_Schema.String }),
36839
+ activeAt: exports_Schema.optional(exports_Schema.String)
36840
+ });
36841
+ var FolderSchema = exports_Schema.Struct({
36842
+ uid: exports_Schema.String,
36843
+ title: exports_Schema.String,
36844
+ url: exports_Schema.optional(exports_Schema.String)
36845
+ });
36846
+ var AnnotationSchema = exports_Schema.Struct({
36847
+ id: exports_Schema.Number,
36848
+ dashboardUID: exports_Schema.optional(exports_Schema.String),
36849
+ time: exports_Schema.Number,
36850
+ timeEnd: exports_Schema.optional(exports_Schema.Number),
36851
+ text: exports_Schema.String,
36852
+ tags: exports_Schema.Array(exports_Schema.String)
36853
+ });
36854
+ var CreateAnnotationResponseSchema = exports_Schema.Struct({
36855
+ id: exports_Schema.Number
36856
+ });
36857
+ var HealthStatusSchema = exports_Schema.Struct({
36858
+ commit: exports_Schema.String,
36859
+ database: exports_Schema.String,
36860
+ version: exports_Schema.String
36861
+ });
36862
+
36863
+ class HttpError extends Error {
36864
+ status;
36865
+ constructor(status, message) {
36866
+ super(message);
36867
+ this.status = status;
36868
+ this.name = "HttpError";
36869
+ }
36870
+ }
36794
36871
  var wrapFetch = (label, fn2) => exports_Effect.tryPromise({
36795
36872
  try: fn2,
36796
- catch: (e) => new GrafanaError({ message: `${label} failed`, cause: e })
36873
+ catch: (e) => e instanceof HttpError ? new GrafanaError({ message: `${label} failed: HTTP ${e.status} ${e.message}`, cause: e }) : new GrafanaError({ message: `${label} failed`, cause: e })
36797
36874
  });
36875
+ var decode6 = (schema) => (raw) => exports_Schema.decodeUnknown(schema)(raw).pipe(exports_Effect.mapError((e) => new GrafanaError({
36876
+ message: `Response validation failed: ${e.message}`,
36877
+ cause: e
36878
+ })));
36798
36879
  var GrafanaClientLive = exports_Layer.effect(GrafanaClient, exports_Effect.gen(function* () {
36799
36880
  const { url: url3, apiKey } = yield* exports_Effect.orDie(GrafanaConfig);
36800
36881
  const baseUrl = url3.replace(/\/$/, "");
@@ -36805,12 +36886,9 @@ var GrafanaClientLive = exports_Layer.effect(GrafanaClient, exports_Effect.gen(f
36805
36886
  };
36806
36887
  const get13 = (path) => wrapFetch(`GET ${path}`, async () => {
36807
36888
  const res = await fetch(`${baseUrl}${path}`, { headers });
36808
- if (res.status === 404) {
36809
- throw new Error(`404 Not Found: ${path}`);
36810
- }
36811
36889
  if (!res.ok) {
36812
36890
  const text = await res.text();
36813
- throw new Error(`HTTP ${res.status}: ${text}`);
36891
+ throw new HttpError(res.status, text);
36814
36892
  }
36815
36893
  return res.json();
36816
36894
  });
@@ -36828,69 +36906,59 @@ var GrafanaClientLive = exports_Layer.effect(GrafanaClient, exports_Effect.gen(f
36828
36906
  });
36829
36907
  const del = (path) => wrapFetch(`DELETE ${path}`, async () => {
36830
36908
  const res = await fetch(`${baseUrl}${path}`, { method: "DELETE", headers });
36831
- if (res.status === 404) {
36832
- throw new Error(`404 Not Found: ${path}`);
36833
- }
36834
36909
  if (!res.ok) {
36835
36910
  const text = await res.text();
36836
- throw new Error(`HTTP ${res.status}: ${text}`);
36911
+ throw new HttpError(res.status, text);
36837
36912
  }
36838
36913
  });
36839
36914
  const mapNotFound = (resource, id, effect2) => exports_Effect.catchAll(effect2, (e) => {
36840
- if (e.message.includes("404")) {
36915
+ if (e.cause instanceof HttpError && e.cause.status === 404) {
36841
36916
  return exports_Effect.fail(new NotFoundError({ resource, id }));
36842
36917
  }
36843
36918
  return exports_Effect.fail(e);
36844
36919
  });
36920
+ const fetchDashboardDetail = (uid) => get13(`/api/dashboards/uid/${uid}`).pipe(exports_Effect.flatMap(decode6(DashboardEnvelopeSchema)), exports_Effect.map(({ dashboard, meta }) => new DashboardDetail({
36921
+ uid: String(dashboard.uid ?? uid),
36922
+ title: String(dashboard.title ?? ""),
36923
+ json: JSON.stringify(dashboard),
36924
+ version: meta.version ?? 0,
36925
+ folderTitle: meta.folderTitle
36926
+ })));
36927
+ const fetchDashboardVersion = (uid) => get13(`/api/dashboards/uid/${uid}`).pipe(exports_Effect.flatMap(decode6(DashboardEnvelopeSchema)), exports_Effect.map(({ meta }) => meta.version ?? 0));
36928
+ const listAndMap = (path, itemSchema, mapper) => get13(path).pipe(exports_Effect.flatMap(decode6(exports_Schema.Array(itemSchema))), exports_Effect.map((items) => items.map(mapper)));
36845
36929
  return {
36846
- listDashboards: (query, limit = 100) => get13(`/api/search?type=dash-db&limit=${limit}${query ? `&query=${encodeURIComponent(query)}` : ""}`).pipe(exports_Effect.map((items) => items.map((d) => new Dashboard({
36930
+ listDashboards: (query, limit = 100) => listAndMap(`/api/search?type=dash-db&limit=${limit}${query ? `&query=${encodeURIComponent(query)}` : ""}`, SearchItemSchema, (d) => new Dashboard({
36847
36931
  uid: d.uid,
36848
36932
  title: d.title,
36849
36933
  url: d.url,
36850
36934
  folderTitle: d.folderTitle,
36851
- tags: d.tags ?? []
36852
- })))),
36853
- getDashboard: (uid) => mapNotFound("dashboard", uid, get13(`/api/dashboards/uid/${uid}`).pipe(exports_Effect.map(({ dashboard, meta }) => new DashboardDetail({
36854
- uid: String(dashboard.uid ?? uid),
36855
- title: String(dashboard.title ?? ""),
36856
- json: JSON.stringify(dashboard),
36857
- version: meta.version ?? 0,
36858
- folderTitle: meta.folderTitle
36859
- })))),
36935
+ tags: [...d.tags ?? []]
36936
+ })),
36937
+ getDashboard: (uid) => mapNotFound("dashboard", uid, fetchDashboardDetail(uid)),
36860
36938
  createDashboard: (dashboardJson, folderUid, message) => post("/api/dashboards/db", {
36861
36939
  dashboard: JSON.parse(dashboardJson),
36862
36940
  folderUid,
36863
36941
  message,
36864
36942
  overwrite: false
36865
- }).pipe(exports_Effect.flatMap((res) => get13(`/api/dashboards/uid/${res.uid}`).pipe(exports_Effect.map(({ dashboard, meta }) => new DashboardDetail({
36866
- uid: res.uid,
36867
- title: String(dashboard.title ?? ""),
36868
- json: JSON.stringify(dashboard),
36869
- version: meta.version
36870
- }))))),
36871
- updateDashboard: (uid, dashboardJson, message) => mapNotFound("dashboard", uid, get13(`/api/dashboards/uid/${uid}`).pipe(exports_Effect.flatMap(({ dashboard: _dashboard, meta }) => {
36872
- const updated = { ...JSON.parse(dashboardJson), uid, version: meta.version };
36943
+ }).pipe(exports_Effect.flatMap(decode6(CreateDashboardResponseSchema)), exports_Effect.flatMap((res) => fetchDashboardDetail(res.uid))),
36944
+ updateDashboard: (uid, dashboardJson, message) => mapNotFound("dashboard", uid, fetchDashboardVersion(uid).pipe(exports_Effect.flatMap((version2) => {
36945
+ const updated = { ...JSON.parse(dashboardJson), uid, version: version2 };
36873
36946
  return post("/api/dashboards/db", {
36874
36947
  dashboard: updated,
36875
36948
  message,
36876
36949
  overwrite: true
36877
36950
  });
36878
- }), exports_Effect.flatMap((res) => get13(`/api/dashboards/uid/${res.uid}`).pipe(exports_Effect.map(({ dashboard, meta }) => new DashboardDetail({
36879
- uid: res.uid,
36880
- title: String(dashboard.title ?? ""),
36881
- json: JSON.stringify(dashboard),
36882
- version: meta.version
36883
- })))))),
36951
+ }), exports_Effect.flatMap(decode6(UpdateDashboardResponseSchema)), exports_Effect.flatMap((res) => fetchDashboardDetail(res.uid)))),
36884
36952
  deleteDashboard: (uid) => mapNotFound("dashboard", uid, del(`/api/dashboards/uid/${uid}`)),
36885
- listDatasources: () => get13("/api/datasources").pipe(exports_Effect.map((items) => items.map((d) => new Datasource({
36953
+ listDatasources: () => listAndMap("/api/datasources", DatasourceSchema, (d) => new Datasource({
36886
36954
  id: d.id,
36887
36955
  uid: d.uid,
36888
36956
  name: d.name,
36889
36957
  type: d.type,
36890
36958
  url: d.url ?? "",
36891
36959
  isDefault: d.isDefault ?? false
36892
- })))),
36893
- getDatasource: (uid) => mapNotFound("datasource", uid, get13(`/api/datasources/uid/${uid}`).pipe(exports_Effect.map((d) => new Datasource({
36960
+ })),
36961
+ getDatasource: (uid) => mapNotFound("datasource", uid, get13(`/api/datasources/uid/${uid}`).pipe(exports_Effect.flatMap(decode6(DatasourceSchema)), exports_Effect.map((d) => new Datasource({
36894
36962
  id: d.id,
36895
36963
  uid: d.uid,
36896
36964
  name: d.name,
@@ -36898,7 +36966,7 @@ var GrafanaClientLive = exports_Layer.effect(GrafanaClient, exports_Effect.gen(f
36898
36966
  url: d.url ?? "",
36899
36967
  isDefault: d.isDefault ?? false
36900
36968
  })))),
36901
- createDatasource: (name, type, url4, isDefault = false) => post("/api/datasources", { name, type, url: url4, access: "proxy", isDefault }).pipe(exports_Effect.map(({ datasource: d }) => new Datasource({
36969
+ createDatasource: (name, type, url4, isDefault = false) => post("/api/datasources", { name, type, url: url4, access: "proxy", isDefault }).pipe(exports_Effect.flatMap(decode6(CreateDatasourceResponseSchema)), exports_Effect.map(({ datasource: d }) => new Datasource({
36902
36970
  id: d.id,
36903
36971
  uid: d.uid,
36904
36972
  name: d.name,
@@ -36907,7 +36975,7 @@ var GrafanaClientLive = exports_Layer.effect(GrafanaClient, exports_Effect.gen(f
36907
36975
  isDefault: d.isDefault ?? false
36908
36976
  }))),
36909
36977
  deleteDatasource: (uid) => mapNotFound("datasource", uid, del(`/api/datasources/uid/${uid}`)),
36910
- listAlertRules: () => get13("/api/v1/provisioning/alert-rules").pipe(exports_Effect.map((items) => items.map((r) => new AlertRule({
36978
+ listAlertRules: () => listAndMap("/api/v1/provisioning/alert-rules", AlertRuleSchema, (r) => new AlertRule({
36911
36979
  uid: r.uid,
36912
36980
  title: r.title,
36913
36981
  condition: r.condition,
@@ -36915,8 +36983,8 @@ var GrafanaClientLive = exports_Layer.effect(GrafanaClient, exports_Effect.gen(f
36915
36983
  ruleGroup: r.ruleGroup,
36916
36984
  noDataState: r.noDataState,
36917
36985
  execErrState: r.execErrState
36918
- })))),
36919
- getAlertRule: (uid) => mapNotFound("alert-rule", uid, get13(`/api/v1/provisioning/alert-rules/${uid}`).pipe(exports_Effect.map((r) => new AlertRule({
36986
+ })),
36987
+ getAlertRule: (uid) => mapNotFound("alert-rule", uid, get13(`/api/v1/provisioning/alert-rules/${uid}`).pipe(exports_Effect.flatMap(decode6(AlertRuleSchema)), exports_Effect.map((r) => new AlertRule({
36920
36988
  uid: r.uid,
36921
36989
  title: r.title,
36922
36990
  condition: r.condition,
@@ -36925,28 +36993,28 @@ var GrafanaClientLive = exports_Layer.effect(GrafanaClient, exports_Effect.gen(f
36925
36993
  noDataState: r.noDataState,
36926
36994
  execErrState: r.execErrState
36927
36995
  })))),
36928
- listAlertInstances: () => get13("/api/alertmanager/grafana/api/v2/alerts").pipe(exports_Effect.map((items) => items.map((a) => new AlertInstance({
36996
+ listAlertInstances: () => get13("/api/alertmanager/grafana/api/v2/alerts").pipe(exports_Effect.flatMap(decode6(exports_Schema.Array(AlertInstanceSchema))), exports_Effect.map((items) => items.map((a) => new AlertInstance({
36929
36997
  labels: a.labels,
36930
36998
  state: a.status?.state ?? "unknown",
36931
36999
  activeAt: a.activeAt
36932
37000
  })))),
36933
- listFolders: () => get13("/api/folders").pipe(exports_Effect.map((items) => items.map((f) => new Folder({ uid: f.uid, title: f.title, url: f.url })))),
37001
+ listFolders: () => listAndMap("/api/folders", FolderSchema, (f) => new Folder({ uid: f.uid, title: f.title, url: f.url })),
36934
37002
  createFolder: (title, uid) => post("/api/folders", {
36935
37003
  title,
36936
37004
  ...uid !== undefined ? { uid } : {}
36937
- }).pipe(exports_Effect.map((f) => new Folder({ uid: f.uid, title: f.title, url: f.url }))),
37005
+ }).pipe(exports_Effect.flatMap(decode6(FolderSchema)), exports_Effect.map((f) => new Folder({ uid: f.uid, title: f.title, url: f.url }))),
36938
37006
  deleteFolder: (uid) => mapNotFound("folder", uid, del(`/api/folders/${uid}`)),
36939
37007
  listAnnotations: (dashboardUID, limit = 100) => {
36940
37008
  const params = new URLSearchParams({ limit: String(limit) });
36941
37009
  if (dashboardUID !== undefined)
36942
37010
  params.set("dashboardUID", dashboardUID);
36943
- return get13(`/api/annotations?${params.toString()}`).pipe(exports_Effect.map((items) => items.map((a) => new Annotation({
37011
+ return get13(`/api/annotations?${params.toString()}`).pipe(exports_Effect.flatMap(decode6(exports_Schema.Array(AnnotationSchema))), exports_Effect.map((items) => items.map((a) => new Annotation({
36944
37012
  id: a.id,
36945
37013
  dashboardUID: a.dashboardUID,
36946
37014
  time: a.time,
36947
37015
  timeEnd: a.timeEnd,
36948
37016
  text: a.text,
36949
- tags: a.tags ?? []
37017
+ tags: [...a.tags ?? []]
36950
37018
  }))));
36951
37019
  },
36952
37020
  createAnnotation: (text, tags, dashboardUID, time3, timeEnd) => post("/api/annotations", {
@@ -36955,7 +37023,7 @@ var GrafanaClientLive = exports_Layer.effect(GrafanaClient, exports_Effect.gen(f
36955
37023
  ...dashboardUID !== undefined ? { dashboardUID } : {},
36956
37024
  ...time3 !== undefined ? { time: time3 } : {},
36957
37025
  ...timeEnd !== undefined ? { timeEnd } : {}
36958
- }).pipe(exports_Effect.map(({ id }) => new Annotation({
37026
+ }).pipe(exports_Effect.flatMap(decode6(CreateAnnotationResponseSchema)), exports_Effect.map(({ id }) => new Annotation({
36959
37027
  id,
36960
37028
  dashboardUID,
36961
37029
  time: time3 ?? Date.now(),
@@ -36963,7 +37031,7 @@ var GrafanaClientLive = exports_Layer.effect(GrafanaClient, exports_Effect.gen(f
36963
37031
  text,
36964
37032
  tags
36965
37033
  }))),
36966
- healthCheck: () => get13("/api/health").pipe(exports_Effect.map((h) => new HealthStatus({
37034
+ healthCheck: () => get13("/api/health").pipe(exports_Effect.flatMap(decode6(HealthStatusSchema)), exports_Effect.map((h) => new HealthStatus({
36967
37035
  commit: h.commit,
36968
37036
  database: h.database,
36969
37037
  version: h.version
@@ -44570,38 +44638,47 @@ var formatError2 = (cause3) => ({
44570
44638
  ],
44571
44639
  isError: true
44572
44640
  });
44641
+ var runTool = async (runtime5, effect2) => {
44642
+ const result = await runtime5.runPromiseExit(effect2);
44643
+ if (result._tag === "Failure")
44644
+ return formatError2(result.cause);
44645
+ return formatSuccess(result.value);
44646
+ };
44573
44647
 
44574
44648
  // src/mcp/tools/alerts.ts
44575
44649
  var registerAlertTools = (server, runtime5) => {
44576
- server.tool("list_alert_rules", "List all Grafana alert rules. Returns uid, title, condition, folder, rule group, and state settings.", {}, { title: "List Alert Rules", readOnlyHint: true, openWorldHint: true }, async () => {
44577
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44578
- const client = yield* GrafanaClient;
44579
- return yield* client.listAlertRules();
44580
- }));
44581
- if (result._tag === "Failure")
44582
- return formatError2(result.cause);
44583
- return formatSuccess(result.value);
44584
- });
44650
+ server.tool("list_alert_rules", "List all Grafana alert rules. Returns uid, title, condition, folder, rule group, and state settings.", {}, {
44651
+ title: "List Alert Rules",
44652
+ readOnlyHint: true,
44653
+ destructiveHint: false,
44654
+ idempotentHint: true,
44655
+ openWorldHint: true
44656
+ }, () => runTool(runtime5, exports_Effect.gen(function* () {
44657
+ const client = yield* GrafanaClient;
44658
+ return yield* client.listAlertRules();
44659
+ })));
44585
44660
  server.tool("get_alert_rule", "Get a Grafana alert rule by UID.", {
44586
44661
  uid: exports_external.string().describe("Alert rule UID")
44587
- }, { title: "Get Alert Rule", readOnlyHint: true, openWorldHint: true }, async ({ uid }) => {
44588
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44589
- const client = yield* GrafanaClient;
44590
- return yield* client.getAlertRule(uid);
44591
- }));
44592
- if (result._tag === "Failure")
44593
- return formatError2(result.cause);
44594
- return formatSuccess(result.value);
44595
- });
44596
- server.tool("list_alert_instances", "List currently firing Grafana alert instances from Alertmanager. Returns labels, state, and activeAt.", {}, { title: "List Alert Instances", readOnlyHint: true, openWorldHint: true }, async () => {
44597
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44598
- const client = yield* GrafanaClient;
44599
- return yield* client.listAlertInstances();
44600
- }));
44601
- if (result._tag === "Failure")
44602
- return formatError2(result.cause);
44603
- return formatSuccess(result.value);
44604
- });
44662
+ }, {
44663
+ title: "Get Alert Rule",
44664
+ readOnlyHint: true,
44665
+ destructiveHint: false,
44666
+ idempotentHint: true,
44667
+ openWorldHint: true
44668
+ }, ({ uid }) => runTool(runtime5, exports_Effect.gen(function* () {
44669
+ const client = yield* GrafanaClient;
44670
+ return yield* client.getAlertRule(uid);
44671
+ })));
44672
+ server.tool("list_alert_instances", "List currently firing Grafana alert instances from Alertmanager. Returns labels, state, and activeAt.", {}, {
44673
+ title: "List Alert Instances",
44674
+ readOnlyHint: true,
44675
+ destructiveHint: false,
44676
+ idempotentHint: true,
44677
+ openWorldHint: true
44678
+ }, () => runTool(runtime5, exports_Effect.gen(function* () {
44679
+ const client = yield* GrafanaClient;
44680
+ return yield* client.listAlertInstances();
44681
+ })));
44605
44682
  };
44606
44683
 
44607
44684
  // src/mcp/tools/annotations.ts
@@ -44609,15 +44686,16 @@ var registerAnnotationTools = (server, runtime5) => {
44609
44686
  server.tool("list_annotations", "List Grafana annotations, optionally filtered by dashboard UID.", {
44610
44687
  dashboardUid: exports_external.string().optional().describe("Filter annotations by dashboard UID"),
44611
44688
  limit: exports_external.number().optional().describe("Maximum number of results (default: 100)")
44612
- }, { title: "List Annotations", readOnlyHint: true, openWorldHint: true }, async ({ dashboardUid, limit }) => {
44613
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44614
- const client = yield* GrafanaClient;
44615
- return yield* client.listAnnotations(dashboardUid, limit);
44616
- }));
44617
- if (result._tag === "Failure")
44618
- return formatError2(result.cause);
44619
- return formatSuccess(result.value);
44620
- });
44689
+ }, {
44690
+ title: "List Annotations",
44691
+ readOnlyHint: true,
44692
+ destructiveHint: false,
44693
+ idempotentHint: true,
44694
+ openWorldHint: true
44695
+ }, ({ dashboardUid, limit }) => runTool(runtime5, exports_Effect.gen(function* () {
44696
+ const client = yield* GrafanaClient;
44697
+ return yield* client.listAnnotations(dashboardUid, limit);
44698
+ })));
44621
44699
  server.tool("create_annotation", "Create a Grafana annotation, optionally pinned to a dashboard.", {
44622
44700
  text: exports_external.string().describe("Annotation text / description"),
44623
44701
  tags: exports_external.array(exports_external.string()).describe("Tags to attach to the annotation"),
@@ -44628,16 +44706,12 @@ var registerAnnotationTools = (server, runtime5) => {
44628
44706
  title: "Create Annotation",
44629
44707
  readOnlyHint: false,
44630
44708
  destructiveHint: false,
44709
+ idempotentHint: false,
44631
44710
  openWorldHint: true
44632
- }, async ({ text, tags, dashboardUid, time: time3, timeEnd }) => {
44633
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44634
- const client = yield* GrafanaClient;
44635
- return yield* client.createAnnotation(text, tags, dashboardUid, time3, timeEnd);
44636
- }));
44637
- if (result._tag === "Failure")
44638
- return formatError2(result.cause);
44639
- return formatSuccess(result.value);
44640
- });
44711
+ }, ({ text, tags, dashboardUid, time: time3, timeEnd }) => runTool(runtime5, exports_Effect.gen(function* () {
44712
+ const client = yield* GrafanaClient;
44713
+ return yield* client.createAnnotation(text, tags, dashboardUid, time3, timeEnd);
44714
+ })));
44641
44715
  };
44642
44716
 
44643
44717
  // src/mcp/tools/dashboards.ts
@@ -44645,87 +44719,95 @@ var registerDashboardTools = (server, runtime5) => {
44645
44719
  server.tool("list_dashboards", "Search and list Grafana dashboards. Returns uid, title, url, folderTitle, and tags.", {
44646
44720
  query: exports_external.string().optional().describe("Search query to filter dashboards by title"),
44647
44721
  limit: exports_external.number().optional().describe("Maximum number of results (default: 100)")
44648
- }, { title: "List Dashboards", readOnlyHint: true, openWorldHint: true }, async ({ query, limit }) => {
44649
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44650
- const client = yield* GrafanaClient;
44651
- return yield* client.listDashboards(query, limit);
44652
- }));
44653
- if (result._tag === "Failure")
44654
- return formatError2(result.cause);
44655
- return formatSuccess(result.value);
44656
- });
44722
+ }, {
44723
+ title: "List Dashboards",
44724
+ readOnlyHint: true,
44725
+ destructiveHint: false,
44726
+ idempotentHint: true,
44727
+ openWorldHint: true
44728
+ }, ({ query, limit }) => runTool(runtime5, exports_Effect.gen(function* () {
44729
+ const client = yield* GrafanaClient;
44730
+ return yield* client.listDashboards(query, limit);
44731
+ })));
44657
44732
  server.tool("get_dashboard", "Get a Grafana dashboard by UID. Returns full dashboard JSON, version, and folder.", {
44658
44733
  uid: exports_external.string().describe("Dashboard UID")
44659
- }, { title: "Get Dashboard", readOnlyHint: true, openWorldHint: true }, async ({ uid }) => {
44660
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44661
- const client = yield* GrafanaClient;
44662
- return yield* client.getDashboard(uid);
44663
- }));
44664
- if (result._tag === "Failure")
44665
- return formatError2(result.cause);
44666
- return formatSuccess(result.value);
44667
- });
44734
+ }, {
44735
+ title: "Get Dashboard",
44736
+ readOnlyHint: true,
44737
+ destructiveHint: false,
44738
+ idempotentHint: true,
44739
+ openWorldHint: true
44740
+ }, ({ uid }) => runTool(runtime5, exports_Effect.gen(function* () {
44741
+ const client = yield* GrafanaClient;
44742
+ return yield* client.getDashboard(uid);
44743
+ })));
44668
44744
  server.tool("create_dashboard", "Create a new Grafana dashboard from a JSON definition string.", {
44669
44745
  dashboardJson: exports_external.string().describe("Dashboard JSON as a string (must include at minimum a 'title' field)"),
44670
44746
  folderUid: exports_external.string().optional().describe("UID of the folder to place the dashboard in"),
44671
44747
  message: exports_external.string().optional().describe("Commit message for the dashboard version")
44672
- }, { title: "Create Dashboard", readOnlyHint: false, destructiveHint: false, openWorldHint: true }, async ({ dashboardJson, folderUid, message }) => {
44673
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44674
- const client = yield* GrafanaClient;
44675
- return yield* client.createDashboard(dashboardJson, folderUid, message);
44676
- }));
44677
- if (result._tag === "Failure")
44678
- return formatError2(result.cause);
44679
- return formatSuccess(result.value);
44680
- });
44748
+ }, {
44749
+ title: "Create Dashboard",
44750
+ readOnlyHint: false,
44751
+ destructiveHint: false,
44752
+ idempotentHint: false,
44753
+ openWorldHint: true
44754
+ }, ({ dashboardJson, folderUid, message }) => runTool(runtime5, exports_Effect.gen(function* () {
44755
+ const client = yield* GrafanaClient;
44756
+ return yield* client.createDashboard(dashboardJson, folderUid, message);
44757
+ })));
44681
44758
  server.tool("update_dashboard", "Update an existing Grafana dashboard by UID with a new JSON definition.", {
44682
44759
  uid: exports_external.string().describe("Dashboard UID"),
44683
44760
  dashboardJson: exports_external.string().describe("Updated dashboard JSON as a string"),
44684
44761
  message: exports_external.string().optional().describe("Commit message for the new version")
44685
- }, { title: "Update Dashboard", readOnlyHint: false, destructiveHint: false, openWorldHint: true }, async ({ uid, dashboardJson, message }) => {
44686
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44687
- const client = yield* GrafanaClient;
44688
- return yield* client.updateDashboard(uid, dashboardJson, message);
44689
- }));
44690
- if (result._tag === "Failure")
44691
- return formatError2(result.cause);
44692
- return formatSuccess(result.value);
44693
- });
44762
+ }, {
44763
+ title: "Update Dashboard",
44764
+ readOnlyHint: false,
44765
+ destructiveHint: false,
44766
+ idempotentHint: false,
44767
+ openWorldHint: true
44768
+ }, ({ uid, dashboardJson, message }) => runTool(runtime5, exports_Effect.gen(function* () {
44769
+ const client = yield* GrafanaClient;
44770
+ return yield* client.updateDashboard(uid, dashboardJson, message);
44771
+ })));
44694
44772
  server.tool("delete_dashboard", "Delete a Grafana dashboard by UID.", {
44695
44773
  uid: exports_external.string().describe("Dashboard UID")
44696
- }, { title: "Delete Dashboard", readOnlyHint: false, destructiveHint: true, openWorldHint: true }, async ({ uid }) => {
44697
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44698
- const client = yield* GrafanaClient;
44699
- yield* client.deleteDashboard(uid);
44700
- }));
44701
- if (result._tag === "Failure")
44702
- return formatError2(result.cause);
44703
- return formatSuccess({ ok: true });
44704
- });
44774
+ }, {
44775
+ title: "Delete Dashboard",
44776
+ readOnlyHint: false,
44777
+ destructiveHint: true,
44778
+ idempotentHint: true,
44779
+ openWorldHint: true
44780
+ }, ({ uid }) => runTool(runtime5, exports_Effect.gen(function* () {
44781
+ const client = yield* GrafanaClient;
44782
+ yield* client.deleteDashboard(uid);
44783
+ return { ok: true };
44784
+ })));
44705
44785
  };
44706
44786
 
44707
44787
  // src/mcp/tools/datasources.ts
44708
44788
  var registerDatasourceTools = (server, runtime5) => {
44709
- server.tool("list_datasources", "List all configured Grafana datasources. Returns id, uid, name, type, url, and isDefault.", {}, { title: "List Datasources", readOnlyHint: true, openWorldHint: true }, async () => {
44710
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44711
- const client = yield* GrafanaClient;
44712
- return yield* client.listDatasources();
44713
- }));
44714
- if (result._tag === "Failure")
44715
- return formatError2(result.cause);
44716
- return formatSuccess(result.value);
44717
- });
44789
+ server.tool("list_datasources", "List all configured Grafana datasources. Returns id, uid, name, type, url, and isDefault.", {}, {
44790
+ title: "List Datasources",
44791
+ readOnlyHint: true,
44792
+ destructiveHint: false,
44793
+ idempotentHint: true,
44794
+ openWorldHint: true
44795
+ }, () => runTool(runtime5, exports_Effect.gen(function* () {
44796
+ const client = yield* GrafanaClient;
44797
+ return yield* client.listDatasources();
44798
+ })));
44718
44799
  server.tool("get_datasource", "Get a Grafana datasource by UID.", {
44719
44800
  uid: exports_external.string().describe("Datasource UID")
44720
- }, { title: "Get Datasource", readOnlyHint: true, openWorldHint: true }, async ({ uid }) => {
44721
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44722
- const client = yield* GrafanaClient;
44723
- return yield* client.getDatasource(uid);
44724
- }));
44725
- if (result._tag === "Failure")
44726
- return formatError2(result.cause);
44727
- return formatSuccess(result.value);
44728
- });
44801
+ }, {
44802
+ title: "Get Datasource",
44803
+ readOnlyHint: true,
44804
+ destructiveHint: false,
44805
+ idempotentHint: true,
44806
+ openWorldHint: true
44807
+ }, ({ uid }) => runTool(runtime5, exports_Effect.gen(function* () {
44808
+ const client = yield* GrafanaClient;
44809
+ return yield* client.getDatasource(uid);
44810
+ })));
44729
44811
  server.tool("create_datasource", "Create a new Grafana datasource.", {
44730
44812
  name: exports_external.string().describe("Datasource name"),
44731
44813
  type: exports_external.string().describe("Datasource type (e.g. prometheus, loki, elasticsearch, postgres)"),
@@ -44735,76 +44817,79 @@ var registerDatasourceTools = (server, runtime5) => {
44735
44817
  title: "Create Datasource",
44736
44818
  readOnlyHint: false,
44737
44819
  destructiveHint: false,
44820
+ idempotentHint: false,
44738
44821
  openWorldHint: true
44739
- }, async ({ name, type, url: url3, isDefault }) => {
44740
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44741
- const client = yield* GrafanaClient;
44742
- return yield* client.createDatasource(name, type, url3, isDefault);
44743
- }));
44744
- if (result._tag === "Failure")
44745
- return formatError2(result.cause);
44746
- return formatSuccess(result.value);
44747
- });
44822
+ }, ({ name, type, url: url3, isDefault }) => runTool(runtime5, exports_Effect.gen(function* () {
44823
+ const client = yield* GrafanaClient;
44824
+ return yield* client.createDatasource(name, type, url3, isDefault);
44825
+ })));
44748
44826
  server.tool("delete_datasource", "Delete a Grafana datasource by UID.", {
44749
44827
  uid: exports_external.string().describe("Datasource UID")
44750
- }, { title: "Delete Datasource", readOnlyHint: false, destructiveHint: true, openWorldHint: true }, async ({ uid }) => {
44751
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44752
- const client = yield* GrafanaClient;
44753
- yield* client.deleteDatasource(uid);
44754
- }));
44755
- if (result._tag === "Failure")
44756
- return formatError2(result.cause);
44757
- return formatSuccess({ ok: true });
44758
- });
44828
+ }, {
44829
+ title: "Delete Datasource",
44830
+ readOnlyHint: false,
44831
+ destructiveHint: true,
44832
+ idempotentHint: true,
44833
+ openWorldHint: true
44834
+ }, ({ uid }) => runTool(runtime5, exports_Effect.gen(function* () {
44835
+ const client = yield* GrafanaClient;
44836
+ yield* client.deleteDatasource(uid);
44837
+ return { ok: true };
44838
+ })));
44759
44839
  };
44760
44840
 
44761
44841
  // src/mcp/tools/folders.ts
44762
44842
  var registerFolderTools = (server, runtime5) => {
44763
- server.tool("list_folders", "List all Grafana folders. Returns uid, title, and url.", {}, { title: "List Folders", readOnlyHint: true, openWorldHint: true }, async () => {
44764
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44765
- const client = yield* GrafanaClient;
44766
- return yield* client.listFolders();
44767
- }));
44768
- if (result._tag === "Failure")
44769
- return formatError2(result.cause);
44770
- return formatSuccess(result.value);
44771
- });
44843
+ server.tool("list_folders", "List all Grafana folders. Returns uid, title, and url.", {}, {
44844
+ title: "List Folders",
44845
+ readOnlyHint: true,
44846
+ destructiveHint: false,
44847
+ idempotentHint: true,
44848
+ openWorldHint: true
44849
+ }, () => runTool(runtime5, exports_Effect.gen(function* () {
44850
+ const client = yield* GrafanaClient;
44851
+ return yield* client.listFolders();
44852
+ })));
44772
44853
  server.tool("create_folder", "Create a new Grafana folder for organising dashboards.", {
44773
44854
  title: exports_external.string().describe("Folder title"),
44774
44855
  uid: exports_external.string().optional().describe("Optional custom UID for the folder")
44775
- }, { title: "Create Folder", readOnlyHint: false, destructiveHint: false, openWorldHint: true }, async ({ title, uid }) => {
44776
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44777
- const client = yield* GrafanaClient;
44778
- return yield* client.createFolder(title, uid);
44779
- }));
44780
- if (result._tag === "Failure")
44781
- return formatError2(result.cause);
44782
- return formatSuccess(result.value);
44783
- });
44856
+ }, {
44857
+ title: "Create Folder",
44858
+ readOnlyHint: false,
44859
+ destructiveHint: false,
44860
+ idempotentHint: false,
44861
+ openWorldHint: true
44862
+ }, ({ title, uid }) => runTool(runtime5, exports_Effect.gen(function* () {
44863
+ const client = yield* GrafanaClient;
44864
+ return yield* client.createFolder(title, uid);
44865
+ })));
44784
44866
  server.tool("delete_folder", "Delete a Grafana folder by UID. Deleting a folder also deletes all dashboards within it.", {
44785
44867
  uid: exports_external.string().describe("Folder UID")
44786
- }, { title: "Delete Folder", readOnlyHint: false, destructiveHint: true, openWorldHint: true }, async ({ uid }) => {
44787
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44788
- const client = yield* GrafanaClient;
44789
- yield* client.deleteFolder(uid);
44790
- }));
44791
- if (result._tag === "Failure")
44792
- return formatError2(result.cause);
44793
- return formatSuccess({ ok: true });
44794
- });
44868
+ }, {
44869
+ title: "Delete Folder",
44870
+ readOnlyHint: false,
44871
+ destructiveHint: true,
44872
+ idempotentHint: true,
44873
+ openWorldHint: true
44874
+ }, ({ uid }) => runTool(runtime5, exports_Effect.gen(function* () {
44875
+ const client = yield* GrafanaClient;
44876
+ yield* client.deleteFolder(uid);
44877
+ return { ok: true };
44878
+ })));
44795
44879
  };
44796
44880
 
44797
44881
  // src/mcp/tools/health.ts
44798
44882
  var registerHealthTools = (server, runtime5) => {
44799
- server.tool("health_check", "Check the health of the Grafana instance. Returns version, database status, and commit hash.", {}, { title: "Health Check", readOnlyHint: true, openWorldHint: true }, async () => {
44800
- const result = await runtime5.runPromiseExit(exports_Effect.gen(function* () {
44801
- const client = yield* GrafanaClient;
44802
- return yield* client.healthCheck();
44803
- }));
44804
- if (result._tag === "Failure")
44805
- return formatError2(result.cause);
44806
- return formatSuccess(result.value);
44807
- });
44883
+ server.tool("health_check", "Check the health of the Grafana instance. Returns version, database status, and commit hash.", {}, {
44884
+ title: "Health Check",
44885
+ readOnlyHint: true,
44886
+ destructiveHint: false,
44887
+ idempotentHint: true,
44888
+ openWorldHint: true
44889
+ }, () => runTool(runtime5, exports_Effect.gen(function* () {
44890
+ const client = yield* GrafanaClient;
44891
+ return yield* client.healthCheck();
44892
+ })));
44808
44893
  };
44809
44894
 
44810
44895
  // src/mcp/server.ts
@@ -44823,8 +44908,7 @@ var createMcpServer = (runtime5) => {
44823
44908
  };
44824
44909
 
44825
44910
  // src/main.ts
44826
- var layer = exports_Layer.mergeAll(GrafanaClientLive);
44827
- var runtime5 = exports_ManagedRuntime.make(layer);
44911
+ var runtime5 = exports_ManagedRuntime.make(GrafanaClientLive);
44828
44912
  var server = createMcpServer(runtime5);
44829
44913
  var transport = new StdioServerTransport;
44830
44914
  await server.connect(transport);
package/package.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "name": "@daanrongen/grafana-mcp",
3
- "version": "1.0.4",
3
+ "version": "1.2.0",
4
4
  "description": "MCP server for Grafana — manage dashboards, datasources, alerts, folders, and annotations over stdio",
5
5
  "type": "module",
6
- "bin": "./dist/main.js",
6
+ "bin": {
7
+ "grafana-mcp": "./dist/main.js"
8
+ },
7
9
  "main": "./dist/main.js",
8
10
  "files": [
9
11
  "dist"