@mcp-consultant-tools/figma 27.0.0 → 28.0.0-beta.10

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.
Files changed (69) hide show
  1. package/build/cli/commands/ado-story-commands.d.ts +7 -0
  2. package/build/cli/commands/ado-story-commands.d.ts.map +1 -0
  3. package/build/cli/commands/ado-story-commands.js +46 -0
  4. package/build/cli/commands/ado-story-commands.js.map +1 -0
  5. package/build/cli/commands/figma-data-commands.d.ts +7 -0
  6. package/build/cli/commands/figma-data-commands.d.ts.map +1 -0
  7. package/build/cli/commands/figma-data-commands.js +44 -0
  8. package/build/cli/commands/figma-data-commands.js.map +1 -0
  9. package/build/cli/commands/image-commands.d.ts +7 -0
  10. package/build/cli/commands/image-commands.d.ts.map +1 -0
  11. package/build/cli/commands/image-commands.js +20 -0
  12. package/build/cli/commands/image-commands.js.map +1 -0
  13. package/build/cli/commands/index.d.ts +11 -0
  14. package/build/cli/commands/index.d.ts.map +1 -0
  15. package/build/cli/commands/index.js +18 -0
  16. package/build/cli/commands/index.js.map +1 -0
  17. package/build/cli/commands/semantic-commands.d.ts +7 -0
  18. package/build/cli/commands/semantic-commands.d.ts.map +1 -0
  19. package/build/cli/commands/semantic-commands.js +62 -0
  20. package/build/cli/commands/semantic-commands.js.map +1 -0
  21. package/build/cli/output.d.ts +11 -0
  22. package/build/cli/output.d.ts.map +1 -0
  23. package/build/cli/output.js +10 -0
  24. package/build/cli/output.js.map +1 -0
  25. package/build/cli.d.ts +9 -0
  26. package/build/cli.d.ts.map +1 -0
  27. package/build/cli.js +27 -0
  28. package/build/cli.js.map +1 -0
  29. package/build/context-factory.d.ts +4 -0
  30. package/build/context-factory.d.ts.map +1 -0
  31. package/build/context-factory.js +26 -0
  32. package/build/context-factory.js.map +1 -0
  33. package/build/index.d.ts +7 -11
  34. package/build/index.d.ts.map +1 -1
  35. package/build/index.js +20 -124
  36. package/build/index.js.map +1 -1
  37. package/build/models/api-types.d.ts +25 -0
  38. package/build/models/api-types.d.ts.map +1 -0
  39. package/build/models/api-types.js +5 -0
  40. package/build/models/api-types.js.map +1 -0
  41. package/build/models/index.d.ts +5 -0
  42. package/build/models/index.d.ts.map +1 -0
  43. package/build/models/index.js +2 -0
  44. package/build/models/index.js.map +1 -0
  45. package/build/services/figma-service.d.ts +44 -0
  46. package/build/services/figma-service.d.ts.map +1 -0
  47. package/build/services/figma-service.js +162 -0
  48. package/build/services/figma-service.js.map +1 -0
  49. package/build/services/index.d.ts +5 -0
  50. package/build/services/index.d.ts.map +1 -0
  51. package/build/services/index.js +5 -0
  52. package/build/services/index.js.map +1 -0
  53. package/build/tool-examples.d.ts +34 -0
  54. package/build/tool-examples.d.ts.map +1 -0
  55. package/build/tool-examples.js +55 -0
  56. package/build/tool-examples.js.map +1 -0
  57. package/build/tools/figma-tools.d.ts +3 -0
  58. package/build/tools/figma-tools.d.ts.map +1 -0
  59. package/build/tools/figma-tools.js +109 -0
  60. package/build/tools/figma-tools.js.map +1 -0
  61. package/build/tools/index.d.ts +7 -0
  62. package/build/tools/index.d.ts.map +1 -0
  63. package/build/tools/index.js +6 -0
  64. package/build/tools/index.js.map +1 -0
  65. package/build/types.d.ts +9 -0
  66. package/build/types.d.ts.map +1 -0
  67. package/build/types.js +2 -0
  68. package/build/types.js.map +1 -0
  69. package/package.json +5 -3
