Skip to main content
Glama

get_external_css

Extract design tokens from external CSS files to analyze design systems without hitting response size limits. Returns colors, spacing, typography tokens and file statistics by default.

Instructions

Extract design tokens from CSS files. DEFAULT BEHAVIOR: Returns ONLY tokens and file statistics (small response ~1-3K tokens). Does NOT return CSS content by default to avoid token limits. For full CSS content, explicitly set includeFullCSS=true and maxContentSize. Perfect for analyzing design system tokens without hitting response size limits.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
cssUrlYesURL of CSS file to analyze. IMPORTANT: Tool returns only design tokens by default (not CSS content) to avoid response size limits.
extractTokensNoExtract design tokens (colors, spacing, typography, etc.). Default: true. This is the main purpose of this tool.
includeFullCSSNoOPTIONAL: Set to true ONLY if you need the actual CSS content. WARNING: Large CSS files may hit token limits. Default: false (recommended).
maxContentSizeNoOPTIONAL: Max CSS content characters when includeFullCSS=true. Default: 10000. Larger files will be truncated.

Implementation Reference

  • Main execution logic for the 'get_external_css' tool. Validates input, resolves URL, performs domain security check, fetches CSS with timeout, extracts design tokens using extractDesignTokens, analyzes CSS stats, and returns structured JSON response with optional full CSS content.
    export async function handleGetExternalCSS(input: any) { let validatedInput: any; try { validatedInput = validateGetExternalCSSInput(input); const client = new StorybookClient(); const baseUrl = client.getStorybookUrl(); // Make URL absolute if it's relative const absoluteUrl = await makeAbsoluteUrl(validatedInput.cssUrl, baseUrl); // Security check: Only allow URLs from the same domain as Storybook if (!isDomainAllowed(absoluteUrl, baseUrl)) { const securityError = createSecurityError( 'fetch external CSS', absoluteUrl, 'CSS URL domain is not allowed. Only URLs from the Storybook domain are permitted for security reasons.' ); throw new Error(securityError.message); } // Fetch CSS content with timeout const timeout = getEnvironmentTimeout(OPERATION_TIMEOUTS.fetchExternalCSS); const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeout); let response; try { response = await fetch(absoluteUrl, { signal: controller.signal, headers: { Accept: 'text/css,*/*;q=0.1', 'User-Agent': 'MCP-Design-System-Extractor/1.0', }, }); } catch (error: any) { if (error.name === 'AbortError') { const timeoutError = createTimeoutError( 'fetch external CSS', timeout, absoluteUrl, 'CSS file' ); throw new Error(timeoutError.message); } const connectionError = createConnectionError('fetch external CSS', absoluteUrl, error); throw new Error(connectionError.message); } finally { clearTimeout(timeoutId); } if (!response.ok) { const connectionError = createConnectionError( 'fetch external CSS', absoluteUrl, `HTTP ${response.status}: ${response.statusText}`, response.status ); throw new Error(connectionError.message); } const cssContent = await response.text(); const contentLength = cssContent.length; // Always perform CSS analysis const analysis = analyzeCSSContent(cssContent); // Extract design tokens if requested let tokens: DesignToken[] = []; let organizedTokens: OrganizedTokens | null = null; if (validatedInput.extractTokens) { tokens = extractDesignTokens(cssContent); organizedTokens = organizeTokens(tokens); } // Build optimized response (tokens-first approach) const result: any = { url: absoluteUrl, originalUrl: validatedInput.cssUrl, fileSize: contentLength, fileSizeFormatted: formatBytes(contentLength), analysis, tokensExtracted: validatedInput.extractTokens, tokenCount: tokens.length, tokens: organizedTokens, }; // Only include CSS content if explicitly requested if (validatedInput.includeFullCSS) { const maxSize = validatedInput.maxContentSize || 10000; if (contentLength <= maxSize) { result.content = cssContent; result.truncated = false; result.displayedSize = contentLength; } else { result.content = cssContent.substring(0, maxSize) + '\n\n/* ... Content truncated due to size limit ... */'; result.truncated = true; result.displayedSize = maxSize; result.truncationWarning = `Content truncated from ${formatBytes(contentLength)} to ${formatBytes(maxSize)}. Use maxContentSize parameter to adjust limit.`; } } const message = validatedInput.includeFullCSS ? `CSS content included from ${validatedInput.cssUrl} (${formatBytes(contentLength)})${ result.truncated ? ' - TRUNCATED due to size' : '' }${validatedInput.extractTokens ? `, ${tokens.length} design tokens extracted` : ''}` : `SUCCESS: Extracted ${tokens.length} design tokens from ${validatedInput.cssUrl} (${formatBytes(contentLength)} file). CSS content NOT included (use includeFullCSS=true if needed).`; return formatSuccessResponse(result, message); } catch (error) { return handleErrorWithContext(error, 'get external CSS', { url: validatedInput?.cssUrl || 'unknown', resource: 'external CSS file', }); } }
  • Tool definition including input schema for validation. Defines parameters like cssUrl (required), extractTokens, includeFullCSS, maxContentSize.
    export const getExternalCSSTool: Tool = { name: 'get_external_css', description: 'Extract design tokens from CSS files. DEFAULT BEHAVIOR: Returns ONLY tokens and file statistics (small response ~1-3K tokens). Does NOT return CSS content by default to avoid token limits. For full CSS content, explicitly set includeFullCSS=true and maxContentSize. Perfect for analyzing design system tokens without hitting response size limits.', inputSchema: { type: 'object', properties: { cssUrl: { type: 'string', description: 'URL of CSS file to analyze. IMPORTANT: Tool returns only design tokens by default (not CSS content) to avoid response size limits.', }, extractTokens: { type: 'boolean', description: 'Extract design tokens (colors, spacing, typography, etc.). Default: true. This is the main purpose of this tool.', }, includeFullCSS: { type: 'boolean', description: 'OPTIONAL: Set to true ONLY if you need the actual CSS content. WARNING: Large CSS files may hit token limits. Default: false (recommended).', }, maxContentSize: { type: 'number', description: 'OPTIONAL: Max CSS content characters when includeFullCSS=true. Default: 10000. Larger files will be truncated.', }, }, required: ['cssUrl'], }, };
  • src/index.ts:15-24 (registration)
    Registers the handler function for 'get_external_css' in the toolHandlers Map, which is used by the MCP server to dispatch tool calls to the correct handler.
    const toolHandlers = new Map<string, (input: any) => Promise<any>>([ ['list_components', tools.handleListComponents], ['get_component_html', tools.handleGetComponentHTML], ['get_component_variants', tools.handleGetComponentVariants], ['search_components', tools.handleSearchComponents], ['get_component_dependencies', tools.handleGetComponentDependencies], ['get_theme_info', tools.handleGetThemeInfo], ['get_component_by_purpose', tools.handleGetComponentByPurpose], ['get_external_css', tools.handleGetExternalCSS], ]);
  • src/index.ts:26-35 (registration)
    Adds the getExternalCSSTool to the allTools array returned by ListToolsRequestHandler for tool discovery.
    const allTools = [ tools.listComponentsTool, tools.getComponentHTMLTool, tools.getComponentVariantsTool, tools.searchComponentsTool, tools.getComponentDependenciesTool, tools.getThemeInfoTool, tools.getComponentByPurposeTool, tools.getExternalCSSTool, ];
  • Runtime input validation function that coerces and validates parameters against the schema, applying defaults.
    function validateGetExternalCSSInput(input: any): GetExternalCSSInput { if (!input || typeof input !== 'object') { throw new Error('Input must be an object'); } if (!input.cssUrl || typeof input.cssUrl !== 'string') { throw new Error('cssUrl must be a non-empty string'); } return { cssUrl: input.cssUrl, extractTokens: input.extractTokens !== false, // Default to true includeFullCSS: input.includeFullCSS === true, // Default to false maxContentSize: input.maxContentSize || 10000, // Default to 10000 chars }; }

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/freema/mcp-design-system-extractor'

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