frameforge 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Arun
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # frameforge
2
+
3
+ MCP server for generating UI mockups using Google Gemini image generation (Imagen / Nano Banana).
4
+
5
+ Generates high-fidelity web UI mockup PNGs and returns them inline in Claude Code.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npx -y frameforge
11
+ ```
12
+
13
+ ## Setup
14
+
15
+ Add to `~/.claude/mcp_config.json`:
16
+
17
+ ```json
18
+ {
19
+ "mcpServers": {
20
+ "frameforge": {
21
+ "type": "stdio",
22
+ "command": "npx",
23
+ "args": ["-y", "frameforge"],
24
+ "env": {
25
+ "GEMINI_API_KEY": "your-api-key-here"
26
+ }
27
+ }
28
+ }
29
+ }
30
+ ```
31
+
32
+ ### Local development
33
+
34
+ ```json
35
+ {
36
+ "mcpServers": {
37
+ "frameforge": {
38
+ "type": "stdio",
39
+ "command": "node",
40
+ "args": ["/path/to/frameforge/dist/index.js"],
41
+ "env": {
42
+ "GEMINI_API_KEY": "your-api-key-here"
43
+ }
44
+ }
45
+ }
46
+ }
47
+ ```
48
+
49
+ ## Tool: `generate_ui_preview`
50
+
51
+ | Param | Type | Required | Default | Description |
52
+ |-------|------|----------|---------|-------------|
53
+ | `prompt` | string | yes | — | Description of the UI to generate |
54
+ | `component_name` | string | yes | — | Name used in the output filename |
55
+ | `style_hints` | string | no | — | Style guidance (e.g. "dark mode", "mobile") |
56
+ | `aspect_ratio` | string | no | "16:9" | Aspect ratio for the image |
57
+ | `model` | string | no | "gemini-2.0-flash-exp" | Gemini model ID |
58
+ | `output_dir` | string | no | "./previews" | Directory to save PNGs |
59
+
60
+ ## Example
61
+
62
+ In Claude Code:
63
+
64
+ > Generate a UI preview of a dashboard with a sidebar, header with search bar, and a grid of analytics cards showing revenue, users, and conversion metrics.
65
+
66
+ The tool returns an inline image visible directly in the terminal, and saves the PNG to `./previews/`.
67
+
68
+ ## Requirements
69
+
70
+ - Node.js 18+
71
+ - `GEMINI_API_KEY` environment variable
72
+
73
+ ## License
74
+
75
+ MIT
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { GoogleGenAI, Modality } from "@google/genai";
5
+ import { z } from "zod";
6
+ import { writeFile, mkdir } from "node:fs/promises";
7
+ import { resolve, join } from "node:path";
8
+ const SYSTEM_PROMPT = `Generate a clean, high-fidelity web UI mockup. Use a modern SaaS design aesthetic: clean typography, ample whitespace, subtle shadows, professional color palette. Show the component as it would appear in a real web application. Do not include browser chrome or device frames unless explicitly asked.`;
9
+ const apiKey = process.env.GEMINI_API_KEY;
10
+ if (!apiKey) {
11
+ console.error("frameforge: GEMINI_API_KEY environment variable is required");
12
+ process.exit(1);
13
+ }
14
+ const ai = new GoogleGenAI({ apiKey });
15
+ const server = new McpServer({
16
+ name: "frameforge",
17
+ version: "0.1.0",
18
+ });
19
+ server.registerTool("generate_ui_preview", {
20
+ title: "Generate UI Preview",
21
+ description: "Generate a high-fidelity UI mockup image using Google Gemini image generation. Returns an inline image and saves the PNG to disk.",
22
+ inputSchema: {
23
+ prompt: z.string().describe("Description of the UI component or page to generate"),
24
+ component_name: z.string().describe("Name for the component (used in the output filename)"),
25
+ style_hints: z
26
+ .string()
27
+ .optional()
28
+ .describe("Additional style guidance (e.g. 'dark mode', 'mobile layout', 'minimal')"),
29
+ aspect_ratio: z
30
+ .string()
31
+ .optional()
32
+ .default("16:9")
33
+ .describe("Aspect ratio for the generated image"),
34
+ model: z
35
+ .string()
36
+ .optional()
37
+ .default("gemini-2.0-flash-exp")
38
+ .describe("Gemini model to use for image generation"),
39
+ output_dir: z
40
+ .string()
41
+ .optional()
42
+ .default("./previews")
43
+ .describe("Directory to save the generated image"),
44
+ },
45
+ }, async (args) => {
46
+ const { prompt, component_name, style_hints, aspect_ratio, model, output_dir } = args;
47
+ const fullPrompt = [
48
+ SYSTEM_PROMPT,
49
+ style_hints ? `Style hints: ${style_hints}` : "",
50
+ `Aspect ratio: ${aspect_ratio}`,
51
+ prompt,
52
+ ]
53
+ .filter(Boolean)
54
+ .join("\n\n");
55
+ console.error(`frameforge: Generating "${component_name}" with model ${model}...`);
56
+ const response = await ai.models.generateContent({
57
+ model,
58
+ contents: fullPrompt,
59
+ config: {
60
+ responseModalities: [Modality.IMAGE, Modality.TEXT],
61
+ },
62
+ });
63
+ const parts = response.candidates?.[0]?.content?.parts;
64
+ if (!parts || parts.length === 0) {
65
+ return {
66
+ content: [{ type: "text", text: "Error: No content returned from Gemini." }],
67
+ isError: true,
68
+ };
69
+ }
70
+ const imagePart = parts.find((p) => p.inlineData?.mimeType?.startsWith("image/"));
71
+ if (!imagePart?.inlineData) {
72
+ const textParts = parts
73
+ .filter((p) => p.text)
74
+ .map((p) => p.text)
75
+ .join("\n");
76
+ return {
77
+ content: [
78
+ {
79
+ type: "text",
80
+ text: `Error: No image generated. Model response:\n${textParts || "(empty)"}`,
81
+ },
82
+ ],
83
+ isError: true,
84
+ };
85
+ }
86
+ const { data, mimeType } = imagePart.inlineData;
87
+ if (!data || !mimeType) {
88
+ return {
89
+ content: [{ type: "text", text: "Error: Image data is empty." }],
90
+ isError: true,
91
+ };
92
+ }
93
+ // Save to disk
94
+ const resolvedDir = resolve(output_dir);
95
+ await mkdir(resolvedDir, { recursive: true });
96
+ const timestamp = Date.now();
97
+ const filename = `${component_name}-${timestamp}.png`;
98
+ const filepath = join(resolvedDir, filename);
99
+ await writeFile(filepath, Buffer.from(data, "base64"));
100
+ console.error(`frameforge: Saved ${filepath}`);
101
+ return {
102
+ content: [
103
+ { type: "image", data, mimeType },
104
+ { type: "text", text: `Saved: ${filepath}` },
105
+ ],
106
+ };
107
+ });
108
+ async function main() {
109
+ const transport = new StdioServerTransport();
110
+ await server.connect(transport);
111
+ console.error("frameforge: MCP server running on stdio");
112
+ }
113
+ main().catch((err) => {
114
+ console.error("frameforge: Fatal error:", err);
115
+ process.exit(1);
116
+ });
117
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "frameforge",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for generating UI mockups using Google Gemini image generation",
5
+ "type": "module",
6
+ "bin": {
7
+ "frameforge": "./dist/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsx src/index.ts",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "keywords": [
16
+ "mcp",
17
+ "gemini",
18
+ "ui-preview",
19
+ "image-generation",
20
+ "claude",
21
+ "mockup"
22
+ ],
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "@google/genai": "^1.40.0",
26
+ "@modelcontextprotocol/sdk": "^1.12.0",
27
+ "zod": "^3.24.0"
28
+ },
29
+ "devDependencies": {
30
+ "typescript": "^5.7.0",
31
+ "tsx": "^4.19.0",
32
+ "@types/node": "^22.0.0"
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "README.md",
37
+ "LICENSE"
38
+ ]
39
+ }