unframer 4.0.3 → 4.0.4
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/dist/bin.d.ts +2 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +3 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +51 -1
- package/dist/cli.js.map +1 -1
- package/dist/framer-chunks/chunk-76VXR6QG.js +91 -0
- package/dist/framer-chunks/chunk-OAKBJJLO.js +105 -0
- package/dist/framer-chunks/fontshare-LJWOE5KG-36DNQHCT.js +27099 -0
- package/dist/framer-chunks/fontshare-LTYJMI6Q-XCFP3GWO.js +119 -0
- package/dist/framer-chunks/fontshare-MHXFPDHS-VQYPAYVC.js +825 -0
- package/dist/framer-chunks/fontshare-Q7VOJ3QT-LXRXXTSM.js +119 -0
- package/dist/framer-chunks/fontshare-X63NXWGB-NRPGYMPJ.js +825 -0
- package/dist/framer-chunks/fontshare-XMKN2FOD-D5TWBHNT.js +27099 -0
- package/dist/framer-chunks/framer-font-D6RMCRV4-XCFIRDL6.js +7 -0
- package/dist/framer-chunks/framer-font-G73BNA7N-B3OPPZB7.js +7 -0
- package/dist/framer-chunks/google-AG6EYFMK-QBWWKKVD.js +1612 -0
- package/dist/framer-chunks/google-CQFUID6E-C6DG6E7T.js +6792 -0
- package/dist/framer-chunks/google-EJBUPU3N-LSIK52DF.js +616382 -0
- package/dist/framer-chunks/google-LLNWFNMY-PWPZVCX5.js +6792 -0
- package/dist/framer-chunks/google-TRAPONMP-UUEFJ4ZF.js +616382 -0
- package/dist/framer-chunks/google-VQ4ZP4WR-C2T2J24Z.js +1612 -0
- package/dist/framer.js +827 -582
- package/dist/lib/config.d.ts +17 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +26 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/mcp-to-cli.d.ts +25 -0
- package/dist/lib/mcp-to-cli.d.ts.map +1 -0
- package/dist/lib/mcp-to-cli.js +176 -0
- package/dist/lib/mcp-to-cli.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +93 -92
- package/src/bin.ts +3 -0
- package/src/cli.ts +61 -2
- package/src/framer.js +827 -582
- package/src/lib/config.ts +43 -0
- package/src/lib/mcp-to-cli.ts +229 -0
- package/src/styles/framer.css +16 -16
- package/src/version.ts +1 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface CachedMcpTools {
|
|
2
|
+
tools: Array<{
|
|
3
|
+
name: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
inputSchema?: unknown;
|
|
6
|
+
}>;
|
|
7
|
+
timestamp: number;
|
|
8
|
+
sessionId?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface UnframerConfig {
|
|
11
|
+
mcpUrl?: string;
|
|
12
|
+
cachedMcpTools?: CachedMcpTools;
|
|
13
|
+
}
|
|
14
|
+
export declare function loadConfig(): UnframerConfig;
|
|
15
|
+
export declare function saveConfig(config: UnframerConfig): void;
|
|
16
|
+
export declare function getConfigPath(): string;
|
|
17
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc;IAC3B,KAAK,EAAE,KAAK,CAAC;QACT,IAAI,EAAE,MAAM,CAAA;QACZ,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,WAAW,CAAC,EAAE,OAAO,CAAA;KACxB,CAAC,CAAA;IACF,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,cAAc;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,cAAc,CAAC,EAAE,cAAc,CAAA;CAClC;AAED,wBAAgB,UAAU,IAAI,cAAc,CAS3C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAKvD;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
const CONFIG_DIR = path.join(os.homedir(), '.unframer');
|
|
5
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
6
|
+
export function loadConfig() {
|
|
7
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
|
8
|
+
return {};
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8'));
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return {};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function saveConfig(config) {
|
|
18
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
19
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
20
|
+
}
|
|
21
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
22
|
+
}
|
|
23
|
+
export function getConfigPath() {
|
|
24
|
+
return CONFIG_FILE;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,MAAM,IAAI,CAAA;AAEnB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAA;AACvD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAA;AAiBxD,MAAM,UAAU,UAAU,GAAmB;IACzC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,CAAA;IACb,CAAC;IACD,IAAI,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAA;IAC5D,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAA;IACb,CAAC;AAAA,CACJ;AAED,MAAM,UAAU,UAAU,CAAC,MAAsB,EAAQ;IACrD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACjD,CAAC;IACD,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;AAAA,CACjE;AAED,MAAM,UAAU,aAAa,GAAW;IACpC,OAAO,WAAW,CAAA;AAAA,CACrB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
2
|
+
import type { CAC } from "@xmorse/cac";
|
|
3
|
+
export type { Transport };
|
|
4
|
+
export interface AddMcpCommandsOptions {
|
|
5
|
+
cli: CAC;
|
|
6
|
+
commandPrefix: string;
|
|
7
|
+
/**
|
|
8
|
+
* Name used when connecting to the MCP server.
|
|
9
|
+
* @default 'mcp-cli-client'
|
|
10
|
+
*/
|
|
11
|
+
clientName?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Returns a transport to connect to the MCP server, or null if not configured.
|
|
14
|
+
* If null is returned, no MCP tool commands will be registered.
|
|
15
|
+
* @param sessionId - Optional session ID from cache to reuse existing session
|
|
16
|
+
*/
|
|
17
|
+
getMcpTransport: (sessionId?: string) => Transport | null | Promise<Transport | null>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Adds MCP tool commands to a cac CLI instance.
|
|
21
|
+
* Tools are cached for 1 hour to avoid connecting on every CLI invocation.
|
|
22
|
+
* Session ID is also cached to skip MCP initialization handshake.
|
|
23
|
+
*/
|
|
24
|
+
export declare function addMcpCommands(options: AddMcpCommandsOptions): Promise<void>;
|
|
25
|
+
//# sourceMappingURL=mcp-to-cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-to-cli.d.ts","sourceRoot":"","sources":["../../src/lib/mcp-to-cli.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAC;AAC/E,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAGvC,YAAY,EAAE,SAAS,EAAE,CAAC;AAI1B,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,GAAG,CAAC;IACT,aAAa,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,eAAe,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;CACvF;AA8ED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0HlF"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { loadConfig, saveConfig } from "./config.js";
|
|
3
|
+
const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
|
|
4
|
+
/**
|
|
5
|
+
* Convert JSON schema to compact JSON string for display
|
|
6
|
+
*/
|
|
7
|
+
function schemaToString(schema) {
|
|
8
|
+
// Show compact JSON schema
|
|
9
|
+
const compact = { ...schema };
|
|
10
|
+
// Remove verbose fields for display
|
|
11
|
+
delete compact.description;
|
|
12
|
+
return JSON.stringify(compact);
|
|
13
|
+
}
|
|
14
|
+
function parseToolArguments(options, inputSchema) {
|
|
15
|
+
const args = {};
|
|
16
|
+
if (!inputSchema?.properties) {
|
|
17
|
+
return args;
|
|
18
|
+
}
|
|
19
|
+
for (const [name, schema] of Object.entries(inputSchema.properties)) {
|
|
20
|
+
let value = options[name];
|
|
21
|
+
if (value === undefined) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
// cac wraps values in arrays when using type: [String] or type: [Number]
|
|
25
|
+
// Always unwrap single-element arrays - for object/array schema types,
|
|
26
|
+
// the inner value is a JSON string that we'll parse below
|
|
27
|
+
if (Array.isArray(value) && value.length === 1) {
|
|
28
|
+
value = value[0];
|
|
29
|
+
}
|
|
30
|
+
const type = schema.type || "string";
|
|
31
|
+
if ((type === "object" || type === "array") && typeof value === "string") {
|
|
32
|
+
try {
|
|
33
|
+
args[name] = JSON.parse(value);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
console.error(`Invalid JSON for --${name}: ${value}`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
args[name] = value;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return args;
|
|
45
|
+
}
|
|
46
|
+
function outputResult(result) {
|
|
47
|
+
for (const block of result.content) {
|
|
48
|
+
if (block.type === "text" && block.text) {
|
|
49
|
+
console.log(block.text);
|
|
50
|
+
}
|
|
51
|
+
else if (block.type === "image") {
|
|
52
|
+
// Skip base64 image data in CLI output
|
|
53
|
+
console.log("[Image content omitted]");
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
console.log(JSON.stringify(block, null, 2));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Adds MCP tool commands to a cac CLI instance.
|
|
62
|
+
* Tools are cached for 1 hour to avoid connecting on every CLI invocation.
|
|
63
|
+
* Session ID is also cached to skip MCP initialization handshake.
|
|
64
|
+
*/
|
|
65
|
+
export async function addMcpCommands(options) {
|
|
66
|
+
const { cli, commandPrefix, clientName = "mcp-cli-client", getMcpTransport } = options;
|
|
67
|
+
// Try to use cached tools first
|
|
68
|
+
const config = loadConfig();
|
|
69
|
+
const cachedTools = config.cachedMcpTools;
|
|
70
|
+
const isCacheValid = cachedTools && (Date.now() - cachedTools.timestamp) < CACHE_TTL_MS;
|
|
71
|
+
let tools;
|
|
72
|
+
let cachedSessionId;
|
|
73
|
+
if (isCacheValid) {
|
|
74
|
+
// Use cached tools to register commands
|
|
75
|
+
tools = cachedTools.tools;
|
|
76
|
+
cachedSessionId = cachedTools.sessionId;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// Cache invalid/missing - connect to fetch tools
|
|
80
|
+
const transport = await getMcpTransport();
|
|
81
|
+
if (!transport) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const client = new Client({ name: clientName, version: "1.0.0" }, { capabilities: {} });
|
|
85
|
+
try {
|
|
86
|
+
await client.connect(transport);
|
|
87
|
+
const result = await client.listTools();
|
|
88
|
+
tools = result.tools;
|
|
89
|
+
// Get session ID from transport if available
|
|
90
|
+
const sessionId = transport.sessionId;
|
|
91
|
+
// Save tools and session ID to cache
|
|
92
|
+
saveConfig({
|
|
93
|
+
...config,
|
|
94
|
+
cachedMcpTools: {
|
|
95
|
+
tools: tools.map((t) => ({
|
|
96
|
+
name: t.name,
|
|
97
|
+
description: t.description,
|
|
98
|
+
inputSchema: t.inputSchema,
|
|
99
|
+
})),
|
|
100
|
+
timestamp: Date.now(),
|
|
101
|
+
sessionId,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
cachedSessionId = sessionId;
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
console.error(`Failed to connect to MCP server: ${err instanceof Error ? err.message : err}`);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
await client.close();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
for (const tool of tools) {
|
|
115
|
+
const inputSchema = tool.inputSchema;
|
|
116
|
+
const cmdName = `${commandPrefix} ${tool.name}`;
|
|
117
|
+
const description = tool.description || `Run MCP tool ${tool.name}`;
|
|
118
|
+
const cmd = cli.command(cmdName, description);
|
|
119
|
+
// Add options for each property in the input schema
|
|
120
|
+
if (inputSchema?.properties) {
|
|
121
|
+
for (const [propName, propSchema] of Object.entries(inputSchema.properties)) {
|
|
122
|
+
const isRequired = inputSchema.required?.includes(propName) ?? false;
|
|
123
|
+
const schemaType = propSchema.type || "string";
|
|
124
|
+
// Boolean options are flags without <value>
|
|
125
|
+
// Other types use <value> syntax
|
|
126
|
+
const optionStr = schemaType === "boolean" ? `--${propName}` : `--${propName} <${propName}>`;
|
|
127
|
+
let optionDesc = propSchema.description || propName;
|
|
128
|
+
if (isRequired) {
|
|
129
|
+
optionDesc += " (required)";
|
|
130
|
+
}
|
|
131
|
+
// Add schema hint for non-scalar types
|
|
132
|
+
if (schemaType === "object" || schemaType === "array") {
|
|
133
|
+
optionDesc += ` (JSON: ${schemaToString(propSchema)})`;
|
|
134
|
+
}
|
|
135
|
+
// Build option config with type transform
|
|
136
|
+
// Use type: [Type] to prevent cac/mri from auto-converting values
|
|
137
|
+
// This wraps values in arrays which we unwrap in parseToolArguments
|
|
138
|
+
const optionConfig = {};
|
|
139
|
+
if (propSchema.default !== undefined) {
|
|
140
|
+
optionConfig.default = propSchema.default;
|
|
141
|
+
}
|
|
142
|
+
if (schemaType === "number" || schemaType === "integer") {
|
|
143
|
+
optionConfig.type = [Number];
|
|
144
|
+
}
|
|
145
|
+
else if (schemaType !== "boolean") {
|
|
146
|
+
// String for string/object/array types - prevents mri from mangling JSON strings
|
|
147
|
+
optionConfig.type = [String];
|
|
148
|
+
}
|
|
149
|
+
cmd.option(optionStr, optionDesc, optionConfig);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
cmd.action(async (cliOptions) => {
|
|
153
|
+
const parsedArgs = parseToolArguments(cliOptions, inputSchema);
|
|
154
|
+
// Connect with cached session ID to skip initialization handshake
|
|
155
|
+
const transport = await getMcpTransport(cachedSessionId);
|
|
156
|
+
if (!transport) {
|
|
157
|
+
console.error("MCP transport not available");
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
const actionClient = new Client({ name: clientName, version: "1.0.0" }, { capabilities: {} });
|
|
161
|
+
await actionClient.connect(transport);
|
|
162
|
+
try {
|
|
163
|
+
const result = await actionClient.callTool({ name: tool.name, arguments: parsedArgs });
|
|
164
|
+
outputResult(result);
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
console.error(`Error calling ${tool.name}:`, err instanceof Error ? err.message : err);
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
await actionClient.close();
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=mcp-to-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-to-cli.js","sourceRoot":"","sources":["../../src/lib/mcp-to-cli.ts"],"names":[],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "4.0.
|
|
1
|
+
export declare const version = "4.0.4";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const version = '4.0.
|
|
1
|
+
export const version = '4.0.4';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
package/package.json
CHANGED
|
@@ -1,98 +1,99 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
2
|
+
"name": "unframer",
|
|
3
|
+
"version": "4.0.4",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Import Framer components directly in your React app, type safe and customizable",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"repository": "https://github.com/remorses/unframer",
|
|
8
|
+
"bin": "bin.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"framer-fixed",
|
|
12
|
+
"bin.js",
|
|
13
|
+
"src",
|
|
14
|
+
"!src/framer-chunks",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"default": "./dist/index.js"
|
|
15
23
|
},
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"framer-fixed",
|
|
20
|
-
"bin.js",
|
|
21
|
-
"src",
|
|
22
|
-
"!src/framer-chunks",
|
|
23
|
-
"README.md"
|
|
24
|
-
],
|
|
25
|
-
"main": "./dist/index.js",
|
|
26
|
-
"types": "./dist/index.d.ts",
|
|
27
|
-
"exports": {
|
|
28
|
-
".": {
|
|
29
|
-
"types": "./dist/index.d.ts",
|
|
30
|
-
"default": "./dist/index.js"
|
|
31
|
-
},
|
|
32
|
-
"./src/framer.js": {
|
|
33
|
-
"types": "./dist/framer.d.ts",
|
|
34
|
-
"default": "./src/framer.js"
|
|
35
|
-
},
|
|
36
|
-
"./dist/exporter": {
|
|
37
|
-
"types": "./dist/exporter.d.ts",
|
|
38
|
-
"default": "./dist/exporter.js"
|
|
39
|
-
},
|
|
40
|
-
"./styles/*": {
|
|
41
|
-
"default": "./src/styles/*"
|
|
42
|
-
},
|
|
43
|
-
"./src/*": {
|
|
44
|
-
"default": "./src/*.ts"
|
|
45
|
-
},
|
|
46
|
-
"./package.json": "./package.json"
|
|
24
|
+
"./src/framer.js": {
|
|
25
|
+
"types": "./dist/framer.d.ts",
|
|
26
|
+
"default": "./src/framer.js"
|
|
47
27
|
},
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"peerDependencies": {
|
|
52
|
-
"react": "*",
|
|
53
|
-
"react-dom": "*"
|
|
28
|
+
"./dist/exporter": {
|
|
29
|
+
"types": "./dist/exporter.d.ts",
|
|
30
|
+
"default": "./dist/exporter.js"
|
|
54
31
|
},
|
|
55
|
-
"
|
|
56
|
-
|
|
32
|
+
"./styles/*": {
|
|
33
|
+
"default": "./src/styles/*"
|
|
57
34
|
},
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
"@babel/core": "^7.28.6",
|
|
61
|
-
"@biomejs/js-api": "^0.7.1",
|
|
62
|
-
"@biomejs/wasm-nodejs": "^1.9.4",
|
|
63
|
-
"async-sema": "^3.1.1",
|
|
64
|
-
"cac": "^6.7.14",
|
|
65
|
-
"esbuild": "^0.25.8",
|
|
66
|
-
"esbuild-plugins-node-modules-polyfill": "^1.6.8",
|
|
67
|
-
"nanospinner": "^1.2.2",
|
|
68
|
-
"picocolors": "^1.1.1",
|
|
69
|
-
"real-framer-motion": "npm:framer-motion@^12.23.12",
|
|
70
|
-
"spiceflow": "^1.17.10",
|
|
71
|
-
"string-dedent": "^3.0.1",
|
|
72
|
-
"undici": "^7.18.2"
|
|
35
|
+
"./src/*": {
|
|
36
|
+
"default": "./src/*.ts"
|
|
73
37
|
},
|
|
74
|
-
"
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
38
|
+
"./package.json": "./package.json"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [],
|
|
41
|
+
"author": "Tommaso De Rossi, morse <beats.by.morse@gmail.com>",
|
|
42
|
+
"license": "",
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"react": "*",
|
|
45
|
+
"react-dom": "*"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18.0.0"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@antfu/ni": "^25.0.0",
|
|
52
|
+
"@babel/core": "^7.28.6",
|
|
53
|
+
"@biomejs/js-api": "^0.7.1",
|
|
54
|
+
"@biomejs/wasm-nodejs": "^1.9.4",
|
|
55
|
+
"@inquirer/prompts": "^8.2.0",
|
|
56
|
+
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
57
|
+
"@xmorse/cac": "^6.0.7",
|
|
58
|
+
"async-sema": "^3.1.1",
|
|
59
|
+
"esbuild": "^0.25.8",
|
|
60
|
+
"esbuild-plugins-node-modules-polyfill": "^1.6.8",
|
|
61
|
+
"nanospinner": "^1.2.2",
|
|
62
|
+
"picocolors": "^1.1.1",
|
|
63
|
+
"real-framer-motion": "npm:framer-motion@^12.23.12",
|
|
64
|
+
"spiceflow": "^1.17.10",
|
|
65
|
+
"string-dedent": "^3.0.1",
|
|
66
|
+
"undici": "^7.18.2"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@babel/helper-annotate-as-pure": "^7.25.9",
|
|
70
|
+
"@babel/helper-environment-visitor": "^7.24.7",
|
|
71
|
+
"@babel/helper-split-export-declaration": "^7.24.7",
|
|
72
|
+
"@babel/plugin-transform-react-pure-annotations": "^7.25.9",
|
|
73
|
+
"@babel/traverse": "^7.28.6",
|
|
74
|
+
"@babel/types": "^7.28.6",
|
|
75
|
+
"@types/babel__core": "^7.20.5",
|
|
76
|
+
"@types/babel__traverse": "^7.28.0",
|
|
77
|
+
"@types/bun": "^1.1.6",
|
|
78
|
+
"@types/node": "^22.15.21",
|
|
79
|
+
"@types/react": "^19.2.7",
|
|
80
|
+
"@types/react-dom": "^19.2.3",
|
|
81
|
+
"@typescript/native-preview": "7.0.0-dev.20260117.1",
|
|
82
|
+
"@xmorse/deployment-utils": "^0.7.4",
|
|
83
|
+
"concurrently": "^9.1.2",
|
|
84
|
+
"dprint-node": "^1.0.8",
|
|
85
|
+
"openai": "^4.80.1",
|
|
86
|
+
"posthtml": "^0.16.6",
|
|
87
|
+
"react": "19.2.3",
|
|
88
|
+
"react-dom": "19.2.3",
|
|
89
|
+
"tiktoken": "^1.0.18",
|
|
90
|
+
"typescript": "^5.9.3"
|
|
91
|
+
},
|
|
92
|
+
"scripts": {
|
|
93
|
+
"build": "rm -rf dist && pnpm tsgo && cp ../README.md ./README.md && cp ./src/framer.d.ts ./dist/framer.d.ts && cp ./src/framer.js ./dist/framer.js && cp -r ./src/framer-chunks ./dist/framer-chunks",
|
|
94
|
+
"test": "vitest",
|
|
95
|
+
"gen-client": "export DIR=./src/generated/ && cd ../../website && pnpm tsc; rm -rf $DIR && mkdir -p $DIR && cp ./dist/src/lib/api-client.* $DIR",
|
|
96
|
+
"download-framer": "tsx scripts/download.ts",
|
|
97
|
+
"watch": "rm -rf dist && pnpm tsc -w"
|
|
98
|
+
}
|
|
99
|
+
}
|
package/src/bin.ts
ADDED
package/src/cli.ts
CHANGED
|
@@ -4,12 +4,13 @@ import pico from 'picocolors'
|
|
|
4
4
|
const { blue, bgBlue, green } = pico
|
|
5
5
|
import { fetch } from 'undici'
|
|
6
6
|
import './sentry.js'
|
|
7
|
+
import { input } from '@inquirer/prompts'
|
|
7
8
|
|
|
8
9
|
import { bundle, StyleToken, createExampleComponentCode } from './exporter.js'
|
|
9
10
|
import { createClient } from './generated/api-client.js'
|
|
10
11
|
import { generateStackblitzFiles } from './stackblitz.js'
|
|
11
12
|
|
|
12
|
-
import { cac } from 'cac'
|
|
13
|
+
import { cac } from '@xmorse/cac'
|
|
13
14
|
import { exec } from 'child_process'
|
|
14
15
|
import { promisify } from 'util'
|
|
15
16
|
|
|
@@ -27,6 +28,11 @@ import {
|
|
|
27
28
|
import { getPackageManager } from './package-manager.js'
|
|
28
29
|
import { notifyError } from './sentry.js'
|
|
29
30
|
import { dispatcher } from './undici-dispatcher.js'
|
|
31
|
+
import { loadConfig, saveConfig, getConfigPath } from './lib/config.js'
|
|
32
|
+
import { addMcpCommands } from './lib/mcp-to-cli.js'
|
|
33
|
+
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'
|
|
34
|
+
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
|
|
35
|
+
|
|
30
36
|
const configNames = ['unframer.config.json', 'unframer.json']
|
|
31
37
|
|
|
32
38
|
export const cli = cac('unframer')
|
|
@@ -50,7 +56,7 @@ cli.command('[projectId]', 'Run unframer with optional project ID')
|
|
|
50
56
|
.option('--metafile', 'Generate meta.json file with build metadata', {
|
|
51
57
|
default: false,
|
|
52
58
|
})
|
|
53
|
-
|
|
59
|
+
.action(async function main(projectId, options) {
|
|
54
60
|
const external_ = options.external
|
|
55
61
|
const allExternal = external_ === true
|
|
56
62
|
const externalPackages: string[] = Array.isArray(external_)
|
|
@@ -178,6 +184,7 @@ function fixOldUnframerPath() {
|
|
|
178
184
|
|
|
179
185
|
const version = pkg.version
|
|
180
186
|
|
|
187
|
+
|
|
181
188
|
cli.version(version).help()
|
|
182
189
|
|
|
183
190
|
cli.command(
|
|
@@ -312,6 +319,58 @@ cli.command(
|
|
|
312
319
|
}
|
|
313
320
|
})
|
|
314
321
|
|
|
322
|
+
|
|
323
|
+
cli.command(
|
|
324
|
+
'mcp login [url]',
|
|
325
|
+
'Store MCP server URL. After login, other MCP commands will appear in --help. The MCP URL is visible in the Framer MCP plugin.',
|
|
326
|
+
).action(async (url?: string) => {
|
|
327
|
+
// Prompt for URL if not provided, avoids shell escaping issues with & in URLs
|
|
328
|
+
if (!url) {
|
|
329
|
+
const shortcut = process.platform === 'darwin' ? 'Cmd+K' : 'Ctrl+K'
|
|
330
|
+
console.log('\nTo get your MCP URL:')
|
|
331
|
+
console.log(' 1. Go to https://framer.com and open your project')
|
|
332
|
+
console.log(` 2. Press ${shortcut} and search for "MCP" plugin`)
|
|
333
|
+
console.log(' 3. Copy the URL shown in the plugin\n')
|
|
334
|
+
}
|
|
335
|
+
let mcpUrl = url
|
|
336
|
+
if (!mcpUrl) {
|
|
337
|
+
try {
|
|
338
|
+
mcpUrl = await input({ message: 'Paste MCP URL:' })
|
|
339
|
+
} catch (error) {
|
|
340
|
+
// Handle Ctrl+C gracefully
|
|
341
|
+
if (error instanceof Error && error.name === 'ExitPromptError') {
|
|
342
|
+
process.exit(0)
|
|
343
|
+
}
|
|
344
|
+
throw error
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (!mcpUrl) {
|
|
348
|
+
console.error('MCP URL is required')
|
|
349
|
+
process.exit(1)
|
|
350
|
+
}
|
|
351
|
+
saveConfig({ mcpUrl })
|
|
352
|
+
console.log(`MCP URL saved to ${getConfigPath()}`)
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
// Add MCP tool commands - only registered if transport is available
|
|
356
|
+
await addMcpCommands({
|
|
357
|
+
cli,
|
|
358
|
+
commandPrefix: 'mcp',
|
|
359
|
+
getMcpTransport: (sessionId?: string) => {
|
|
360
|
+
const config = loadConfig()
|
|
361
|
+
if (!config.mcpUrl) {
|
|
362
|
+
return null
|
|
363
|
+
}
|
|
364
|
+
const url = new URL(config.mcpUrl)
|
|
365
|
+
// Use /mcp endpoint for StreamableHTTP
|
|
366
|
+
if (url.pathname.endsWith('/sse')) {
|
|
367
|
+
url.pathname = url.pathname.replace(/\/sse$/, '/mcp')
|
|
368
|
+
}
|
|
369
|
+
return new StreamableHTTPClientTransport(url, { sessionId })
|
|
370
|
+
},
|
|
371
|
+
}).catch(e => console.error(e))
|
|
372
|
+
|
|
373
|
+
|
|
315
374
|
export type Config = {
|
|
316
375
|
jsx?: boolean
|
|
317
376
|
components: {
|