figmanage 1.3.0 → 1.3.2

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 (56) hide show
  1. package/dist/cli/analytics.js +3 -2
  2. package/dist/cli/branching.js +9 -3
  3. package/dist/cli/comments.js +10 -4
  4. package/dist/cli/components.js +21 -4
  5. package/dist/cli/compound-commands.js +13 -12
  6. package/dist/cli/export.js +3 -2
  7. package/dist/cli/files.js +14 -8
  8. package/dist/cli/helpers.d.ts +1 -0
  9. package/dist/cli/helpers.js +10 -0
  10. package/dist/cli/libraries.js +2 -1
  11. package/dist/cli/navigate.js +11 -10
  12. package/dist/cli/org.js +13 -12
  13. package/dist/cli/permissions.js +13 -7
  14. package/dist/cli/projects.js +12 -6
  15. package/dist/cli/reading.js +3 -2
  16. package/dist/cli/teams.js +9 -3
  17. package/dist/cli/variables.js +29 -7
  18. package/dist/cli/versions.js +3 -2
  19. package/dist/cli/webhooks.js +14 -4
  20. package/dist/helpers.d.ts +11 -0
  21. package/dist/helpers.js +41 -0
  22. package/dist/operations/analytics.js +1 -1
  23. package/dist/operations/components.d.ts +8 -2
  24. package/dist/operations/components.js +4 -2
  25. package/dist/operations/compound-manager.js +8 -9
  26. package/dist/operations/compound.d.ts +3 -0
  27. package/dist/operations/compound.js +14 -8
  28. package/dist/operations/files.js +1 -1
  29. package/dist/operations/libraries.js +1 -1
  30. package/dist/operations/org.js +1 -1
  31. package/dist/operations/reading.js +2 -0
  32. package/dist/operations/teams.js +1 -1
  33. package/dist/operations/variables.js +11 -0
  34. package/dist/operations/webhooks.d.ts +4 -1
  35. package/dist/operations/webhooks.js +2 -1
  36. package/dist/tools/analytics.js +6 -5
  37. package/dist/tools/branching.js +7 -6
  38. package/dist/tools/comments.js +14 -9
  39. package/dist/tools/components.js +24 -15
  40. package/dist/tools/compound-manager.js +10 -7
  41. package/dist/tools/compound.js +34 -22
  42. package/dist/tools/export.js +6 -5
  43. package/dist/tools/files.js +13 -12
  44. package/dist/tools/libraries.js +6 -3
  45. package/dist/tools/navigate.js +29 -18
  46. package/dist/tools/org.js +25 -24
  47. package/dist/tools/permissions.js +14 -11
  48. package/dist/tools/projects.js +10 -9
  49. package/dist/tools/reading.js +11 -7
  50. package/dist/tools/register.d.ts +8 -2
  51. package/dist/tools/register.js +9 -14
  52. package/dist/tools/teams.js +7 -6
  53. package/dist/tools/variables.js +12 -8
  54. package/dist/tools/versions.js +6 -5
  55. package/dist/tools/webhooks.js +15 -12
  56. package/package.json +1 -1