@@ -0,0 +1,7 @@
1
+ /**
2
+ * ADO Story Extraction CLI Commands - maps to extract-ado-stories MCP tool
3
+ */
4
+ import type { Command } from 'commander';
5
+ import type { ServiceContext } from '../../types.js';
6
+ export declare function registerAdoStoryCommands(program: Command, ctx: ServiceContext): void;
7
+ //# sourceMappingURL=ado-story-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ado-story-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/ado-story-commands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAKrD,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CA0CpF"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * ADO Story Extraction CLI Commands - maps to extract-ado-stories MCP tool
3
+ */
4
+ import { getGlobalFlags, handleCliError } from '@mcp-consultant-tools/core';
5
+ import { extractAdoStories } from '../../figma/extractors/ado-story-extractor.js';
6
+ import { outputResult } from '../output.js';
7
+ export function registerAdoStoryCommands(program, ctx) {
8
+ program
9
+ .command('extract-ado-stories')
10
+ .description('Extract ADO User Story Components from a FigJam board or section')
11
+ .argument('<fileKey>', 'Figma file key (alphanumeric string from URL)')
12
+ .option('-n, --node-id <nodeId>', 'Section node ID to scope extraction')
13
+ .option('--ado-org <org>', 'Azure DevOps organization name (for constructing work item links)')
14
+ .option('--ado-project <project>', 'Azure DevOps project name (for constructing work item links)')
15
+ .option('--include-placeholders', 'Include ADO components with placeholder IDs (e.g. "ADO xxxxx")', false)
16
+ .action(async (fileKey, opts) => {
17
+ try {
18
+ // Fetch with component properties preserved
19
+ const dataOptions = {
20
+ excludeStyles: true,
21
+ simplifyComponentInstances: true,
22
+ simplifyConnectors: true,
23
+ tablesToMarkdown: true,
24
+ };
25
+ const rawData = await ctx.figma.getFigmaData(fileKey, opts.nodeId, undefined, dataOptions);
26
+ const result = extractAdoStories(rawData, {
27
+ fileKey,
28
+ adoOrganization: opts.adoOrg,
29
+ adoProject: opts.adoProject,
30
+ includePlaceholders: opts.includePlaceholders,
31
+ });
32
+ const statesSummary = Object.entries(result.byState)
33
+ .map(([state, count]) => `${state}: ${count}`)
34
+ .join(', ');
35
+ outputResult({
36
+ fileName: `figma-ado-stories-${fileKey}`,
37
+ data: result,
38
+ summary: `Extracted ${result.totalCount} ADO story component(s) from '${fileKey}'${opts.nodeId ? ` (node: ${opts.nodeId})` : ''}${statesSummary ? ` [${statesSummary}]` : ''}`,
39
+ }, getGlobalFlags(program));
40
+ }
41
+ catch (error) {
42
+ handleCliError(error, 'extract ADO stories');
43
+ }
44
+ });
45
+ }
46
+ //# sourceMappingURL=ado-story-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ado-story-commands.js","sourceRoot":"","sources":["../../../src/cli/commands/ado-story-commands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAG5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,UAAU,wBAAwB,CAAC,OAAgB,EAAE,GAAmB;IAC5E,OAAO;SACJ,OAAO,CAAC,qBAAqB,CAAC;SAC9B,WAAW,CAAC,kEAAkE,CAAC;SAC/E,QAAQ,CAAC,WAAW,EAAE,+CAA+C,CAAC;SACtE,MAAM,CAAC,wBAAwB,EAAE,qCAAqC,CAAC;SACvE,MAAM,CAAC,iBAAiB,EAAE,mEAAmE,CAAC;SAC9F,MAAM,CAAC,yBAAyB,EAAE,8DAA8D,CAAC;SACjG,MAAM,CAAC,wBAAwB,EAAE,gEAAgE,EAAE,KAAK,CAAC;SACzG,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,IAAS,EAAE,EAAE;QAC3C,IAAI,CAAC;YACH,4CAA4C;YAC5C,MAAM,WAAW,GAAqB;gBACpC,aAAa,EAAE,IAAI;gBACnB,0BAA0B,EAAE,IAAI;gBAChC,kBAAkB,EAAE,IAAI;gBACxB,gBAAgB,EAAE,IAAI;aACvB,CAAC;YAEF,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;YAE3F,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,EAAE;gBACxC,OAAO;gBACP,eAAe,EAAE,IAAI,CAAC,MAAM;gBAC5B,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;aAC9C,CAAC,CAAC;YAEH,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;iBACjD,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,KAAK,KAAK,EAAE,CAAC;iBAC7C,IAAI,CAAC,IAAI,CAAC,CAAC;YAEd,YAAY,CACV;gBACE,QAAQ,EAAE,qBAAqB,OAAO,EAAE;gBACxC,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,aAAa,MAAM,CAAC,UAAU,iCAAiC,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,aAAa,CAAC,CAAC,CAAC,KAAK,aAAa,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;aAC/K,EACD,cAAc,CAAC,OAAO,CAAC,CACxB,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,cAAc,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Figma Data CLI Commands - maps to get-figma-data MCP tool
3
+ */
4
+ import type { Command } from 'commander';
5
+ import type { ServiceContext } from '../../types.js';
6
+ export declare function registerFigmaDataCommands(program: Command, ctx: ServiceContext): void;
7
+ //# sourceMappingURL=figma-data-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figma-data-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/figma-data-commands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAIrD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CAwCrF"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Figma Data CLI Commands - maps to get-figma-data MCP tool
3
+ */
4
+ import { getGlobalFlags, handleCliError } from '@mcp-consultant-tools/core';
5
+ import { outputResult } from '../output.js';
6
+ export function registerFigmaDataCommands(program, ctx) {
7
+ program
8
+ .command('get-data')
9
+ .description('Get comprehensive Figma design data in simplified, AI-friendly format')
10
+ .argument('<fileKey>', 'Figma file key (alphanumeric string from URL)')
11
+ .option('-n, --node-id <nodeId>', 'Specific node ID(s) to fetch (format: "1234:5678" or "1:10;2:20")')
12
+ .option('-d, --depth <depth>', 'Tree traversal depth limit')
13
+ .option('--no-exclude-styles', 'Include all styling info (default: excluded)')
14
+ .option('--no-tables-to-markdown', 'Keep TABLE nodes as nested structures (default: converted to markdown)')
15
+ .option('--no-simplify-connectors', 'Keep full CONNECTOR node data (default: simplified)')
16
+ .option('--no-simplify-components', 'Keep full INSTANCE node data (default: simplified)')
17
+ .option('--extractors <extractors>', 'Comma-separated list of extractors: layout,text,visuals,component')
18
+ .action(async (fileKey, opts) => {
19
+ try {
20
+ const extractors = opts.extractors
21
+ ? opts.extractors.split(',').map((e) => e.trim())
22
+ : undefined;
23
+ const dataOptions = {
24
+ excludeStyles: opts.excludeStyles,
25
+ tablesToMarkdown: opts.tablesToMarkdown,
26
+ simplifyConnectors: opts.simplifyConnectors,
27
+ simplifyComponentInstances: opts.simplifyComponents,
28
+ extractors,
29
+ };
30
+ const depth = opts.depth ? parseInt(opts.depth) : undefined;
31
+ const result = await ctx.figma.getFigmaData(fileKey, opts.nodeId, depth, dataOptions);
32
+ const nodeCount = Array.isArray(result.nodes) ? result.nodes.length : 0;
33
+ outputResult({
34
+ fileName: `figma-data-${fileKey}`,
35
+ data: result,
36
+ summary: `Fetched Figma data for file '${fileKey}'${opts.nodeId ? ` (node: ${opts.nodeId})` : ''} - ${nodeCount} top-level node(s)`,
37
+ }, getGlobalFlags(program));
38
+ }
39
+ catch (error) {
40
+ handleCliError(error, 'get figma data');
41
+ }
42
+ });
43
+ }
44
+ //# sourceMappingURL=figma-data-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figma-data-commands.js","sourceRoot":"","sources":["../../../src/cli/commands/figma-data-commands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAG5E,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,UAAU,yBAAyB,CAAC,OAAgB,EAAE,GAAmB;IAC7E,OAAO;SACJ,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,uEAAuE,CAAC;SACpF,QAAQ,CAAC,WAAW,EAAE,+CAA+C,CAAC;SACtE,MAAM,CAAC,wBAAwB,EAAE,mEAAmE,CAAC;SACrG,MAAM,CAAC,qBAAqB,EAAE,4BAA4B,CAAC;SAC3D,MAAM,CAAC,qBAAqB,EAAE,8CAA8C,CAAC;SAC7E,MAAM,CAAC,yBAAyB,EAAE,wEAAwE,CAAC;SAC3G,MAAM,CAAC,0BAA0B,EAAE,qDAAqD,CAAC;SACzF,MAAM,CAAC,0BAA0B,EAAE,oDAAoD,CAAC;SACxF,MAAM,CAAC,2BAA2B,EAAE,mEAAmE,CAAC;SACxG,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,IAAS,EAAE,EAAE;QAC3C,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU;gBAChC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAoD;gBAC5G,CAAC,CAAC,SAAS,CAAC;YAEd,MAAM,WAAW,GAAqB;gBACpC,aAAa,EAAE,IAAI,CAAC,aAAa;gBACjC,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;gBACvC,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;gBAC3C,0BAA0B,EAAE,IAAI,CAAC,kBAAkB;gBACnD,UAAU;aACX,CAAC;YAEF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC5D,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;YAEtF,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACxE,YAAY,CACV;gBACE,QAAQ,EAAE,cAAc,OAAO,EAAE;gBACjC,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,gCAAgC,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,SAAS,oBAAoB;aACpI,EACD,cAAc,CAAC,OAAO,CAAC,CACxB,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,cAAc,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;QAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Image Download CLI Commands - maps to download-figma-images MCP tool
3
+ */
4
+ import type { Command } from 'commander';
5
+ import type { ServiceContext } from '../../types.js';
6
+ export declare function registerImageCommands(program: Command, _ctx: ServiceContext): void;
7
+ //# sourceMappingURL=image-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/image-commands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAWlF"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Image Download CLI Commands - maps to download-figma-images MCP tool
3
+ */
4
+ import { handleCliError } from '@mcp-consultant-tools/core';
5
+ export function registerImageCommands(program, _ctx) {
6
+ program
7
+ .command('download-images')
8
+ .description('Download and process images from Figma designs (Coming in v2)')
9
+ .argument('<fileKey>', 'Figma file key')
10
+ .argument('<localPath>', 'Local path to save images')
11
+ .action(async (_fileKey, _localPath) => {
12
+ try {
13
+ throw new Error('Image download functionality is coming in v2. Use get-data for design metadata.');
14
+ }
15
+ catch (error) {
16
+ handleCliError(error, 'download figma images');
17
+ }
18
+ });
19
+ }
20
+ //# sourceMappingURL=image-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-commands.js","sourceRoot":"","sources":["../../../src/cli/commands/image-commands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAG5D,MAAM,UAAU,qBAAqB,CAAC,OAAgB,EAAE,IAAoB;IAC1E,OAAO;SACJ,OAAO,CAAC,iBAAiB,CAAC;SAC1B,WAAW,CAAC,+DAA+D,CAAC;SAC5E,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC;SACvC,QAAQ,CAAC,aAAa,EAAE,2BAA2B,CAAC;SACpD,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,UAAkB,EAAE,EAAE;QACrD,IAAI,CAAC;YACH,MAAM,IAAI,KAAK,CAAC,iFAAiF,CAAC,CAAC;QACrG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,cAAc,CAAC,KAAK,EAAE,uBAAuB,CAAC,CAAC;QAAC,CAAC;IACrE,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * CLI Commands barrel export + combined registration
3
+ */
4
+ import type { Command } from 'commander';
5
+ import type { ServiceContext } from '../../types.js';
6
+ export declare function registerAllCommands(program: Command, ctx: ServiceContext): void;
7
+ export { registerFigmaDataCommands } from './figma-data-commands.js';
8
+ export { registerSemanticCommands } from './semantic-commands.js';
9
+ export { registerAdoStoryCommands } from './ado-story-commands.js';
10
+ export { registerImageCommands } from './image-commands.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAMrD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CAK/E;AAED,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * CLI Commands barrel export + combined registration
3
+ */
4
+ import { registerFigmaDataCommands } from './figma-data-commands.js';
5
+ import { registerSemanticCommands } from './semantic-commands.js';
6
+ import { registerAdoStoryCommands } from './ado-story-commands.js';
7
+ import { registerImageCommands } from './image-commands.js';
8
+ export function registerAllCommands(program, ctx) {
9
+ registerFigmaDataCommands(program, ctx);
10
+ registerSemanticCommands(program, ctx);
11
+ registerAdoStoryCommands(program, ctx);
12
+ registerImageCommands(program, ctx);
13
+ }
14
+ export { registerFigmaDataCommands } from './figma-data-commands.js';
15
+ export { registerSemanticCommands } from './semantic-commands.js';
16
+ export { registerAdoStoryCommands } from './ado-story-commands.js';
17
+ export { registerImageCommands } from './image-commands.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/commands/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,MAAM,UAAU,mBAAmB,CAAC,OAAgB,EAAE,GAAmB;IACvE,yBAAyB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACxC,wBAAwB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACvC,wBAAwB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACvC,qBAAqB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AACtC,CAAC;AAED,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Semantic Extraction CLI Commands - maps to get-figma-semantic MCP tool
3
+ */
4
+ import type { Command } from 'commander';
5
+ import type { ServiceContext } from '../../types.js';
6
+ export declare function registerSemanticCommands(program: Command, ctx: ServiceContext): void;
7
+ //# sourceMappingURL=semantic-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/semantic-commands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAMrD,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CAyDpF"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Semantic Extraction CLI Commands - maps to get-figma-semantic MCP tool
3
+ */
4
+ import { getGlobalFlags, handleCliError } from '@mcp-consultant-tools/core';
5
+ import { extractSemanticData } from '../../figma/extractors/semantic-extractor.js';
6
+ import { outputResult } from '../output.js';
7
+ export function registerSemanticCommands(program, ctx) {
8
+ program
9
+ .command('get-semantic')
10
+ .description('Extract semantically meaningful data from FigJam boards (diff-friendly)')
11
+ .argument('<fileKey>', 'Figma file key (alphanumeric string from URL)')
12
+ .option('-n, --node-id <nodeId>', 'Specific node/section ID to fetch')
13
+ .option('--sticky-overrides <json>', 'JSON map of hex colors to sticky categories (e.g. \'{"#FF0000":"blocker"}\')')
14
+ .option('--story-pattern <regex>', 'Custom regex pattern for extracting story IDs')
15
+ .action(async (fileKey, opts) => {
16
+ try {
17
+ // Fetch with fills preserved for sticky categorization
18
+ const dataOptions = {
19
+ excludeStyles: false, // Need fills for sticky color detection
20
+ simplifyConnectors: true,
21
+ simplifyComponentInstances: true,
22
+ tablesToMarkdown: true,
23
+ };
24
+ const rawData = await ctx.figma.getFigmaData(fileKey, opts.nodeId, undefined, dataOptions);
25
+ // Parse sticky color overrides
26
+ let stickyColorOverrides;
27
+ if (opts.stickyOverrides) {
28
+ try {
29
+ stickyColorOverrides = JSON.parse(opts.stickyOverrides);
30
+ }
31
+ catch {
32
+ throw new Error(`Invalid JSON for --sticky-overrides: ${opts.stickyOverrides}`);
33
+ }
34
+ }
35
+ // Parse custom story pattern
36
+ let customPattern;
37
+ if (opts.storyPattern) {
38
+ try {
39
+ customPattern = new RegExp(opts.storyPattern, 'gi');
40
+ }
41
+ catch {
42
+ throw new Error(`Invalid regex for --story-pattern: ${opts.storyPattern}`);
43
+ }
44
+ }
45
+ const semanticData = extractSemanticData(rawData, fileKey, opts.nodeId, {
46
+ stickyColorOverrides,
47
+ storyIdPattern: customPattern,
48
+ });
49
+ const stickyCount = semanticData.stickies?.length ?? 0;
50
+ const storyCount = semanticData.userStories?.length ?? 0;
51
+ outputResult({
52
+ fileName: `figma-semantic-${fileKey}`,
53
+ data: semanticData,
54
+ summary: `Extracted semantic data from '${fileKey}'${opts.nodeId ? ` (node: ${opts.nodeId})` : ''} - ${stickyCount} sticky note(s), ${storyCount} user story ref(s)`,
55
+ }, getGlobalFlags(program));
56
+ }
57
+ catch (error) {
58
+ handleCliError(error, 'get figma semantic data');
59
+ }
60
+ });
61
+ }
62
+ //# sourceMappingURL=semantic-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-commands.js","sourceRoot":"","sources":["../../../src/cli/commands/semantic-commands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAG5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAC;AAEnF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,UAAU,wBAAwB,CAAC,OAAgB,EAAE,GAAmB;IAC5E,OAAO;SACJ,OAAO,CAAC,cAAc,CAAC;SACvB,WAAW,CAAC,yEAAyE,CAAC;SACtF,QAAQ,CAAC,WAAW,EAAE,+CAA+C,CAAC;SACtE,MAAM,CAAC,wBAAwB,EAAE,mCAAmC,CAAC;SACrE,MAAM,CAAC,2BAA2B,EAAE,8EAA8E,CAAC;SACnH,MAAM,CAAC,yBAAyB,EAAE,+CAA+C,CAAC;SAClF,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,IAAS,EAAE,EAAE;QAC3C,IAAI,CAAC;YACH,uDAAuD;YACvD,MAAM,WAAW,GAAqB;gBACpC,aAAa,EAAE,KAAK,EAAE,wCAAwC;gBAC9D,kBAAkB,EAAE,IAAI;gBACxB,0BAA0B,EAAE,IAAI;gBAChC,gBAAgB,EAAE,IAAI;aACvB,CAAC;YAEF,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;YAE3F,+BAA+B;YAC/B,IAAI,oBAAgE,CAAC;YACrE,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;gBACzB,IAAI,CAAC;oBACH,oBAAoB,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;gBAC1D,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;gBAClF,CAAC;YACH,CAAC;YAED,6BAA6B;YAC7B,IAAI,aAAiC,CAAC;YACtC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACtB,IAAI,CAAC;oBACH,aAAa,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;gBACtD,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM,IAAI,KAAK,CAAC,sCAAsC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;gBAC7E,CAAC;YACH,CAAC;YAED,MAAM,YAAY,GAAG,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE;gBACtE,oBAAoB;gBACpB,cAAc,EAAE,aAAa;aAC9B,CAAC,CAAC;YAEH,MAAM,WAAW,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC;YACvD,MAAM,UAAU,GAAG,YAAY,CAAC,WAAW,EAAE,MAAM,IAAI,CAAC,CAAC;YACzD,YAAY,CACV;gBACE,QAAQ,EAAE,kBAAkB,OAAO,EAAE;gBACrC,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE,iCAAiC,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,WAAW,oBAAoB,UAAU,oBAAoB;aACrK,EACD,cAAc,CAAC,OAAO,CAAC,CACxB,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,cAAc,CAAC,KAAK,EAAE,yBAAyB,CAAC,CAAC;QAAC,CAAC;IACvE,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * CLI output helper for figma package.
3
+ * Thin wrapper setting the package-specific cache directory.
4
+ */
5
+ import { type GlobalFlags } from '@mcp-consultant-tools/core';
6
+ export declare function outputResult(opts: {
7
+ fileName: string;
8
+ data: unknown;
9
+ summary: string;
10
+ }, flags: GlobalFlags): void;
11
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/cli/output.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAoC,KAAK,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAIhG,wBAAgB,YAAY,CAC1B,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAC1D,KAAK,EAAE,WAAW,GACjB,IAAI,CAEN"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * CLI output helper for figma package.
3
+ * Thin wrapper setting the package-specific cache directory.
4
+ */
5
+ import { outputResult as coreOutputResult } from '@mcp-consultant-tools/core';
6
+ const CACHE_DIR = '.mcp-figma-cache';
7
+ export function outputResult(opts, flags) {
8
+ coreOutputResult({ ...opts, cacheDir: CACHE_DIR }, flags);
9
+ }
10
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/cli/output.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAAoB,MAAM,4BAA4B,CAAC;AAEhG,MAAM,SAAS,GAAG,kBAAkB,CAAC;AAErC,MAAM,UAAU,YAAY,CAC1B,IAA0D,EAC1D,KAAkB;IAElB,gBAAgB,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,KAAK,CAAC,CAAC;AAC5D,CAAC"}
package/build/cli.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @mcp-consultant-tools/figma CLI
4
+ *
5
+ * Command-line interface for Figma operations.
6
+ * Reuses the same ServiceContext and services as the MCP server.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;GAKG"}
package/build/cli.js ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @mcp-consultant-tools/figma CLI
4
+ *
5
+ * Command-line interface for Figma operations.
6
+ * Reuses the same ServiceContext and services as the MCP server.
7
+ */
8
+ import { createCliProgram, loadEnvForCli } from '@mcp-consultant-tools/core';
9
+ import { createServiceContext } from './context-factory.js';
10
+ import { registerAllCommands } from './cli/commands/index.js';
11
+ const program = createCliProgram({
12
+ name: 'mcp-figma-cli',
13
+ description: 'Figma CLI - design data extraction, semantic analysis, ADO story extraction',
14
+ version: '28.0.0-beta.8',
15
+ });
16
+ // Load env before parsing (--env-file handled by commander hook)
17
+ program.hook('preAction', (thisCommand) => {
18
+ const opts = thisCommand.opts();
19
+ loadEnvForCli(opts.envFile);
20
+ });
21
+ const ctx = createServiceContext();
22
+ registerAllCommands(program, ctx);
23
+ program.parseAsync(process.argv).catch((error) => {
24
+ console.error('CLI error:', error.message);
25
+ process.exit(1);
26
+ });
27
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D,MAAM,OAAO,GAAG,gBAAgB,CAAC;IAC/B,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,6EAA6E;IAC1F,OAAO,EAAE,eAAe;CACzB,CAAC,CAAC;AAEH,iEAAiE;AACjE,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,WAAgB,EAAE,EAAE;IAC7C,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;IAChC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC9B,CAAC,CAAC,CAAC;AAEH,MAAM,GAAG,GAAG,oBAAoB,EAAE,CAAC;AACnC,mBAAmB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAElC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAU,EAAE,EAAE;IACpD,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { ServiceContext } from './types.js';
2
+ export type { ServiceContext } from './types.js';
3
+ export declare function createServiceContext(): ServiceContext;
4
+ //# sourceMappingURL=context-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-factory.d.ts","sourceRoot":"","sources":["../src/context-factory.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,wBAAgB,oBAAoB,IAAI,cAAc,CA0BrD"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Shared service context factory - used by both MCP server and CLI.
3
+ */
4
+ import { FigmaService } from './services/figma-service.js';
5
+ export function createServiceContext() {
6
+ let service = null;
7
+ function getService() {
8
+ if (!service) {
9
+ if (!process.env.FIGMA_API_KEY && !process.env.FIGMA_OAUTH_TOKEN) {
10
+ throw new Error('Missing required Figma configuration: FIGMA_API_KEY or FIGMA_OAUTH_TOKEN');
11
+ }
12
+ const config = {
13
+ apiKey: process.env.FIGMA_API_KEY,
14
+ oauthToken: process.env.FIGMA_OAUTH_TOKEN,
15
+ useOAuth: process.env.FIGMA_USE_OAUTH === 'true',
16
+ };
17
+ service = new FigmaService(config);
18
+ console.error('Figma service initialized');
19
+ }
20
+ return service;
21
+ }
22
+ return {
23
+ get figma() { return getService(); },
24
+ };
25
+ }
26
+ //# sourceMappingURL=context-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-factory.js","sourceRoot":"","sources":["../src/context-factory.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAM3D,MAAM,UAAU,oBAAoB;IAClC,IAAI,OAAO,GAAwB,IAAI,CAAC;IAExC,SAAS,UAAU;QACjB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;gBACjE,MAAM,IAAI,KAAK,CACb,0EAA0E,CAC3E,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAgB;gBAC1B,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa;gBACjC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;gBACzC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,MAAM;aACjD,CAAC;YAEF,OAAO,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;YACnC,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO;QACL,IAAI,KAAK,KAAK,OAAO,UAAU,EAAE,CAAC,CAAC,CAAC;KACrC,CAAC;AACJ,CAAC"}
package/build/index.d.ts CHANGED
@@ -3,18 +3,14 @@
3
3
  * @mcp-consultant-tools/figma
