@promptui-lib/mcp-agent 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/bin/agent.js ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { startAgent } from '../dist/index.js';
4
+
5
+ startAgent().catch((error) => {
6
+ console.error('[PromptUI] Failed to start agent:', error.message);
7
+ process.exit(1);
8
+ });
@@ -0,0 +1,3 @@
1
+ export { loadConfig, resolveConfig, validateConfig } from './load-config.js';
2
+ export type { IResolvedConfig } from './load-config.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC7E,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1 @@
1
+ export { loadConfig, resolveConfig, validateConfig } from './load-config.js';
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Config Loader
3
+ * Carrega configuração do projeto
4
+ */
5
+ import type { IPromptUIConfig } from '@promptui-lib/core';
6
+ export interface IResolvedConfig {
7
+ figmaToken: string;
8
+ figmaFileId: string;
9
+ outputBasePath: string;
10
+ port: number;
11
+ }
12
+ /**
13
+ * Carrega configuração do projeto
14
+ */
15
+ export declare function loadConfig(cwd?: string): Promise<IPromptUIConfig | null>;
16
+ /**
17
+ * Resolve configuração com valores padrão e env vars
18
+ */
19
+ export declare function resolveConfig(config: IPromptUIConfig | null, envOverrides?: Partial<IResolvedConfig>): IResolvedConfig;
20
+ /**
21
+ * Valida configuração resolvida
22
+ */
23
+ export declare function validateConfig(config: IResolvedConfig): string[];
24
+ //# sourceMappingURL=load-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-config.d.ts","sourceRoot":"","sources":["../../src/config/load-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAS1D,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;AAuCD;;GAEG;AACH,wBAAsB,UAAU,CAC9B,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAQjC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,eAAe,GAAG,IAAI,EAC9B,YAAY,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GACtC,eAAe,CA+BjB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,EAAE,CAYhE"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Config Loader
3
+ * Carrega configuração do projeto
4
+ */
5
+ import { readFile, access } from 'node:fs/promises';
6
+ import { join } from 'node:path';
7
+ const CONFIG_FILES = [
8
+ 'promptui.config.json',
9
+ 'promptui.config.js',
10
+ '.promptuirc',
11
+ '.promptuirc.json',
12
+ ];
13
+ /**
14
+ * Verifica se arquivo existe
15
+ */
16
+ async function fileExists(path) {
17
+ try {
18
+ await access(path);
19
+ return true;
20
+ }
21
+ catch {
22
+ return false;
23
+ }
24
+ }
25
+ /**
26
+ * Carrega configuração de um arquivo JSON
27
+ */
28
+ async function loadJsonConfig(path) {
29
+ try {
30
+ const content = await readFile(path, 'utf-8');
31
+ return JSON.parse(content);
32
+ }
33
+ catch {
34
+ return null;
35
+ }
36
+ }
37
+ /**
38
+ * Busca arquivo de configuração no diretório
39
+ */
40
+ async function findConfigFile(dir) {
41
+ for (const file of CONFIG_FILES) {
42
+ const path = join(dir, file);
43
+ if (await fileExists(path)) {
44
+ return path;
45
+ }
46
+ }
47
+ return null;
48
+ }
49
+ /**
50
+ * Carrega configuração do projeto
51
+ */
52
+ export async function loadConfig(cwd = process.cwd()) {
53
+ const configPath = await findConfigFile(cwd);
54
+ if (!configPath) {
55
+ return null;
56
+ }
57
+ return loadJsonConfig(configPath);
58
+ }
59
+ /**
60
+ * Resolve configuração com valores padrão e env vars
61
+ */
62
+ export function resolveConfig(config, envOverrides) {
63
+ // Prioridade: env vars > config file > defaults
64
+ const figmaToken = envOverrides?.figmaToken ??
65
+ process.env.FIGMA_TOKEN ??
66
+ config?.figma?.token ??
67
+ '';
68
+ const figmaFileId = envOverrides?.figmaFileId ??
69
+ process.env.FIGMA_FILE_ID ??
70
+ config?.figma?.fileId ??
71
+ '';
72
+ const outputBasePath = envOverrides?.outputBasePath ??
73
+ process.env.PROMPTUI_OUTPUT_PATH ??
74
+ config?.output?.basePath ??
75
+ 'src/components';
76
+ const port = envOverrides?.port ??
77
+ (process.env.PROMPTUI_PORT ? parseInt(process.env.PROMPTUI_PORT, 10) : null) ??
78
+ 17890;
79
+ return {
80
+ figmaToken,
81
+ figmaFileId,
82
+ outputBasePath,
83
+ port,
84
+ };
85
+ }
86
+ /**
87
+ * Valida configuração resolvida
88
+ */
89
+ export function validateConfig(config) {
90
+ const errors = [];
91
+ if (!config.figmaToken) {
92
+ errors.push('Missing FIGMA_TOKEN. Set via environment variable or config file.');
93
+ }
94
+ if (!config.figmaFileId) {
95
+ errors.push('Missing FIGMA_FILE_ID. Set via environment variable or config file.');
96
+ }
97
+ return errors;
98
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Generate Handler
3
+ * Orquestra o pipeline de geração: Figma → Parser → Codegen → Files
4
+ */
5
+ import type { IGenerateRequest, IGenerateResponse } from '@promptui-lib/core';
6
+ export interface IGenerateHandlerOptions {
7
+ request: IGenerateRequest;
8
+ figmaToken: string;
9
+ figmaFileId: string;
10
+ outputBasePath: string;
11
+ }
12
+ /**
13
+ * Handler principal de geração
14
+ */
15
+ export declare function handleGenerate(options: IGenerateHandlerOptions): Promise<IGenerateResponse>;
16
+ //# sourceMappingURL=generate-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-handler.d.ts","sourceRoot":"","sources":["../../src/handlers/generate-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAK9E,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,gBAAgB,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CA6F5B"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Generate Handler
3
+ * Orquestra o pipeline de geração: Figma → Parser → Codegen → Files
4
+ */
5
+ import { createFigmaClient } from '@promptui-lib/figma-parser';
6
+ import { parseNode } from '@promptui-lib/figma-parser';
7
+ import { writeComponent, generateCode } from '@promptui-lib/codegen';
8
+ /**
9
+ * Handler principal de geração
10
+ */
11
+ export async function handleGenerate(options) {
12
+ const { request, figmaToken, figmaFileId, outputBasePath } = options;
13
+ const errors = [];
14
+ const warnings = [];
15
+ try {
16
+ console.log(`[PromptUI] Generating component for node: ${request.nodeId}`);
17
+ // 1. Busca node do Figma
18
+ const figmaClient = createFigmaClient({ token: figmaToken });
19
+ const fileId = request.fileId ?? figmaFileId;
20
+ const node = await figmaClient.getNode(fileId, request.nodeId);
21
+ if (!node) {
22
+ return {
23
+ success: false,
24
+ componentName: '',
25
+ layer: 'atoms',
26
+ files: { tsx: '', scss: '', index: '' },
27
+ outputPath: '',
28
+ errors: [`Node not found: ${request.nodeId}`],
29
+ };
30
+ }
31
+ console.log(`[PromptUI] Found node: ${node.name} (${node.type})`);
32
+ // 2. Parseia node para AST
33
+ const ast = parseNode(node, {
34
+ forceLayer: request.options?.layer,
35
+ componentName: request.options?.componentName,
36
+ });
37
+ console.log(`[PromptUI] Parsed: ${ast.name} (${ast.layer})`);
38
+ // 3. Se é preview, retorna apenas o código
39
+ if (request.options?.preview) {
40
+ const code = generateCode(ast);
41
+ return {
42
+ success: true,
43
+ componentName: ast.name,
44
+ layer: ast.layer,
45
+ files: { tsx: '', scss: '', index: '' },
46
+ outputPath: '',
47
+ code,
48
+ warnings,
49
+ };
50
+ }
51
+ // 4. Escreve arquivos
52
+ const basePath = request.outputPath ?? outputBasePath;
53
+ const writeResult = await writeComponent(ast, {
54
+ basePath,
55
+ forceOverwrite: request.options?.forceOverwrite,
56
+ });
57
+ if (!writeResult.success) {
58
+ return {
59
+ success: false,
60
+ componentName: ast.name,
61
+ layer: ast.layer,
62
+ files: writeResult.files,
63
+ outputPath: basePath,
64
+ errors: writeResult.errors,
65
+ };
66
+ }
67
+ console.log(`[PromptUI] Generated: ${writeResult.files.tsx}`);
68
+ return {
69
+ success: true,
70
+ componentName: ast.name,
71
+ layer: ast.layer,
72
+ files: writeResult.files,
73
+ outputPath: basePath,
74
+ warnings,
75
+ };
76
+ }
77
+ catch (error) {
78
+ const message = error instanceof Error ? error.message : 'Unknown error';
79
+ errors.push(message);
80
+ console.error(`[PromptUI] Error:`, message);
81
+ return {
82
+ success: false,
83
+ componentName: '',
84
+ layer: 'atoms',
85
+ files: { tsx: '', scss: '', index: '' },
86
+ outputPath: '',
87
+ errors,
88
+ };
89
+ }
90
+ }
@@ -0,0 +1,3 @@
1
+ export { handleGenerate } from './generate-handler.js';
2
+ export type { IGenerateHandlerOptions } from './generate-handler.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1 @@
1
+ export { handleGenerate } from './generate-handler.js';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @promptui-lib/mcp-agent
3
+ * MCP Agent server for PromptUI
4
+ */
5
+ export * from './server/index.js';
6
+ export * from './handlers/index.js';
7
+ export * from './config/index.js';
8
+ /**
9
+ * Inicia o agente MCP
10
+ */
11
+ export declare function startAgent(): Promise<void>;
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAElC;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAkDhD"}
package/dist/index.js ADDED
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @promptui-lib/mcp-agent
3
+ * MCP Agent server for PromptUI
4
+ */
5
+ import { createHttpServer } from './server/index.js';
6
+ import { loadConfig, resolveConfig, validateConfig } from './config/index.js';
7
+ export * from './server/index.js';
8
+ export * from './handlers/index.js';
9
+ export * from './config/index.js';
10
+ /**
11
+ * Inicia o agente MCP
12
+ */
13
+ export async function startAgent() {
14
+ console.log('[PromptUI] Starting agent...');
15
+ // Carrega configuração
16
+ const config = await loadConfig();
17
+ const resolved = resolveConfig(config);
18
+ // Valida configuração
19
+ const errors = validateConfig(resolved);
20
+ if (errors.length > 0) {
21
+ console.error('[PromptUI] Configuration errors:');
22
+ for (const error of errors) {
23
+ console.error(` - ${error}`);
24
+ }
25
+ console.error('\n[PromptUI] Create a promptui.config.json or set environment variables.');
26
+ console.error('Example config:');
27
+ console.error(JSON.stringify({
28
+ figma: {
29
+ token: 'your-figma-token',
30
+ fileId: 'your-file-id'
31
+ },
32
+ output: {
33
+ basePath: 'src/components'
34
+ }
35
+ }, null, 2));
36
+ process.exit(1);
37
+ }
38
+ // Cria e inicia servidor
39
+ const server = createHttpServer({
40
+ port: resolved.port,
41
+ figmaToken: resolved.figmaToken,
42
+ figmaFileId: resolved.figmaFileId,
43
+ outputBasePath: resolved.outputBasePath,
44
+ });
45
+ await server.start();
46
+ // Handle graceful shutdown
47
+ process.on('SIGINT', async () => {
48
+ console.log('\n[PromptUI] Shutting down...');
49
+ await server.stop();
50
+ process.exit(0);
51
+ });
52
+ process.on('SIGTERM', async () => {
53
+ console.log('\n[PromptUI] Shutting down...');
54
+ await server.stop();
55
+ process.exit(0);
56
+ });
57
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * HTTP Server
3
+ * Expõe API REST para comunicação com o Figma Plugin
4
+ */
5
+ export interface IServerConfig {
6
+ port: number;
7
+ figmaToken: string;
8
+ figmaFileId: string;
9
+ outputBasePath: string;
10
+ }
11
+ export interface IHttpServer {
12
+ start(): Promise<void>;
13
+ stop(): Promise<void>;
14
+ }
15
+ /**
16
+ * Cria o servidor HTTP
17
+ */
18
+ export declare function createHttpServer(config: IServerConfig): IHttpServer;
19
+ //# sourceMappingURL=http-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../../src/server/http-server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAsCD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,WAAW,CA2EnE"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * HTTP Server
3
+ * Expõe API REST para comunicação com o Figma Plugin
4
+ */
5
+ import { createServer } from 'node:http';
6
+ import { parse as parseUrl } from 'node:url';
7
+ import { handleGenerate } from '../handlers/generate-handler.js';
8
+ /**
9
+ * Parseia body JSON de uma request
10
+ */
11
+ async function parseBody(req) {
12
+ return new Promise((resolve, reject) => {
13
+ let body = '';
14
+ req.on('data', (chunk) => {
15
+ body += chunk.toString();
16
+ });
17
+ req.on('end', () => {
18
+ try {
19
+ resolve(JSON.parse(body));
20
+ }
21
+ catch {
22
+ reject(new Error('Invalid JSON body'));
23
+ }
24
+ });
25
+ req.on('error', reject);
26
+ });
27
+ }
28
+ /**
29
+ * Envia resposta JSON
30
+ */
31
+ function sendJson(res, status, data) {
32
+ res.writeHead(status, {
33
+ 'Content-Type': 'application/json',
34
+ 'Access-Control-Allow-Origin': '*',
35
+ 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
36
+ 'Access-Control-Allow-Headers': 'Content-Type',
37
+ });
38
+ res.end(JSON.stringify(data));
39
+ }
40
+ /**
41
+ * Cria o servidor HTTP
42
+ */
43
+ export function createHttpServer(config) {
44
+ const server = createServer(async (req, res) => {
45
+ const { pathname } = parseUrl(req.url ?? '/', true);
46
+ const method = req.method ?? 'GET';
47
+ // CORS preflight
48
+ if (method === 'OPTIONS') {
49
+ res.writeHead(204, {
50
+ 'Access-Control-Allow-Origin': '*',
51
+ 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
52
+ 'Access-Control-Allow-Headers': 'Content-Type',
53
+ });
54
+ res.end();
55
+ return;
56
+ }
57
+ try {
58
+ // Health check
59
+ if (pathname === '/health' && method === 'GET') {
60
+ sendJson(res, 200, { status: 'ok', version: '0.1.0' });
61
+ return;
62
+ }
63
+ // Generate component
64
+ if (pathname === '/generate' && method === 'POST') {
65
+ const body = await parseBody(req);
66
+ const result = await handleGenerate({
67
+ request: body,
68
+ figmaToken: config.figmaToken,
69
+ figmaFileId: config.figmaFileId,
70
+ outputBasePath: config.outputBasePath,
71
+ });
72
+ sendJson(res, result.success ? 200 : 400, result);
73
+ return;
74
+ }
75
+ // List available frames
76
+ if (pathname === '/frames' && method === 'GET') {
77
+ // TODO: implementar listagem de frames
78
+ sendJson(res, 200, { frames: [] });
79
+ return;
80
+ }
81
+ // 404
82
+ sendJson(res, 404, { error: 'Not found' });
83
+ }
84
+ catch (error) {
85
+ const message = error instanceof Error ? error.message : 'Unknown error';
86
+ console.error('[PromptUI] Error:', message);
87
+ sendJson(res, 500, { error: message });
88
+ }
89
+ });
90
+ return {
91
+ start: () => new Promise((resolve) => {
92
+ server.listen(config.port, () => {
93
+ console.log(`[PromptUI] Agent running at http://localhost:${config.port}`);
94
+ console.log('[PromptUI] Endpoints:');
95
+ console.log(` GET /health - Health check`);
96
+ console.log(` POST /generate - Generate component from Figma node`);
97
+ console.log(` GET /frames - List available frames`);
98
+ resolve();
99
+ });
100
+ }),
101
+ stop: () => new Promise((resolve, reject) => {
102
+ server.close((err) => {
103
+ if (err)
104
+ reject(err);
105
+ else
106
+ resolve();
107
+ });
108
+ }),
109
+ };
110
+ }
@@ -0,0 +1,3 @@
1
+ export { createHttpServer } from './http-server.js';
2
+ export type { IServerConfig, IHttpServer } from './http-server.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1 @@
1
+ export { createHttpServer } from './http-server.js';
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@promptui-lib/mcp-agent",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "description": "MCP Agent server for PromptUI - bridges Figma Plugin to code generation",
6
+ "license": "UNLICENSED",
7
+ "author": {
8
+ "name": "Desiree Menezes",
9
+ "url": "https://github.com/desireemenezes"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/desireemenezes/promptUI.git",
14
+ "directory": "packages/mcp-agent"
15
+ },
16
+ "homepage": "https://github.com/desireemenezes/promptUI#readme",
17
+ "type": "module",
18
+ "main": "./dist/index.js",
19
+ "types": "./dist/index.d.ts",
20
+ "bin": {
21
+ "promptui-agent": "./bin/agent.js"
22
+ },
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "import": "./dist/index.js"
30
+ }
31
+ },
32
+ "files": [
33
+ "dist",
34
+ "bin"
35
+ ],
36
+ "dependencies": {
37
+ "@promptui-lib/core": "0.1.0",
38
+ "@promptui-lib/figma-parser": "0.1.0",
39
+ "@promptui-lib/codegen": "0.1.0"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^20.0.0",
43
+ "typescript": "^5.3.0",
44
+ "rimraf": "^5.0.0"
45
+ },
46
+ "scripts": {
47
+ "build": "tsc",
48
+ "dev": "tsc --watch",
49
+ "start": "node dist/index.js",
50
+ "clean": "rimraf dist"
51
+ }
52
+ }