@wireweave/mcp-server 1.8.0 → 1.8.1
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/README.md +43 -122
- package/dist/index.js +614 -795
- package/package.json +39 -14
package/dist/index.js
CHANGED
|
@@ -21,139 +21,137 @@ var tools = [
|
|
|
21
21
|
name: "wireweave_parse",
|
|
22
22
|
description: "Parse Wireweave DSL source code into an AST (Abstract Syntax Tree)",
|
|
23
23
|
inputSchema: {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
type: "object",
|
|
25
|
+
properties: {
|
|
26
|
+
source: {
|
|
27
|
+
type: "string",
|
|
28
|
+
description: "The Wireweave DSL source code to parse"
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
|
-
|
|
32
|
-
"source"
|
|
33
|
-
]
|
|
31
|
+
required: ["source"]
|
|
34
32
|
}
|
|
35
33
|
},
|
|
36
34
|
{
|
|
37
35
|
name: "wireweave_validate",
|
|
38
36
|
description: "Validate Wireweave DSL syntax without generating output. Use strict mode to also check for unknown attributes.",
|
|
39
37
|
inputSchema: {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
type: "object",
|
|
39
|
+
properties: {
|
|
40
|
+
source: {
|
|
41
|
+
type: "string",
|
|
42
|
+
description: "The Wireweave DSL source code to validate"
|
|
45
43
|
},
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
strict: {
|
|
45
|
+
type: "boolean",
|
|
46
|
+
description: "Enable strict mode to also validate that only known attributes are used. Recommended for catching typos and incorrect attribute names.",
|
|
47
|
+
default: false
|
|
50
48
|
}
|
|
51
49
|
},
|
|
52
|
-
|
|
53
|
-
"source"
|
|
54
|
-
]
|
|
50
|
+
required: ["source"]
|
|
55
51
|
}
|
|
56
52
|
},
|
|
57
53
|
{
|
|
58
54
|
name: "wireweave_grammar",
|
|
59
55
|
description: "Get the Wireweave DSL grammar documentation and syntax reference",
|
|
60
56
|
inputSchema: {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
57
|
+
type: "object",
|
|
58
|
+
properties: {},
|
|
59
|
+
required: []
|
|
64
60
|
}
|
|
65
61
|
},
|
|
66
62
|
{
|
|
67
63
|
name: "wireweave_guide",
|
|
68
64
|
description: "Get the comprehensive LLM guide for Wireweave DSL. This is the PRIMARY resource for learning the language - includes syntax, components, patterns, and best practices. Call this FIRST before generating wireframes.",
|
|
69
65
|
inputSchema: {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
type: "object",
|
|
67
|
+
properties: {},
|
|
68
|
+
required: []
|
|
73
69
|
}
|
|
74
70
|
},
|
|
75
71
|
{
|
|
76
72
|
name: "wireweave_patterns",
|
|
77
73
|
description: "Get common layout patterns for wireframes including headers, sidebars, forms, cards, and more. Use these as building blocks.",
|
|
78
74
|
inputSchema: {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
type: "object",
|
|
76
|
+
properties: {},
|
|
77
|
+
required: []
|
|
82
78
|
}
|
|
83
79
|
},
|
|
84
80
|
{
|
|
85
81
|
name: "wireweave_examples",
|
|
86
82
|
description: "Get Wireweave code examples. Use this to learn patterns and best practices for different UI types.",
|
|
87
83
|
inputSchema: {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
"layout",
|
|
96
|
-
"navigation",
|
|
97
|
-
"form",
|
|
98
|
-
"dashboard"
|
|
99
|
-
],
|
|
100
|
-
"description": 'Filter examples by category. Use "all" to get all examples. Categories cover generic component compositions (basic, layout, navigation, form) and a domain-agnostic dashboard shell.',
|
|
101
|
-
"default": "all"
|
|
84
|
+
type: "object",
|
|
85
|
+
properties: {
|
|
86
|
+
category: {
|
|
87
|
+
type: "string",
|
|
88
|
+
enum: ["all", "basic", "layout", "navigation", "form", "dashboard"],
|
|
89
|
+
description: 'Filter examples by category. Use "all" to get all examples. Categories cover generic component compositions (basic, layout, navigation, form) and a domain-agnostic dashboard shell.',
|
|
90
|
+
default: "all"
|
|
102
91
|
},
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
92
|
+
limit: {
|
|
93
|
+
type: "number",
|
|
94
|
+
description: "Maximum number of examples to return",
|
|
95
|
+
default: 5
|
|
107
96
|
}
|
|
108
97
|
},
|
|
109
|
-
|
|
98
|
+
required: []
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: "wireweave_list_components",
|
|
103
|
+
description: "List Wireweave DSL components with their categories, attributes, and examples. Use this to discover available components for wireframe generation. Filter by category (layout, navigation, form, etc.) when narrowing the search.",
|
|
104
|
+
inputSchema: {
|
|
105
|
+
type: "object",
|
|
106
|
+
properties: {
|
|
107
|
+
category: {
|
|
108
|
+
type: "string",
|
|
109
|
+
description: 'Filter components by category (e.g., "layout", "navigation", "form", "content", "interaction"). Omit to return all components.'
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
required: []
|
|
110
113
|
}
|
|
111
114
|
},
|
|
112
115
|
{
|
|
113
116
|
name: "wireweave_render_html_code",
|
|
114
117
|
description: "Render Wireweave DSL to HTML code. Returns the HTML content directly. This is an alias for wireweave_render_html with explicit naming.",
|
|
115
118
|
inputSchema: {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
type: "object",
|
|
120
|
+
properties: {
|
|
121
|
+
source: {
|
|
122
|
+
type: "string",
|
|
123
|
+
description: "The Wireweave DSL source code to render"
|
|
121
124
|
},
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
],
|
|
128
|
-
"description": "Color theme for rendering",
|
|
129
|
-
"default": "light"
|
|
125
|
+
theme: {
|
|
126
|
+
type: "string",
|
|
127
|
+
enum: ["light", "dark"],
|
|
128
|
+
description: "Color theme for rendering",
|
|
129
|
+
default: "light"
|
|
130
130
|
},
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
131
|
+
fullDocument: {
|
|
132
|
+
type: "boolean",
|
|
133
|
+
description: "Return a complete HTML document instead of fragment",
|
|
134
|
+
default: false
|
|
135
135
|
}
|
|
136
136
|
},
|
|
137
|
-
|
|
138
|
-
"source"
|
|
139
|
-
]
|
|
137
|
+
required: ["source"]
|
|
140
138
|
}
|
|
141
139
|
},
|
|
142
140
|
{
|
|
143
141
|
name: "wireweave_validate_ux",
|
|
144
142
|
description: "Validate Wireweave DSL for UX best practices. Returns issues with severity levels and actionable recommendations.",
|
|
145
143
|
inputSchema: {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
144
|
+
type: "object",
|
|
145
|
+
properties: {
|
|
146
|
+
source: {
|
|
147
|
+
type: "string",
|
|
148
|
+
description: "The Wireweave DSL source code to validate"
|
|
151
149
|
},
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
150
|
+
categories: {
|
|
151
|
+
type: "array",
|
|
152
|
+
items: {
|
|
153
|
+
type: "string",
|
|
154
|
+
enum: [
|
|
157
155
|
"accessibility",
|
|
158
156
|
"usability",
|
|
159
157
|
"form",
|
|
@@ -166,516 +164,510 @@ var tools = [
|
|
|
166
164
|
"interaction"
|
|
167
165
|
]
|
|
168
166
|
},
|
|
169
|
-
|
|
167
|
+
description: "UX rule categories to check. If not specified, all categories are checked."
|
|
170
168
|
},
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
"info"
|
|
177
|
-
],
|
|
178
|
-
"description": "Minimum severity level to report",
|
|
179
|
-
"default": "info"
|
|
169
|
+
minSeverity: {
|
|
170
|
+
type: "string",
|
|
171
|
+
enum: ["error", "warning", "info"],
|
|
172
|
+
description: "Minimum severity level to report",
|
|
173
|
+
default: "info"
|
|
180
174
|
},
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
175
|
+
maxIssues: {
|
|
176
|
+
type: "number",
|
|
177
|
+
description: "Maximum number of issues to return"
|
|
184
178
|
},
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
179
|
+
disabledRules: {
|
|
180
|
+
type: "array",
|
|
181
|
+
items: {
|
|
182
|
+
type: "string"
|
|
189
183
|
},
|
|
190
|
-
|
|
184
|
+
description: 'List of rule IDs to disable (e.g., ["a11y-input-label", "form-submit-button"])'
|
|
191
185
|
}
|
|
192
186
|
},
|
|
193
|
-
|
|
194
|
-
"source"
|
|
195
|
-
]
|
|
187
|
+
required: ["source"]
|
|
196
188
|
}
|
|
197
189
|
},
|
|
198
190
|
{
|
|
199
191
|
name: "wireweave_ux_rules",
|
|
200
192
|
description: "Get available UX rule categories and their descriptions",
|
|
201
193
|
inputSchema: {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
194
|
+
type: "object",
|
|
195
|
+
properties: {},
|
|
196
|
+
required: []
|
|
205
197
|
}
|
|
206
198
|
},
|
|
207
199
|
{
|
|
208
200
|
name: "wireweave_diff",
|
|
209
201
|
description: "Compare two Wireweave DSL sources and return the differences between them",
|
|
210
202
|
inputSchema: {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
203
|
+
type: "object",
|
|
204
|
+
properties: {
|
|
205
|
+
oldSource: {
|
|
206
|
+
type: "string",
|
|
207
|
+
description: "The original Wireweave DSL source code"
|
|
208
|
+
},
|
|
209
|
+
newSource: {
|
|
210
|
+
type: "string",
|
|
211
|
+
description: "The modified Wireweave DSL source code"
|
|
216
212
|
},
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
213
|
+
ignoreAttributes: {
|
|
214
|
+
type: "boolean",
|
|
215
|
+
description: "Ignore attribute changes, only compare structure",
|
|
216
|
+
default: false
|
|
217
|
+
},
|
|
218
|
+
ignoreOrder: {
|
|
219
|
+
type: "boolean",
|
|
220
|
+
description: "Ignore the order of children when comparing",
|
|
221
|
+
default: false
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
required: ["oldSource", "newSource"]
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: "wireweave_export_json",
|
|
229
|
+
description: "Export Wireweave DSL to JSON format",
|
|
230
|
+
inputSchema: {
|
|
231
|
+
type: "object",
|
|
232
|
+
properties: {
|
|
233
|
+
source: {
|
|
234
|
+
type: "string",
|
|
235
|
+
description: "The Wireweave DSL source code to export"
|
|
220
236
|
},
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
237
|
+
includeLocations: {
|
|
238
|
+
type: "boolean",
|
|
239
|
+
description: "Include source location information in output",
|
|
240
|
+
default: false
|
|
225
241
|
},
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
242
|
+
prettyPrint: {
|
|
243
|
+
type: "boolean",
|
|
244
|
+
description: "Format JSON with indentation",
|
|
245
|
+
default: true
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
required: ["source"]
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
name: "wireweave_export_figma",
|
|
253
|
+
description: "Export Wireweave DSL to Figma-compatible format",
|
|
254
|
+
inputSchema: {
|
|
255
|
+
type: "object",
|
|
256
|
+
properties: {
|
|
257
|
+
source: {
|
|
258
|
+
type: "string",
|
|
259
|
+
description: "The Wireweave DSL source code to export"
|
|
230
260
|
}
|
|
231
261
|
},
|
|
232
|
-
|
|
233
|
-
"oldSource",
|
|
234
|
-
"newSource"
|
|
235
|
-
]
|
|
262
|
+
required: ["source"]
|
|
236
263
|
}
|
|
237
264
|
},
|
|
238
265
|
{
|
|
239
266
|
name: "wireweave_analyze",
|
|
240
267
|
description: "Analyze Wireweave DSL for statistics and metrics including component usage, tree structure, accessibility score, and complexity",
|
|
241
268
|
inputSchema: {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
269
|
+
type: "object",
|
|
270
|
+
properties: {
|
|
271
|
+
source: {
|
|
272
|
+
type: "string",
|
|
273
|
+
description: "The Wireweave DSL source code to analyze"
|
|
247
274
|
},
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
275
|
+
includeComponentBreakdown: {
|
|
276
|
+
type: "boolean",
|
|
277
|
+
description: "Include detailed component usage breakdown",
|
|
278
|
+
default: true
|
|
252
279
|
},
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
280
|
+
includeAccessibility: {
|
|
281
|
+
type: "boolean",
|
|
282
|
+
description: "Include accessibility analysis",
|
|
283
|
+
default: true
|
|
257
284
|
},
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
285
|
+
includeComplexity: {
|
|
286
|
+
type: "boolean",
|
|
287
|
+
description: "Include complexity metrics",
|
|
288
|
+
default: true
|
|
262
289
|
},
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
290
|
+
includeLayout: {
|
|
291
|
+
type: "boolean",
|
|
292
|
+
description: "Include layout pattern analysis",
|
|
293
|
+
default: true
|
|
267
294
|
},
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
295
|
+
includeContent: {
|
|
296
|
+
type: "boolean",
|
|
297
|
+
description: "Include content analysis",
|
|
298
|
+
default: true
|
|
272
299
|
}
|
|
273
300
|
},
|
|
274
|
-
|
|
275
|
-
"source"
|
|
276
|
-
]
|
|
301
|
+
required: ["source"]
|
|
277
302
|
}
|
|
278
303
|
},
|
|
279
304
|
{
|
|
280
305
|
name: "wireweave_cloud_list_projects",
|
|
281
306
|
description: "List all your Wireweave projects. Projects help organize your wireframes. WORKFLOW: Call this first before saving wireframes. If the list is empty, ask the user whether to create a new project (call wireweave_cloud_create_project) or use the default project.",
|
|
282
307
|
inputSchema: {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
308
|
+
type: "object",
|
|
309
|
+
properties: {
|
|
310
|
+
includeArchived: {
|
|
311
|
+
type: "boolean",
|
|
312
|
+
description: "Include archived projects",
|
|
313
|
+
default: false
|
|
289
314
|
}
|
|
290
315
|
},
|
|
291
|
-
|
|
316
|
+
required: []
|
|
292
317
|
}
|
|
293
318
|
},
|
|
294
319
|
{
|
|
295
320
|
name: "wireweave_cloud_create_project",
|
|
296
321
|
description: "Create a new project to organize wireframes. Use this when the user wants to organize their wireframes into a specific project. The project can have a custom name, description, and color.",
|
|
297
322
|
inputSchema: {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
323
|
+
type: "object",
|
|
324
|
+
properties: {
|
|
325
|
+
name: {
|
|
326
|
+
type: "string",
|
|
327
|
+
description: "Project name"
|
|
303
328
|
},
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
329
|
+
description: {
|
|
330
|
+
type: "string",
|
|
331
|
+
description: "Project description"
|
|
307
332
|
},
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
333
|
+
color: {
|
|
334
|
+
type: "string",
|
|
335
|
+
description: "Project color (hex code, e.g., #6366f1)"
|
|
311
336
|
}
|
|
312
337
|
},
|
|
313
|
-
|
|
314
|
-
"name"
|
|
315
|
-
]
|
|
338
|
+
required: ["name"]
|
|
316
339
|
}
|
|
317
340
|
},
|
|
318
341
|
{
|
|
319
342
|
name: "wireweave_cloud_update_project",
|
|
320
343
|
description: "Update an existing project",
|
|
321
344
|
inputSchema: {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
345
|
+
type: "object",
|
|
346
|
+
properties: {
|
|
347
|
+
id: {
|
|
348
|
+
type: "string",
|
|
349
|
+
description: "Project ID to update"
|
|
327
350
|
},
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
351
|
+
name: {
|
|
352
|
+
type: "string",
|
|
353
|
+
description: "New project name"
|
|
331
354
|
},
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
355
|
+
description: {
|
|
356
|
+
type: "string",
|
|
357
|
+
description: "New project description"
|
|
335
358
|
},
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
359
|
+
color: {
|
|
360
|
+
type: "string",
|
|
361
|
+
description: "New project color (hex code)"
|
|
339
362
|
},
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
363
|
+
isArchived: {
|
|
364
|
+
type: "boolean",
|
|
365
|
+
description: "Archive or unarchive the project"
|
|
343
366
|
}
|
|
344
367
|
},
|
|
345
|
-
|
|
346
|
-
"id"
|
|
347
|
-
]
|
|
368
|
+
required: ["id"]
|
|
348
369
|
}
|
|
349
370
|
},
|
|
350
371
|
{
|
|
351
372
|
name: "wireweave_cloud_list_wireframes",
|
|
352
373
|
description: "List your saved wireframes. Optionally filter by project or tags.",
|
|
353
374
|
inputSchema: {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
375
|
+
type: "object",
|
|
376
|
+
properties: {
|
|
377
|
+
projectId: {
|
|
378
|
+
type: "string",
|
|
379
|
+
description: "Filter by project ID"
|
|
359
380
|
},
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
381
|
+
tags: {
|
|
382
|
+
type: "array",
|
|
383
|
+
items: {
|
|
384
|
+
type: "string"
|
|
364
385
|
},
|
|
365
|
-
|
|
386
|
+
description: "Filter by tags"
|
|
366
387
|
},
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
388
|
+
limit: {
|
|
389
|
+
type: "number",
|
|
390
|
+
description: "Maximum number of wireframes to return",
|
|
391
|
+
default: 20
|
|
371
392
|
},
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
393
|
+
offset: {
|
|
394
|
+
type: "number",
|
|
395
|
+
description: "Offset for pagination",
|
|
396
|
+
default: 0
|
|
376
397
|
}
|
|
377
398
|
},
|
|
378
|
-
|
|
399
|
+
required: []
|
|
379
400
|
}
|
|
380
401
|
},
|
|
381
402
|
{
|
|
382
403
|
name: "wireweave_cloud_get_wireframe",
|
|
383
404
|
description: "Get a specific wireframe by ID, including its code and metadata",
|
|
384
405
|
inputSchema: {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
406
|
+
type: "object",
|
|
407
|
+
properties: {
|
|
408
|
+
id: {
|
|
409
|
+
type: "string",
|
|
410
|
+
description: "Wireframe ID"
|
|
390
411
|
}
|
|
391
412
|
},
|
|
392
|
-
|
|
393
|
-
"id"
|
|
394
|
-
]
|
|
413
|
+
required: ["id"]
|
|
395
414
|
}
|
|
396
415
|
},
|
|
397
416
|
{
|
|
398
417
|
name: "wireweave_cloud_save_wireframe",
|
|
399
418
|
description: "Save a new wireframe to the cloud. Free (v2.0+).\n\nRECOMMENDED WORKFLOW:\n1. Call wireweave_cloud_list_projects to get available projects\n2. If projects exist: Ask user which project to save to\n3. If no projects: Ask user to (a) create a new project, or (b) save to default project\n4. Call this tool with the chosen projectId (or omit for default project)\n\nNote: If projectId is not provided, the wireframe will be saved to the user's default project.",
|
|
400
419
|
inputSchema: {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
420
|
+
type: "object",
|
|
421
|
+
properties: {
|
|
422
|
+
name: {
|
|
423
|
+
type: "string",
|
|
424
|
+
description: "Wireframe name"
|
|
406
425
|
},
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
426
|
+
code: {
|
|
427
|
+
type: "string",
|
|
428
|
+
description: "Wireweave DSL code"
|
|
410
429
|
},
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
430
|
+
description: {
|
|
431
|
+
type: "string",
|
|
432
|
+
description: "Wireframe description"
|
|
414
433
|
},
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
434
|
+
projectId: {
|
|
435
|
+
type: "string",
|
|
436
|
+
description: "Project ID to save to. Get available projects using wireweave_cloud_list_projects first."
|
|
418
437
|
},
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
438
|
+
tags: {
|
|
439
|
+
type: "array",
|
|
440
|
+
items: {
|
|
441
|
+
type: "string"
|
|
423
442
|
},
|
|
424
|
-
|
|
443
|
+
description: "Tags for categorization"
|
|
425
444
|
},
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
445
|
+
isPublic: {
|
|
446
|
+
type: "boolean",
|
|
447
|
+
description: "Make wireframe publicly visible",
|
|
448
|
+
default: false
|
|
430
449
|
}
|
|
431
450
|
},
|
|
432
|
-
|
|
433
|
-
"name",
|
|
434
|
-
"code"
|
|
435
|
-
]
|
|
451
|
+
required: ["name", "code"]
|
|
436
452
|
}
|
|
437
453
|
},
|
|
438
454
|
{
|
|
439
455
|
name: "wireweave_cloud_update_wireframe",
|
|
440
456
|
description: "Update an existing wireframe. Creates a new version automatically. Free (v2.0+).",
|
|
441
457
|
inputSchema: {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
458
|
+
type: "object",
|
|
459
|
+
properties: {
|
|
460
|
+
id: {
|
|
461
|
+
type: "string",
|
|
462
|
+
description: "Wireframe ID to update"
|
|
447
463
|
},
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
464
|
+
name: {
|
|
465
|
+
type: "string",
|
|
466
|
+
description: "New name (optional)"
|
|
451
467
|
},
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
468
|
+
code: {
|
|
469
|
+
type: "string",
|
|
470
|
+
description: "New Wireweave DSL code (optional)"
|
|
455
471
|
},
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
472
|
+
description: {
|
|
473
|
+
type: "string",
|
|
474
|
+
description: "New description (optional)"
|
|
459
475
|
},
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
476
|
+
tags: {
|
|
477
|
+
type: "array",
|
|
478
|
+
items: {
|
|
479
|
+
type: "string"
|
|
464
480
|
},
|
|
465
|
-
|
|
481
|
+
description: "New tags (optional)"
|
|
466
482
|
},
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
483
|
+
isPublic: {
|
|
484
|
+
type: "boolean",
|
|
485
|
+
description: "Update public visibility (optional)"
|
|
470
486
|
}
|
|
471
487
|
},
|
|
472
|
-
|
|
473
|
-
"id"
|
|
474
|
-
]
|
|
488
|
+
required: ["id"]
|
|
475
489
|
}
|
|
476
490
|
},
|
|
477
491
|
{
|
|
478
492
|
name: "wireweave_cloud_delete_wireframe",
|
|
479
493
|
description: "Delete a wireframe permanently",
|
|
480
494
|
inputSchema: {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
495
|
+
type: "object",
|
|
496
|
+
properties: {
|
|
497
|
+
id: {
|
|
498
|
+
type: "string",
|
|
499
|
+
description: "Wireframe ID to delete"
|
|
486
500
|
}
|
|
487
501
|
},
|
|
488
|
-
|
|
489
|
-
"id"
|
|
490
|
-
]
|
|
502
|
+
required: ["id"]
|
|
491
503
|
}
|
|
492
504
|
},
|
|
493
505
|
{
|
|
494
506
|
name: "wireweave_cloud_get_versions",
|
|
495
507
|
description: "Get version history of a wireframe",
|
|
496
508
|
inputSchema: {
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
509
|
+
type: "object",
|
|
510
|
+
properties: {
|
|
511
|
+
wireframeId: {
|
|
512
|
+
type: "string",
|
|
513
|
+
description: "Wireframe ID"
|
|
502
514
|
}
|
|
503
515
|
},
|
|
504
|
-
|
|
505
|
-
"wireframeId"
|
|
506
|
-
]
|
|
516
|
+
required: ["wireframeId"]
|
|
507
517
|
}
|
|
508
518
|
},
|
|
509
519
|
{
|
|
510
520
|
name: "wireweave_cloud_restore_version",
|
|
511
521
|
description: "Restore a wireframe to a previous version. Free (v2.0+).",
|
|
512
522
|
inputSchema: {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
523
|
+
type: "object",
|
|
524
|
+
properties: {
|
|
525
|
+
wireframeId: {
|
|
526
|
+
type: "string",
|
|
527
|
+
description: "Wireframe ID"
|
|
518
528
|
},
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
529
|
+
version: {
|
|
530
|
+
type: "number",
|
|
531
|
+
description: "Version number to restore"
|
|
522
532
|
}
|
|
523
533
|
},
|
|
524
|
-
|
|
525
|
-
"wireframeId",
|
|
526
|
-
"version"
|
|
527
|
-
]
|
|
534
|
+
required: ["wireframeId", "version"]
|
|
528
535
|
}
|
|
529
536
|
},
|
|
530
537
|
{
|
|
531
538
|
name: "wireweave_cloud_create_share_link",
|
|
532
539
|
description: "Create a shareable link for a wireframe. Free (v2.0+).",
|
|
533
540
|
inputSchema: {
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
541
|
+
type: "object",
|
|
542
|
+
properties: {
|
|
543
|
+
wireframeId: {
|
|
544
|
+
type: "string",
|
|
545
|
+
description: "Wireframe ID to share"
|
|
539
546
|
},
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
547
|
+
title: {
|
|
548
|
+
type: "string",
|
|
549
|
+
description: "Custom title for the shared view"
|
|
543
550
|
},
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
551
|
+
allowCopy: {
|
|
552
|
+
type: "boolean",
|
|
553
|
+
description: "Allow viewers to copy the code",
|
|
554
|
+
default: false
|
|
548
555
|
},
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
556
|
+
password: {
|
|
557
|
+
type: "string",
|
|
558
|
+
description: "Password protection (optional)"
|
|
552
559
|
},
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
560
|
+
expiresInDays: {
|
|
561
|
+
type: "number",
|
|
562
|
+
description: "Link expiration in days (optional, null = never)"
|
|
556
563
|
}
|
|
557
564
|
},
|
|
558
|
-
|
|
559
|
-
"wireframeId"
|
|
560
|
-
]
|
|
565
|
+
required: ["wireframeId"]
|
|
561
566
|
}
|
|
562
567
|
},
|
|
563
568
|
{
|
|
564
569
|
name: "wireweave_cloud_list_shares",
|
|
565
570
|
description: "List share links for a wireframe",
|
|
566
571
|
inputSchema: {
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
+
type: "object",
|
|
573
|
+
properties: {
|
|
574
|
+
wireframeId: {
|
|
575
|
+
type: "string",
|
|
576
|
+
description: "Wireframe ID"
|
|
572
577
|
}
|
|
573
578
|
},
|
|
574
|
-
|
|
575
|
-
"wireframeId"
|
|
576
|
-
]
|
|
579
|
+
required: ["wireframeId"]
|
|
577
580
|
}
|
|
578
581
|
},
|
|
579
582
|
{
|
|
580
583
|
name: "wireweave_cloud_diff_versions",
|
|
581
584
|
description: "Compare two versions of a wireframe and return the differences. Useful for reviewing changes without loading full code.",
|
|
582
585
|
inputSchema: {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
586
|
+
type: "object",
|
|
587
|
+
properties: {
|
|
588
|
+
wireframeId: {
|
|
589
|
+
type: "string",
|
|
590
|
+
description: "Wireframe ID"
|
|
588
591
|
},
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
+
versionA: {
|
|
593
|
+
type: "number",
|
|
594
|
+
description: "First version number to compare"
|
|
592
595
|
},
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
+
versionB: {
|
|
597
|
+
type: "number",
|
|
598
|
+
description: "Second version number to compare"
|
|
596
599
|
}
|
|
597
600
|
},
|
|
598
|
-
|
|
599
|
-
"wireframeId",
|
|
600
|
-
"versionA",
|
|
601
|
-
"versionB"
|
|
602
|
-
]
|
|
601
|
+
required: ["wireframeId", "versionA", "versionB"]
|
|
603
602
|
}
|
|
604
603
|
},
|
|
605
604
|
{
|
|
606
605
|
name: "wireweave_account_balance",
|
|
607
606
|
description: "Check your current credit balance and subscription status",
|
|
608
607
|
inputSchema: {
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
608
|
+
type: "object",
|
|
609
|
+
properties: {},
|
|
610
|
+
required: []
|
|
612
611
|
}
|
|
613
612
|
},
|
|
614
613
|
{
|
|
615
614
|
name: "wireweave_account_subscription",
|
|
616
615
|
description: "Get detailed subscription information including plan features",
|
|
617
616
|
inputSchema: {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
617
|
+
type: "object",
|
|
618
|
+
properties: {},
|
|
619
|
+
required: []
|
|
621
620
|
}
|
|
622
621
|
},
|
|
623
622
|
{
|
|
624
623
|
name: "wireweave_account_transactions",
|
|
625
624
|
description: "View your credit transaction history",
|
|
626
625
|
inputSchema: {
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
626
|
+
type: "object",
|
|
627
|
+
properties: {
|
|
628
|
+
limit: {
|
|
629
|
+
type: "number",
|
|
630
|
+
description: "Number of transactions to return",
|
|
631
|
+
default: 20
|
|
633
632
|
},
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
"subscription",
|
|
639
|
-
"usage",
|
|
640
|
-
"refund",
|
|
641
|
-
"bonus",
|
|
642
|
-
"admin"
|
|
643
|
-
],
|
|
644
|
-
"description": "Filter by transaction type"
|
|
633
|
+
type: {
|
|
634
|
+
type: "string",
|
|
635
|
+
enum: ["purchase", "subscription", "usage", "refund", "bonus", "admin"],
|
|
636
|
+
description: "Filter by transaction type"
|
|
645
637
|
}
|
|
646
638
|
},
|
|
647
|
-
|
|
639
|
+
required: []
|
|
648
640
|
}
|
|
649
641
|
},
|
|
650
642
|
{
|
|
651
643
|
name: "wireweave_pricing",
|
|
652
644
|
description: "Get current pricing information for plans, credit packs, and feature costs",
|
|
653
645
|
inputSchema: {
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
646
|
+
type: "object",
|
|
647
|
+
properties: {},
|
|
648
|
+
required: []
|
|
657
649
|
}
|
|
658
650
|
},
|
|
659
651
|
{
|
|
660
652
|
name: "wireweave_gallery",
|
|
661
653
|
description: "Browse public wireframe gallery for inspiration",
|
|
662
654
|
inputSchema: {
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
655
|
+
type: "object",
|
|
656
|
+
properties: {
|
|
657
|
+
tags: {
|
|
658
|
+
type: "array",
|
|
659
|
+
items: {
|
|
660
|
+
type: "string"
|
|
669
661
|
},
|
|
670
|
-
|
|
662
|
+
description: "Filter by tags"
|
|
671
663
|
},
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
664
|
+
limit: {
|
|
665
|
+
type: "number",
|
|
666
|
+
description: "Number of wireframes to return",
|
|
667
|
+
default: 20
|
|
676
668
|
}
|
|
677
669
|
},
|
|
678
|
-
|
|
670
|
+
required: []
|
|
679
671
|
}
|
|
680
672
|
}
|
|
681
673
|
];
|
|
@@ -686,44 +678,83 @@ var toolEndpoints = {
|
|
|
686
678
|
wireweave_guide: { method: "GET", path: "/tools/guide" },
|
|
687
679
|
wireweave_patterns: { method: "GET", path: "/tools/patterns" },
|
|
688
680
|
wireweave_examples: { method: "GET", path: "/tools/examples" },
|
|
681
|
+
wireweave_list_components: { method: "GET", path: "/tools/list-components" },
|
|
689
682
|
wireweave_render_html_code: { method: "POST", path: "/tools/render/html" },
|
|
690
683
|
wireweave_validate_ux: { method: "POST", path: "/tools/validate/ux" },
|
|
691
684
|
wireweave_ux_rules: { method: "GET", path: "/tools/ux-rules" },
|
|
692
685
|
wireweave_diff: { method: "POST", path: "/tools/diff" },
|
|
686
|
+
wireweave_export_json: { method: "POST", path: "/tools/export/json" },
|
|
687
|
+
wireweave_export_figma: { method: "POST", path: "/tools/export/figma" },
|
|
693
688
|
wireweave_analyze: { method: "POST", path: "/tools/analyze" },
|
|
694
689
|
wireweave_cloud_list_projects: { method: "GET", path: "/cloud/projects" },
|
|
695
690
|
wireweave_cloud_create_project: { method: "POST", path: "/cloud/projects" },
|
|
696
|
-
wireweave_cloud_update_project: {
|
|
691
|
+
wireweave_cloud_update_project: {
|
|
692
|
+
method: "PATCH",
|
|
693
|
+
path: "/cloud/projects/:id",
|
|
694
|
+
pathParams: ["id"]
|
|
695
|
+
},
|
|
697
696
|
wireweave_cloud_list_wireframes: { method: "GET", path: "/cloud/wireframes" },
|
|
698
|
-
wireweave_cloud_get_wireframe: {
|
|
697
|
+
wireweave_cloud_get_wireframe: {
|
|
698
|
+
method: "GET",
|
|
699
|
+
path: "/cloud/wireframes/:id",
|
|
700
|
+
pathParams: ["id"]
|
|
701
|
+
},
|
|
699
702
|
wireweave_cloud_save_wireframe: { method: "POST", path: "/cloud/wireframes" },
|
|
700
|
-
wireweave_cloud_update_wireframe: {
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
703
|
+
wireweave_cloud_update_wireframe: {
|
|
704
|
+
method: "PATCH",
|
|
705
|
+
path: "/cloud/wireframes/:id",
|
|
706
|
+
pathParams: ["id"]
|
|
707
|
+
},
|
|
708
|
+
wireweave_cloud_delete_wireframe: {
|
|
709
|
+
method: "DELETE",
|
|
710
|
+
path: "/cloud/wireframes/:id",
|
|
711
|
+
pathParams: ["id"]
|
|
712
|
+
},
|
|
713
|
+
wireweave_cloud_get_versions: {
|
|
714
|
+
method: "GET",
|
|
715
|
+
path: "/cloud/wireframes/:wireframeId/versions",
|
|
716
|
+
pathParams: ["wireframeId"]
|
|
717
|
+
},
|
|
718
|
+
wireweave_cloud_restore_version: {
|
|
719
|
+
method: "POST",
|
|
720
|
+
path: "/cloud/wireframes/:wireframeId/versions/:version/restore",
|
|
721
|
+
pathParams: ["wireframeId", "version"]
|
|
722
|
+
},
|
|
723
|
+
wireweave_cloud_create_share_link: {
|
|
724
|
+
method: "POST",
|
|
725
|
+
path: "/cloud/wireframes/:wireframeId/shares",
|
|
726
|
+
pathParams: ["wireframeId"]
|
|
727
|
+
},
|
|
728
|
+
wireweave_cloud_list_shares: {
|
|
729
|
+
method: "GET",
|
|
730
|
+
path: "/cloud/wireframes/:wireframeId/shares",
|
|
731
|
+
pathParams: ["wireframeId"]
|
|
732
|
+
},
|
|
733
|
+
wireweave_cloud_diff_versions: {
|
|
734
|
+
method: "GET",
|
|
735
|
+
path: "/cloud/wireframes/:wireframeId/diff",
|
|
736
|
+
pathParams: ["wireframeId"]
|
|
737
|
+
},
|
|
707
738
|
wireweave_account_balance: { method: "GET", path: "/billing/balance" },
|
|
708
739
|
wireweave_account_subscription: { method: "GET", path: "/billing/subscription" },
|
|
709
740
|
wireweave_account_transactions: { method: "GET", path: "/billing/transactions" },
|
|
710
741
|
wireweave_pricing: { method: "GET", path: "/billing/pricing" },
|
|
711
742
|
wireweave_gallery: { method: "GET", path: "/cloud/gallery" }
|
|
712
743
|
};
|
|
744
|
+
var localToolNames = /* @__PURE__ */ new Set([
|
|
745
|
+
"wireweave_parse",
|
|
746
|
+
"wireweave_validate",
|
|
747
|
+
"wireweave_list_components",
|
|
748
|
+
"wireweave_render_html_code",
|
|
749
|
+
"wireweave_validate_ux",
|
|
750
|
+
"wireweave_diff",
|
|
751
|
+
"wireweave_export_json",
|
|
752
|
+
"wireweave_export_figma",
|
|
753
|
+
"wireweave_analyze"
|
|
754
|
+
]);
|
|
713
755
|
|
|
714
756
|
// src/prompts.ts
|
|
715
757
|
var prompts = [
|
|
716
|
-
{
|
|
717
|
-
name: "create_wireframe",
|
|
718
|
-
description: "Create a new wireframe from a natural language description. Generates Wireweave DSL code.",
|
|
719
|
-
arguments: [
|
|
720
|
-
{
|
|
721
|
-
name: "description",
|
|
722
|
-
description: 'Description of the wireframe to create (e.g., "dashboard with sidebar nav and a stats card row")',
|
|
723
|
-
required: true
|
|
724
|
-
}
|
|
725
|
-
]
|
|
726
|
-
},
|
|
727
758
|
{
|
|
728
759
|
name: "improve_ux",
|
|
729
760
|
description: "Analyze existing wireframe code and suggest UX improvements based on best practices.",
|
|
@@ -750,27 +781,38 @@ var prompts = [
|
|
|
750
781
|
required: false
|
|
751
782
|
}
|
|
752
783
|
]
|
|
784
|
+
},
|
|
785
|
+
{
|
|
786
|
+
name: "create_wireframe",
|
|
787
|
+
description: "Create a new wireframe from a natural language description. Generates Wireweave DSL code.",
|
|
788
|
+
arguments: [
|
|
789
|
+
{
|
|
790
|
+
name: "description",
|
|
791
|
+
description: 'Description of the wireframe to create (e.g., "dashboard with sidebar nav and a stats card row")',
|
|
792
|
+
required: true
|
|
793
|
+
}
|
|
794
|
+
]
|
|
753
795
|
}
|
|
754
796
|
];
|
|
755
797
|
var promptTemplates = {
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
Please use the wireweave_guide tool first to understand the DSL syntax, then generate valid Wireweave code.
|
|
759
|
-
After generating, use wireweave_validate to check the syntax and wireweave_validate_ux to check UX best practices.`,
|
|
760
|
-
"improve_ux": `Analyze and improve the UX of this Wireweave wireframe:
|
|
798
|
+
improve_ux: `Analyze and improve the UX of this Wireweave wireframe:
|
|
761
799
|
|
|
762
800
|
\`\`\`wireframe
|
|
763
801
|
{{code}}
|
|
764
802
|
\`\`\`
|
|
765
803
|
|
|
766
804
|
Please use wireweave_validate_ux to get specific recommendations, then suggest improvements.`,
|
|
767
|
-
|
|
805
|
+
convert_to_wireframe: `Convert this UI description to Wireweave DSL code:
|
|
768
806
|
|
|
769
807
|
{{ui_description}}
|
|
770
808
|
|
|
771
809
|
Style preference: {{style}}
|
|
772
810
|
|
|
773
|
-
Use wireweave_guide for syntax reference and wireweave_patterns for common layouts
|
|
811
|
+
Use wireweave_guide for syntax reference and wireweave_patterns for common layouts.`,
|
|
812
|
+
create_wireframe: `Create a Wireweave DSL wireframe for: {{description}}
|
|
813
|
+
|
|
814
|
+
Please use the wireweave_guide tool first to understand the DSL syntax, then generate valid Wireweave code.
|
|
815
|
+
After generating, use wireweave_validate to check the syntax and wireweave_validate_ux to check UX best practices.`
|
|
774
816
|
};
|
|
775
817
|
|
|
776
818
|
// src/resources.ts
|
|
@@ -814,231 +856,80 @@ var resourceToTool = {
|
|
|
814
856
|
"wireweave://ux-rules": "wireweave_ux_rules"
|
|
815
857
|
};
|
|
816
858
|
|
|
817
|
-
// src/
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
if (value !== void 0) {
|
|
825
|
-
path2 = path2.replace(`:${param}`, String(value));
|
|
826
|
-
delete body[param];
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
let url = `${config.apiUrl}${path2}`;
|
|
831
|
-
const options = {
|
|
832
|
-
method: endpoint.method,
|
|
833
|
-
headers: {
|
|
834
|
-
"Content-Type": "application/json",
|
|
835
|
-
"x-api-key": config.apiKey
|
|
836
|
-
}
|
|
859
|
+
// src/handlers.ts
|
|
860
|
+
import { dispatch } from "@wireweave/sdk";
|
|
861
|
+
function dispatchOptions(ctx) {
|
|
862
|
+
return {
|
|
863
|
+
apiConfig: ctx.apiConfig,
|
|
864
|
+
endpoints: ctx.endpoints,
|
|
865
|
+
fetchFn: ctx.fetchFn
|
|
837
866
|
};
|
|
838
|
-
if (["POST", "PATCH", "PUT"].includes(endpoint.method) && Object.keys(body).length > 0) {
|
|
839
|
-
options.body = JSON.stringify(body);
|
|
840
|
-
} else if (endpoint.method === "GET" && Object.keys(body).length > 0) {
|
|
841
|
-
const params = new URLSearchParams();
|
|
842
|
-
for (const [key, value] of Object.entries(body)) {
|
|
843
|
-
if (value !== void 0 && value !== null) {
|
|
844
|
-
if (Array.isArray(value)) {
|
|
845
|
-
params.append(key, value.join(","));
|
|
846
|
-
} else {
|
|
847
|
-
params.append(key, String(value));
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
url = `${url}?${params.toString()}`;
|
|
852
|
-
}
|
|
853
|
-
return { url, options, bodyForGet: body };
|
|
854
867
|
}
|
|
855
|
-
function
|
|
856
|
-
|
|
857
|
-
if (status === 402) return `Insufficient credits. ${error.message || "Please add more credits."}`;
|
|
858
|
-
if (status === 403) return "Access denied. Upgrade your plan for this feature.";
|
|
859
|
-
if (status === 404 && error.error?.includes("project")) {
|
|
860
|
-
return "Project not found. Call wireweave_cloud_list_projects to see available projects.";
|
|
861
|
-
}
|
|
862
|
-
if (status === 400 && error.error?.includes("name")) {
|
|
863
|
-
return "Invalid wireframe name. Provide a non-empty name for the wireframe.";
|
|
864
|
-
}
|
|
865
|
-
if (status === 429) return "Rate limit exceeded. Please wait and try again.";
|
|
866
|
-
if (status >= 500) return "Service temporarily unavailable";
|
|
867
|
-
return error.error || error.message || "Request failed";
|
|
868
|
+
function handleListTools() {
|
|
869
|
+
return { tools };
|
|
868
870
|
}
|
|
869
|
-
function
|
|
870
|
-
return {
|
|
871
|
-
balance: headers.get("X-Credits-Balance") ? parseInt(headers.get("X-Credits-Balance"), 10) : void 0,
|
|
872
|
-
monthlyRemaining: headers.get("X-Credits-Monthly-Remaining") ? parseInt(headers.get("X-Credits-Monthly-Remaining"), 10) : void 0,
|
|
873
|
-
totalAvailable: headers.get("X-Credits-Total-Available") ? parseInt(headers.get("X-Credits-Total-Available"), 10) : void 0
|
|
874
|
-
};
|
|
871
|
+
async function handleCallTool(name, args, ctx) {
|
|
872
|
+
return dispatch(name, args ?? {}, dispatchOptions(ctx));
|
|
875
873
|
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
const
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
if (!response.ok) {
|
|
884
|
-
const error = await response.json().catch(() => ({ error: "Request failed" }));
|
|
885
|
-
const userMessage = parseErrorMessage(response.status, error);
|
|
886
|
-
throw new Error(userMessage);
|
|
874
|
+
function handleListPrompts() {
|
|
875
|
+
return { prompts };
|
|
876
|
+
}
|
|
877
|
+
function handleGetPrompt(name, args) {
|
|
878
|
+
const prompt = prompts.find((p) => p.name === name);
|
|
879
|
+
if (!prompt) {
|
|
880
|
+
throw new Error(`Prompt not found: ${name}`);
|
|
887
881
|
}
|
|
888
|
-
const
|
|
889
|
-
if (
|
|
890
|
-
|
|
891
|
-
...result,
|
|
892
|
-
_credits: creditInfo
|
|
893
|
-
};
|
|
882
|
+
const template = promptTemplates[name];
|
|
883
|
+
if (!template) {
|
|
884
|
+
throw new Error(`Prompt template not found: ${name}`);
|
|
894
885
|
}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
import * as fs from "fs";
|
|
900
|
-
import * as path from "path";
|
|
901
|
-
import * as os from "os";
|
|
902
|
-
var localTools = [
|
|
903
|
-
{
|
|
904
|
-
name: "wireweave_render_html_file",
|
|
905
|
-
description: "Render Wireweave DSL to HTML and save to a local file. Returns the file path. Use this when you need a persistent HTML file for preview or browser viewing. Credits are charged via internal API call.",
|
|
906
|
-
inputSchema: {
|
|
907
|
-
type: "object",
|
|
908
|
-
properties: {
|
|
909
|
-
source: {
|
|
910
|
-
type: "string",
|
|
911
|
-
description: "The Wireweave DSL source code to render"
|
|
912
|
-
},
|
|
913
|
-
theme: {
|
|
914
|
-
type: "string",
|
|
915
|
-
enum: ["light", "dark"],
|
|
916
|
-
description: "Color theme for rendering",
|
|
917
|
-
default: "light"
|
|
918
|
-
},
|
|
919
|
-
outputDir: {
|
|
920
|
-
type: "string",
|
|
921
|
-
description: "Output directory for the HTML file. Defaults to system temp directory."
|
|
922
|
-
},
|
|
923
|
-
filename: {
|
|
924
|
-
type: "string",
|
|
925
|
-
description: "Custom filename without extension. Defaults to wireframe-{timestamp}."
|
|
926
|
-
}
|
|
927
|
-
},
|
|
928
|
-
required: ["source"]
|
|
886
|
+
let messageText = template;
|
|
887
|
+
if (args) {
|
|
888
|
+
for (const [key, value] of Object.entries(args)) {
|
|
889
|
+
messageText = messageText.replace(new RegExp(`\\{\\{${key}\\}\\}`, "g"), String(value));
|
|
929
890
|
}
|
|
930
891
|
}
|
|
931
|
-
];
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
return {
|
|
939
|
-
content: [
|
|
940
|
-
{
|
|
941
|
-
type: "text",
|
|
942
|
-
text: JSON.stringify({ error: `Unknown local tool: ${name}` }, null, 2)
|
|
943
|
-
}
|
|
944
|
-
],
|
|
945
|
-
isError: true
|
|
946
|
-
};
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
async function handleRenderHtmlFile(args, apiConfig2) {
|
|
950
|
-
const { source, theme = "light", outputDir, filename } = args;
|
|
951
|
-
if (!source || typeof source !== "string") {
|
|
952
|
-
return {
|
|
953
|
-
content: [
|
|
954
|
-
{
|
|
892
|
+
messageText = messageText.replace(/\{\{[^}]+\}\}/g, "");
|
|
893
|
+
return {
|
|
894
|
+
description: prompt.description,
|
|
895
|
+
messages: [
|
|
896
|
+
{
|
|
897
|
+
role: "user",
|
|
898
|
+
content: {
|
|
955
899
|
type: "text",
|
|
956
|
-
text:
|
|
900
|
+
text: messageText
|
|
957
901
|
}
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
902
|
+
}
|
|
903
|
+
]
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
function handleListResources() {
|
|
907
|
+
return { resources };
|
|
908
|
+
}
|
|
909
|
+
async function handleReadResource(uri, ctx) {
|
|
910
|
+
const resource = resources.find((r) => r.uri === uri);
|
|
911
|
+
if (!resource) {
|
|
912
|
+
throw new Error(`Resource not found: ${uri}`);
|
|
961
913
|
}
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
{ error: "wireweave_render_html_code endpoint not found" },
|
|
971
|
-
null,
|
|
972
|
-
2
|
|
973
|
-
)
|
|
974
|
-
}
|
|
975
|
-
],
|
|
976
|
-
isError: true
|
|
977
|
-
};
|
|
978
|
-
}
|
|
979
|
-
const result = await callApi(apiConfig2, endpoint, {
|
|
980
|
-
source,
|
|
981
|
-
theme,
|
|
982
|
-
fullDocument: true
|
|
983
|
-
// Always request full document for file output
|
|
984
|
-
});
|
|
985
|
-
if (!result.success || !result.html) {
|
|
986
|
-
return {
|
|
987
|
-
content: [
|
|
988
|
-
{
|
|
989
|
-
type: "text",
|
|
990
|
-
text: JSON.stringify(
|
|
991
|
-
{ error: result.error || "No HTML content returned from API" },
|
|
992
|
-
null,
|
|
993
|
-
2
|
|
994
|
-
)
|
|
995
|
-
}
|
|
996
|
-
],
|
|
997
|
-
isError: true
|
|
998
|
-
};
|
|
999
|
-
}
|
|
1000
|
-
const dir = typeof outputDir === "string" ? outputDir : os.tmpdir();
|
|
1001
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
1002
|
-
const fname = typeof filename === "string" ? filename : `wireframe-${timestamp}`;
|
|
1003
|
-
const filePath = path.join(dir, `${fname}.html`);
|
|
1004
|
-
let htmlContent = result.html;
|
|
1005
|
-
if (result.css && !htmlContent.includes("<style>")) {
|
|
1006
|
-
htmlContent = htmlContent.replace("</head>", `<style>${result.css}</style></head>`);
|
|
1007
|
-
}
|
|
1008
|
-
fs.writeFileSync(filePath, htmlContent, "utf-8");
|
|
1009
|
-
return {
|
|
1010
|
-
content: [
|
|
1011
|
-
{
|
|
1012
|
-
type: "text",
|
|
1013
|
-
text: JSON.stringify(
|
|
1014
|
-
{
|
|
1015
|
-
success: true,
|
|
1016
|
-
filePath,
|
|
1017
|
-
message: `HTML file saved to: ${filePath}`
|
|
1018
|
-
},
|
|
1019
|
-
null,
|
|
1020
|
-
2
|
|
1021
|
-
)
|
|
1022
|
-
}
|
|
1023
|
-
]
|
|
1024
|
-
};
|
|
1025
|
-
} catch (error) {
|
|
1026
|
-
return {
|
|
1027
|
-
content: [
|
|
1028
|
-
{
|
|
1029
|
-
type: "text",
|
|
1030
|
-
text: JSON.stringify(
|
|
1031
|
-
{
|
|
1032
|
-
error: error instanceof Error ? error.message : "Failed to render HTML file"
|
|
1033
|
-
},
|
|
1034
|
-
null,
|
|
1035
|
-
2
|
|
1036
|
-
)
|
|
1037
|
-
}
|
|
1038
|
-
],
|
|
1039
|
-
isError: true
|
|
1040
|
-
};
|
|
914
|
+
const toolName = resourceToTool[uri];
|
|
915
|
+
if (!toolName) {
|
|
916
|
+
throw new Error(`No tool mapping for resource: ${uri}`);
|
|
917
|
+
}
|
|
918
|
+
const result = await dispatch(toolName, {}, dispatchOptions(ctx));
|
|
919
|
+
if (result.isError) {
|
|
920
|
+
const message = result.content[0]?.text ?? "Unknown error";
|
|
921
|
+
throw new Error(`Failed to fetch resource: ${message}`);
|
|
1041
922
|
}
|
|
923
|
+
const text = result.content[0]?.text ?? "";
|
|
924
|
+
return {
|
|
925
|
+
contents: [
|
|
926
|
+
{
|
|
927
|
+
uri,
|
|
928
|
+
mimeType: resource.mimeType,
|
|
929
|
+
text
|
|
930
|
+
}
|
|
931
|
+
]
|
|
932
|
+
};
|
|
1042
933
|
}
|
|
1043
934
|
|
|
1044
935
|
// src/index.ts
|
|
@@ -1048,13 +939,22 @@ var apiConfig = {
|
|
|
1048
939
|
apiUrl: API_URL,
|
|
1049
940
|
apiKey: API_KEY
|
|
1050
941
|
};
|
|
942
|
+
var handlerContext = {
|
|
943
|
+
apiConfig,
|
|
944
|
+
endpoints: toolEndpoints
|
|
945
|
+
};
|
|
1051
946
|
var isHttpMode = process.argv.includes("--http") || process.env.WIREWEAVE_TRANSPORT === "http";
|
|
1052
947
|
var HTTP_PORT = parseInt(process.env.WIREWEAVE_MCP_PORT || "3305", 10);
|
|
1053
948
|
var HTTP_HOST = process.env.WIREWEAVE_MCP_HOST || "127.0.0.1";
|
|
1054
949
|
function log(message, level = "info") {
|
|
1055
950
|
const prefix = level === "error" ? "\u274C" : level === "warn" ? "\u26A0\uFE0F" : "\u2713";
|
|
1056
|
-
const
|
|
1057
|
-
|
|
951
|
+
const line = `[Wireweave] ${prefix} ${message}
|
|
952
|
+
`;
|
|
953
|
+
if (isHttpMode) {
|
|
954
|
+
process.stdout.write(line);
|
|
955
|
+
} else {
|
|
956
|
+
process.stderr.write(line);
|
|
957
|
+
}
|
|
1058
958
|
}
|
|
1059
959
|
function createMcpServer() {
|
|
1060
960
|
const server = new Server(
|
|
@@ -1070,119 +970,20 @@ function createMcpServer() {
|
|
|
1070
970
|
}
|
|
1071
971
|
}
|
|
1072
972
|
);
|
|
1073
|
-
server.setRequestHandler(ListToolsRequestSchema,
|
|
1074
|
-
return { tools: [...tools, ...localTools] };
|
|
1075
|
-
});
|
|
973
|
+
server.setRequestHandler(ListToolsRequestSchema, () => handleListTools());
|
|
1076
974
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
1077
975
|
const { name, arguments: args } = request.params;
|
|
1078
|
-
|
|
1079
|
-
return handleLocalTool(name, args, apiConfig);
|
|
1080
|
-
}
|
|
1081
|
-
const endpoint = toolEndpoints[name];
|
|
1082
|
-
if (!endpoint) {
|
|
1083
|
-
const allTools = [...tools, ...localTools];
|
|
1084
|
-
return {
|
|
1085
|
-
content: [
|
|
1086
|
-
{
|
|
1087
|
-
type: "text",
|
|
1088
|
-
text: JSON.stringify({
|
|
1089
|
-
error: `Unknown tool: ${name}`,
|
|
1090
|
-
availableTools: allTools.map((t) => t.name)
|
|
1091
|
-
}, null, 2)
|
|
1092
|
-
}
|
|
1093
|
-
],
|
|
1094
|
-
isError: true
|
|
1095
|
-
};
|
|
1096
|
-
}
|
|
1097
|
-
try {
|
|
1098
|
-
const result = await callApi(apiConfig, endpoint, args);
|
|
1099
|
-
return {
|
|
1100
|
-
content: [
|
|
1101
|
-
{
|
|
1102
|
-
type: "text",
|
|
1103
|
-
text: JSON.stringify(result, null, 2)
|
|
1104
|
-
}
|
|
1105
|
-
]
|
|
1106
|
-
};
|
|
1107
|
-
} catch (error) {
|
|
1108
|
-
return {
|
|
1109
|
-
content: [
|
|
1110
|
-
{
|
|
1111
|
-
type: "text",
|
|
1112
|
-
text: JSON.stringify({
|
|
1113
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
1114
|
-
}, null, 2)
|
|
1115
|
-
}
|
|
1116
|
-
],
|
|
1117
|
-
isError: true
|
|
1118
|
-
};
|
|
1119
|
-
}
|
|
976
|
+
return handleCallTool(name, args, handlerContext);
|
|
1120
977
|
});
|
|
1121
|
-
server.setRequestHandler(ListPromptsRequestSchema,
|
|
1122
|
-
|
|
1123
|
-
});
|
|
1124
|
-
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
978
|
+
server.setRequestHandler(ListPromptsRequestSchema, () => handleListPrompts());
|
|
979
|
+
server.setRequestHandler(GetPromptRequestSchema, (request) => {
|
|
1125
980
|
const { name, arguments: args } = request.params;
|
|
1126
|
-
|
|
1127
|
-
if (!prompt) {
|
|
1128
|
-
throw new Error(`Prompt not found: ${name}`);
|
|
1129
|
-
}
|
|
1130
|
-
const template = promptTemplates[name];
|
|
1131
|
-
if (!template) {
|
|
1132
|
-
throw new Error(`Prompt template not found: ${name}`);
|
|
1133
|
-
}
|
|
1134
|
-
let messageText = template;
|
|
1135
|
-
if (args) {
|
|
1136
|
-
for (const [key, value] of Object.entries(args)) {
|
|
1137
|
-
messageText = messageText.replace(new RegExp(`\\{\\{${key}\\}\\}`, "g"), String(value));
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
messageText = messageText.replace(/\{\{[^}]+\}\}/g, "");
|
|
1141
|
-
return {
|
|
1142
|
-
description: prompt.description,
|
|
1143
|
-
messages: [
|
|
1144
|
-
{
|
|
1145
|
-
role: "user",
|
|
1146
|
-
content: {
|
|
1147
|
-
type: "text",
|
|
1148
|
-
text: messageText
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
]
|
|
1152
|
-
};
|
|
1153
|
-
});
|
|
1154
|
-
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
1155
|
-
return { resources };
|
|
981
|
+
return handleGetPrompt(name, args);
|
|
1156
982
|
});
|
|
983
|
+
server.setRequestHandler(ListResourcesRequestSchema, () => handleListResources());
|
|
1157
984
|
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
1158
985
|
const { uri } = request.params;
|
|
1159
|
-
|
|
1160
|
-
if (!resource) {
|
|
1161
|
-
throw new Error(`Resource not found: ${uri}`);
|
|
1162
|
-
}
|
|
1163
|
-
const toolName = resourceToTool[uri];
|
|
1164
|
-
if (!toolName) {
|
|
1165
|
-
throw new Error(`No tool mapping for resource: ${uri}`);
|
|
1166
|
-
}
|
|
1167
|
-
const endpoint = toolEndpoints[toolName];
|
|
1168
|
-
if (!endpoint) {
|
|
1169
|
-
throw new Error(`Tool endpoint not found: ${toolName}`);
|
|
1170
|
-
}
|
|
1171
|
-
try {
|
|
1172
|
-
const result = await callApi(apiConfig, endpoint, {});
|
|
1173
|
-
const content = typeof result === "string" ? result : JSON.stringify(result, null, 2);
|
|
1174
|
-
return {
|
|
1175
|
-
contents: [
|
|
1176
|
-
{
|
|
1177
|
-
uri,
|
|
1178
|
-
mimeType: resource.mimeType,
|
|
1179
|
-
text: content
|
|
1180
|
-
}
|
|
1181
|
-
]
|
|
1182
|
-
};
|
|
1183
|
-
} catch (error) {
|
|
1184
|
-
throw new Error(`Failed to fetch resource: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1185
|
-
}
|
|
986
|
+
return handleReadResource(uri, handlerContext);
|
|
1186
987
|
});
|
|
1187
988
|
server.onerror = () => {
|
|
1188
989
|
log("An error occurred", "error");
|
|
@@ -1193,91 +994,109 @@ async function startStdio() {
|
|
|
1193
994
|
const server = createMcpServer();
|
|
1194
995
|
const transport = new StdioServerTransport();
|
|
1195
996
|
await server.connect(transport);
|
|
1196
|
-
process.on("SIGINT",
|
|
1197
|
-
|
|
1198
|
-
|
|
997
|
+
process.on("SIGINT", () => {
|
|
998
|
+
void (async () => {
|
|
999
|
+
await server.close();
|
|
1000
|
+
process.exit(0);
|
|
1001
|
+
})();
|
|
1199
1002
|
});
|
|
1200
|
-
log(
|
|
1003
|
+
log(
|
|
1004
|
+
`MCP server started (stdio) with ${tools.length} tools (${localToolNames.size} local + ${tools.length - localToolNames.size} server), ${prompts.length} prompts, ${resources.length} resources`
|
|
1005
|
+
);
|
|
1201
1006
|
if (!API_KEY) {
|
|
1202
1007
|
log("API key not configured. Get one at https://wireweave.org", "warn");
|
|
1203
1008
|
}
|
|
1204
1009
|
}
|
|
1205
|
-
|
|
1010
|
+
function startHttp() {
|
|
1206
1011
|
const transports = /* @__PURE__ */ new Map();
|
|
1207
|
-
const httpServer = createServer(
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
if (url.pathname
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1012
|
+
const httpServer = createServer((req, res) => {
|
|
1013
|
+
void (async () => {
|
|
1014
|
+
const url = new URL(req.url || "/", `http://${req.headers.host}`);
|
|
1015
|
+
if (url.pathname !== "/mcp") {
|
|
1016
|
+
if (url.pathname === "/health") {
|
|
1017
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1018
|
+
res.end(
|
|
1019
|
+
JSON.stringify({
|
|
1020
|
+
status: "ok",
|
|
1021
|
+
transport: "streamable-http",
|
|
1022
|
+
activeSessions: transports.size,
|
|
1023
|
+
tools: tools.length
|
|
1024
|
+
})
|
|
1025
|
+
);
|
|
1026
|
+
return;
|
|
1027
|
+
}
|
|
1028
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1029
|
+
res.end(JSON.stringify({ error: "Not found. Use /mcp for MCP protocol." }));
|
|
1218
1030
|
return;
|
|
1219
1031
|
}
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
if (sessionId && transports.has(sessionId)) {
|
|
1226
|
-
const existing = transports.get(sessionId);
|
|
1227
|
-
await existing.transport.handleRequest(req, res);
|
|
1228
|
-
return;
|
|
1229
|
-
}
|
|
1230
|
-
if (req.method === "DELETE") {
|
|
1231
|
-
res.writeHead(404);
|
|
1232
|
-
res.end();
|
|
1233
|
-
return;
|
|
1234
|
-
}
|
|
1235
|
-
if (req.method !== "POST") {
|
|
1236
|
-
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1237
|
-
res.end(JSON.stringify({ error: "Session required. Send an initialization POST first." }));
|
|
1238
|
-
return;
|
|
1239
|
-
}
|
|
1240
|
-
const MAX_SESSIONS = parseInt(process.env.WIREWEAVE_MCP_MAX_SESSIONS || "10", 10);
|
|
1241
|
-
if (transports.size >= MAX_SESSIONS) {
|
|
1242
|
-
res.writeHead(503, { "Content-Type": "application/json" });
|
|
1243
|
-
res.end(JSON.stringify({ error: "Too many active sessions" }));
|
|
1244
|
-
return;
|
|
1245
|
-
}
|
|
1246
|
-
const server = createMcpServer();
|
|
1247
|
-
const transport = new StreamableHTTPServerTransport({
|
|
1248
|
-
sessionIdGenerator: () => randomUUID(),
|
|
1249
|
-
onsessioninitialized: (sessionId2) => {
|
|
1250
|
-
transports.set(sessionId2, { server, transport });
|
|
1251
|
-
log(`New session: ${sessionId2}`);
|
|
1032
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
1033
|
+
if (sessionId && transports.has(sessionId)) {
|
|
1034
|
+
const existing = transports.get(sessionId);
|
|
1035
|
+
await existing.transport.handleRequest(req, res);
|
|
1036
|
+
return;
|
|
1252
1037
|
}
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1038
|
+
if (req.method === "DELETE") {
|
|
1039
|
+
res.writeHead(404);
|
|
1040
|
+
res.end();
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
if (req.method !== "POST") {
|
|
1044
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1045
|
+
res.end(JSON.stringify({ error: "Session required. Send an initialization POST first." }));
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
const MAX_SESSIONS = parseInt(process.env.WIREWEAVE_MCP_MAX_SESSIONS || "10", 10);
|
|
1049
|
+
if (transports.size >= MAX_SESSIONS) {
|
|
1050
|
+
res.writeHead(503, { "Content-Type": "application/json" });
|
|
1051
|
+
res.end(JSON.stringify({ error: "Too many active sessions" }));
|
|
1052
|
+
return;
|
|
1258
1053
|
}
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1054
|
+
const server = createMcpServer();
|
|
1055
|
+
const transport = new StreamableHTTPServerTransport({
|
|
1056
|
+
sessionIdGenerator: () => randomUUID(),
|
|
1057
|
+
onsessioninitialized: (sessionId2) => {
|
|
1058
|
+
transports.set(sessionId2, { server, transport });
|
|
1059
|
+
log(`New session: ${sessionId2}`);
|
|
1060
|
+
}
|
|
1061
|
+
});
|
|
1062
|
+
transport.onclose = () => {
|
|
1063
|
+
if (transport.sessionId) {
|
|
1064
|
+
transports.delete(transport.sessionId);
|
|
1065
|
+
log(`Session closed: ${transport.sessionId}`);
|
|
1066
|
+
}
|
|
1067
|
+
};
|
|
1068
|
+
await server.connect(transport);
|
|
1069
|
+
await transport.handleRequest(req, res);
|
|
1070
|
+
})();
|
|
1262
1071
|
});
|
|
1263
1072
|
httpServer.listen(HTTP_PORT, HTTP_HOST, () => {
|
|
1264
1073
|
log(`MCP server started (streamable-http) at http://${HTTP_HOST}:${HTTP_PORT}/mcp`);
|
|
1265
1074
|
log(`Health check: http://${HTTP_HOST}:${HTTP_PORT}/health`);
|
|
1266
|
-
log(
|
|
1075
|
+
log(
|
|
1076
|
+
`${tools.length} tools (${localToolNames.size} local + ${tools.length - localToolNames.size} server), ${prompts.length} prompts, ${resources.length} resources`
|
|
1077
|
+
);
|
|
1267
1078
|
if (!API_KEY) {
|
|
1268
1079
|
log("API key not configured. Get one at https://wireweave.org", "warn");
|
|
1269
1080
|
}
|
|
1270
1081
|
});
|
|
1271
|
-
process.on("SIGINT",
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1082
|
+
process.on("SIGINT", () => {
|
|
1083
|
+
void (async () => {
|
|
1084
|
+
log("Shutting down...");
|
|
1085
|
+
for (const [, { server }] of transports) {
|
|
1086
|
+
await server.close();
|
|
1087
|
+
}
|
|
1088
|
+
httpServer.close();
|
|
1089
|
+
process.exit(0);
|
|
1090
|
+
})();
|
|
1278
1091
|
});
|
|
1279
1092
|
}
|
|
1280
|
-
|
|
1093
|
+
async function main() {
|
|
1094
|
+
if (isHttpMode) {
|
|
1095
|
+
startHttp();
|
|
1096
|
+
} else {
|
|
1097
|
+
await startStdio();
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1281
1100
|
main().catch(() => {
|
|
1282
1101
|
log("Failed to start server", "error");
|
|
1283
1102
|
process.exit(1);
|