|
7 | 7 | "github.com/mark3labs/mcp-go/mcp" |
8 | 8 | "github.com/mark3labs/mcp-go/server" |
9 | 9 |
|
| 10 | + "github.com/grafana/grafana-openapi-client-go/client/access_control" |
10 | 11 | "github.com/grafana/grafana-openapi-client-go/client/org" |
11 | 12 | "github.com/grafana/grafana-openapi-client-go/client/teams" |
12 | 13 | "github.com/grafana/grafana-openapi-client-go/models" |
@@ -61,7 +62,193 @@ var ListUsersByOrg = mcpgrafana.MustTool( |
61 | 62 | mcp.WithReadOnlyHintAnnotation(true), |
62 | 63 | ) |
63 | 64 |
|
| 65 | +type ListAllRolesParams struct { |
| 66 | + DelegatableOnly bool `json:"delegatableOnly,omitempty" jsonschema:"description=Optional: If set true only return roles that can be delegated by current user"` |
| 67 | +} |
| 68 | + |
| 69 | +func listAllRoles(ctx context.Context, args ListAllRolesParams) ([]*models.RoleDTO, error) { |
| 70 | + c := mcpgrafana.GrafanaClientFromContext(ctx) |
| 71 | + params := access_control.NewListRolesParamsWithContext(ctx) |
| 72 | + |
| 73 | + if args.DelegatableOnly { |
| 74 | + delegatable := true |
| 75 | + params.Delegatable = &delegatable |
| 76 | + } |
| 77 | + |
| 78 | + resp, err := c.AccessControl.ListRoles(params) |
| 79 | + if err != nil { |
| 80 | + return nil, fmt.Errorf("list all roles: %w", err) |
| 81 | + } |
| 82 | + return resp.Payload, nil |
| 83 | +} |
| 84 | + |
| 85 | +var ListAllRoles = mcpgrafana.MustTool( |
| 86 | + "list_all_roles", |
| 87 | + "List all roles in Grafana. Optionally filter to show only roles that can be delegated by the current user. Returns role details including UID, name, permissions, and metadata.", |
| 88 | + listAllRoles, |
| 89 | + mcp.WithTitleAnnotation("List all roles"), |
| 90 | + mcp.WithIdempotentHintAnnotation(true), |
| 91 | + mcp.WithReadOnlyHintAnnotation(true), |
| 92 | +) |
| 93 | + |
| 94 | +type GetRoleDetailsParams struct { |
| 95 | + RoleUID string `json:"roleUID" jsonschema:"required,description=Role UID to retrieve"` |
| 96 | +} |
| 97 | + |
| 98 | +func getRoleDetails(ctx context.Context, args GetRoleDetailsParams) (*models.RoleDTO, error) { |
| 99 | + c := mcpgrafana.GrafanaClientFromContext(ctx) |
| 100 | + params := access_control.NewGetRoleParamsWithContext(ctx).WithRoleUID(args.RoleUID) |
| 101 | + |
| 102 | + resp, err := c.AccessControl.GetRoleWithParams(params) |
| 103 | + if err != nil { |
| 104 | + return nil, fmt.Errorf("get role details: %w", err) |
| 105 | + } |
| 106 | + return resp.Payload, nil |
| 107 | +} |
| 108 | + |
| 109 | +var GetRoleDetails = mcpgrafana.MustTool( |
| 110 | + "get_role_details", |
| 111 | + "Get detailed information about a specific Grafana role by its UID, including permissions, metadata, and configuration.", |
| 112 | + getRoleDetails, |
| 113 | + mcp.WithTitleAnnotation("Get role details"), |
| 114 | + mcp.WithIdempotentHintAnnotation(true), |
| 115 | + mcp.WithReadOnlyHintAnnotation(true), |
| 116 | +) |
| 117 | + |
| 118 | +type GetRoleAssignmentsParams struct { |
| 119 | + RoleUID string `json:"roleUID" jsonschema:"required,description=Role UID to retrieve"` |
| 120 | +} |
| 121 | + |
| 122 | +func getRoleAssignments(ctx context.Context, args GetRoleAssignmentsParams) (*models.RoleAssignmentsDTO, error) { |
| 123 | + c := mcpgrafana.GrafanaClientFromContext(ctx) |
| 124 | + params := access_control.NewGetRoleAssignmentsParamsWithContext(ctx).WithRoleUID(args.RoleUID) |
| 125 | + |
| 126 | + resp, err := c.AccessControl.GetRoleAssignmentsWithParams(params) |
| 127 | + if err != nil { |
| 128 | + return nil, fmt.Errorf("get role assignments: %w", err) |
| 129 | + } |
| 130 | + return resp.Payload, nil |
| 131 | +} |
| 132 | + |
| 133 | +var GetRoleAssignments = mcpgrafana.MustTool( |
| 134 | + "get_role_assignments", |
| 135 | + "List all assignments for a specific role, showing which users, teams, and service accounts have been assigned this role.", |
| 136 | + getRoleAssignments, |
| 137 | + mcp.WithTitleAnnotation("Get role assignments"), |
| 138 | + mcp.WithIdempotentHintAnnotation(true), |
| 139 | + mcp.WithReadOnlyHintAnnotation(true), |
| 140 | +) |
| 141 | + |
| 142 | +type ListUserRolesParams struct { |
| 143 | + UserIDs []int64 `json:"userIds" jsonschema:"required,description=User ID(s) to get roles for. Can be a single user or multiple users."` |
| 144 | +} |
| 145 | + |
| 146 | +func listUserRoles(ctx context.Context, args ListUserRolesParams) (map[string][]models.RoleDTO, error) { |
| 147 | + c := mcpgrafana.GrafanaClientFromContext(ctx) |
| 148 | + searchQuery := &models.RolesSearchQuery{UserIds: args.UserIDs} |
| 149 | + params := access_control.NewListUsersRolesParamsWithContext(ctx).WithBody(searchQuery) |
| 150 | + |
| 151 | + resp, err := c.AccessControl.ListUsersRolesWithParams(params) |
| 152 | + if err != nil { |
| 153 | + return nil, fmt.Errorf("list user roles: %w", err) |
| 154 | + } |
| 155 | + return resp.Payload, nil |
| 156 | +} |
| 157 | + |
| 158 | +var ListUserRoles = mcpgrafana.MustTool( |
| 159 | + "list_user_roles", |
| 160 | + "List all roles assigned to one or more users. Returns a map of user IDs to their assigned roles, excluding built-in roles and team-inherited roles.", |
| 161 | + listUserRoles, |
| 162 | + mcp.WithTitleAnnotation("List user roles"), |
| 163 | + mcp.WithIdempotentHintAnnotation(true), |
| 164 | + mcp.WithReadOnlyHintAnnotation(true), |
| 165 | +) |
| 166 | + |
| 167 | +type ListTeamRolesParams struct { |
| 168 | + TeamIDs []int64 `json:"teamIds" jsonschema:"required,description=Team ID(s) to get roles for. Can be a single team or multiple teams."` |
| 169 | +} |
| 170 | + |
| 171 | +func listTeamRoles(ctx context.Context, args ListTeamRolesParams) (map[string][]models.RoleDTO, error) { |
| 172 | + c := mcpgrafana.GrafanaClientFromContext(ctx) |
| 173 | + searchQuery := &models.RolesSearchQuery{TeamIds: args.TeamIDs} |
| 174 | + params := access_control.NewListTeamsRolesParamsWithContext(ctx).WithBody(searchQuery) |
| 175 | + |
| 176 | + resp, err := c.AccessControl.ListTeamsRolesWithParams(params) |
| 177 | + if err != nil { |
| 178 | + return nil, fmt.Errorf("list team roles: %w", err) |
| 179 | + } |
| 180 | + return resp.Payload, nil |
| 181 | +} |
| 182 | + |
| 183 | +var ListTeamRoles = mcpgrafana.MustTool( |
| 184 | + "list_team_roles", |
| 185 | + "List all roles assigned to one or more teams. Returns a map of team IDs to their assigned roles.", |
| 186 | + listTeamRoles, |
| 187 | + mcp.WithTitleAnnotation("List team roles"), |
| 188 | + mcp.WithIdempotentHintAnnotation(true), |
| 189 | + mcp.WithReadOnlyHintAnnotation(true), |
| 190 | +) |
| 191 | + |
| 192 | +type GetResourcePermissionsParams struct { |
| 193 | + Resource string `json:"resource" jsonschema:"required,description=Resource type (e.g. 'dashboards' 'datasources' 'folders')"` |
| 194 | + ResourceID string `json:"resourceId" jsonschema:"required,description=Unique identifier of the resource (UID for dashboards/datasources/folders)"` |
| 195 | +} |
| 196 | + |
| 197 | +func getResourcePermissions(ctx context.Context, args GetResourcePermissionsParams) ([]*models.ResourcePermissionDTO, error) { |
| 198 | + c := mcpgrafana.GrafanaClientFromContext(ctx) |
| 199 | + params := access_control.NewGetResourcePermissionsParamsWithContext(ctx).WithResource(args.Resource).WithResourceID(args.ResourceID) |
| 200 | + |
| 201 | + resp, err := c.AccessControl.GetResourcePermissionsWithParams(params) |
| 202 | + if err != nil { |
| 203 | + return nil, fmt.Errorf("get resource permissions: %w", err) |
| 204 | + } |
| 205 | + return resp.Payload, nil |
| 206 | +} |
| 207 | + |
| 208 | +var GetResourcePermissions = mcpgrafana.MustTool( |
| 209 | + "get_resource_permissions", |
| 210 | + "List all permissions set on a specific Grafana resource (e.g., dashboard, datasource, folder) by its type and ID.", |
| 211 | + getResourcePermissions, |
| 212 | + mcp.WithTitleAnnotation("Get resource permissions"), |
| 213 | + mcp.WithIdempotentHintAnnotation(true), |
| 214 | + mcp.WithReadOnlyHintAnnotation(true), |
| 215 | +) |
| 216 | + |
| 217 | +type GetResourceDescriptionParams struct { |
| 218 | + ResourceType string `json:"resourceType" jsonschema:"required,enum=dashboards,enum=datasources,enum=folders,enum=teams,enum=users,enum=serviceaccounts,description=Type of Grafana resource to get description for"` |
| 219 | +} |
| 220 | + |
| 221 | +func getResourceDescription(ctx context.Context, args GetResourceDescriptionParams) (*models.Description, error) { |
| 222 | + c := mcpgrafana.GrafanaClientFromContext(ctx) |
| 223 | + |
| 224 | + params := access_control.NewGetResourceDescriptionParamsWithContext(ctx). |
| 225 | + WithResource(args.ResourceType) |
| 226 | + |
| 227 | + resp, err := c.AccessControl.GetResourceDescriptionWithParams(params) |
| 228 | + if err != nil { |
| 229 | + return nil, fmt.Errorf("get resource description: %w", err) |
| 230 | + } |
| 231 | + |
| 232 | + return resp.Payload, nil |
| 233 | +} |
| 234 | + |
| 235 | +var GetResourceDescription = mcpgrafana.MustTool( |
| 236 | + "get_resource_description", |
| 237 | + "List available permissions and assignment capabilities for a Grafana resource type.", |
| 238 | + getResourceDescription, |
| 239 | + mcp.WithTitleAnnotation("Get resource description"), |
| 240 | + mcp.WithIdempotentHintAnnotation(true), |
| 241 | + mcp.WithReadOnlyHintAnnotation(true), |
| 242 | +) |
| 243 | + |
64 | 244 | func AddAdminTools(mcp *server.MCPServer) { |
65 | 245 | ListTeams.Register(mcp) |
66 | 246 | ListUsersByOrg.Register(mcp) |
| 247 | + ListAllRoles.Register(mcp) |
| 248 | + GetRoleDetails.Register(mcp) |
| 249 | + GetRoleAssignments.Register(mcp) |
| 250 | + ListUserRoles.Register(mcp) |
| 251 | + ListTeamRoles.Register(mcp) |
| 252 | + GetResourcePermissions.Register(mcp) |
| 253 | + GetResourceDescription.Register(mcp) |
67 | 254 | } |
0 commit comments