@drawcall/design 0.5.9 → 0.5.12

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.
@@ -0,0 +1,108 @@
1
+ import { z } from "zod";
2
+ import { MAX_FRAME_DIMENSION, designIdSchema, frameNameSchema, imageUrlSchema, marketAssetSchema, projectDirectoryPathSchema, projectFilePathSchema, } from "../v1/schemas.js";
3
+ export const projectIdSchema = designIdSchema.describe("Exact project ID returned by list_projects");
4
+ export const frameIdSchema = designIdSchema.describe("Exact frame ID returned by list_frames");
5
+ export const directoryPathSchema = projectDirectoryPathSchema.describe("Project-absolute directory path without a trailing slash; omit it to list the entire project");
6
+ export const filePathSchema = projectFilePathSchema.describe("Project-absolute file path returned by list_files, including the frame ID; pass it unchanged");
7
+ const sizeSchema = z.coerce.number().int().min(1).max(MAX_FRAME_DIMENSION);
8
+ const positionSchema = z.coerce.number().finite();
9
+ // Some MCP clients lose property types in discriminated unions and serialize
10
+ // every create_frame argument as a string. Keep the wire schema flat.
11
+ export const createFrameSchema = z
12
+ .object({
13
+ project: projectIdSchema,
14
+ name: frameNameSchema,
15
+ type: z.enum(["glts", "image", "market"]),
16
+ width: sizeSchema.optional(),
17
+ height: sizeSchema.optional(),
18
+ image: imageUrlSchema.optional(),
19
+ asset: marketAssetSchema.optional(),
20
+ x: positionSchema.optional(),
21
+ y: positionSchema.optional(),
22
+ })
23
+ .strict()
24
+ .superRefine((input, context) => {
25
+ const require = (key) => {
26
+ if (input[key] !== undefined)
27
+ return;
28
+ context.addIssue({
29
+ code: "custom",
30
+ path: [key],
31
+ message: `${key} is required for a ${input.type} frame`,
32
+ });
33
+ };
34
+ const reject = (key) => {
35
+ if (input[key] === undefined)
36
+ return;
37
+ context.addIssue({
38
+ code: "custom",
39
+ path: [key],
40
+ message: `${key} is not valid for a ${input.type} frame`,
41
+ });
42
+ };
43
+ switch (input.type) {
44
+ case "glts":
45
+ require("width");
46
+ require("height");
47
+ reject("image");
48
+ reject("asset");
49
+ break;
50
+ case "image":
51
+ require("image");
52
+ reject("width");
53
+ reject("height");
54
+ reject("asset");
55
+ break;
56
+ case "market":
57
+ require("asset");
58
+ reject("width");
59
+ reject("height");
60
+ reject("image");
61
+ break;
62
+ }
63
+ });
64
+ export const projectInput = z.object({ project: projectIdSchema }).strict();
65
+ export const frameInput = projectInput.extend({ frame: frameIdSchema });
66
+ export const fileInput = projectInput.extend({ path: filePathSchema });
67
+ export function frameCreationInput(input) {
68
+ const position = {
69
+ ...(input.x === undefined ? {} : { x: input.x }),
70
+ ...(input.y === undefined ? {} : { y: input.y }),
71
+ };
72
+ switch (input.type) {
73
+ case "glts":
74
+ if (input.width === undefined || input.height === undefined) {
75
+ throw new Error("Validated GLTS frame input is missing dimensions");
76
+ }
77
+ return {
78
+ project: input.project,
79
+ name: input.name,
80
+ type: input.type,
81
+ width: input.width,
82
+ height: input.height,
83
+ ...position,
84
+ };
85
+ case "image":
86
+ if (input.image === undefined) {
87
+ throw new Error("Validated image frame input is missing an image");
88
+ }
89
+ return {
90
+ project: input.project,
91
+ name: input.name,
92
+ type: input.type,
93
+ image: input.image,
94
+ ...position,
95
+ };
96
+ case "market":
97
+ if (input.asset === undefined) {
98
+ throw new Error("Validated Market frame input is missing an asset");
99
+ }
100
+ return {
101
+ project: input.project,
102
+ name: input.name,
103
+ type: input.type,
104
+ asset: input.asset,
105
+ ...position,
106
+ };
107
+ }
108
+ }
@@ -0,0 +1,2 @@
1
+ import type { DesignMcpServer } from "./types.js";
2
+ export declare function registerSkillTool(server: DesignMcpServer): void;
@@ -0,0 +1,14 @@
1
+ import { z } from "zod";
2
+ import { mcpDesignSkill } from "../skill.generated.js";
3
+ export function registerSkillTool(server) {
4
+ server.registerTool("get_skill", {
5
+ description: "Return instructions for building and composing 3D GLTS assets in Drawcall Design. Read it before creating or changing GLTS files.",
6
+ inputSchema: z.object({}).strict(),
7
+ annotations: {
8
+ readOnlyHint: true,
9
+ destructiveHint: false,
10
+ openWorldHint: false,
11
+ idempotentHint: true,
12
+ },
13
+ }, async () => ({ content: [{ type: "text", text: mcpDesignSkill }] }));
14
+ }
@@ -0,0 +1,54 @@
1
+ import type { CreateFrame, DesignFile, FileList, FileMutation, Frame, GenerateImageFrame, Project, Screenshot } from "../v1/schemas.js";
2
+ import type { z } from "zod";
3
+ export interface DesignMcpToolResult {
4
+ [key: string]: unknown;
5
+ content: Array<{
6
+ type: "text";
7
+ text: string;
8
+ } | {
9
+ type: "image";
10
+ data: string;
11
+ mimeType: string;
12
+ }>;
13
+ structuredContent?: Record<string, unknown>;
14
+ }
15
+ interface DesignMcpToolAnnotations {
16
+ readOnlyHint?: boolean;
17
+ destructiveHint?: boolean;
18
+ idempotentHint?: boolean;
19
+ openWorldHint?: boolean;
20
+ }
21
+ interface DesignMcpToolConfig<Input extends z.ZodType | undefined> {
22
+ description?: string;
23
+ inputSchema?: Input;
24
+ annotations?: DesignMcpToolAnnotations;
25
+ }
26
+ type DesignMcpToolHandler<Input extends z.ZodType | undefined> = Input extends z.ZodType ? (input: z.output<Input>) => Promise<DesignMcpToolResult> : () => Promise<DesignMcpToolResult>;
27
+ export interface DesignMcpServer {
28
+ registerTool<Input extends z.ZodType | undefined = undefined>(name: string, config: DesignMcpToolConfig<Input>, handler: DesignMcpToolHandler<Input>): unknown;
29
+ }
30
+ export interface DesignMcpScreenshot extends Screenshot {
31
+ png: Uint8Array;
32
+ }
33
+ export type DesignMcpOperationRunner = <Result>(name: string, operation: () => Promise<Result>) => Promise<Result>;
34
+ export interface DesignMcpOperations {
35
+ listProjects(): Promise<Project[]>;
36
+ createProject(name: string): Promise<Project>;
37
+ deleteProject(project: string): Promise<{
38
+ id: string;
39
+ }>;
40
+ listFrames(project: string): Promise<Frame[]>;
41
+ createFrame(input: CreateFrame): Promise<Frame>;
42
+ generateImage(input: GenerateImageFrame): Promise<Frame>;
43
+ renameFrame(project: string, frame: string, name: string): Promise<Frame>;
44
+ deleteFrame(project: string, frame: string): Promise<{
45
+ id: string;
46
+ }>;
47
+ listFiles(project: string, path?: string): Promise<FileList>;
48
+ readFile(project: string, path: string): Promise<DesignFile>;
49
+ writeFile(project: string, path: string, text: string): Promise<FileMutation>;
50
+ editFile(project: string, path: string, oldText: string, newText: string): Promise<FileMutation>;
51
+ deleteFile(project: string, path: string): Promise<FileMutation>;
52
+ screenshot(project: string, frame: string): Promise<DesignMcpScreenshot>;
53
+ }
54
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function apiOption(command: Command): string | undefined;
@@ -0,0 +1,4 @@
1
+ export function apiOption(command) {
2
+ const value = command.optsWithGlobals().api;
3
+ return typeof value === "string" ? value : undefined;
4
+ }
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ import { type DesignCommandOptions } from "./command.js";
3
+ export declare function createDesignCli(options?: DesignCommandOptions): Command;
@@ -0,0 +1,7 @@
1
+ import { createLoginCommand, createLogoutCommand } from "./auth.js";
2
+ import { createDesignCommand } from "./command.js";
3
+ export function createDesignCli(options = {}) {
4
+ return createDesignCommand(options)
5
+ .addCommand(createLoginCommand())
6
+ .addCommand(createLogoutCommand());
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawcall/design",
3
- "version": "0.5.9",
3
+ "version": "0.5.12",
4
4
  "description": "Typed API and remote CLI for Drawcall Design",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,19 +8,15 @@
8
8
  "directory": "packages/design"
9
9
  },
