@reframejs/unframer 4.2.0-reframe.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.
Files changed (111) hide show
  1. package/README.md +389 -0
  2. package/bin.js +5 -0
  3. package/dist/babel-jsx.d.ts +24 -0
  4. package/dist/babel-jsx.js +299 -0
  5. package/dist/babel-plugin-imports.d.ts +15 -0
  6. package/dist/babel-plugin-imports.js +211 -0
  7. package/dist/babel-typedoc.d.ts +39 -0
  8. package/dist/babel-typedoc.js +76 -0
  9. package/dist/bin.d.ts +2 -0
  10. package/dist/bin.js +3 -0
  11. package/dist/cli.d.ts +59 -0
  12. package/dist/cli.js +821 -0
  13. package/dist/compat.d.ts +2 -0
  14. package/dist/compat.js +23 -0
  15. package/dist/config.d.ts +18 -0
  16. package/dist/config.js +27 -0
  17. package/dist/css-core.d.ts +50 -0
  18. package/dist/css-core.js +231 -0
  19. package/dist/css.d.ts +15 -0
  20. package/dist/css.js +36 -0
  21. package/dist/esbuild.d.ts +31 -0
  22. package/dist/esbuild.js +317 -0
  23. package/dist/exporter.d.ts +96 -0
  24. package/dist/exporter.js +1151 -0
  25. package/dist/flat-cache-interceptor.d.ts +24 -0
  26. package/dist/flat-cache-interceptor.js +87 -0
  27. package/dist/framer-chunks/chunk-IKQSD2QC.js +10 -0
  28. package/dist/framer-chunks/fontshare-PZLWRK4B-MHMZIGTX.js +7 -0
  29. package/dist/framer-chunks/fontshare-SXU5BGFE-OWTMMPGS.js +7 -0
  30. package/dist/framer-chunks/fontshare-TIA7QUPT-PUDLUTQ7.js +7 -0
  31. package/dist/framer-chunks/framer-font-RD2SUPQH-Q4MS7WS6.js +7 -0
  32. package/dist/framer-chunks/google-EGNT223R-P4DUHBW2.js +7 -0
  33. package/dist/framer-chunks/google-H6SFY4F5-5JSJCGDR.js +7 -0
  34. package/dist/framer-chunks/google-YSYBFRE6-L7YAHH7V.js +7 -0
  35. package/dist/framer-client.server.d.ts +4 -0
  36. package/dist/framer-client.server.js +45 -0
  37. package/dist/framer-package-versions.d.ts +781 -0
  38. package/dist/framer-package-versions.js +782 -0
  39. package/dist/framer-types.d.ts +30 -0
  40. package/dist/framer-types.js +35 -0
  41. package/dist/framer.d.ts +4990 -0
  42. package/dist/framer.js +64296 -0
  43. package/dist/index.d.ts +10 -0
  44. package/dist/index.js +13 -0
  45. package/dist/package-manager.d.ts +10 -0
  46. package/dist/package-manager.js +138 -0
  47. package/dist/plugin-mcp-dist/lib/client-websocket.d.ts +5 -0
  48. package/dist/plugin-mcp-dist/lib/client-websocket.js +103 -0
  49. package/dist/plugin-mcp-dist/lib/cms.d.ts +10 -0
  50. package/dist/plugin-mcp-dist/lib/cms.js +58 -0
  51. package/dist/plugin-mcp-dist/lib/errors.d.ts +5 -0
  52. package/dist/plugin-mcp-dist/lib/errors.js +48 -0
  53. package/dist/plugin-mcp-dist/lib/framer-client.d.ts +2 -0
  54. package/dist/plugin-mcp-dist/lib/framer-client.js +4 -0
  55. package/dist/plugin-mcp-dist/lib/framer-client.server.d.ts +3 -0
  56. package/dist/plugin-mcp-dist/lib/framer-client.server.js +46 -0
  57. package/dist/plugin-mcp-dist/lib/framer.d.ts +30 -0
  58. package/dist/plugin-mcp-dist/lib/framer.js +1084 -0
  59. package/dist/plugin-mcp-dist/lib/hooks.d.ts +6 -0
  60. package/dist/plugin-mcp-dist/lib/hooks.js +46 -0
  61. package/dist/plugin-mcp-dist/lib/mcp-client.d.ts +142 -0
  62. package/dist/plugin-mcp-dist/lib/mcp-client.js +40 -0
  63. package/dist/plugin-mcp-dist/lib/mcp-handlers.d.ts +385 -0
  64. package/dist/plugin-mcp-dist/lib/mcp-handlers.js +1924 -0
  65. package/dist/plugin-mcp-dist/lib/mcp-tools.d.ts +5 -0
  66. package/dist/plugin-mcp-dist/lib/mcp-tools.js +5 -0
  67. package/dist/plugin-mcp-dist/lib/mcp-websocket.d.ts +10 -0
  68. package/dist/plugin-mcp-dist/lib/mcp-websocket.js +88 -0
  69. package/dist/plugin-mcp-dist/lib/plugin-websocket.d.ts +5 -0
  70. package/dist/plugin-mcp-dist/lib/plugin-websocket.js +170 -0
  71. package/dist/plugin-mcp-dist/lib/react-export.d.ts +51 -0
  72. package/dist/plugin-mcp-dist/lib/react-export.js +358 -0
  73. package/dist/plugin-mcp-dist/lib/schema.d.ts +276 -0
  74. package/dist/plugin-mcp-dist/lib/schema.js +907 -0
  75. package/dist/plugin-mcp-dist/lib/store.d.ts +2 -0
  76. package/dist/plugin-mcp-dist/lib/store.js +10 -0
  77. package/dist/plugin-mcp-dist/lib/tree-utils.d.ts +6 -0
  78. package/dist/plugin-mcp-dist/lib/tree-utils.js +141 -0
  79. package/dist/plugin-mcp-dist/lib/tunnel.d.ts +46 -0
  80. package/dist/plugin-mcp-dist/lib/tunnel.js +117 -0
  81. package/dist/plugin-mcp-dist/lib/types.d.ts +110 -0
  82. package/dist/plugin-mcp-dist/lib/types.js +188 -0
  83. package/dist/plugin-mcp-dist/lib/upstream-socket.d.ts +13 -0
  84. package/dist/plugin-mcp-dist/lib/upstream-socket.js +56 -0
  85. package/dist/plugin-mcp-dist/lib/utils.d.ts +13 -0
  86. package/dist/plugin-mcp-dist/lib/utils.js +57 -0
  87. package/dist/plugin-mcp-dist/lib/websocket-server.d.ts +10 -0
  88. package/dist/plugin-mcp-dist/lib/websocket-server.js +88 -0
  89. package/dist/plugin-mcp-dist/lib/xml.d.ts +10 -0
  90. package/dist/plugin-mcp-dist/lib/xml.js +395 -0
  91. package/dist/react.d.ts +76 -0
  92. package/dist/react.js +280 -0
  93. package/dist/renamer.d.ts +11 -0
  94. package/dist/renamer.js +139 -0
  95. package/dist/sentry.d.ts +2 -0
  96. package/dist/sentry.js +5 -0
  97. package/dist/stackblitz.d.ts +9 -0
  98. package/dist/stackblitz.js +179 -0
  99. package/dist/styles/framer.css +920 -0
  100. package/dist/styles/reset.css +37 -0
  101. package/dist/typescript.d.ts +24 -0
  102. package/dist/typescript.js +197 -0
  103. package/dist/undici-dispatcher.d.ts +2 -0
  104. package/dist/undici-dispatcher.js +10 -0
  105. package/dist/unframer-loader.d.ts +2 -0
  106. package/dist/unframer-loader.js +12 -0
  107. package/dist/utils.d.ts +20 -0
  108. package/dist/utils.js +81 -0
  109. package/dist/version.d.ts +2 -0
  110. package/dist/version.js +2 -0
  111. package/package.json +131 -0
