flowspec-mcp 2.0.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 (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -0
  3. package/dist/config.d.ts +5 -0
  4. package/dist/config.js +16 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/db.d.ts +47 -0
  7. package/dist/db.js +283 -0
  8. package/dist/db.js.map +1 -0
  9. package/dist/export/yamlExporter.d.ts +6 -0
  10. package/dist/export/yamlExporter.js +155 -0
  11. package/dist/export/yamlExporter.js.map +1 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +7 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/server.d.ts +2 -0
  16. package/dist/server.js +42 -0
  17. package/dist/server.js.map +1 -0
  18. package/dist/tools/analyseProject.d.ts +21 -0
  19. package/dist/tools/analyseProject.js +105 -0
  20. package/dist/tools/analyseProject.js.map +1 -0
  21. package/dist/tools/createEdge.d.ts +33 -0
  22. package/dist/tools/createEdge.js +31 -0
  23. package/dist/tools/createEdge.js.map +1 -0
  24. package/dist/tools/createNode.d.ts +45 -0
  25. package/dist/tools/createNode.js +31 -0
  26. package/dist/tools/createNode.js.map +1 -0
  27. package/dist/tools/createProject.d.ts +17 -0
  28. package/dist/tools/createProject.js +16 -0
  29. package/dist/tools/createProject.js.map +1 -0
  30. package/dist/tools/deleteEdge.d.ts +24 -0
  31. package/dist/tools/deleteEdge.js +19 -0
  32. package/dist/tools/deleteEdge.js.map +1 -0
  33. package/dist/tools/deleteNode.d.ts +24 -0
  34. package/dist/tools/deleteNode.js +19 -0
  35. package/dist/tools/deleteNode.js.map +1 -0
  36. package/dist/tools/deleteProject.d.ts +21 -0
  37. package/dist/tools/deleteProject.js +18 -0
  38. package/dist/tools/deleteProject.js.map +1 -0
  39. package/dist/tools/getProject.d.ts +21 -0
  40. package/dist/tools/getProject.js +18 -0
  41. package/dist/tools/getProject.js.map +1 -0
  42. package/dist/tools/getScreenContext.d.ts +24 -0
  43. package/dist/tools/getScreenContext.js +65 -0
  44. package/dist/tools/getScreenContext.js.map +1 -0
  45. package/dist/tools/getYaml.d.ts +21 -0
  46. package/dist/tools/getYaml.js +23 -0
  47. package/dist/tools/getYaml.js.map +1 -0
  48. package/dist/tools/listProjects.d.ts +8 -0
  49. package/dist/tools/listProjects.js +14 -0
  50. package/dist/tools/listProjects.js.map +1 -0
  51. package/dist/tools/searchNodes.d.ts +17 -0
  52. package/dist/tools/searchNodes.js +22 -0
  53. package/dist/tools/searchNodes.js.map +1 -0
  54. package/dist/tools/updateNode.d.ts +45 -0
  55. package/dist/tools/updateNode.js +29 -0
  56. package/dist/tools/updateNode.js.map +1 -0
  57. package/dist/tools/updateProject.d.ts +27 -0
  58. package/dist/tools/updateProject.js +25 -0
  59. package/dist/tools/updateProject.js.map +1 -0
  60. package/dist/types.d.ts +92 -0
  61. package/dist/types.js +3 -0
  62. package/dist/types.js.map +1 -0
  63. package/package.json +44 -0
@@ -0,0 +1,65 @@
1
+ import { z } from 'zod';
2
+ import { getProject } from '../db.js';
3
+ export const getScreenContextSchema = z.object({
4
+ projectId: z.string().describe('UUID of the FlowSpec project'),
5
+ screenId: z.string().optional().describe('Specific screen ID (omit for all screens)'),
6
+ });
7
+ export async function handleGetScreenContext(args) {
8
+ const project = await getProject(args.projectId);
9
+ if (!project) {
10
+ return {
11
+ content: [{ type: 'text', text: `Project not found: ${args.projectId}` }],
12
+ isError: true,
13
+ };
14
+ }
15
+ const screens = project.canvas_state?.screens ?? [];
16
+ if (screens.length === 0) {
17
+ return {
18
+ content: [{ type: 'text', text: 'No screens defined in this project.' }],
19
+ };
20
+ }
21
+ // Build node label lookup from canvas nodes
22
+ const nodes = project.canvas_state?.nodes ?? [];
23
+ const nodeLabelMap = new Map();
24
+ for (const n of nodes) {
25
+ if (n.type === 'image')
26
+ continue;
27
+ const label = n.data.label ?? 'Untitled';
28
+ nodeLabelMap.set(n.id, { label, type: n.type ?? 'unknown' });
29
+ }
30
+ // Filter to specific screen if requested
31
+ const targetScreens = args.screenId
32
+ ? screens.filter((s) => s.id === args.screenId)
33
+ : screens;
34
+ if (args.screenId && targetScreens.length === 0) {
35
+ return {
36
+ content: [{ type: 'text', text: `Screen not found: ${args.screenId}` }],
37
+ isError: true,
38
+ };
39
+ }
40
+ const result = targetScreens.map((sc) => ({
41
+ id: sc.id,
42
+ name: sc.name,
43
+ imageFilename: sc.imageFilename ?? null,
44
+ regionCount: sc.regions.length,
45
+ elementCount: sc.regions.reduce((sum, r) => sum + r.elementIds.length, 0),
46
+ regions: sc.regions.map((r) => ({
47
+ id: r.id,
48
+ label: r.label ?? null,
49
+ position: r.position,
50
+ size: r.size,
51
+ elements: r.elementIds.map((eid) => {
52
+ const info = nodeLabelMap.get(eid);
53
+ return {
54
+ nodeId: eid,
55
+ nodeLabel: info?.label ?? 'Missing element',
56
+ nodeType: info?.type ?? 'unknown',
57
+ };
58
+ }),
59
+ })),
60
+ }));
61
+ return {
62
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
63
+ };
64
+ }
65
+ //# sourceMappingURL=getScreenContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getScreenContext.js","sourceRoot":"","sources":["../../src/tools/getScreenContext.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod';
2
+ export declare const getYamlSchema: z.ZodObject<{
3
+ projectId: z.ZodString;
4
+ }, "strip", z.ZodTypeAny, {
5
+ projectId: string;
6
+ }, {
7
+ projectId: string;
8
+ }>;
9
+ export declare function handleGetYaml(args: z.infer<typeof getYamlSchema>): Promise<{
10
+ content: {
11
+ type: "text";
12
+ text: string;
13
+ }[];
14
+ isError: boolean;
15
+ } | {
16
+ content: {
17
+ type: "text";
18
+ text: string;
19
+ }[];
20
+ isError?: undefined;
21
+ }>;
@@ -0,0 +1,23 @@
1
+ import { z } from 'zod';
2
+ import { getProject } from '../db.js';
3
+ import { exportToYaml } from '../export/yamlExporter.js';
4
+ export const getYamlSchema = z.object({
5
+ projectId: z.string().describe('UUID of the FlowSpec project'),
6
+ });
7
+ export async function handleGetYaml(args) {
8
+ const project = await getProject(args.projectId);
9
+ if (!project) {
10
+ return {
11
+ content: [{ type: 'text', text: `Project not found: ${args.projectId}` }],
12
+ isError: true,
13
+ };
14
+ }
15
+ const nodes = project.canvas_state?.nodes ?? [];
16
+ const edges = project.canvas_state?.edges ?? [];
17
+ const screens = project.canvas_state?.screens ?? [];
18
+ const yaml = exportToYaml(nodes, edges, project.name, screens);
19
+ return {
20
+ content: [{ type: 'text', text: yaml }],
21
+ };
22
+ }
23
+ //# sourceMappingURL=getYaml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getYaml.js","sourceRoot":"","sources":["../../src/tools/getYaml.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;CAC/D,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAmC;IACrE,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEjD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,sBAAsB,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YAClF,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC;IAChD,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC;IAChD,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,OAAO,IAAI,EAAE,CAAC;IAEpD,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE/D,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;KACjD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+ export declare const listProjectsSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
3
+ export declare function handleListProjects(): Promise<{
4
+ content: {
5
+ type: "text";
6
+ text: string;
7
+ }[];
8
+ }>;
@@ -0,0 +1,14 @@
1
+ import { z } from 'zod';
2
+ import { listProjects } from '../db.js';
3
+ export const listProjectsSchema = z.object({});
4
+ export async function handleListProjects() {
5
+ const projects = await listProjects();
6
+ if (projects.length === 0) {
7
+ return { content: [{ type: 'text', text: 'No projects found.' }] };
8
+ }
9
+ const lines = projects.map((p) => `- **${p.name}** (id: ${p.id}) — updated ${p.updated_at}`);
10
+ return {
11
+ content: [{ type: 'text', text: `Found ${projects.length} project(s):\n\n${lines.join('\n')}` }],
12
+ };
13
+ }
14
+ //# sourceMappingURL=listProjects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listProjects.js","sourceRoot":"","sources":["../../src/tools/listProjects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IAEtC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,oBAAoB,EAAE,CAAC,EAAE,CAAC;IAC9E,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CACxB,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,UAAU,EAAE,CACjE,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,SAAS,QAAQ,CAAC,MAAM,mBAAmB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;KAC1G,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { z } from 'zod';
2
+ export declare const searchNodesSchema: z.ZodObject<{
3
+ query: z.ZodString;
4
+ nodeType: z.ZodOptional<z.ZodEnum<["datapoint", "component", "transform"]>>;
5
+ }, "strip", z.ZodTypeAny, {
6
+ query: string;
7
+ nodeType?: "datapoint" | "component" | "transform" | undefined;
8
+ }, {
9
+ query: string;
10
+ nodeType?: "datapoint" | "component" | "transform" | undefined;
11
+ }>;
12
+ export declare function handleSearchNodes(args: z.infer<typeof searchNodesSchema>): Promise<{
13
+ content: {
14
+ type: "text";
15
+ text: string;
16
+ }[];
17
+ }>;
@@ -0,0 +1,22 @@
1
+ import { z } from 'zod';
2
+ import { searchNodes } from '../db.js';
3
+ export const searchNodesSchema = z.object({
4
+ query: z.string().describe('Search term to match against node labels'),
5
+ nodeType: z
6
+ .enum(['datapoint', 'component', 'transform'])
7
+ .optional()
8
+ .describe('Filter by node type'),
9
+ });
10
+ export async function handleSearchNodes(args) {
11
+ const results = await searchNodes(args.query, args.nodeType);
12
+ if (results.length === 0) {
13
+ return {
14
+ content: [{ type: 'text', text: `No nodes found matching "${args.query}".` }],
15
+ };
16
+ }
17
+ const lines = results.map((r) => `- **${r.label}** (${r.nodeType}) in project "${r.projectName}" (node: ${r.nodeId}, project: ${r.projectId})`);
18
+ return {
19
+ content: [{ type: 'text', text: `Found ${results.length} node(s):\n\n${lines.join('\n')}` }],
20
+ };
21
+ }
22
+ //# sourceMappingURL=searchNodes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"searchNodes.js","sourceRoot":"","sources":["../../src/tools/searchNodes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;IACtE,QAAQ,EAAE,CAAC;SACR,IAAI,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;SAC7C,QAAQ,EAAE;SACV,QAAQ,CAAC,qBAAqB,CAAC;CACnC,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAuC;IAC7E,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAE7D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,4BAA4B,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;SACvF,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CACvB,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,QAAQ,iBAAiB,CAAC,CAAC,WAAW,YAAY,CAAC,CAAC,MAAM,cAAc,CAAC,CAAC,SAAS,GAAG,CACrH,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,SAAS,OAAO,CAAC,MAAM,gBAAgB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;KACtG,CAAC;AACJ,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { z } from 'zod';
2
+ export declare const updateNodeSchema: z.ZodObject<{
3
+ projectId: z.ZodString;
4
+ nodeId: z.ZodString;
5
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
6
+ position: z.ZodOptional<z.ZodObject<{
7
+ x: z.ZodNumber;
8
+ y: z.ZodNumber;
9
+ }, "strip", z.ZodTypeAny, {
10
+ x: number;
11
+ y: number;
12
+ }, {
13
+ x: number;
14
+ y: number;
15
+ }>>;
16
+ }, "strip", z.ZodTypeAny, {
17
+ projectId: string;
18
+ nodeId: string;
19
+ data?: Record<string, unknown> | undefined;
20
+ position?: {
21
+ x: number;
22
+ y: number;
23
+ } | undefined;
24
+ }, {
25
+ projectId: string;
26
+ nodeId: string;
27
+ data?: Record<string, unknown> | undefined;
28
+ position?: {
29
+ x: number;
30
+ y: number;
31
+ } | undefined;
32
+ }>;
33
+ export declare function handleUpdateNode(args: z.infer<typeof updateNodeSchema>): Promise<{
34
+ content: {
35
+ type: "text";
36
+ text: string;
37
+ }[];
38
+ isError: boolean;
39
+ } | {
40
+ content: {
41
+ type: "text";
42
+ text: string;
43
+ }[];
44
+ isError?: undefined;
45
+ }>;
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ import { updateNodeViaApi } from '../db.js';
3
+ export const updateNodeSchema = z.object({
4
+ projectId: z.string().describe('UUID of the project'),
5
+ nodeId: z.string().describe('UUID of the node to update'),
6
+ data: z.record(z.unknown()).optional().describe('Node data fields to merge (label, type, constraints, etc.)'),
7
+ position: z.object({
8
+ x: z.number(),
9
+ y: z.number(),
10
+ }).optional().describe('New canvas position'),
11
+ });
12
+ export async function handleUpdateNode(args) {
13
+ const updates = {};
14
+ if (args.data)
15
+ updates.data = args.data;
16
+ if (args.position)
17
+ updates.position = args.position;
18
+ const node = await updateNodeViaApi(args.projectId, args.nodeId, updates);
19
+ if (!node) {
20
+ return {
21
+ content: [{ type: 'text', text: `Node or project not found: ${args.nodeId}` }],
22
+ isError: true,
23
+ };
24
+ }
25
+ return {
26
+ content: [{ type: 'text', text: `Updated node ${args.nodeId}` }],
27
+ };
28
+ }
29
+ //# sourceMappingURL=updateNode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updateNode.js","sourceRoot":"","sources":["../../src/tools/updateNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC;IACrD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;IACzD,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4DAA4D,CAAC;IAC7G,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC;QACjB,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;QACb,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;KACd,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC;CAC9C,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAsC;IAC3E,MAAM,OAAO,GAA4B,EAAE,CAAC;IAC5C,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACxC,IAAI,IAAI,CAAC,QAAQ;QAAE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAEpD,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE1E,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,8BAA8B,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACvF,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,gBAAgB,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;KAC1E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { z } from 'zod';
2
+ export declare const updateProjectSchema: z.ZodObject<{
3
+ projectId: z.ZodString;
4
+ name: z.ZodOptional<z.ZodString>;
5
+ canvas_state: z.ZodOptional<z.ZodAny>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ projectId: string;
8
+ name?: string | undefined;
9
+ canvas_state?: any;
10
+ }, {
11
+ projectId: string;
12
+ name?: string | undefined;
13
+ canvas_state?: any;
14
+ }>;
15
+ export declare function handleUpdateProject(args: z.infer<typeof updateProjectSchema>): Promise<{
16
+ content: {
17
+ type: "text";
18
+ text: string;
19
+ }[];
20
+ isError: boolean;
21
+ } | {
22
+ content: {
23
+ type: "text";
24
+ text: string;
25
+ }[];
26
+ isError?: undefined;
27
+ }>;
@@ -0,0 +1,25 @@
1
+ import { z } from 'zod';
2
+ import { updateProjectViaApi } from '../db.js';
3
+ export const updateProjectSchema = z.object({
4
+ projectId: z.string().describe('UUID of the project to update'),
5
+ name: z.string().optional().describe('New project name'),
6
+ canvas_state: z.any().optional().describe('Full replacement canvas state JSON'),
7
+ });
8
+ export async function handleUpdateProject(args) {
9
+ const updates = {};
10
+ if (args.name)
11
+ updates.name = args.name;
12
+ if (args.canvas_state)
13
+ updates.canvas_state = args.canvas_state;
14
+ const project = await updateProjectViaApi(args.projectId, updates);
15
+ if (!project) {
16
+ return {
17
+ content: [{ type: 'text', text: `Project not found: ${args.projectId}` }],
18
+ isError: true,
19
+ };
20
+ }
21
+ return {
22
+ content: [{ type: 'text', text: `Updated project **${project.name}** (id: ${project.id})` }],
23
+ };
24
+ }
25
+ //# sourceMappingURL=updateProject.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updateProject.js","sourceRoot":"","sources":["../../src/tools/updateProject.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IAC/D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IACxD,YAAY,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;CAChF,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAyC;IACjF,MAAM,OAAO,GAA8C,EAAE,CAAC;IAC9D,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACxC,IAAI,IAAI,CAAC,YAAY;QAAE,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;IAEhE,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAEnE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,sBAAsB,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YAClF,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,qBAAqB,OAAO,CAAC,IAAI,WAAW,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;KACtG,CAAC;AACJ,CAAC"}
@@ -0,0 +1,92 @@
1
+ export type DataType = 'string' | 'number' | 'boolean' | 'object' | 'array';
2
+ export type SourceType = 'captured' | 'inferred';
3
+ export type LogicType = 'formula' | 'validation' | 'workflow';
4
+ export type TableSourceType = 'database' | 'api' | 'file' | 'manual';
5
+ export type EdgeType = 'flows-to' | 'derives-from' | 'transforms' | 'validates' | 'contains';
6
+ export interface DataPointData {
7
+ label: string;
8
+ type: DataType;
9
+ source: SourceType;
10
+ sourceDefinition: string;
11
+ constraints: string[];
12
+ }
13
+ export interface ComponentData {
14
+ label: string;
15
+ wireframeRef?: string;
16
+ displays: string[];
17
+ captures: string[];
18
+ }
19
+ export interface TransformData {
20
+ label: string;
21
+ type: LogicType;
22
+ description: string;
23
+ inputs: string[];
24
+ outputs: string[];
25
+ logic: {
26
+ type: 'formula' | 'decision_table' | 'steps';
27
+ content: string | Record<string, unknown>;
28
+ };
29
+ }
30
+ export interface TableData {
31
+ label: string;
32
+ columns: Array<{
33
+ name: string;
34
+ type: DataType;
35
+ }>;
36
+ sourceType: TableSourceType;
37
+ endpoint?: string;
38
+ }
39
+ export interface ScreenRegion {
40
+ id: string;
41
+ label?: string;
42
+ position: {
43
+ x: number;
44
+ y: number;
45
+ };
46
+ size: {
47
+ width: number;
48
+ height: number;
49
+ };
50
+ elementIds: string[];
51
+ componentNodeId?: string;
52
+ }
53
+ export interface Screen {
54
+ id: string;
55
+ name: string;
56
+ imageUrl: string;
57
+ imageWidth: number;
58
+ imageHeight: number;
59
+ imageFilename?: string;
60
+ regions: ScreenRegion[];
61
+ }
62
+ export interface CanvasNode {
63
+ id: string;
64
+ type: string;
65
+ position: {
66
+ x: number;
67
+ y: number;
68
+ };
69
+ data: Record<string, unknown>;
70
+ }
71
+ export interface CanvasEdge {
72
+ id: string;
73
+ source: string;
74
+ target: string;
75
+ type?: string;
76
+ data?: Record<string, unknown>;
77
+ }
78
+ export interface Project {
79
+ id: string;
80
+ name: string;
81
+ canvas_state: {
82
+ nodes: CanvasNode[];
83
+ edges: CanvasEdge[];
84
+ screens?: Screen[];
85
+ backgroundImage?: unknown | null;
86
+ };
87
+ thumbnail_url: string | null;
88
+ user_id: string;
89
+ is_public: boolean;
90
+ created_at: string;
91
+ updated_at: string;
92
+ }
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ // Minimal types for FlowSpec MCP server — no @xyflow/svelte dependency
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,uEAAuE"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "flowspec-mcp",
3
+ "version": "2.0.0",
4
+ "type": "module",
5
+ "description": "MCP server for FlowSpec — exposes project specs to Claude Code",
6
+ "bin": {
7
+ "flowspec-mcp": "dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "prepublishOnly": "npm run build",
15
+ "start": "node dist/index.js",
16
+ "typecheck": "tsc --noEmit"
17
+ },
18
+ "engines": {
19
+ "node": ">=18.0.0"
20
+ },
21
+ "author": "James King",
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/Jktfe/flowspec-mcp.git"
26
+ },
27
+ "keywords": [
28
+ "mcp",
29
+ "flowspec",
30
+ "claude",
31
+ "model-context-protocol",
32
+ "data-architecture"
33
+ ],
34
+ "dependencies": {
35
+ "@modelcontextprotocol/sdk": "1.12.1",
36
+ "@neondatabase/serverless": "^1.0.2",
37
+ "yaml": "^2.8.2",
38
+ "zod": "^3.24.4"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^20.0.0",
42
+ "typescript": "^5.5.0"
43
+ }
44
+ }