4
4
  *
5
5
  * MCP server for Figma integration.
6
- * Provides design data extraction and transformation capabilities.
6
+ * Entry point: MCP server startup + backward-compatible registerFigmaTools().
7
7
  */
8
- import { FigmaService } from "./FigmaService.js";
9
8
  /**
10
- * Register Figma tools and prompts to an MCP server
11
- * @param server - The MCP server instance
12
- * @param figmaService - Optional pre-configured FigmaService (for testing or custom configs)
9
+ * Register Figma tools to an MCP server.
10
+ * Backward-compatible API for the meta package.
13
11
  */
14
- export declare function registerFigmaTools(server: any, figmaService?: FigmaService): void;
15
- /**
16
- * Export service class for direct usage
17
- */
18
- export { FigmaService } from "./FigmaService.js";
19
- export type { FigmaConfig, FigmaDataOptions } from "./FigmaService.js";
12
+ export declare function registerFigmaTools(server: any): void;
13
+ export { FigmaService } from './services/figma-service.js';
14
+ export type { FigmaConfig, FigmaDataOptions } from './models/index.js';
15
+ export type { ServiceContext } from './types.js';
20
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAOH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAMjD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,GAAG,EAAE,YAAY,CAAC,EAAE,YAAY,QAsN1E;AAED;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAiDH;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAGpD;AAGD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
package/build/index.js CHANGED
@@ -3,24 +3,20 @@
3
3
  * @mcp-consultant-tools/figma
