Skip to main content
Glama
AGENTS.md16.3 kB
# AGENTS.md - Guide for AI Agents Working in ECL MCP Server ## Project Overview This is an **MCP (Model Context Protocol) server** that provides comprehensive knowledge about the **Europa Component Library (ECL)** - the design system for the European Commission. The server exposes ECL's 50+ components, design guidelines, setup instructions, and code generation tools through the MCP protocol. **Technology Stack:** - Node.js (>=18.0.0) with ES modules - @modelcontextprotocol/sdk v1.0.4 - Pure JavaScript (no TypeScript, no build step) - Stdio-based MCP server **Project Type:** MCP server / Design system knowledge base ## Essential Commands ### Development ```bash npm start # Start the server npm run dev # Start with auto-restart (--watch flag) npm install # Install dependencies ``` ### Testing the Server ```bash node index.js # Run directly - should output "ECL MCP Server running on stdio" ``` **Note:** There are no test scripts, linters, or build tools configured. This is intentional - it's a simple, single-file server. ## Code Organization ``` ecl_mcp/ ├── index.js # Main server implementation (single file) ├── ecl-data.json # Complete ECL component database ├── package.json # NPM configuration ├── README.md # User documentation ├── SETUP.md # Installation instructions └── .gitignore # Git ignore rules ``` ### File Structure **`index.js` (720 lines)** - Complete MCP server implementation: - Lines 1-28: Imports, ECL data loading, initialization - Lines 30-42: Server instance creation - Lines 44-80: Resource listing (5 resources) - Lines 82-178: Resource content handlers - Lines 180-290: Tool definitions (7 tools) - Lines 292-716: Tool request handlers - Lines 718-728: Server startup **`ecl-data.json`** - Structured data containing: - Metadata: version (4.11.1), name, description - Installation methods: npm, yarn, CDN patterns - Setup: HTML template, dependencies, JavaScript init - Components: 54 components across 6 categories - Guidelines: typography, colours, images, iconography, spacing - Utilities and resources - Important implementation notes ## Data Schema ### Component Structure Every component in `ecl-data.json` has these fields: ```javascript { "name": "Button", // Display name "category": "content", // Category (forms/navigation/content/media/banners/site-wide) "url": "https://...", // Official ECL documentation URL "description": "Brief description", // What the component is "usage": "When to use it", // Usage guidance "auto_init": "Button", // Optional: JS initialization class name "example": "<button>...</button>", // Optional: HTML code example "variants": ["primary", "secondary"],// Optional: Available variants "dependencies": ["pikaday"], // Optional: External dependencies "sizes": ["xs", "s", "m", "l"], // Optional: Available sizes (icons only) "format": "DD/MM/YYYY" // Optional: Data format (datepicker) } ``` ### Component Categories - **content** (26 components): accordion, button, card, icon, modal, table, tag, etc. - **navigation** (9 components): breadcrumb, menu, pagination, tabs, links - **forms** (11 components): checkbox, text-field, datepicker, file-upload, select, etc. - **banners** (2 components): banner, carousel - **media** (3 components): gallery, featured-item, media-container - **site-wide** (3 components): site-header, site-footer, page-header ### Component Naming Convention Components are keyed by **kebab-case slugs**: `accordion`, `text-field`, `inpage-navigation`, `list-illustration` ## MCP Server Architecture ### Available Resources (5) Resources are read-only content accessible via URIs: 1. `ecl://overview` - ECL metadata and important notes 2. `ecl://installation` - Installation and setup instructions 3. `ecl://components` - Complete component list 4. `ecl://guidelines` - Design guidelines 5. `ecl://setup-template` - Ready-to-use HTML template ### Available Tools (7) Tools are callable functions with parameters: 1. **`get_component`** - Get detailed component info - Param: `component_name` (string) - Returns: Full component data 2. **`search_components`** - Search by category/keyword - Param: `query` (string) - Returns: Matching components with metadata 3. **`generate_component_code`** - Generate HTML code - Params: `component_name` (string), `variant` (optional string) - Returns: HTML with comments for variants and auto-init 4. **`get_setup_guide`** - Get setup instructions - Param: `method` (enum: "npm", "cdn", "complete") - Returns: Setup guide for chosen method 5. **`list_components_by_category`** - List by category - Param: `category` (enum: forms/navigation/content/media/banners/site-wide) - Returns: All components in category 6. **`get_guidelines`** - Get design guidelines - Param: `guideline_type` (enum: typography/colours/colors/images/iconography/spacing/all) - Returns: Requested guideline data - Note: Accepts both "colours" and "colors" 7. **`get_javascript_init`** - Get JS initialization code - Param: `component_name` (optional string) - Returns: Auto-init patterns or general JS guidance ## Code Patterns and Conventions ### ES Modules This project uses **ES modules** (`"type": "module"` in package.json): ```javascript import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import fs from 'fs/promises'; ``` Always use `.js` extensions in import paths and `fs/promises` for async file operations. ### Error Handling Pattern All tool handlers follow this pattern: ```javascript try { // Tool logic return { content: [{ type: 'text', text: 'Response data' }] }; } catch (error) { return { content: [{ type: 'text', text: `Error: ${error.message}` }], isError: true }; } ``` ### Component Name Normalization Always normalize component names before lookup: ```javascript const componentName = args.component_name.toLowerCase().replace(/\s+/g, '-'); const component = eclData.components[componentName]; ``` This allows users to input "Text Field", "text field", or "text-field" interchangeably. ### JSON Response Formatting All structured data responses use pretty-printed JSON: ```javascript text: JSON.stringify(data, null, 2) ``` ### Request Handler Pattern All request handlers use the MCP SDK schema pattern: ```javascript server.setRequestHandler(SchemaName, async (request) => { const { params } = request; // Handler logic return { ... }; }); ``` ### Stdio Transport The server uses stdio transport for communication: ```javascript const transport = new StdioServerTransport(); await server.connect(transport); console.error('ECL MCP Server running on stdio'); ``` **Important:** Use `console.error()` for logging (not `console.log()`) to avoid interfering with stdio protocol. ## Important Gotchas ### 1. ECL Data Loading is Synchronous at Startup The server loads `ecl-data.json` at startup. If this file is missing or malformed, the server exits immediately: ```javascript try { const data = await fs.readFile(eclDataPath, 'utf-8'); eclData = JSON.parse(data); } catch (error) { console.error('Error loading ECL data:', error); process.exit(1); // Hard exit } ``` **Never modify the server without ensuring `ecl-data.json` is valid.** ### 2. Component Lookup is Case-Sensitive in the Data While user input is normalized, the internal keys in `ecl-data.json` must be kebab-case. If you add components, use: `text-field`, not `Text-Field` or `text_field`. ### 3. Auto-init Values Match ECL JavaScript Classes The `auto_init` field contains ECL's JavaScript class names (e.g., "Accordion", "Datepicker"). These must match ECL's actual implementation. Don't invent auto-init values. ### 4. Colour vs Color Spelling ECL uses British spelling "colours" in the data, but the tool accepts both: ```javascript const guidelineKey = type === 'colors' ? 'colours' : type; ``` When adding guideline types, maintain this pattern. ### 5. No Component Validation in generate_component_code The code generation tool doesn't validate variants or dependencies - it just returns the example with comments. It's informational, not a full template engine. ### 6. Resource URIs are Hardcoded The 5 resources have fixed URIs (`ecl://overview`, etc.). If you add resources, update both `ListResourcesRequestSchema` handler and `ReadResourceRequestSchema` handler. ### 7. Tool Schemas Must Match Handler Logic If you modify tool parameters in `ListToolsRequestSchema`, you must also update the corresponding handler in `CallToolRequestSchema`. The SDK doesn't auto-validate this. ### 8. Server Runs Forever The stdio server runs indefinitely until killed. There's no timeout or shutdown mechanism. This is standard for MCP servers. ## ECL-Specific Knowledge ### ECL Version This server is based on **ECL v4.11.1 (EU variant)**. The EC (European Commission) variant exists but is not included. ### Critical ECL Implementation Notes When helping users implement ECL: 1. **SVG Sprites:** Must be hosted on the same domain (CORS issues) 2. **CDN vs Local:** Recommend local hosting over CDN 3. **Pikaday Dependency:** Datepicker requires separate Pikaday and Moment.js installation 4. **Cookie Consent:** Required before production deployment 5. **Auto-init Pattern:** Components need `data-ecl-auto-init="[ClassName]"` and `ECL.autoInit()` call ### JavaScript Initialization ECL components with interactive behavior need JavaScript: ```html <!-- Add to component root --> <div data-ecl-auto-init="Accordion">...</div> <!-- Call at page end --> <script src="/scripts/ecl-eu.js"></script> <script> ECL.autoInit(); </script> ``` Components requiring JS: Accordion, Banner, Carousel, Category Filter, Datepicker, Expandable, File Upload, Gallery, Inpage Navigation, Mega Menu, Menu, Message, Modal, Navigation List, Notification, Popover, Tabs, Timeline ### Form Component Pattern All ECL form components follow this wrapper pattern: ```html <div class="ecl-form-group"> <label class="ecl-form-label">Label</label> <div class="ecl-[component]"> <!-- Component markup --> </div> </div> ``` ## Modifying This Project ### Adding a New Component to ecl-data.json 1. Add entry with kebab-case key 2. Include all required fields: name, category, url, description, usage 3. Add optional fields: auto_init (if JS needed), example, variants, dependencies 4. Ensure URL points to official ECL documentation 5. Test with `get_component` and `search_components` tools ### Adding a New Tool 1. Add tool definition in `ListToolsRequestSchema` handler 2. Add tool handler in `CallToolRequestSchema` handler 3. Follow error handling pattern with try-catch 4. Return structured content with `type: 'text'` 5. Update README.md with tool documentation ### Adding a New Resource 1. Add resource entry in `ListResourcesRequestSchema` handler 2. Add URI handler in `ReadResourceRequestSchema` handler 3. Use consistent `ecl://` URI scheme 4. Return appropriate mimeType (application/json or text/html) ### Modifying ecl-data.json This file is the **single source of truth**. All tool responses derive from it. Changes here automatically affect all tools. No code changes needed unless you're adding new top-level sections. ### Code Style Notes - No semicolons enforced (some present, some absent - inconsistent but functional) - Use 2-space indentation - Use arrow functions for handlers - No TypeScript types or JSDoc (intentionally simple) - No external utilities or helpers (inline all logic) ## Configuration for MCP Clients ### Claude Desktop ```json { "mcpServers": { "ecl": { "command": "node", "args": ["/absolute/path/to/ecl_mcp/index.js"] } } } ``` Config locations: - **Linux:** `~/.config/Claude/claude_desktop_config.json` - **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json` - **Windows:** `%APPDATA%\Claude\claude_desktop_config.json` ### Cline (VS Code Extension) Add to VS Code settings.json: ```json { "mcp.servers": { "ecl": { "command": "node", "args": ["/absolute/path/to/ecl_mcp/index.js"] } } } ``` **Important:** Always use absolute paths. Relative paths may fail depending on client working directory. ## Debugging and Testing ### Manual Testing Run the server and check for startup message: ```bash node index.js # Should output: ECL MCP Server running on stdio ``` If it exits immediately, check: 1. `ecl-data.json` exists and is valid JSON 2. Node version is >=18.0.0 3. Dependencies are installed (`npm install`) ### Testing with MCP Inspector Use the official MCP Inspector tool: ```bash npx @modelcontextprotocol/inspector node index.js ``` This provides a UI to test tools and resources interactively. ### Common Issues **"Cannot find module '@modelcontextprotocol/sdk'"** - Run: `npm install` **"Error loading ECL data"** - Check `ecl-data.json` exists in project root - Validate JSON syntax - Check file permissions **Server starts but tools don't work in client** - Verify absolute path in client config - Restart the MCP client application - Check client logs for connection errors **Changes not reflected** - Restart the server (it doesn't hot-reload) - If using `npm run dev`, it should auto-restart on file changes ## Project Context ### Purpose This server bridges the gap between AI assistants and ECL documentation. Instead of web scraping or hallucinating component APIs, the AI can query structured, verified ECL data. ### Target Users - Developers building EU Commission websites - Teams implementing ECL design system - AI assistants helping with ECL integration ### Maintenance The project is maintained by Simon Hengchen (simon.hengchen@ext.ec.europa.eu). Updates should track official ECL releases. ### Future Enhancements (Not Yet Implemented) - Component preview generation - Accessibility guideline integration - EC variant support (currently EU only) - Component dependency graph - Code validation for generated snippets ## Quick Reference ### Most Common Operations **Find a component:** ```javascript // Tool: search_components { "query": "button" } ``` **Get component details:** ```javascript // Tool: get_component { "component_name": "accordion" } ``` **Generate HTML:** ```javascript // Tool: generate_component_code { "component_name": "button", "variant": "primary" } ``` **List forms:** ```javascript // Tool: list_components_by_category { "category": "forms" } ``` **Setup guide:** ```javascript // Tool: get_setup_guide { "method": "complete" } ``` ### Key Data Locations - **All components:** `eclData.components[componentSlug]` - **Guidelines:** `eclData.guidelines[guidelineType]` - **Installation:** `eclData.installation` - **Setup:** `eclData.setup` - **Version:** `eclData.version` - **Important notes:** `eclData.important_notes` ### Response Patterns **Success with data:** ```javascript return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; ``` **Success with plain text:** ```javascript return { content: [{ type: 'text', text: 'Plain text response' }] }; ``` **Error:** ```javascript return { content: [{ type: 'text', text: `Error: ${error.message}` }], isError: true }; ``` **Not found:** ```javascript return { content: [{ type: 'text', text: 'Component "xyz" not found. Use search_components to find available components.' }] }; ``` ## Summary This is a **simple, single-file MCP server** with no build process, no tests, and no complex tooling. The entire implementation is in `index.js` (720 lines), and all data is in `ecl-data.json`. When making changes: 1. **Read the code first** - it's straightforward and well-structured 2. **Test manually** - just run `node index.js` 3. **Keep it simple** - don't add unnecessary complexity 4. **Respect the data schema** - components have specific required fields 5. **Follow MCP patterns** - use the SDK properly for tools and resources The server's value is in the **curated ECL data**, not complex code. Focus on data accuracy and completeness over clever abstractions.

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/brownrl/eco_mcp'

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