@@ -12,14 +12,6 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
1212import type { ListPromptsRequestSchema , GetPromptRequestSchema } from "@modelcontextprotocol/sdk/types"
1313import { z } from 'zod' ;
1414import { designTokens } from './optics-data.js' ;
15- import { generateTheme } from './tools/theme-generator.js' ;
16- import { validateTokenUsage , formatValidationReport } from './tools/validate.js' ;
17-
18- import { checkTokenContrast , formatContrastResult } from './tools/accessibility.js' ;
19- import { suggestTokenMigration , formatMigrationSuggestions } from './tools/migration.js' ;
20- import { generateComponentScaffold , formatScaffoldOutput } from './tools/scaffold.js' ;
21- import { generateStickerSheet , formatStickerSheet } from './tools/sticker-sheet.js' ;
22- import { getRecipe , searchRecipes , formatRecipe , formatRecipeList } from './tools/recipes.js' ;
2315
2416// Resources
2517import * as systemOverview from './resources/system-overview.js' ;
@@ -35,8 +27,6 @@ import * as accessibleColorComboPrompt from './prompts/accessible-color-combo.js
3527import * as designReviewPrompt from './prompts/design-review.js' ;
3628import * as explainTokenSystemPrompt from './prompts/explain-token-system.js' ;
3729import * as getTokenReferencePrompt from './prompts/get-token-reference.js' ;
38- import * as configureIconsPrompt from './prompts/configure-icons.js' ;
39- import * as useRecipePrompt from './prompts/use-recipe.js' ;
4030
4131// Tools
4232import GetTokenTool from './tools/get-token-tool.js' ;
@@ -46,20 +36,20 @@ import ListComponentsTool from './tools/list-components-tool.js'
4636import GetComponentInfoTool from './tools/get-component-info-tool.js' ;
4737import GetComponentTokensTool from './tools/get-component-tokens-tool.js' ;
4838import SearchDocumentationTool from './tools/search-documentation-tool.js' ;
39+ import GenerateThemeTool from './tools/generate-theme-tool.js' ;
40+ import ValidateTokenUsageTool from './tools/validate-token-usage-tool.js' ;
4941import ReplaceHardCodedValuesTool from './tools/replace-hard-coded-values-tool.js' ;
42+ import CheckContrastTool from './tools/check-contrast-tool.js' ;
43+ import SuggestTokenMigrationTool from './tools/suggest-token-migration-tool.js' ;
44+ import GenerateComponentScaffoldTool from './tools/generate-component-scaffold-tool.js' ;
45+ import GenerateStickerSheetTool from './tools/generate-sticker-sheet-tool.js' ;
5046
5147/**
5248 * Create and configure the MCP server
5349 */
5450const server = new McpServer ( {
5551 name : 'optics-mcp' ,
5652 version : '0.1.0' ,
57- } , {
58- capabilities : {
59- tools : { } ,
60- prompts : { } ,
61- resources : { } ,
62- }
6353} ) ;
6454
6555/**
@@ -156,9 +146,7 @@ const prompts = [
156146 accessibleColorComboPrompt ,
157147 designReviewPrompt ,
158148 explainTokenSystemPrompt ,
159- getTokenReferencePrompt ,
160- configureIconsPrompt ,
161- useRecipePrompt
149+ getTokenReferencePrompt
162150]
163151
164152prompts . forEach ( ( prompt ) => {
@@ -200,7 +188,13 @@ const tools = [
200188 new GetComponentInfoTool ( ) ,
201189 new GetComponentTokensTool ( ) ,
202190 new SearchDocumentationTool ( ) ,
203- new ReplaceHardCodedValuesTool ( )
191+ new GenerateThemeTool ( ) ,
192+ new ValidateTokenUsageTool ( ) ,
193+ new ReplaceHardCodedValuesTool ( ) ,
194+ new CheckContrastTool ( ) ,
195+ new SuggestTokenMigrationTool ( ) ,
196+ new GenerateComponentScaffoldTool ( ) ,
197+ new GenerateStickerSheetTool ( )
204198]
205199
206200tools . forEach ( ( tool ) => {
@@ -226,194 +220,6 @@ tools.forEach((tool) => {
226220 )
227221} )
228222
229- /**
230- * Tool: Generate Theme
231- */
232- server . registerTool (
233- 'generate_theme' ,
234- {
235- title : 'Generate Theme' ,
236- description : 'Generate a custom Optics theme with CSS variable overrides' ,
237- inputSchema : {
238- brandName : z . string ( ) . describe ( 'Name of the brand/theme (e.g., "Acme Corp")' ) ,
239- primary : z . string ( ) . describe ( 'Primary brand color (hex, e.g., "#0066CC")' ) ,
240- secondary : z . string ( ) . optional ( ) . describe ( 'Secondary color (hex, optional)' ) ,
241- } ,
242- } ,
243- async ( { brandName, primary, secondary } ) => {
244- const brandColors = {
245- primary,
246- secondary,
247- } ;
248-
249- const theme = generateTheme ( brandName , brandColors ) ;
250-
251- return {
252- content : [
253- {
254- type : 'text' ,
255- text : `# ${ brandName } Theme Generated\n\n## CSS Variables\n\n\`\`\`css\n${ theme . cssVariables } \n\`\`\`\n\n## Figma Variables\n\nSave this as \`figma-variables.json\`:\n\n\`\`\`json\n${ theme . figmaVariables } \n\`\`\`\n\n## Summary\n\n- **Total tokens**: ${ theme . tokens . length } \n- **Colors**: ${ theme . tokens . filter ( t => t . category === 'color' ) . length } \n- **Typography**: ${ theme . tokens . filter ( t => t . category === 'typography' ) . length } \n- **Spacing**: ${ theme . tokens . filter ( t => t . category === 'spacing' ) . length } \n\n${ theme . documentation } ` ,
256- } ,
257- ] ,
258- } ;
259- }
260- ) ;
261-
262- /**
263- * Tool: Validate Token Usage
264- */
265- server . registerTool (
266- 'validate_token_usage' ,
267- {
268- title : 'Validate Token Usage' ,
269- description : 'Validate code for hard-coded values that should use design tokens' ,
270- inputSchema : {
271- code : z . string ( ) . describe ( 'CSS or component code to validate' ) ,
272- } ,
273- } ,
274- async ( { code } ) => {
275- const report = validateTokenUsage ( code , designTokens ) ;
276- const formatted = formatValidationReport ( report ) ;
277-
278- return {
279- content : [
280- {
281- type : 'text' ,
282- text : formatted ,
283- } ,
284- ] ,
285- } ;
286- }
287- ) ;
288-
289-
290-
291- /**
292- * Tool: Check Contrast
293- */
294- server . registerTool (
295- 'check_contrast' ,
296- {
297- title : 'Check Contrast' ,
298- description : 'Check WCAG contrast ratio between two color tokens' ,
299- inputSchema : {
300- foregroundToken : z . string ( ) . describe ( 'Foreground color token name' ) ,
301- backgroundToken : z . string ( ) . describe ( 'Background color token name' ) ,
302- } ,
303- } ,
304- async ( { foregroundToken, backgroundToken } ) => {
305- const result = checkTokenContrast ( foregroundToken , backgroundToken , designTokens ) ;
306- const formatted = formatContrastResult ( result ) ;
307-
308- return {
309- content : [
310- {
311- type : 'text' ,
312- text : formatted ,
313- } ,
314- ] ,
315- } ;
316- }
317- ) ;
318-
319- /**
320- * Tool: Suggest Token Migration
321- */
322- server . registerTool (
323- 'suggest_token_migration' ,
324- {
325- title : 'Suggest Token Migration' ,
326- description : 'Suggest design tokens for a hard-coded value' ,
327- inputSchema : {
328- value : z . string ( ) . describe ( 'Hard-coded value to find tokens for (e.g., "#0066CC", "16px")' ) ,
329- category : z . string ( ) . optional ( ) . describe ( 'Optional category filter (color, spacing, typography)' ) ,
330- } ,
331- } ,
332- async ( { value, category } ) => {
333- const suggestion = suggestTokenMigration ( value , designTokens , category ) ;
334- const formatted = formatMigrationSuggestions ( suggestion ) ;
335-
336- return {
337- content : [
338- {
339- type : 'text' ,
340- text : formatted ,
341- } ,
342- ] ,
343- } ;
344- }
345- ) ;
346-
347- /**
348- * Tool: Generate Component Scaffold
349- */
350- server . registerTool (
351- 'generate_component_scaffold' ,
352- {
353- title : 'Generate Component Scaffold' ,
354- description : 'Generate a React component scaffold with proper token usage' ,
355- inputSchema : {
356- componentName : z . string ( ) . describe ( 'Name of the component (e.g., "Alert", "Card")' ) ,
357- description : z . string ( ) . describe ( 'Brief description of the component' ) ,
358- tokens : z . array ( z . string ( ) ) . describe ( 'List of token names the component should use' ) ,
359- } ,
360- } ,
361- async ( { componentName, description, tokens } ) => {
362- const scaffold = generateComponentScaffold (
363- componentName ,
364- description ,
365- tokens ,
366- designTokens
367- ) ;
368- const formatted = formatScaffoldOutput ( scaffold ) ;
369-
370- return {
371- content : [
372- {
373- type : 'text' ,
374- text : formatted ,
375- } ,
376- ] ,
377- } ;
378- }
379- ) ;
380-
381- /**
382- * Tool: Generate Sticker Sheet
383- */
384- server . registerTool (
385- 'generate_sticker_sheet' ,
386- {
387- title : 'Generate Sticker Sheet' ,
388- description : 'Generate a visual style guide with color swatches and component examples' ,
389- inputSchema : {
390- framework : z . enum ( [ 'react' , 'vue' , 'svelte' , 'html' ] ) . optional ( ) . describe ( 'Target framework (default: react)' ) ,
391- includeColors : z . boolean ( ) . optional ( ) . describe ( 'Include color swatches (default: true)' ) ,
392- includeTypography : z . boolean ( ) . optional ( ) . describe ( 'Include typography specimens (default: true)' ) ,
393- includeComponents : z . boolean ( ) . optional ( ) . describe ( 'Include component examples (default: true)' ) ,
394- } ,
395- } ,
396- async ( { framework, includeColors, includeTypography, includeComponents } ) => {
397- const options = {
398- framework : framework ?? 'react' ,
399- includeColors : includeColors ?? true ,
400- includeTypography : includeTypography ?? true ,
401- includeComponents : includeComponents ?? true ,
402- } ;
403- const sheet = generateStickerSheet ( designTokens , components , options ) ;
404- const formatted = formatStickerSheet ( sheet ) ;
405-
406- return {
407- content : [
408- {
409- type : 'text' ,
410- text : formatted ,
411- } ,
412- ] ,
413- } ;
414- }
415- ) ;
416-
417223/**
418224 * Start the server
419225 */
0 commit comments