Skip to main content
Glama
grafana
by grafana

grafana_ui

Access Grafana UI components, documentation, themes, and metadata to build Grafana-compatible interfaces using React components and design system tokens.

Instructions

Unified tool for accessing Grafana UI components, documentation, themes, and metadata

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYesThe action to perform
componentNameNoName of the Grafana UI component (e.g., "Button", "Alert")
queryNoSearch query string (required for search action)
includeDescriptionNoWhether to search in documentation content (default: false)
categoryNoToken category to filter by (colors, typography, spacing, shadows, etc.)
deepNoWhether to analyze dependencies recursively (default: false)
pathNoPath within the repository (default: components directory)
ownerNoRepository owner (default: "grafana")
repoNoRepository name (default: "grafana")
branchNoBranch name (default: "main")

Implementation Reference

  • Primary handler implementation for the 'grafana_ui' tool. This exported function is used by the MCP server's CallToolRequestSchema handler. It validates params, switches on 'action', and calls various axios and parser utilities to fetch component code, demos, metadata, etc.
    export const toolHandlers = { grafana_ui: async (params: any) => { try { switch (params.action) { case "get_component": const sourceCode = await axios.getComponentSource( params.componentName!, ); return createSuccessResponse(sourceCode); case "get_demo": const demoCode = await axios.getComponentDemo(params.componentName!); return createSuccessResponse(demoCode); case "list_components": const components = await axios.getAvailableComponents(); return createSuccessResponse({ components: components.sort(), total: components.length, }); case "get_metadata": const metadata = await axios.getComponentMetadata( params.componentName!, ); return createSuccessResponse(metadata); case "get_directory": const directoryTree = await axios.buildDirectoryTree( params.owner || axios.paths.REPO_OWNER, params.repo || axios.paths.REPO_NAME, params.path || axios.paths.COMPONENTS_PATH, params.branch || axios.paths.REPO_BRANCH, ); return createSuccessResponse(directoryTree); case "get_documentation": const mdxContent = await axios.getComponentDocumentation( params.componentName!, ); const parsedContent = parseMDXContent( params.componentName!, mdxContent, ); return createSuccessResponse({ title: parsedContent.title, sections: parsedContent.sections.map((section) => ({ title: section.title, level: section.level, content: section.content.substring(0, 500) + (section.content.length > 500 ? "..." : ""), examples: section.examples.length, })), totalExamples: parsedContent.examples.length, imports: parsedContent.imports, components: parsedContent.components, }); case "get_stories": const storyContent = await axios.getComponentDemo( params.componentName!, ); const storyMetadata = parseStoryMetadata( params.componentName!, storyContent, ); const examples = extractStoryExamples(storyContent); return createSuccessResponse({ component: storyMetadata.componentName, meta: storyMetadata.meta, totalStories: storyMetadata.totalStories, hasInteractiveStories: storyMetadata.hasInteractiveStories, examples: examples.slice(0, 5), rawStoryCode: storyContent.substring(0, 1000) + (storyContent.length > 1000 ? "..." : ""), }); case "get_tests": const testContent = await axios.getComponentTests( params.componentName!, ); const testDescriptions = []; const testRegex = /(describe|it|test)\s*\(\s*['`"]([^'`"]+)['`"]/g; let match; while ((match = testRegex.exec(testContent)) !== null) { testDescriptions.push({ type: match[1], description: match[2], }); } return createSuccessResponse({ component: params.componentName, testDescriptions: testDescriptions.slice(0, 10), totalTests: testDescriptions.filter( (t) => t.type === "it" || t.type === "test", ).length, testCode: testContent.substring(0, 2000) + (testContent.length > 2000 ? "..." : ""), }); case "search": const searchResults = await axios.searchComponents( params.query!, params.includeDescription || false, ); return createSuccessResponse({ query: params.query, includeDescription: params.includeDescription || false, results: searchResults, totalResults: searchResults.length, }); case "get_theme_tokens": const themeFiles = await axios.getThemeFiles(params.category); const processedThemes: any = {}; for (const [themeName, themeContent] of Object.entries( themeFiles.themes, )) { if (typeof themeContent === "string") { const tokens = extractThemeTokens(themeContent); const themeMetadata = extractThemeMetadata(themeContent); processedThemes[themeName] = { metadata: themeMetadata, tokens: params.category ? filterTokensByCategory(tokens, params.category) : tokens, }; } } return createSuccessResponse({ category: params.category || "all", themes: processedThemes, availableThemes: Object.keys(processedThemes), }); case "get_dependencies": const dependencies = await axios.getComponentDependencies( params.componentName!, params.deep || false, ); return createSuccessResponse(dependencies); default: throw new McpError( ErrorCode.InvalidParams, `Unknown action: ${params.action}`, ); } } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Failed to execute action "${params.action}": ${error instanceof Error ? error.message : String(error)}`, ); } }, };
  • Zod schema used to validate input parameters for the grafana_ui tool, ensuring required fields like componentName or query based on the action.
    const unifiedToolSchema = z .object({ action: z.enum([ "get_component", "get_demo", "list_components", "get_metadata", "get_directory", "get_documentation", "get_stories", "get_tests", "search", "get_theme_tokens", "get_dependencies", ]), componentName: z.string().optional(), query: z.string().optional(), includeDescription: z.boolean().optional(), category: z.string().optional(), deep: z.boolean().optional(), path: z.string().optional(), owner: z.string().optional(), repo: z.string().optional(), branch: z.string().optional(), }) .refine( (data) => { // Validate required parameters based on action switch (data.action) { case "get_component": case "get_demo": case "get_metadata": case "get_documentation": case "get_stories": case "get_tests": case "get_dependencies": return !!data.componentName; case "search": return !!data.query; case "list_components": case "get_directory": case "get_theme_tokens": return true; default: return false; } }, { message: "Missing required parameters for the specified action", }, );
  • src/tools.ts:321-390 (registration)
    Tool registration object used by ListToolsRequestSchema to advertise the available 'grafana_ui' tool with its description and input schema.
    export const tools = { grafana_ui: { name: "grafana_ui", description: "Unified tool for accessing Grafana UI components, documentation, themes, and metadata", inputSchema: { type: "object", properties: { action: { type: "string", enum: [ "get_component", "get_demo", "list_components", "get_metadata", "get_directory", "get_documentation", "get_stories", "get_tests", "search", "get_theme_tokens", "get_dependencies", ], description: "The action to perform", }, componentName: { type: "string", description: 'Name of the Grafana UI component (e.g., "Button", "Alert")', }, query: { type: "string", description: "Search query string (required for search action)", }, includeDescription: { type: "boolean", description: "Whether to search in documentation content (default: false)", }, category: { type: "string", description: "Token category to filter by (colors, typography, spacing, shadows, etc.)", }, deep: { type: "boolean", description: "Whether to analyze dependencies recursively (default: false)", }, path: { type: "string", description: "Path within the repository (default: components directory)", }, owner: { type: "string", description: 'Repository owner (default: "grafana")', }, repo: { type: "string", description: 'Repository name (default: "grafana")', }, branch: { type: "string", description: 'Branch name (default: "main")', }, }, required: ["action"], }, },
  • Utility function that returns the unifiedToolSchema for 'grafana_ui' during tool execution validation in the main MCP request handler.
    /** * Get Zod schema for tool validation if available * @param toolName Name of the tool * @returns Zod schema or undefined */ function getToolSchema(toolName: string): z.ZodType | undefined { try { switch (toolName) { case "grafana_ui": return unifiedToolSchema; default: return undefined; } } catch (error) { console.error("Error getting schema:", error); return undefined; } }
  • Helper function used by the grafana_ui handler to format successful responses with text content.
    function createSuccessResponse(data: any) { return { content: [ { type: "text" as const, text: typeof data === "string" ? data : JSON.stringify(data, null, 2), }, ], };

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/grafana/grafana-ui-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server