@@ -0,0 +1,2 @@
1
+ export declare const useStore: any;
2
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1,10 @@
1
+ import { create } from 'zustand';
2
+ export const useStore = create((set) => ({
3
+ isConnected: false,
4
+ isSocketOpen: false,
5
+ isExpanded: true,
6
+ isUiHidden: false,
7
+ error: undefined,
8
+ }));
9
+ //# sourceMappingURL=store.js.map
10
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1,6 @@
1
+ export declare const ITEMS_PER_ITERATION = 30;
2
+ export declare function bfsFramerLayersTree(tree: any): any[];
3
+ export declare function mergeCloseChunks(chunks: any, maxSize: any): any;
4
+ export declare function mergeChunksTooSmall(chunks: any, maxSize: any): any;
5
+ export declare function splitTreeInChunks(tree: any, maxChunkTreeSize?: number): any[];
6
+ //# sourceMappingURL=tree-utils.d.ts.map
@@ -0,0 +1,141 @@
1
+ import { addNodeCount } from './xml.js';
2
+ export const ITEMS_PER_ITERATION = 30;
3
+ export function bfsFramerLayersTree(tree) {
4
+ const result = [];
5
+ const queue = [...tree];
6
+ while (queue.length > 0) {
7
+ const node = queue.shift();
8
+ if (!node)
9
+ continue;
10
+ result.push(node);
11
+ if (node.children) {
12
+ queue.push(...node.children);
13
+ }
14
+ }
15
+ return result;
16
+ }
17
+ export function mergeCloseChunks(chunks, maxSize) {
18
+ // If we have 1 or fewer chunks, just return them as-is
19
+ if (chunks.length <= 1) {
20
+ return chunks;
21
+ }
22
+ const result = [];
23
+ let currentChunk = chunks[0];
24
+ // Iterate through chunks starting from the second one
25
+ for (let i = 1; i < chunks.length; i++) {
26
+ const nextChunk = chunks[i];
27
+ const combinedSize = getChunkSize(currentChunk) + getChunkSize(nextChunk);
28
+ // If combining the chunks would exceed maxSize,
29
+ // add current chunk to result and start new chunk
30
+ if (combinedSize > maxSize) {
31
+ result.push(currentChunk);
32
+ currentChunk = nextChunk;
33
+ }
34
+ else {
35
+ // Merge the chunks by concatenating their arrays
36
+ currentChunk = [...currentChunk, ...nextChunk];
37
+ }
38
+ }
39
+ // Don't forget to add the last chunk
40
+ result.push(currentChunk);
41
+ return result;
42
+ }
43
+ export function mergeChunksTooSmall(chunks, maxSize) {
44
+ // If we have 1 or fewer chunks, just return them as-is
45
+ if (chunks.length <= 1) {
46
+ return chunks;
47
+ }
48
+ const minSize = maxSize / 2;
49
+ let result = [...chunks];
50
+ // Keep merging small chunks until no more merges are possible
51
+ let madeChanges = true;
52
+ while (madeChanges) {
53
+ madeChanges = false;
54
+ // Find first small chunk that can be merged
55
+ for (let i = 0; i < result.length; i++) {
56
+ const currentSize = getChunkSize(result[i]);
57
+ if (currentSize < minSize) {
58
+ // Get sizes of previous and next chunks if they exist
59
+ const prevSize = i > 0 ? getChunkSize(result[i - 1]) : Infinity;
60
+ const nextSize = i < result.length - 1
61
+ ? getChunkSize(result[i + 1])
62
+ : Infinity;
63
+ // Determine which neighbor is smaller
64
+ if (prevSize <= nextSize && i > 0) {
65
+ // Merge with previous chunk
66
+ const combinedSize = currentSize + prevSize;
67
+ if (combinedSize < maxSize) {
68
+ result[i - 1] = [...result[i - 1], ...result[i]];
69
+ result.splice(i, 1);
70
+ madeChanges = true;
71
+ break;
72
+ }
73
+ }
74
+ else if (i < result.length - 1) {
75
+ // Merge with next chunk
76
+ const combinedSize = currentSize + nextSize;
77
+ if (combinedSize < maxSize) {
78
+ result[i] = [...result[i], ...result[i + 1]];
79
+ result.splice(i + 1, 1);
80
+ madeChanges = true;
81
+ break;
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
87
+ return result;
88
+ }
89
+ // Helper function to calculate total size of a chunk
90
+ function getChunkSize(chunk) {
91
+ return chunk.reduce((sum, node) => sum + (node.count || 0), 0);
92
+ }
93
+ export function splitTreeInChunks(tree, maxChunkTreeSize = ITEMS_PER_ITERATION) {
94
+ addNodeCount(tree);
95
+ const chunks = splitTreeInChunksRecursive(tree, maxChunkTreeSize, []);
96
+ let prevLength = -1;
97
+ let currentChunks = chunks;
98
+ while (currentChunks.length !== prevLength) {
99
+ prevLength = currentChunks.length;
100
+ currentChunks = mergeCloseChunks(currentChunks, maxChunkTreeSize);
101
+ }
102
+ currentChunks = mergeChunksTooSmall(currentChunks, maxChunkTreeSize * 1.2);
103
+ return currentChunks;
104
+ }
105
+ function findFirstChildrenLayer(tree) {
106
+ let currentLayer = tree;
107
+ let parents = [];
108
+ while (currentLayer.length === 1 && currentLayer[0].children?.length) {
109
+ parents.push({ ...currentLayer[0], children: [] });
110
+ currentLayer = currentLayer[0].children;
111
+ }
112
+ return { layer: currentLayer, parents };
113
+ }
114
+ function splitTreeInChunksRecursive(tree, maxChunkTreeSize, initialParents) {
115
+ let result = [];
116
+ // Find the first layer with more than one child
117
+ const { layer: currentLayer, parents } = findFirstChildrenLayer(tree);
118
+ const allParents = [...initialParents, ...parents];
119
+ for (const node of currentLayer) {
120
+ if (node.count <= maxChunkTreeSize) {
121
+ const chunk = createChunkWithParents(allParents, [node]);
122
+ result.push(chunk);
123
+ }
124
+ else {
125
+ result.push(...splitTreeInChunksRecursive([node], maxChunkTreeSize, allParents));
126
+ }
127
+ }
128
+ return result;
129
+ }
130
+ function createChunkWithParents(parents, children) {
131
+ if (parents.length === 0) {
132
+ return children;
133
+ }
134
+ let currentParent = { ...parents[parents.length - 1], children };
135
+ for (let i = parents.length - 2; i >= 0; i--) {
136
+ currentParent = { ...parents[i], children: [currentParent] };
137
+ }
138
+ return addNodeCount([currentParent]);
139
+ }
140
+ //# sourceMappingURL=tree-utils.js.map
141
+ //# sourceMappingURL=tree-utils.js.map
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Vendored upstream-only tunnel DO for Cloudflare Workers with WebSocket hibernation.
3
+ *
4
+ * Extracted from cloudflare-tunnel library — keeps only what McpTunnel uses:
5
+ * - Upstream WebSocket acceptance with hibernation tags
6
+ * - Upstream replacement (close old with 4009)
7
+ * - Ping auto-response (avoids waking DO)
8
+ * - handleTunnelFetch router
9
+ * - addCors helper
10
+ *
11
+ * Dropped: downstream relay, multiplexer, wildcard subscribers, standalone worker export.
12
+ */
13
+ /**
14
+ * Route /_tunnel/* requests to a Tunnel Durable Object.
15
+ * Use in the worker's fetch handler to add tunnel support.
16
+ */
17
+ export declare function handleTunnelFetch({ req, doNamespace }: {
18
+ doNamespace: any;
19
+ req: any;
20
+ }): any;
21
+ /**
22
+ * Upstream-only Tunnel Durable Object.
23
+ *
24
+ * Accepts upstream WebSocket connections with hibernation. Each upstream is
25
+ * tagged as `up:${id}` so it can be looked up by id. Only one upstream per id
26
+ * is allowed — connecting a second closes the first with code 4009.
27
+ *
28
+ * Ping messages are auto-responded without waking the DO:
29
+ * - 'ping' → 'pong'
30
+ * - '{"type":"ping"}' → '{"type":"pong"}'
31
+ */
32
+ export declare class Tunnel {
33
+ ctx: any;
34
+ env: any;
35
+ constructor(state: any, env: any);
36
+ fetch(req: any): Promise<Response>;
37
+ webSocketMessage(_ws: any, _message: any): Promise<void>;
38
+ webSocketClose(_ws: any, _code: any, _reason: any, _wasClean: any): Promise<void>;
39
+ webSocketError(_ws: any, _error: any): Promise<void>;
40
+ closeUpstreamsForId(id: any, { code, reason }: {
41
+ code: any;
42
+ reason: any;
43
+ }): void;
44
+ }
45
+ export declare const addCors: (r: any) => Response;
46
+ //# sourceMappingURL=tunnel.d.ts.map
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Vendored upstream-only tunnel DO for Cloudflare Workers with WebSocket hibernation.
3
+ *
4
+ * Extracted from cloudflare-tunnel library — keeps only what McpTunnel uses:
5
+ * - Upstream WebSocket acceptance with hibernation tags
6
+ * - Upstream replacement (close old with 4009)
7
+ * - Ping auto-response (avoids waking DO)
8
+ * - handleTunnelFetch router
9
+ * - addCors helper
10
+ *
11
+ * Dropped: downstream relay, multiplexer, wildcard subscribers, standalone worker export.
12
+ */
13
+ /**
14
+ * Route /_tunnel/* requests to a Tunnel Durable Object.
15
+ * Use in the worker's fetch handler to add tunnel support.
16
+ */
17
+ export function handleTunnelFetch({ req, doNamespace, }) {
18
+ const url = new URL(req.url);
19
+ if (!url.pathname.startsWith('/_tunnel/')) {
20
+ return null;
21
+ }
22
+ url.pathname = url.pathname.replace('/_tunnel', '');
23
+ const ids = url.searchParams.getAll('id');
24
+ const doName = ids[0] ?? 'default';
25
+ const doId = doNamespace.idFromName(doName);
26
+ return doNamespace
27
+ .get(doId)
28
+ .fetch(new Request(url.toString(), req))
29
+ .then(addCors);
30
+ }
31
+ /**
32
+ * Upstream-only Tunnel Durable Object.
33
+ *
34
+ * Accepts upstream WebSocket connections with hibernation. Each upstream is
35
+ * tagged as `up:${id}` so it can be looked up by id. Only one upstream per id
36
+ * is allowed — connecting a second closes the first with code 4009.
37
+ *
38
+ * Ping messages are auto-responded without waking the DO:
39
+ * - 'ping' → 'pong'
40
+ * - '{"type":"ping"}' → '{"type":"pong"}'
41
+ */
42
+ export class Tunnel {
43
+ ctx;
44
+ env;
45
+ constructor(state, env) {
46
+ this.ctx = state;
47
+ this.env = env;
48
+ // Only one auto-response pair can be active (second call replaces first).
49
+ // Plugin sends {"type":"ping"} every 5s — must match exactly.
50
+ this.ctx.setWebSocketAutoResponse(new WebSocketRequestResponsePair('{"type":"ping"}', '{"type":"pong"}'));
51
+ }
52
+ async fetch(req) {
53
+ if (req.headers.get('Upgrade') !== 'websocket') {
54
+ return addCors(new Response('Upgrade required', { status: 400 }));
55
+ }
56
+ const url = new URL(req.url);
57
+ const ids = url.searchParams.getAll('id');
58
+ const id = ids[0];
59
+ if (!url.pathname.startsWith('/upstream') || !id) {
60
+ return addCors(new Response('Only upstream connections with id are supported', { status: 400 }));
61
+ }
62
+ this.closeUpstreamsForId(id, { code: 4009, reason: 'Upstream already connected' });
63
+ const connectionOrdinal = this.ctx
64
+ .getWebSockets(`up:${id}`)
65
+ .map((socket) => {
66
+ const attachment = socket.deserializeAttachment();
67
+ return attachment?.connectionOrdinal || 0;
68
+ })
69
+ .reduce((maxOrdinal, ordinal) => {
70
+ return Math.max(maxOrdinal, ordinal);
71
+ }, 0) + 1;
72
+ const pair = new WebSocketPair();
73
+ const [client, server] = Object.values(pair);
74
+ this.ctx.acceptWebSocket(server, [`up:${id}`]);
75
+ server.serializeAttachment({
76
+ role: 'up',
77
+ ids: [id],
78
+ connectionId: crypto.randomUUID(),
79
+ connectionOrdinal,
80
+ connectedAt: Date.now(),
81
+ readyAcked: false,
82
+ });
83
+ return addCors(new Response(null, { status: 101, webSocket: client }));
84
+ }
85
+ async webSocketMessage(_ws, _message) {
86
+ // No relay — McpTunnel overrides this entirely
87
+ }
88
+ async webSocketClose(_ws, _code, _reason, _wasClean) {
89
+ // No downstream notification — McpTunnel overrides this
90
+ }
91
+ async webSocketError(_ws, _error) {
92
+ // No downstream notification — McpTunnel overrides this
93
+ }
94
+ closeUpstreamsForId(id, { code, reason }) {
95
+ const ups = this.ctx.getWebSockets(`up:${id}`);
96
+ for (const up of ups) {
97
+ try {
98
+ up.close(code, reason);
99
+ }
100
+ catch { }
101
+ }
102
+ }
103
+ }
104
+ export const addCors = (r) => {
105
+ const newHeaders = new Headers(r.headers);
106
+ newHeaders.set('Access-Control-Allow-Origin', '*');
107
+ newHeaders.set('Access-Control-Allow-Headers', '*');
108
+ newHeaders.set('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');
109
+ return new Response(r.body, {
110
+ status: r.status,
111
+ statusText: r.statusText,
112
+ headers: newHeaders,
113
+ webSocket: r.webSocket,
114
+ });
115
+ };
116
+ //# sourceMappingURL=tunnel.js.map
117
+ //# sourceMappingURL=tunnel.js.map
@@ -0,0 +1,110 @@
1
+ import { z } from 'zod';
2
+ export declare const mcpTools: {
3
+ getProjectXml: {
4
+ description: string;
5
+ input: z.ZodObject<{}, z.core.$strip>;
6
+ output: z.ZodAny;
7
+ };
8
+ getSelectedNodesXml: {
9
+ description: string;
10
+ input: z.ZodObject<{}, z.core.$strip>;
11
+ output: z.ZodAny;
12
+ };
13
+ zoomIntoView: {
14
+ description: string;
15
+ input: z.ZodObject<{
16
+ nodeId: z.ZodString;
17
+ }, z.core.$strip>;
18
+ output: z.ZodAny;
19
+ };
20
+ getNodeXml: {
21
+ description: string;
22
+ input: z.ZodObject<{
23
+ nodeId: z.ZodString;
24
+ }, z.core.$strip>;
25
+ output: z.ZodAny;
26
+ };
27
+ getProjectColorStyles: {
28
+ description: string;
29
+ input: z.ZodObject<{}, z.core.$strip>;
30
+ };
31
+ getProjectTextStyles: {
32
+ description: string;
33
+ input: z.ZodObject<{}, z.core.$strip>;
34
+ output: z.ZodAny;
35
+ };
36
+ updateXmlForNode: {
37
+ description: string;
38
+ input: z.ZodObject<{
39
+ nodeId: z.ZodString;
40
+ xml: z.ZodString;
41
+ }, z.core.$strip>;
42
+ output: z.ZodAny;
43
+ };
44
+ updateColorStyle: {
45
+ description: string;
46
+ input: z.ZodObject<{
47
+ stylePath: z.ZodString;
48
+ updates: z.ZodObject<{
49
+ name: z.ZodOptional<z.ZodString>;
50
+ light: z.ZodOptional<z.ZodString>;
51
+ dark: z.ZodOptional<z.ZodNullable<z.ZodString>>;
52
+ }, z.core.$strip>;
53
+ }, z.core.$strip>;
54
+ output: z.ZodAny;
55
+ };
56
+ updateTextStyle: {
57
+ description: string;
58
+ input: z.ZodObject<{
59
+ stylePath: z.ZodString;
60
+ updates: z.ZodObject<{
61
+ name: z.ZodOptional<z.ZodString>;
62
+ fontSize: z.ZodOptional<z.ZodString>;
63
+ lineHeight: z.ZodOptional<z.ZodString>;
64
+ letterSpacing: z.ZodOptional<z.ZodString>;
65
+ paragraphSpacing: z.ZodOptional<z.ZodNumber>;
66
+ transform: z.ZodOptional<z.ZodEnum<{
67
+ capitalize: "capitalize";
68
+ lowercase: "lowercase";
69
+ none: "none";
70
+ uppercase: "uppercase";
71
+ }>>;
72
+ alignment: z.ZodOptional<z.ZodEnum<{
73
+ center: "center";
74
+ justify: "justify";
75
+ left: "left";
76
+ right: "right";
77
+ }>>;
78
+ decoration: z.ZodOptional<z.ZodEnum<{
79
+ "line-through": "line-through";
80
+ none: "none";
81
+ underline: "underline";
82
+ }>>;
83
+ balance: z.ZodOptional<z.ZodBoolean>;
84
+ }, z.core.$strip>;
85
+ }, z.core.$strip>;
86
+ output: z.ZodAny;
87
+ };
88
+ searchFonts: {
89
+ description: string;
90
+ input: z.ZodObject<{
91
+ query: z.ZodString;
92
+ }, z.core.$strip>;
93
+ output: z.ZodAny;
94
+ };
95
+ deleteNode: {
96
+ description: string;
97
+ input: z.ZodObject<{
98
+ nodeId: z.ZodString;
99
+ }, z.core.$strip>;
100
+ output: z.ZodAny;
101
+ };
102
+ duplicateNode: {
103
+ description: string;
104
+ input: z.ZodObject<{
105
+ nodeId: z.ZodString;
106
+ }, z.core.$strip>;
107
+ output: z.ZodAny;
108
+ };
109
+ };
110
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,188 @@
1
+ import { z } from 'zod';
2
+ import dedent from 'string-dedent';
3
+ /* ──────────────────────────── Schemas ─────────────────────────── */
4
+ const NodeId = z.string().min(1);
5
+ const Role = z.enum(['background', 'text', 'border']);
6
+ /* ──────────────────────────── Tool Definitions ─────────────────────────── */
7
+ export const mcpTools = {
8
+ getProjectXml: {
9
+ description: dedent `
10
+ Gets the project pages and components XML, with information of the currently focused page or component.
11
+
12
+ The referenced nodeIds can be used with getNodeXml to get the XML of a specific page or component.
13
+
14
+ `,
15
+ input: z.object({}),
16
+ output: z.any(),
17
+ },
18
+ getSelectedNodesXml: {
19
+ description: 'Gets the currently selected nodes as xml',
20
+ input: z.object({}),
21
+ output: z.any(),
22
+ },
23
+ zoomIntoView: {
24
+ description: 'Zooms the canvas to center on the given node ID. It will navigate to the right page or component first.',
25
+ input: z.object({
26
+ nodeId: NodeId.describe('The ID of the node to zoom into view'),
27
+ }),
28
+ output: z.any(),
29
+ },
30
+ getNodeXml: {
31
+ description: 'Get a specific Framer node as XML. You first need to get a node id via getProjectXml or call getSelectedNodesXml instead',
32
+ input: z.object({
33
+ nodeId: NodeId.describe('The ID of the node to get as XML'),
34
+ }),
35
+ output: z.any(),
36
+ },
37
+ getProjectColorStyles: {
38
+ description: 'Gets all project-level color styles',
39
+ input: z.object({}),
40
+ },
41
+ getProjectTextStyles: {
42
+ description: 'Gets all project-level text styles',
43
+ input: z.object({}),
44
+ output: z.any(),
45
+ },
46
+ updateXmlForNode: {
47
+ description: dedent `
48
+ Update the XML for a specific node using its nodeId and passing a new XML string. It can be used to update nodes text or attributes.
49
+
50
+ You can pass a partial a XML string, there is no need to include the full XML structure, missing nodes will not be updated. You can also omit attributes, omitted attributes will not be updated and will be ignored.
51
+
52
+ You can use this tool to
53
+ - Update text for one or multiple text nodes
54
+ - Update attributes of existing nodes
55
+
56
+ This tool cannot duplicate or delete nodes.
57
+
58
+ `,
59
+ input: z.object({
60
+ nodeId: NodeId.describe('The ID of the node to update'),
61
+ xml: z
62
+ .string()
63
+ .min(1)
64
+ .describe('XML string containing the updates. Can include multiple nodes with their nodeId attributes'),
65
+ }),
66
+ output: z.any(),
67
+ },
68
+ updateColorStyle: {
69
+ description: 'Updates a color style by its path. Can modify the name, light color, and dark color.',
70
+ input: z.object({
71
+ stylePath: z
72
+ .string()
73
+ .describe('The path of the color style to update. Must start with /'),
74
+ updates: z
75
+ .object({
76
+ name: z
77
+ .string()
78
+ .optional()
79
+ .describe('New name for the color style'),
80
+ light: z
81
+ .string()
82
+ .optional()
83
+ .describe('Light theme color in any CSS color format (e.g., "rgb(255, 0, 0)", "#FF0000", "red")'),
84
+ dark: z
85
+ .string()
86
+ .nullable()
87
+ .optional()
88
+ .describe('Dark theme color in any CSS color format, or null to remove dark variant'),
89
+ })
90
+ .describe('Properties to update on the color style'),
91
+ }),
92
+ output: z.any(),
93
+ },
94
+ updateTextStyle: {
95
+ description: 'Updates a text style by its path. Can modify various typography properties.',
96
+ input: z.object({
97
+ stylePath: z
98
+ .string()
99
+ .describe('The path of the text style to update. Must start with /'),
100
+ updates: z
101
+ .object({
102
+ name: z
103
+ .string()
104
+ .optional()
105
+ .describe('New name for the text style'),
106
+ fontSize: z
107
+ .string()
108
+ .optional()
109
+ .describe('Font size with units (e.g., "16px", "1.5rem")'),
110
+ lineHeight: z
111
+ .string()
112
+ .optional()
113
+ .describe('Line height with units (e.g., "24px", "1.5em", "150%")'),
114
+ letterSpacing: z
115
+ .string()
116
+ .optional()
117
+ .describe('Letter spacing with units (e.g., "0px", "0.05em")'),
118
+ paragraphSpacing: z
119
+ .number()
120
+ .optional()
121
+ .describe('Space between paragraphs in pixels'),
122
+ transform: z
123
+ .enum(['none', 'uppercase', 'lowercase', 'capitalize'])
124
+ .optional()
125
+ .describe('Text transformation'),
126
+ alignment: z
127
+ .enum(['left', 'center', 'right', 'justify'])
128
+ .optional()
129
+ .describe('Text alignment'),
130
+ decoration: z
131
+ .enum(['none', 'underline', 'line-through'])
132
+ .optional()
133
+ .describe('Text decoration'),
134
+ balance: z
135
+ .boolean()
136
+ .optional()
137
+ .describe('Enable balanced text wrapping for better legibility'),
138
+ })
139
+ .describe('Properties to update on the text style'),
140
+ }),
141
+ output: z.any(),
142
+ },
143
+ searchFonts: {
144
+ description: dedent `
145
+ Search for fonts by selector substring. Returns max 20 results. Use specific search terms for better results.
146
+
147
+ IMPORTANT: The returned 'selector' field is what you use in XML font attributes:
148
+ <Text font="GF;Inter-600">Bold text</Text>
149
+
150
+ NOTE: You can only apply a font attribute to text nodes that do NOT have an inlineTextStyle.
151
+ If a text node has inlineTextStyle="/Heading xl", you must remove it before applying a custom font.
152
+ Text nodes can use EITHER inlineTextStyle (project text style) OR font (custom font), not both.
153
+ `,
154
+ input: z.object({
155
+ query: z
156
+ .string()
157
+ .min(1)
158
+ .describe('Search query to match against font selector (e.g., "Inter", "bold", "italic")'),
159
+ }),
160
+ output: z.any(),
161
+ },
162
+ deleteNode: {
163
+ description: dedent `
164
+ Deletes a Framer node, removing it from the page or component. This permanently removes the node and all its children.
165
+
166
+ IMPORTANT: This action cannot be undone. Use with caution.
167
+ Cannot delete certain protected nodes like the root frame of a component or page.
168
+ `,
169
+ input: z.object({
170
+ nodeId: NodeId.describe('The ID of the node to delete'),
171
+ }),
172
+ output: z.any(),
173
+ },
174
+ duplicateNode: {
175
+ description: dedent `
176
+ Duplicate a node in the Framer project. Creates an exact copy of the node and all its children.
177
+
178
+ The duplicated node will be placed as a sibling of the original node, slightly offset if it's a visual node.
179
+ Returns the ID of the newly created duplicate node.
180
+ `,
181
+ input: z.object({
182
+ nodeId: NodeId.describe('The ID of the node to duplicate'),
183
+ }),
184
+ output: z.any(),
185
+ },
186
+ };
187
+ //# sourceMappingURL=types.js.map
188
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,13 @@
1
+ export declare function getAttachmentConnectionId(attachment: any): any;
2
+ export declare function getAttachmentConnectionOrdinal(attachment: any): any;
3
+ export declare function getAttachmentConnectedAt(attachment: any): any;
4
+ export declare function isAttachmentReadyForRequests(attachment: any): boolean;
5
+ export declare function isSocketUsable(socket: any): boolean;
6
+ export declare function pickActiveUpstreamSocket({ sockets }: {
7
+ sockets: any;
8
+ }): any;
9
+ export declare function matchesPendingRequestSocket({ attachment, pendingRequest }: {
10
+ attachment: any;
11
+ pendingRequest: any;
12
+ }): boolean;
13
+ //# sourceMappingURL=upstream-socket.d.ts.map