Skip to content

Commit 6ea6df6

Browse files
authored
Add dashboard tools (#62)
* Add tool to get dashboard by uid * fix context and dashboard test
1 parent 0e38b40 commit 6ea6df6

File tree

4 files changed

+83
-0
lines changed

4 files changed

+83
-0
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This provides access to your Grafana instance and the surrounding ecosystem.
77
## Features
88

99
- [x] Search for dashboards
10+
- [x] Get dashboard by UID
1011
- [x] List and fetch datasource information
1112
- [ ] Query datasources
1213
- [x] Prometheus
@@ -35,6 +36,7 @@ This is useful if you don't use certain functionality or if you don't want to ta
3536
| Tool | Category | Description |
3637
| --- | --- | --- |
3738
| `search_dashboards` | Search | Search for dashboards |
39+
| `get_dashboard_by_uid` | Dashboard | Get a dashboard by uid |
3840
| `list_datasources` | Datasources | List datasources |
3941
| `get_datasource_by_uid` | Datasources | Get a datasource by uid |
4042
| `get_datasource_by_name` | Datasources | Get a datasource by name |

cmd/mcp-grafana/main.go

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ func newServer() *server.MCPServer {
2323
tools.AddIncidentTools(s)
2424
tools.AddPrometheusTools(s)
2525
tools.AddLokiTools(s)
26+
tools.AddDashboardTools(s)
2627
return s
2728
}
2829

tools/dashboard.go

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package tools
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/mark3labs/mcp-go/server"
8+
9+
"github.com/grafana/grafana-openapi-client-go/models"
10+
mcpgrafana "github.com/grafana/mcp-grafana"
11+
)
12+
13+
type GetDashboardByUIDParams struct {
14+
UID string `json:"uid" jsonschema:"required,description=The UID of the dashboard"`
15+
}
16+
17+
func getDashboardByUID(ctx context.Context, args GetDashboardByUIDParams) (*models.DashboardFullWithMeta, error) {
18+
c := mcpgrafana.GrafanaClientFromContext(ctx)
19+
20+
dashboard, err := c.Dashboards.GetDashboardByUID(args.UID)
21+
if err != nil {
22+
return nil, fmt.Errorf("get dashboard by uid %s: %w", args.UID, err)
23+
}
24+
return dashboard.Payload, nil
25+
}
26+
27+
var GetDashboardByUID = mcpgrafana.MustTool(
28+
"get_dashboard_by_uid",
29+
"Get dashboard by uid",
30+
getDashboardByUID,
31+
)
32+
33+
func AddDashboardTools(mcp *server.MCPServer) {
34+
GetDashboardByUID.Register(mcp)
35+
}

tools/dashboard_test.go

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Requires a Grafana instance running on localhost:3000,
2+
// with a dashboard provisioned.
3+
// Run with `go test -tags integration`.
4+
//go:build integration
5+
6+
package tools
7+
8+
import (
9+
"testing"
10+
11+
"github.com/stretchr/testify/assert"
12+
"github.com/stretchr/testify/require"
13+
)
14+
15+
func TestDashboardTools(t *testing.T) {
16+
t.Run("get dashboard by uid", func(t *testing.T) {
17+
ctx := newTestContext()
18+
19+
// First, let's search for a dashboard to get its UID
20+
searchResults, err := searchDashboards(ctx, SearchDashboardsParams{})
21+
require.NoError(t, err)
22+
require.Greater(t, len(searchResults), 0, "No dashboards found")
23+
24+
dashboardUID := searchResults[0].UID
25+
26+
// Now test the get dashboard by uid functionality
27+
result, err := getDashboardByUID(ctx, GetDashboardByUIDParams{
28+
UID: dashboardUID,
29+
})
30+
require.NoError(t, err)
31+
dashboardMap, ok := result.Dashboard.(map[string]interface{})
32+
require.True(t, ok, "Dashboard should be a map")
33+
assert.Equal(t, dashboardUID, dashboardMap["uid"])
34+
assert.NotNil(t, result.Meta)
35+
})
36+
37+
t.Run("get dashboard by uid - invalid uid", func(t *testing.T) {
38+
ctx := newTestContext()
39+
40+
_, err := getDashboardByUID(ctx, GetDashboardByUIDParams{
41+
UID: "non-existent-uid",
42+
})
43+
require.Error(t, err)
44+
})
45+
}

0 commit comments

Comments
 (0)