@jlcpcb/mcp 0.1.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/CHANGELOG.md +15 -0
- package/README.md +241 -0
- package/debug-text.ts +24 -0
- package/dist/assets/search.html +528 -0
- package/dist/index.js +32364 -0
- package/dist/src/index.js +28521 -0
- package/package.json +49 -0
- package/scripts/build-search-page.ts +68 -0
- package/src/assets/search-built.html +528 -0
- package/src/assets/search.html +458 -0
- package/src/browser/index.ts +381 -0
- package/src/browser/kicad-renderer.ts +646 -0
- package/src/browser/sexpr-parser.ts +321 -0
- package/src/http/routes.ts +253 -0
- package/src/http/server.ts +74 -0
- package/src/index.ts +117 -0
- package/src/tools/details.ts +66 -0
- package/src/tools/easyeda.ts +582 -0
- package/src/tools/index.ts +98 -0
- package/src/tools/library-fix.ts +414 -0
- package/src/tools/library-update.ts +412 -0
- package/src/tools/library.ts +263 -0
- package/src/tools/search.ts +58 -0
- package/tsconfig.json +9 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* jlc-mcp
|
|
5
|
+
* MCP server for JLC/EasyEDA component sourcing and library conversion
|
|
6
|
+
*
|
|
7
|
+
* This server uses LCSC part numbers (e.g., C2040) because LCSC is JLC PCB's
|
|
8
|
+
* preferred component supplier for PCB assembly (PCBA). Components sourced via
|
|
9
|
+
* LCSC are guaranteed to be available for JLC's assembly service.
|
|
10
|
+
*
|
|
11
|
+
* EasyEDA (owned by JLC/LCSC) provides the symbol and footprint data.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
15
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
16
|
+
import {
|
|
17
|
+
CallToolRequestSchema,
|
|
18
|
+
ListToolsRequestSchema,
|
|
19
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
20
|
+
|
|
21
|
+
import { tools, toolHandlers } from './tools/index.js';
|
|
22
|
+
import { createLogger, ensureGlobalLibraryTables } from '@jlcpcb/core';
|
|
23
|
+
import { startHttpServer } from './http/server.js';
|
|
24
|
+
|
|
25
|
+
const logger = createLogger('jlc-mcp');
|
|
26
|
+
|
|
27
|
+
// Create MCP server
|
|
28
|
+
const server = new Server(
|
|
29
|
+
{
|
|
30
|
+
name: 'jlc-mcp',
|
|
31
|
+
version: '0.1.0',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
capabilities: {
|
|
35
|
+
tools: {},
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Handle list tools request
|
|
41
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
42
|
+
logger.debug('Listing tools');
|
|
43
|
+
return { tools };
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Handle tool calls
|
|
47
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
48
|
+
const { name, arguments: args } = request.params;
|
|
49
|
+
|
|
50
|
+
logger.debug(`Tool call: ${name}`, args);
|
|
51
|
+
|
|
52
|
+
const handler = toolHandlers[name];
|
|
53
|
+
|
|
54
|
+
if (!handler) {
|
|
55
|
+
return {
|
|
56
|
+
content: [{ type: 'text', text: `Unknown tool: ${name}` }],
|
|
57
|
+
isError: true,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
return await handler(args);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
logger.error(`Tool error: ${name}`, error);
|
|
65
|
+
return {
|
|
66
|
+
content: [{
|
|
67
|
+
type: 'text',
|
|
68
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
69
|
+
}],
|
|
70
|
+
isError: true,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Run the server
|
|
76
|
+
async function main() {
|
|
77
|
+
// Register JLC libraries in KiCad global tables
|
|
78
|
+
const registration = await ensureGlobalLibraryTables();
|
|
79
|
+
|
|
80
|
+
if (!registration.success) {
|
|
81
|
+
logger.error('Failed to register JLC libraries in KiCad global tables', {
|
|
82
|
+
errors: registration.errors,
|
|
83
|
+
});
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Log registration summary
|
|
88
|
+
const { symLibTable, fpLibTable, libraryStubs, version } = registration;
|
|
89
|
+
if (symLibTable.created || symLibTable.modified || fpLibTable.created || fpLibTable.modified) {
|
|
90
|
+
logger.info(`JLC libraries registered in KiCad ${version}`, {
|
|
91
|
+
symLibTable: symLibTable.created
|
|
92
|
+
? `created with ${symLibTable.entriesAdded} entries`
|
|
93
|
+
: symLibTable.modified
|
|
94
|
+
? `added ${symLibTable.entriesAdded} entries`
|
|
95
|
+
: 'already configured',
|
|
96
|
+
fpLibTable: fpLibTable.created
|
|
97
|
+
? 'created'
|
|
98
|
+
: fpLibTable.modified
|
|
99
|
+
? 'updated'
|
|
100
|
+
: 'already configured',
|
|
101
|
+
stubsCreated: libraryStubs.symbolsCreated.length + libraryStubs.directoriesCreated.length,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Start HTTP server for the component browser UI
|
|
106
|
+
const httpPort = startHttpServer();
|
|
107
|
+
logger.info(`Component browser available at http://localhost:${httpPort}`);
|
|
108
|
+
|
|
109
|
+
const transport = new StdioServerTransport();
|
|
110
|
+
await server.connect(transport);
|
|
111
|
+
logger.info('JLC MCP server running on stdio');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
main().catch((error) => {
|
|
115
|
+
logger.error('Server error', error);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component details tools for MCP
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import type { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
7
|
+
import { easyedaClient } from '@jlcpcb/core';
|
|
8
|
+
|
|
9
|
+
export const getComponentTool: Tool = {
|
|
10
|
+
name: 'component_get',
|
|
11
|
+
description: 'Get detailed component information by LCSC part number (e.g., C2040). LCSC is JLC PCB\'s preferred supplier - components with LCSC IDs are available for JLC assembly. Returns symbol pins, footprint pads, manufacturer info, datasheet URL, and 3D model reference.',
|
|
12
|
+
inputSchema: {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
lcsc_id: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
description: 'LCSC part number (e.g., C2040, C14663)',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
required: ['lcsc_id'],
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const GetComponentParamsSchema = z.object({
|
|
25
|
+
lcsc_id: z.string().regex(/^C\d+$/, 'Invalid LCSC part number'),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export async function handleGetComponent(args: unknown) {
|
|
29
|
+
const params = GetComponentParamsSchema.parse(args);
|
|
30
|
+
|
|
31
|
+
const component = await easyedaClient.getComponentData(params.lcsc_id);
|
|
32
|
+
|
|
33
|
+
if (!component) {
|
|
34
|
+
return {
|
|
35
|
+
content: [{
|
|
36
|
+
type: 'text' as const,
|
|
37
|
+
text: `Component ${params.lcsc_id} not found`,
|
|
38
|
+
}],
|
|
39
|
+
isError: true,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Return a clean summary
|
|
44
|
+
const summary = {
|
|
45
|
+
info: component.info,
|
|
46
|
+
symbol: {
|
|
47
|
+
pin_count: component.symbol.pins.length,
|
|
48
|
+
pins: component.symbol.pins,
|
|
49
|
+
},
|
|
50
|
+
footprint: {
|
|
51
|
+
name: component.footprint.name,
|
|
52
|
+
type: component.footprint.type,
|
|
53
|
+
pad_count: component.footprint.pads.length,
|
|
54
|
+
pads: component.footprint.pads,
|
|
55
|
+
},
|
|
56
|
+
has_3d_model: !!component.model3d,
|
|
57
|
+
model_3d_uuid: component.model3d?.uuid,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
content: [{
|
|
62
|
+
type: 'text' as const,
|
|
63
|
+
text: JSON.stringify(summary, null, 2),
|
|
64
|
+
}],
|
|
65
|
+
};
|
|
66
|
+
}
|