@@ -56,21 +56,16 @@ export function registerTools(server, config, enabledToolsets, readOnly) {
56
56
  export function toolResult(text) {
57
57
  return { content: [{ type: 'text', text }] };
58
58
  }
59
+ /** Format a tool response with a summary line, JSON data, and optional next-step guidance. */
60
+ export function toolSummary(summary, data, nextStep) {
61
+ const parts = [summary, '', JSON.stringify(data, null, 2)];
62
+ if (nextStep)
63
+ parts.push('', nextStep);
64
+ return { content: [{ type: 'text', text: parts.join('\n') }] };
65
+ }
59
66
  export function toolError(message) {
60
67
  return { isError: true, content: [{ type: 'text', text: message }] };
61
68
  }
62
- export function resolveOrgId(config, explicit) {
63
- const id = explicit || config.orgId;
64
- if (id && !/^[\w.:-]+$/.test(id))
65
- throw new Error('Invalid org ID format');
66
- return id;
67
- }
68
- export function requireOrgId(config, explicit) {
69
- const id = explicit || config.orgId;
70
- if (!id)
71
- throw new Error('Org context required. Run list_orgs to see available workspaces, or set FIGMA_ORG_ID.');
72
- if (!/^[\w.:-]+$/.test(id))
73
- throw new Error('Invalid org ID format');
74
- return id;
75
- }
69
+ // Re-export from helpers so existing tool imports still work
70
+ export { resolveOrgId, requireOrgId } from '../helpers.js';
76
71
  //# sourceMappingURL=register.js.map
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { defineTool, toolResult, toolError, figmaId } from './register.js';
2
+ import { defineTool, toolResult, toolError, toolSummary, figmaId } from './register.js';
3
+ import { formatApiError } from '../helpers.js';
3
4
  import { createTeam, renameTeam, deleteTeam } from '../operations/teams.js';
4
5
  // -- create_team --
5
6
  defineTool({
@@ -16,10 +17,10 @@ defineTool({
16
17
  }, async ({ name, org_id }) => {
17
18
  try {
18
19
  const result = await createTeam(config, { name, org_id });
19
- return toolResult(JSON.stringify(result, null, 2));
20
+ return toolSummary(`Created team.`, result, 'Use create_project to add projects to this team.');
20
21
  }
21
22
  catch (e) {
22
- return toolError(`Failed to create team: ${e.response?.status || e.message}`);
23
+ return toolError(`Failed to create team: ${formatApiError(e)}`);
23
24
  }
24
25
  });
25
26
  },
@@ -42,7 +43,7 @@ defineTool({
42
43
  return toolResult(msg);
43
44
  }
44
45
  catch (e) {
45
- return toolError(`Failed to rename team: ${e.response?.status || e.message}`);
46
+ return toolError(`Failed to rename team: ${formatApiError(e)}`);
46
47
  }
47
48
  });
48
49
  },
