| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- #!/usr/bin/env node
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
- import { resolve } from "node:path";
- import { fileURLToPath } from "node:url";
- import { z } from "zod";
- import { runImageSet } from "./tools/image-set-run.mjs";
- import { validateImageSetPlan } from "./tools/image-set-validate.mjs";
- const VERSION = "0.1.0";
- function asToolResult(result = {}) {
- return {
- content: [{
- type: "text",
- text: result.assistantMessage || JSON.stringify(result, null, 2),
- }],
- structuredContent: result,
- isError: !new Set(["ok", "partial"]).has(result.status),
- };
- }
- export function createServer() {
- const server = new McpServer({
- name: "fmode-image-set",
- version: VERSION,
- });
- const outputSchema = {
- status: z.string(),
- assistantMessage: z.string(),
- summary: z.object({}).passthrough().optional(),
- data: z.object({}).passthrough().optional(),
- files: z.array(z.string()).optional(),
- nextActions: z.array(z.string()).optional(),
- warnings: z.array(z.any()).optional(),
- errors: z.array(z.any()).optional(),
- };
- server.registerTool(
- "fmode_image_set_run",
- {
- title: "Run Fmode Image Set",
- description: [
- "Create, execute, resume, or inspect a product-truth-first ecommerce image-set run.",
- "Use start for visual understanding and run allocation.",
- "Use execute only after a valid prompt-plan exists and the user explicitly authorizes paid generation.",
- "Use resume only for the same runId; use status for read-only inspection.",
- ].join(" "),
- inputSchema: {
- action: z.enum(["start", "execute", "resume", "status"]),
- image: z.string().optional(),
- runId: z.string().optional(),
- maxCost: z.union([z.number().nonnegative(), z.string()]).optional(),
- workspaceRoot: z.string().optional(),
- cwd: z.string().optional(),
- claudeConfigDir: z.string().optional(),
- sessionId: z.string().optional(),
- },
- outputSchema,
- },
- async (input) => asToolResult(await runImageSet(input)),
- );
- server.registerTool(
- "fmode_image_set_validate",
- {
- title: "Validate Fmode Image Set Plan",
- description: "Validate a prompt-plan.json before any paid image generation. Checks schema, product identity, evidence, seven-slot allocation, prompt completeness, and cross-image diversity.",
- annotations: {
- readOnlyHint: true,
- destructiveHint: false,
- idempotentHint: true,
- openWorldHint: false,
- },
- inputSchema: {
- planPath: z.string(),
- },
- outputSchema,
- },
- async (input) => asToolResult(await validateImageSetPlan(input)),
- );
- return server;
- }
- if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
- const server = createServer();
- const transport = new StdioServerTransport();
- await server.connect(transport);
- }
|