Skip to content

Commit 79fb28c

Browse files
dominicmacaulaydallasbpeters
authored andcommitted
Extract remaining tools (#27)
* Create read tool file method * extract the theme generator * Finish tool class extractions * Extract md files * specifiy import type * update type * removed unused parameter * removed useless variable stuff
1 parent d83afa4 commit 79fb28c

24 files changed

+1303
-1384
lines changed

src/_internal/resource-path.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,11 @@ const readPromptFile = async (filename: string): Promise<string> => {
1616
return readFileSync(filePath, 'utf-8')
1717
}
1818

19-
export { readResourceFile, readPromptFile }
19+
const readToolFile = async (filename: string): Promise<string> => {
20+
const currentDir = dirname(fileURLToPath(import.meta.url))
21+
const filePath = join(currentDir, '..', 'tools', filename)
22+
23+
return readFileSync(filePath, 'utf-8')
24+
}
25+
26+
export { readResourceFile, readPromptFile, readToolFile }

src/index.ts

Lines changed: 14 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,6 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
1212
import type { ListPromptsRequestSchema, GetPromptRequestSchema } from "@modelcontextprotocol/sdk/types"
1313
import { z } from 'zod';
1414
import { 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
2517
import * as systemOverview from './resources/system-overview.js';
@@ -35,8 +27,6 @@ import * as accessibleColorComboPrompt from './prompts/accessible-color-combo.js
3527
import * as designReviewPrompt from './prompts/design-review.js';
3628
import * as explainTokenSystemPrompt from './prompts/explain-token-system.js';
3729
import * 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
4232
import GetTokenTool from './tools/get-token-tool.js';
@@ -46,20 +36,20 @@ import ListComponentsTool from './tools/list-components-tool.js'
4636
import GetComponentInfoTool from './tools/get-component-info-tool.js';
4737
import GetComponentTokensTool from './tools/get-component-tokens-tool.js';
4838
import 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';
4941
import 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
*/
5450
const 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

164152
prompts.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

206200
tools.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

Comments
 (0)