reicon-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "reicon-mcp",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "MCP server and CLI for browsing and applying Reicon icons.",
6
+ "bin": {
7
+ "reicon-mcp": "bin/run.cjs"
8
+ },
9
+ "main": "./server/index.js",
10
+ "files": [
11
+ "bin",
12
+ "cli",
13
+ "server",
14
+ "core",
15
+ "data",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "scripts": {
20
+ "build": "node scripts/build.cjs"
21
+ },
22
+ "keywords": [
23
+ "reicon",
24
+ "icons",
25
+ "mcp",
26
+ "model-context-protocol",
27
+ "svg"
28
+ ],
29
+ "author": "Dev Chauhan",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/dqev/reicon.git",
34
+ "directory": "packages/reicon-mcp"
35
+ },
36
+ "homepage": "https://reicon.dev",
37
+ "bugs": {
38
+ "url": "https://github.com/dqev/reicon/issues"
39
+ },
40
+ "dependencies": {
41
+ "@modelcontextprotocol/sdk": "^1.12.0",
42
+ "zod": "^3.24.0"
43
+ },
44
+ "engines": {
45
+ "node": ">=18"
46
+ }
47
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,57 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { z } from 'zod';
4
+ import { handleApplyIcon } from './tools/apply-icon.js';
5
+ import { handleListCategories } from './tools/list-categories.js';
6
+ import { handleSearchIcons } from './tools/search-icons.js';
7
+ import { handleViewIcon } from './tools/view-icon.js';
8
+ const server = new McpServer({
9
+ name: 'reicon-mcp',
10
+ version: '1.0.0',
11
+ });
12
+ server.tool('search_icons', 'Search Reicon icons by keyword. Returns ranked matches for agent selection.', {
13
+ query: z.string().describe('Concise search keywords, not full sentences'),
14
+ weight: z.enum(['Outline', 'Filled']).optional(),
15
+ limit: z.number().optional(),
16
+ }, async (args) => {
17
+ const result = handleSearchIcons(args);
18
+ return {
19
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
20
+ };
21
+ });
22
+ server.tool('view_icon', 'View raw SVG markup and metadata for a Reicon icon.', {
23
+ name: z.string().describe('Icon kebab-case name'),
24
+ weight: z.enum(['Outline', 'Filled']),
25
+ }, async (args) => {
26
+ const result = handleViewIcon(args);
27
+ return {
28
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
29
+ };
30
+ });
31
+ server.tool('apply_icon', 'Generate copy-pasteable import and usage code for a Reicon icon.', {
32
+ name: z.string(),
33
+ weight: z.enum(['Outline', 'Filled']),
34
+ framework: z.enum(['react', 'vue', 'svelte', 'html', 'svg']),
35
+ size: z.number().optional(),
36
+ color: z.string().optional(),
37
+ componentName: z.string().optional(),
38
+ }, async (args) => {
39
+ const result = handleApplyIcon(args);
40
+ return {
41
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
42
+ };
43
+ });
44
+ server.tool('list_categories', 'List all icon categories in the Reicon dataset.', {}, async () => {
45
+ const result = handleListCategories();
46
+ return {
47
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
48
+ };
49
+ });
50
+ async function main() {
51
+ const transport = new StdioServerTransport();
52
+ await server.connect(transport);
53
+ }
54
+ main().catch((err) => {
55
+ console.error(err);
56
+ process.exit(1);
57
+ });
@@ -0,0 +1,4 @@
1
+ import type { ApplyIconInput } from '../../core/types.js';
2
+ export declare function handleApplyIcon(args: ApplyIconInput): import("../../core/types.js").ApplyIconOutput | {
3
+ error: string;
4
+ };
@@ -0,0 +1,11 @@
1
+ import { generateCode } from '../../core/codegen.js';
2
+ import { loadIndex } from '../../core/load-index.js';
3
+ import { findIcon } from '../../core/search.js';
4
+ export function handleApplyIcon(args) {
5
+ const index = loadIndex();
6
+ const icon = findIcon(index, args.name);
7
+ if (!icon) {
8
+ return { error: `Icon "${args.name}" not found.` };
9
+ }
10
+ return generateCode(icon, args);
11
+ }
@@ -0,0 +1,3 @@
1
+ export declare function handleListCategories(): {
2
+ categories: string[];
3
+ };
@@ -0,0 +1,6 @@
1
+ import { loadIndex } from '../../core/load-index.js';
2
+ import { listCategories } from '../../core/search.js';
3
+ export function handleListCategories() {
4
+ const index = loadIndex();
5
+ return { categories: listCategories(index) };
6
+ }
@@ -0,0 +1,11 @@
1
+ import type { IconWeight } from '../../core/types.js';
2
+ export declare function handleSearchIcons(args: {
3
+ query: string;
4
+ weight?: IconWeight;
5
+ limit?: number;
6
+ }): {
7
+ results: import("../../core/types.js").SearchResult[];
8
+ instruction: string;
9
+ } | {
10
+ error: string;
11
+ };
@@ -0,0 +1,9 @@
1
+ import { loadIndex } from '../../core/load-index.js';
2
+ import { searchIcons } from '../../core/search.js';
3
+ export function handleSearchIcons(args) {
4
+ const index = loadIndex();
5
+ return searchIcons(index, args.query, {
6
+ weight: args.weight,
7
+ limit: args.limit,
8
+ });
9
+ }
@@ -0,0 +1,12 @@
1
+ import type { IconWeight } from '../../core/types.js';
2
+ export declare function handleViewIcon(args: {
3
+ name: string;
4
+ weight: IconWeight;
5
+ }): {
6
+ error: string;
7
+ } | {
8
+ svg: string;
9
+ viewBox: string;
10
+ tags: string[];
11
+ category: string;
12
+ };
@@ -0,0 +1,21 @@
1
+ import { buildSvgMarkup } from '../../core/codegen.js';
2
+ import { loadIndex } from '../../core/load-index.js';
3
+ import { findIcon } from '../../core/search.js';
4
+ export function handleViewIcon(args) {
5
+ const index = loadIndex();
6
+ const icon = findIcon(index, args.name);
7
+ if (!icon) {
8
+ return { error: `Icon "${args.name}" not found.` };
9
+ }
10
+ const svg = buildSvgMarkup(icon, args.weight);
11
+ if (typeof svg !== 'string') {
12
+ return svg;
13
+ }
14
+ const weightData = icon.weights[args.weight];
15
+ return {
16
+ svg,
17
+ viewBox: weightData.viewBox,
18
+ tags: icon.tags,
19
+ category: icon.category,
20
+ };
21
+ }