@@ -55,7 +56,7 @@ defineTool({
55
56
  destructive: true,
56
57
  register(server, config) {
57
58
  server.registerTool('delete_team', {
58
- description: 'Delete a team. This is destructive and cannot be undone.',
59
+ description: 'Permanently delete a team and all its projects/files. This cannot be undone. All team members lose access.',
59
60
  inputSchema: {
60
61
  team_id: figmaId.describe('Team ID'),
61
62
  },
@@ -65,7 +66,7 @@ defineTool({
65
66
  return toolResult(msg);
66
67
  }
67
68
  catch (e) {
68
- return toolError(`Failed to delete team: ${e.response?.status || e.message}`);
69
+ return toolError(`Failed to delete team: ${formatApiError(e)}`);
69
70
  }
70
71
  });
71
72
  },
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { defineTool, toolResult, toolError, figmaId } from './register.js';
2
+ import { defineTool, toolError, toolSummary, figmaId } from './register.js';
3
+ import { formatApiError } from '../helpers.js';
3
4
  import { listLocalVariables, listPublishedVariables, updateVariables, isEnterpriseScopeError, ENTERPRISE_ERROR, } from '../operations/variables.js';
4
5
  // -- list_local_variables --
5
6
  defineTool({
@@ -14,12 +15,14 @@ defineTool({
14
15
  }, async ({ file_key }) => {
15
16
  try {
16
17
  const result = await listLocalVariables(config, { file_key });
17
- return toolResult(JSON.stringify(result, null, 2));
18
+ const vars = result.variables ? Object.keys(result.variables).length : 0;
19
+ const collections = result.variableCollections ? Object.keys(result.variableCollections).length : 0;
20
+ return toolSummary(`${vars} variable(s) in ${collections} collection(s).`, result);
18
21
  }
19
22
  catch (e) {
20
23
  if (isEnterpriseScopeError(e))
21
24
  return toolError(ENTERPRISE_ERROR);
22
- return toolError(`Failed to list local variables: ${e.response?.status || e.message}`);
25
+ return toolError(`Failed to list local variables: ${formatApiError(e)}`);
23
26
  }
24
27
  });
25
28
  },
@@ -37,12 +40,13 @@ defineTool({
37
40
  }, async ({ file_key }) => {
38
41
  try {
39
42
  const result = await listPublishedVariables(config, { file_key });
40
- return toolResult(JSON.stringify(result, null, 2));
43
+ const vars = result.variables ? Object.keys(result.variables).length : 0;
44
+ return toolSummary(`${vars} published variable(s).`, result);
41
45
  }
42
46
  catch (e) {
43
47
  if (isEnterpriseScopeError(e))
44
48
  return toolError(ENTERPRISE_ERROR);
45
- return toolError(`Failed to list published variables: ${e.response?.status || e.message}`);
49
+ return toolError(`Failed to list published variables: ${formatApiError(e)}`);
46
50
  }
47
51
  });
48
52
  },
@@ -55,7 +59,7 @@ defineTool({
55
59
  destructive: true,
56
60
  register(server, config) {
57
61
  server.registerTool('update_variables', {
58
- description: 'Bulk create, update, or delete variables, collections, modes, and mode values. Requires Enterprise plan.',
62
+ description: 'Bulk create, update, or delete variables, collections, modes, and mode values. Requires Enterprise plan. Each operation object needs an action field (CREATE, UPDATE, or DELETE). Deletions are immediate and cannot be undone -- list variables first to verify IDs.',
59
63
  inputSchema: {
60
64
  file_key: figmaId.describe('File key'),
61
65
  variable_collections: z.array(z.record(z.any())).optional().describe('Collection operations (action: CREATE, UPDATE, or DELETE)'),
@@ -72,12 +76,12 @@ defineTool({
72
76
  variables,
73
77
  variable_mode_values,
74
78
  });
75
- return toolResult(JSON.stringify(result, null, 2));
79
+ return toolSummary('Variables updated.', result, 'Use list_local_variables to verify changes.');
76
80
  }
77
81
  catch (e) {
78
82
  if (isEnterpriseScopeError(e))
79
83
  return toolError(ENTERPRISE_ERROR);
80
- return toolError(`Failed to update variables: ${e.response?.status || e.message}`);
84
+ return toolError(`Failed to update variables: ${formatApiError(e)}`);
81
85
  }
82
86
  });
83
87
  },
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { defineTool, toolResult, toolError, figmaId } from './register.js';
2
+ import { defineTool, toolResult, toolError, toolSummary, figmaId } from './register.js';
3
+ import { formatApiError } from '../helpers.js';
3
4
  import { listVersions, createVersion } from '../operations/versions.js';
4
5
  // -- list_versions --
5
6
  defineTool({
@@ -16,10 +17,10 @@ defineTool({
16
17
  const result = await listVersions(config, { file_key });
17
18
  if (result.length === 0)
18
19
  return toolResult('No versions found.');
19
- return toolResult(JSON.stringify(result, null, 2));
20
+ return toolSummary(`${result.length} version(s).`, result, 'Use create_version to add a named checkpoint.');
20
21
  }
21
22
  catch (e) {
22
- return toolError(`Failed to list versions: ${e.response?.status || e.message}`);
23
+ return toolError(`Failed to list versions: ${formatApiError(e)}`);
23
24
  }
24
25
  });
25
26
  },
@@ -40,10 +41,10 @@ defineTool({
40
41
  }, async ({ file_key, title, description }) => {
41
42
  try {
42
43
  const result = await createVersion(config, { file_key, title, description });
43
- return toolResult(JSON.stringify(result, null, 2));
44
+ return toolSummary(`Created version "${result.label}".`, result);
44
45
  }
45
46
  catch (e) {
46
- return toolError(`Failed to create version: ${e.response?.status || e.message}`);
47
+ return toolError(`Failed to create version: ${formatApiError(e)}`);
47
48
  }
48
49
  });
49
50
  },
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { defineTool, toolResult, toolError, figmaId } from './register.js';
2
+ import { defineTool, toolResult, toolError, toolSummary, figmaId } from './register.js';
3
+ import { formatApiError } from '../helpers.js';
3
4
  import { listWebhooks, createWebhook, updateWebhook, deleteWebhook, } from '../operations/webhooks.js';
4
5
  const eventTypeEnum = z.enum([
5
6
  'FILE_UPDATE',
@@ -15,17 +16,19 @@ defineTool({
15
16
  auth: 'pat',
16
17
  register(server, config) {
17
18
  server.registerTool('list_webhooks', {
18
- description: 'List webhooks for a team.',
19
+ description: 'List webhook subscriptions for a team. Returns webhook IDs, endpoints, event types, and status.',
19
20
  inputSchema: {
20
21
  team_id: figmaId.describe('Team ID'),
21
22
  },
22
23
  }, async ({ team_id }) => {
23
24
  try {
24
- const webhooks = await listWebhooks(config, { team_id });
25
- return toolResult(JSON.stringify(webhooks, null, 2));
25
+ const result = await listWebhooks(config, { team_id });
26
+ if (result.count === 0)
27
+ return toolResult('No webhooks configured for this team.');
28
+ return toolSummary(`${result.count} webhook(s).`, result, 'Use create_webhook to add, or update_webhook/delete_webhook to manage.');
26
29
  }
27
30
  catch (e) {
28
- return toolError(`Failed to list webhooks: ${e.response?.status || e.message}`);
31
+ return toolError(`Failed to list webhooks: ${formatApiError(e)}`);
29
32
  }
30
33
  });
31
34
  },
@@ -48,10 +51,10 @@ defineTool({
48
51
  }, async ({ team_id, event_type, endpoint, passcode, description }) => {
49
52
  try {
50
53
  const result = await createWebhook(config, { team_id, event_type, endpoint, passcode, description });
51
- return toolResult(JSON.stringify(result, null, 2));
54
+ return toolSummary(`Created webhook ${result.id || 'unknown'} for ${result.event_type || event_type} events.`, result);
52
55
  }
53
56
  catch (e) {
54
- return toolError(`Failed to create webhook: ${e.response?.status || e.message}`);
57
+ return toolError(`Failed to create webhook: ${formatApiError(e)}`);
55
58
  }
56
59
  });
57
60
  },
@@ -63,7 +66,7 @@ defineTool({
63
66
  mutates: true,
64
67
  register(server, config) {
65
68
  server.registerTool('update_webhook', {
66
- description: 'Update a webhook.',
69
+ description: "Update a webhook's endpoint, event type, passcode, description, or status (ACTIVE/PAUSED).",
67
70
  inputSchema: {
68
71
  webhook_id: figmaId.describe('Webhook ID'),
69
72
  event_type: eventTypeEnum.optional().describe('Event type to subscribe to'),
@@ -75,10 +78,10 @@ defineTool({
75
78
  }, async ({ webhook_id, event_type, endpoint, passcode, description, status }) => {
76
79
  try {
77
80
  const result = await updateWebhook(config, { webhook_id, event_type, endpoint, passcode, description, status });
78
- return toolResult(JSON.stringify(result, null, 2));
81
+ return toolSummary(`Updated webhook ${result.id || webhook_id}.`, result);
79
82
  }
80
83
  catch (e) {
81
- return toolError(`Failed to update webhook: ${e.response?.status || e.message}`);
84
+ return toolError(`Failed to update webhook: ${formatApiError(e)}`);
82
85
  }
83
86
  });
84
87
  },
@@ -91,7 +94,7 @@ defineTool({
91
94
  destructive: true,
92
95
  register(server, config) {
93
96
  server.registerTool('delete_webhook', {
94
- description: 'Delete a webhook.',
97
+ description: 'Permanently delete a webhook. The webhook stops receiving events immediately. Cannot be undone.',
95
98
  inputSchema: {
96
99
  webhook_id: figmaId.describe('Webhook ID'),
97
100
  },
@@ -101,7 +104,7 @@ defineTool({
101
104
  return toolResult(`Deleted webhook ${webhook_id}`);
102
105
  }
103
106
  catch (e) {
104
- return toolError(`Failed to delete webhook: ${e.response?.status || e.message}`);
107
+ return toolError(`Failed to delete webhook: ${formatApiError(e)}`);
105
108
  }
106
109
  });
107
110
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "figmanage",
3
3
  "mcpName": "io.github.dannykeane/figmanage",
4
- "version": "1.3.0",
4
+ "version": "1.3.2",
5
5
  "description": "MCP server for managing your Figma workspace from the terminal.",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",