10
10
  "type": "module",
11
+ "main": "./dist/index.js",
12
+ "browser": "./dist/browser.js",
11
13
  "types": "./dist/index.d.ts",
12
- "exports": {
13
- ".": {
14
- "types": "./dist/index.d.ts",
15
- "import": "./dist/index.js"
16
- }
17
- },
18
14
  "files": [
19
15
  "dist",
20
16
  "skills"
21
17
  ],
22
18
  "bin": {
23
- "design": "./dist/cli.js"
19
+ "design": "dist/cli.js"
24
20
  },
25
21
  "scripts": {
26
22
  "generate": "node scripts/generate-skill.mjs",
@@ -34,15 +30,23 @@
34
30
  "typecheck": "tsc --noEmit"
35
31
  },
36
32
  "dependencies": {
33
+ "@drawcall/auth": "^0.1.0",
37
34
  "@orpc/client": "^1.14.13",
38
35
  "@orpc/contract": "^1.14.13",
39
36
  "@orpc/openapi-client": "^1.14.13",
40
37
  "commander": "^14.0.3",
41
- "open": "^10.1.0",
42
- "openid-client": "^6.8.4",
43
38
  "zod": "^4.3.6"
44
39
  },
40
+ "peerDependencies": {
41
+ "@modelcontextprotocol/server": "^2.0.0"
42
+ },
43
+ "peerDependenciesMeta": {
44
+ "@modelcontextprotocol/server": {
45
+ "optional": true
46
+ }
47
+ },
45
48
  "devDependencies": {
49
+ "@modelcontextprotocol/server": "^2.0.0",
46
50
  "@types/node": "^25.6.0",
47
51
  "prettier": "^3.6.2",
48
52
  "tsx": "^4.21.0",