4
4
  *
5
5
  * MCP server for Figma integration.
6
- * Provides design data extraction and transformation capabilities.
6
+ * Entry point: MCP server startup + backward-compatible registerFigmaTools().
7
7
  */
8
8
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
- import { z } from "zod";
10
9
  import { pathToFileURL } from "node:url";
11
10
  import { realpathSync } from "node:fs";
12
- import { createMcpServer, createEnvLoader, createErrorResponse, createSuccessResponse } from "@mcp-consultant-tools/core";
13
- import { FigmaService } from "./FigmaService.js";
14
- import { extractSemanticData } from "./figma/extractors/semantic-extractor.js";
15
- import { extractAdoStories } from "./figma/extractors/ado-story-extractor.js";
11
+ import { createMcpServer, createEnvLoader } from "@mcp-consultant-tools/core";
12
+ import { FigmaService } from './services/figma-service.js';
13
+ import { registerAllTools } from './tools/index.js';
16
14
  /**
17
- * Register Figma tools and prompts to an MCP server
18
- * @param server - The MCP server instance
19
- * @param figmaService - Optional pre-configured FigmaService (for testing or custom configs)
15
+ * Build a ServiceContext from environment variables (lazy service initialization).
20
16
  */
21
- export function registerFigmaTools(server, figmaService) {
22
- let service = figmaService || null;
23
- function getFigmaService() {
17
+ function createServiceContext() {
18
+ let service = null;
19
+ function getService() {
24
20
  if (!service) {
25
21
  const missingConfig = [];
26
22
  if (!process.env.FIGMA_API_KEY && !process.env.FIGMA_OAUTH_TOKEN) {
@@ -40,123 +36,23 @@ export function registerFigmaTools(server, figmaService) {
40
36
  }
41
37
  return service;
42
38
  }
43
- // Tool: get-figma-data
44
- server.tool("get-figma-data", "Get comprehensive Figma design data including layout, text, styles, and components. Fetches from Figma API and transforms into simplified, AI-friendly format. Can fetch entire files or specific nodes. Automatically deduplicates styles. Supports optimization options to reduce context window usage.", {
45
- fileKey: z.string().describe("Figma file key (alphanumeric string from URL). Example: From 'https://figma.com/file/ABC123/MyFile', use 'ABC123'"),
46
- nodeId: z.string().optional().describe("Optional specific node ID(s) to fetch. Format: '1234:5678' or multiple '1:10;2:20'. If omitted, fetches entire file."),
47
- depth: z.number().optional().describe("Optional tree traversal depth limit. Useful for large files. Example: depth=3 stops after 3 levels of children."),
48
- // Optimization options for reducing context window usage
49
- excludeStyles: z.boolean().optional().describe("Remove all styling info (fills, strokes, effects, textStyle, opacity, borderRadius) and globalVars.styles. Useful for understanding architecture without visual details. Default: true. Set to false for full styling data."),
50
- tablesToMarkdown: z.boolean().optional().describe("Convert TABLE nodes to markdown table format instead of nested node structures. Significantly reduces token usage for tables. Default: true. Set to false for full node tree."),
51
- simplifyConnectors: z.boolean().optional().describe("Simplify CONNECTOR nodes to just connection endpoints (startNodeId, endNodeId, text). Preserves relationship data while removing visual properties. Default: true. Set to false for full connector data."),
52
- simplifyComponentInstances: z.boolean().optional().describe("Keep componentId and componentProperties on INSTANCE nodes but remove visual styling. Ideal for ADO User Story components. Default: true. Set to false for full instance data."),
53
- extractors: z.array(z.enum(["layout", "text", "visuals", "component"])).optional().describe("Override which extractors to use. Options: layout, text, visuals, component. Default uses all. Example: ['text', 'component'] for content-focused extraction."),
54
- }, async ({ fileKey, nodeId, depth, excludeStyles, tablesToMarkdown, simplifyConnectors, simplifyComponentInstances, extractors }) => {
55
- try {
56
- const figmaService = getFigmaService();
57
- // Build data options from parameters
58
- const dataOptions = {
59
- excludeStyles,
60
- tablesToMarkdown,
61
- simplifyConnectors,
62
- simplifyComponentInstances,
63
- extractors,
64
- };
65
- const result = await figmaService.getFigmaData(fileKey, nodeId, depth, dataOptions);
66
- return createSuccessResponse(result);
67
- }
68
- catch (error) {
69
- return createErrorResponse(error, "get-figma-data");
70
- }
71
- });
72
- // Tool: get-figma-semantic
73
- server.tool("get-figma-semantic", "Extract semantically meaningful data from FigJam boards while discarding positional/visual information. Produces deterministic, diff-friendly output ideal for change detection. Categorizes sticky notes by color, extracts user story IDs, and preserves connector relationships.", {
74
- fileKey: z.string().describe("Figma file key (alphanumeric string from URL). Example: From 'https://figma.com/board/ABC123/MyBoard', use 'ABC123'"),
75
- nodeId: z.string().optional().describe("Optional specific node/section ID to fetch. Format: '1234:5678'. If omitted, fetches entire file."),
76
- stickyColorOverrides: z.record(z.enum([
77
- "blocker", "tbd", "si-investigation", "done", "info", "note", "unknown"
78
- ])).optional().describe("Optional color to category overrides. Map hex colors to categories. Example: {'#FF0000': 'blocker', '#00FF00': 'done'}"),
79
- storyIdPattern: z.string().optional().describe("Optional custom regex pattern for extracting story IDs. Default: strict pattern requiring prefix (US787, Story #787, Task787, Bug #787)"),
80
- }, async ({ fileKey, nodeId, stickyColorOverrides, storyIdPattern, }) => {
81
- try {
82
- const figmaService = getFigmaService();
83
- // Fetch with fills preserved for sticky categorization
84
- const dataOptions = {
85
- excludeStyles: false, // Need fills for sticky color detection
86
- simplifyConnectors: true,
87
- simplifyComponentInstances: true,
88
- tablesToMarkdown: true,
89
- };
90
- const rawData = await figmaService.getFigmaData(fileKey, nodeId, undefined, dataOptions);
91
- // Parse custom story pattern if provided
92
- let customPattern;
93
- if (storyIdPattern) {
94
- try {
95
- customPattern = new RegExp(storyIdPattern, "gi");
96
- }
97
- catch (e) {
98
- return createErrorResponse(new Error(`Invalid storyIdPattern regex: ${storyIdPattern}`), "get-figma-semantic");
99
- }
100
- }
101
- // Extract semantic data
102
- const semanticData = extractSemanticData(rawData, fileKey, nodeId, {
103
- stickyColorOverrides,
104
- storyIdPattern: customPattern,
105
- });
106
- return createSuccessResponse(semanticData);
107
- }
108
- catch (error) {
109
- return createErrorResponse(error, "get-figma-semantic");
110
- }
111
- });
112
- // Tool: extract-ado-stories
113
- server.tool("extract-ado-stories", "Extract all ADO User Story Components from a FigJam board or section. Returns structured data with IDs, descriptions, states, parent context, and links. Reduces ~200K raw node data to ~5K structured result.", {
114
- fileKey: z.string().describe("Figma file key (alphanumeric string from URL). Example: From 'https://figma.com/board/ABC123/MyBoard', use 'ABC123'"),
115
- nodeId: z.string().optional().describe("Optional section node ID to scope extraction. Format: '1234:5678'. If omitted, extracts from entire file."),
116
- adoOrganization: z.string().optional().describe("Azure DevOps organization name for constructing work item links. Example: 'myorg'"),
117
- adoProject: z.string().optional().describe("Azure DevOps project name for constructing work item links. Example: 'MyProject'"),
118
- includePlaceholders: z.boolean().optional().describe("Include ADO components with placeholder IDs (e.g. 'ADO xxxxx'). Default: false (placeholders are filtered out)."),
119
- }, async ({ fileKey, nodeId, adoOrganization, adoProject, includePlaceholders, }) => {
120
- try {
121
- const figmaService = getFigmaService();
122
- // Fetch with component properties preserved
123
- const dataOptions = {
124
- excludeStyles: true,
125
- simplifyComponentInstances: true,
126
- simplifyConnectors: true,
127
- tablesToMarkdown: true,
128
- };
129
- const rawData = await figmaService.getFigmaData(fileKey, nodeId, undefined, dataOptions);
130
- const result = extractAdoStories(rawData, {
131
- fileKey,
132
- adoOrganization,
133
- adoProject,
134
- includePlaceholders,
135
- });
136
- return createSuccessResponse(result);
137
- }
138
- catch (error) {
139
- return createErrorResponse(error, "extract-ado-stories");
140
- }
141
- });
142
- // Tool: download-figma-images (placeholder for v2)
143
- server.tool("download-figma-images", "Download and process images from Figma designs (Coming in v2)", {
144
- fileKey: z.string().describe("Figma file key"),
145
- localPath: z.string().describe("Local path to save images"),
146
- }, async ({ fileKey, localPath }) => {
147
- return createErrorResponse(new Error("Image download functionality is coming in v2. Use get-figma-data for design metadata."), "download-figma-images");
148
- });
149
- console.error("Figma tools registered: 4 tools");
39
+ return {
40
+ get figma() { return getService(); },
41
+ };
150
42
  }
151
43
  /**
152
- * Export service class for direct usage
44
+ * Register Figma tools to an MCP server.
45
+ * Backward-compatible API for the meta package.
153
46
  */
154
- export { FigmaService } from "./FigmaService.js";
47
+ export function registerFigmaTools(server) {
48
+ const ctx = createServiceContext();
49
+ registerAllTools(server, ctx);
50
+ }
51
+ // Backward-compatible exports
52
+ export { FigmaService } from './services/figma-service.js';
155
53
  /**
156
54
  * Standalone CLI server (when run directly)
157
- *
158
- * Uses realpathSync to resolve symlinks created by npx, ensuring import.meta.url
159
- * matches the resolved path in process.argv[1]
55
+ * Uses realpathSync to resolve symlinks created by npx
160
56
  */
161
57
  if (import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href) {
162
58
  const loadEnv = createEnvLoader();