@wevi/mcp 0.1.2 → 0.2.2
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 +21 -0
- package/README.md +48 -25
- package/dist/chunk-YQ5AW3YY.js +798 -0
- package/dist/chunk-YQ5AW3YY.js.map +1 -0
- package/dist/http.d.ts +2 -0
- package/dist/http.js +148 -0
- package/dist/http.js.map +1 -0
- package/dist/index.js +21 -547
- package/dist/index.js.map +1 -1
- package/package.json +8 -4
package/dist/index.js
CHANGED
|
@@ -1,552 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
WeviApiClient,
|
|
4
|
+
buildServerInstructions,
|
|
5
|
+
registerAllTools
|
|
6
|
+
} from "./chunk-YQ5AW3YY.js";
|
|
2
7
|
|
|
3
8
|
// src/index.ts
|
|
4
9
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
10
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
11
|
import dotenv from "dotenv";
|
|
7
|
-
|
|
8
|
-
// src/client/wevi-api-client.ts
|
|
9
|
-
var WeviApiClient = class {
|
|
10
|
-
apiKey;
|
|
11
|
-
baseUrl;
|
|
12
|
-
constructor(config) {
|
|
13
|
-
this.apiKey = config.apiKey.trim();
|
|
14
|
-
this.baseUrl = config.apiUrl.replace(/\/+$/, "");
|
|
15
|
-
}
|
|
16
|
-
get headers() {
|
|
17
|
-
return {
|
|
18
|
-
"Content-Type": "application/json",
|
|
19
|
-
"X-API-Key": this.apiKey,
|
|
20
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
21
|
-
"User-Agent": "Wevi-MCP-Server/0.1.0"
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
async request(endpoint, options = {}) {
|
|
25
|
-
const url = `${this.baseUrl}${endpoint.startsWith("/") ? "" : "/"}${endpoint}`;
|
|
26
|
-
let response;
|
|
27
|
-
try {
|
|
28
|
-
response = await fetch(url, {
|
|
29
|
-
...options,
|
|
30
|
-
headers: {
|
|
31
|
-
...this.headers,
|
|
32
|
-
...options.headers || {}
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
} catch (err) {
|
|
36
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
37
|
-
throw new Error(
|
|
38
|
-
`Failed to connect to Wevi API at ${this.baseUrl}: ${msg}`
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
if (!response.ok) {
|
|
42
|
-
let errorBody = {};
|
|
43
|
-
try {
|
|
44
|
-
errorBody = await response.json();
|
|
45
|
-
} catch {
|
|
46
|
-
}
|
|
47
|
-
const errObj = errorBody.error;
|
|
48
|
-
const message = typeof errorBody.message === "string" && errorBody.message || typeof errObj === "string" && errObj || typeof errObj === "object" && errObj !== null && typeof errObj.message === "string" && errObj.message || `Wevi API error (${response.status} ${response.statusText})`;
|
|
49
|
-
if (response.status === 402) {
|
|
50
|
-
throw new Error(
|
|
51
|
-
`[402 Payment Required] Render credit limit reached. Please upgrade your plan at https://app.wevi.ai/settings/billing to continue rendering.
|
|
52
|
-
Details: ${message}`
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
if (response.status === 401) {
|
|
56
|
-
throw new Error(
|
|
57
|
-
`[401 Unauthorized] Invalid or revoked Wevi API key. Please check your WEVI_API_KEY in settings at https://app.wevi.ai/settings/api-keys.`
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
throw new Error(`[Wevi API Error ${response.status}] ${message}`);
|
|
61
|
-
}
|
|
62
|
-
if (response.status === 204) {
|
|
63
|
-
return {};
|
|
64
|
-
}
|
|
65
|
-
return await response.json();
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Lists published templates with optional filtering.
|
|
69
|
-
*/
|
|
70
|
-
async listTemplates(params) {
|
|
71
|
-
const query = new URLSearchParams();
|
|
72
|
-
if (params?.category) query.set("category", params.category);
|
|
73
|
-
if (params?.aspectRatio) query.set("aspectRatio", params.aspectRatio);
|
|
74
|
-
if (params?.search) query.set("search", params.search);
|
|
75
|
-
if (params?.limit) query.set("limit", String(params.limit));
|
|
76
|
-
if (params?.page) query.set("page", String(params.page));
|
|
77
|
-
const qs = query.toString();
|
|
78
|
-
const endpoint = `/templates${qs ? `?${qs}` : ""}`;
|
|
79
|
-
const result = await this.request(endpoint);
|
|
80
|
-
const rawData = result?.data ?? result;
|
|
81
|
-
const items = Array.isArray(rawData) ? rawData : Array.isArray(rawData?.templates) ? rawData.templates : Array.isArray(rawData?.items) ? rawData.items : [];
|
|
82
|
-
const total = rawData?.meta?.total ?? result?.total ?? rawData?.total ?? items.length;
|
|
83
|
-
return { items, total };
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Retrieves full template details including editable dynamic layers.
|
|
87
|
-
*/
|
|
88
|
-
async getTemplate(templateId) {
|
|
89
|
-
const res = await this.request(
|
|
90
|
-
`/templates/${encodeURIComponent(templateId)}`
|
|
91
|
-
);
|
|
92
|
-
return res?.data ?? res;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Creates a draft video project with template parameters.
|
|
96
|
-
*/
|
|
97
|
-
async createProject(data) {
|
|
98
|
-
const res = await this.request("/projects", {
|
|
99
|
-
method: "POST",
|
|
100
|
-
body: JSON.stringify(data)
|
|
101
|
-
});
|
|
102
|
-
return res?.data ?? res;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Retrieves project details and current render state.
|
|
106
|
-
*/
|
|
107
|
-
async getProject(projectId) {
|
|
108
|
-
const res = await this.request(
|
|
109
|
-
`/projects/${encodeURIComponent(projectId)}`
|
|
110
|
-
);
|
|
111
|
-
return res?.data?.project ?? res?.data ?? res;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Triggers a high-definition video render export.
|
|
115
|
-
*/
|
|
116
|
-
async triggerRender(projectId) {
|
|
117
|
-
const res = await this.request(
|
|
118
|
-
`/exports/projects/${encodeURIComponent(projectId)}`,
|
|
119
|
-
{
|
|
120
|
-
method: "POST",
|
|
121
|
-
body: JSON.stringify({ quality: "1080p" })
|
|
122
|
-
}
|
|
123
|
-
);
|
|
124
|
-
const exportData = res?.data?.export ?? res?.export ?? res?.data ?? res;
|
|
125
|
-
const exportId = exportData?.id ?? exportData?.exportId ?? "";
|
|
126
|
-
const status = exportData?.status ?? "QUEUED";
|
|
127
|
-
return {
|
|
128
|
-
id: exportId,
|
|
129
|
-
exportId,
|
|
130
|
-
status
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Checks the status of an ongoing render export.
|
|
135
|
-
*/
|
|
136
|
-
async getRenderStatus(exportId) {
|
|
137
|
-
const res = await this.request(
|
|
138
|
-
`/exports/${encodeURIComponent(exportId)}`
|
|
139
|
-
);
|
|
140
|
-
return res?.data?.export ?? res?.data ?? res;
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Polls render export status until complete (SUCCESS or FAILED) or timed out.
|
|
144
|
-
*/
|
|
145
|
-
async pollRenderUntilComplete(exportId, timeoutSeconds = 90, pollIntervalMs = 3e3) {
|
|
146
|
-
const startTime = Date.now();
|
|
147
|
-
const maxDurationMs = timeoutSeconds * 1e3;
|
|
148
|
-
while (Date.now() - startTime < maxDurationMs) {
|
|
149
|
-
const status = await this.getRenderStatus(exportId);
|
|
150
|
-
if (status.status === "SUCCESS" || status.status === "FAILED") {
|
|
151
|
-
return status;
|
|
152
|
-
}
|
|
153
|
-
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
154
|
-
}
|
|
155
|
-
const lastStatus = await this.getRenderStatus(exportId);
|
|
156
|
-
return lastStatus;
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Generates an AI storyboard / copy for a template given a prompt.
|
|
160
|
-
*/
|
|
161
|
-
async generateStoryboard(data) {
|
|
162
|
-
const res = await this.request("/ai/storyboard/draft", {
|
|
163
|
-
method: "POST",
|
|
164
|
-
body: JSON.stringify(data)
|
|
165
|
-
});
|
|
166
|
-
return res?.data?.draft ?? res?.data ?? res;
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Captures a high-resolution screenshot from a live URL.
|
|
170
|
-
*/
|
|
171
|
-
async captureWebUi(data) {
|
|
172
|
-
const res = await this.request(
|
|
173
|
-
"/browse/capture",
|
|
174
|
-
{
|
|
175
|
-
method: "POST",
|
|
176
|
-
body: JSON.stringify(data)
|
|
177
|
-
}
|
|
178
|
-
);
|
|
179
|
-
return res?.data ?? res;
|
|
180
|
-
}
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
// src/tools/templates.tools.ts
|
|
184
|
-
import { z } from "zod";
|
|
185
|
-
function registerTemplateTools(server2, client2) {
|
|
186
|
-
server2.tool(
|
|
187
|
-
"wevi_list_templates",
|
|
188
|
-
"List and search available video templates on Wevi with category, aspect ratio, and keyword filters.",
|
|
189
|
-
{
|
|
190
|
-
category: z.string().optional().describe("Category filter (e.g., 'SaaS', 'E-commerce', 'Social Media', 'Product Promo')"),
|
|
191
|
-
aspectRatio: z.enum(["16:9", "16:12", "4:3"]).optional().describe("Target video aspect ratio: '16:9' (Widescreen landscape 1920x1080) or '16:12' (Desktop app focus frame 1920x1440 / 4:3)"),
|
|
192
|
-
search: z.string().optional().describe("Search keyword matching template titles, tags, or descriptions"),
|
|
193
|
-
limit: z.number().min(1).max(50).optional().default(20).describe("Number of templates to return (default: 20)")
|
|
194
|
-
},
|
|
195
|
-
async (args) => {
|
|
196
|
-
try {
|
|
197
|
-
const result = await client2.listTemplates(args);
|
|
198
|
-
return {
|
|
199
|
-
content: [
|
|
200
|
-
{
|
|
201
|
-
type: "text",
|
|
202
|
-
text: JSON.stringify(
|
|
203
|
-
{
|
|
204
|
-
totalTemplates: result.total,
|
|
205
|
-
templates: result.items.map((t) => ({
|
|
206
|
-
id: t.id,
|
|
207
|
-
name: t.name,
|
|
208
|
-
slug: t.slug,
|
|
209
|
-
description: t.description,
|
|
210
|
-
aspectRatio: t.aspectRatio,
|
|
211
|
-
durationSeconds: t.durationSeconds,
|
|
212
|
-
tags: t.tags,
|
|
213
|
-
previewVideoUrl: t.previewVideoUrl,
|
|
214
|
-
thumbnailUrl: t.thumbnailUrl
|
|
215
|
-
}))
|
|
216
|
-
},
|
|
217
|
-
null,
|
|
218
|
-
2
|
|
219
|
-
)
|
|
220
|
-
}
|
|
221
|
-
]
|
|
222
|
-
};
|
|
223
|
-
} catch (err) {
|
|
224
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
225
|
-
return {
|
|
226
|
-
isError: true,
|
|
227
|
-
content: [{ type: "text", text: `Error listing templates: ${msg}` }]
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
);
|
|
232
|
-
server2.tool(
|
|
233
|
-
"wevi_get_template_schema",
|
|
234
|
-
"Inspect the dynamic layer variables for a specific Wevi video template (e.g. text variables, color variables, logos, background videos). Use this before creating a project to know what parameters the template expects.",
|
|
235
|
-
{
|
|
236
|
-
templateId: z.string().describe("The unique ID or slug of the Wevi video template")
|
|
237
|
-
},
|
|
238
|
-
async (args) => {
|
|
239
|
-
try {
|
|
240
|
-
const template = await client2.getTemplate(args.templateId);
|
|
241
|
-
return {
|
|
242
|
-
content: [
|
|
243
|
-
{
|
|
244
|
-
type: "text",
|
|
245
|
-
text: JSON.stringify(
|
|
246
|
-
{
|
|
247
|
-
id: template.id,
|
|
248
|
-
name: template.name,
|
|
249
|
-
slug: template.slug,
|
|
250
|
-
aspectRatio: template.aspectRatio,
|
|
251
|
-
durationSeconds: template.durationSeconds,
|
|
252
|
-
description: template.description,
|
|
253
|
-
editableLayers: template.layers || []
|
|
254
|
-
},
|
|
255
|
-
null,
|
|
256
|
-
2
|
|
257
|
-
)
|
|
258
|
-
}
|
|
259
|
-
]
|
|
260
|
-
};
|
|
261
|
-
} catch (err) {
|
|
262
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
263
|
-
return {
|
|
264
|
-
isError: true,
|
|
265
|
-
content: [{ type: "text", text: `Error fetching template schema: ${msg}` }]
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// src/tools/projects.tools.ts
|
|
273
|
-
import { z as z2 } from "zod";
|
|
274
|
-
function registerProjectTools(server2, client2) {
|
|
275
|
-
server2.tool(
|
|
276
|
-
"wevi_create_project",
|
|
277
|
-
"Create a new video project on Wevi using a chosen template ID and initial layer parameters (such as headlines, descriptions, colors, logos, and animation settings).",
|
|
278
|
-
{
|
|
279
|
-
templateId: z2.string().describe("The ID of the template to base the project on"),
|
|
280
|
-
title: z2.string().optional().describe("Optional project title (e.g., 'Product Promo Q3')"),
|
|
281
|
-
parameters: z2.record(z2.string(), z2.any()).optional().describe("Dynamic parameter key-value pairs matching the template's editable layers (e.g. { TXTTYPINGVAR: 'New AI Features', CLRTEXTTYPINGVAR: '#F8FAFC' })")
|
|
282
|
-
},
|
|
283
|
-
async (args) => {
|
|
284
|
-
try {
|
|
285
|
-
const project = await client2.createProject(args);
|
|
286
|
-
return {
|
|
287
|
-
content: [
|
|
288
|
-
{
|
|
289
|
-
type: "text",
|
|
290
|
-
text: JSON.stringify(
|
|
291
|
-
{
|
|
292
|
-
message: "Project created successfully",
|
|
293
|
-
projectId: project.id,
|
|
294
|
-
title: project.title,
|
|
295
|
-
status: project.status,
|
|
296
|
-
aspectRatio: project.aspectRatio,
|
|
297
|
-
parameters: project.parameters
|
|
298
|
-
},
|
|
299
|
-
null,
|
|
300
|
-
2
|
|
301
|
-
)
|
|
302
|
-
}
|
|
303
|
-
]
|
|
304
|
-
};
|
|
305
|
-
} catch (err) {
|
|
306
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
307
|
-
return {
|
|
308
|
-
isError: true,
|
|
309
|
-
content: [{ type: "text", text: `Error creating project: ${msg}` }]
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
);
|
|
314
|
-
server2.tool(
|
|
315
|
-
"wevi_get_project",
|
|
316
|
-
"Inspect an existing Wevi project's details, configuration parameters, and status.",
|
|
317
|
-
{
|
|
318
|
-
projectId: z2.string().describe("The unique ID of the Wevi project")
|
|
319
|
-
},
|
|
320
|
-
async (args) => {
|
|
321
|
-
try {
|
|
322
|
-
const project = await client2.getProject(args.projectId);
|
|
323
|
-
return {
|
|
324
|
-
content: [
|
|
325
|
-
{
|
|
326
|
-
type: "text",
|
|
327
|
-
text: JSON.stringify(project, null, 2)
|
|
328
|
-
}
|
|
329
|
-
]
|
|
330
|
-
};
|
|
331
|
-
} catch (err) {
|
|
332
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
333
|
-
return {
|
|
334
|
-
isError: true,
|
|
335
|
-
content: [{ type: "text", text: `Error fetching project: ${msg}` }]
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// src/tools/renders.tools.ts
|
|
343
|
-
import { z as z3 } from "zod";
|
|
344
|
-
function registerRenderTools(server2, client2) {
|
|
345
|
-
server2.tool(
|
|
346
|
-
"wevi_trigger_render",
|
|
347
|
-
"Trigger high-quality video rendering for a Wevi project. Supports auto-polling so the tool can wait and return the final MP4 video link directly in one step.",
|
|
348
|
-
{
|
|
349
|
-
projectId: z3.string().describe("The ID of the project to render"),
|
|
350
|
-
pollUntilComplete: z3.boolean().optional().default(true).describe("If true (default), waits for the render to complete before returning the final MP4 download URL."),
|
|
351
|
-
timeoutSeconds: z3.number().min(10).max(300).optional().default(90).describe("Maximum seconds to wait if pollUntilComplete is true (default: 90)")
|
|
352
|
-
},
|
|
353
|
-
async (args) => {
|
|
354
|
-
try {
|
|
355
|
-
const triggerRes = await client2.triggerRender(args.projectId);
|
|
356
|
-
const exportId = triggerRes.exportId || triggerRes.id;
|
|
357
|
-
if (!exportId) {
|
|
358
|
-
return {
|
|
359
|
-
content: [
|
|
360
|
-
{
|
|
361
|
-
type: "text",
|
|
362
|
-
text: JSON.stringify(triggerRes, null, 2)
|
|
363
|
-
}
|
|
364
|
-
]
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
if (args.pollUntilComplete) {
|
|
368
|
-
const finalStatus = await client2.pollRenderUntilComplete(
|
|
369
|
-
exportId,
|
|
370
|
-
args.timeoutSeconds
|
|
371
|
-
);
|
|
372
|
-
if (finalStatus.status === "SUCCESS") {
|
|
373
|
-
return {
|
|
374
|
-
content: [
|
|
375
|
-
{
|
|
376
|
-
type: "text",
|
|
377
|
-
text: JSON.stringify(
|
|
378
|
-
{
|
|
379
|
-
status: "SUCCESS",
|
|
380
|
-
message: "Video rendered successfully!",
|
|
381
|
-
exportId: finalStatus.id,
|
|
382
|
-
videoUrl: finalStatus.videoUrl,
|
|
383
|
-
thumbnailUrl: finalStatus.thumbnailUrl,
|
|
384
|
-
completedAt: finalStatus.completedAt
|
|
385
|
-
},
|
|
386
|
-
null,
|
|
387
|
-
2
|
|
388
|
-
)
|
|
389
|
-
}
|
|
390
|
-
]
|
|
391
|
-
};
|
|
392
|
-
}
|
|
393
|
-
if (finalStatus.status === "FAILED") {
|
|
394
|
-
return {
|
|
395
|
-
isError: true,
|
|
396
|
-
content: [
|
|
397
|
-
{
|
|
398
|
-
type: "text",
|
|
399
|
-
text: `Render failed: ${finalStatus.errorMessage || "Unknown render error"}`
|
|
400
|
-
}
|
|
401
|
-
]
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
return {
|
|
405
|
-
content: [
|
|
406
|
-
{
|
|
407
|
-
type: "text",
|
|
408
|
-
text: JSON.stringify(
|
|
409
|
-
{
|
|
410
|
-
status: finalStatus.status,
|
|
411
|
-
message: "Render is still processing in background. You can check status later using wevi_get_render_status.",
|
|
412
|
-
exportId: finalStatus.id
|
|
413
|
-
},
|
|
414
|
-
null,
|
|
415
|
-
2
|
|
416
|
-
)
|
|
417
|
-
}
|
|
418
|
-
]
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
|
-
return {
|
|
422
|
-
content: [
|
|
423
|
-
{
|
|
424
|
-
type: "text",
|
|
425
|
-
text: JSON.stringify(
|
|
426
|
-
{
|
|
427
|
-
message: "Render queued successfully",
|
|
428
|
-
exportId,
|
|
429
|
-
status: triggerRes.status || "QUEUED"
|
|
430
|
-
},
|
|
431
|
-
null,
|
|
432
|
-
2
|
|
433
|
-
)
|
|
434
|
-
}
|
|
435
|
-
]
|
|
436
|
-
};
|
|
437
|
-
} catch (err) {
|
|
438
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
439
|
-
return {
|
|
440
|
-
isError: true,
|
|
441
|
-
content: [{ type: "text", text: `Error triggering render: ${msg}` }]
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
);
|
|
446
|
-
server2.tool(
|
|
447
|
-
"wevi_get_render_status",
|
|
448
|
-
"Check the real-time status and download URL of an active or completed video export.",
|
|
449
|
-
{
|
|
450
|
-
exportId: z3.string().describe("The unique ID of the export render")
|
|
451
|
-
},
|
|
452
|
-
async (args) => {
|
|
453
|
-
try {
|
|
454
|
-
const status = await client2.getRenderStatus(args.exportId);
|
|
455
|
-
return {
|
|
456
|
-
content: [
|
|
457
|
-
{
|
|
458
|
-
type: "text",
|
|
459
|
-
text: JSON.stringify(status, null, 2)
|
|
460
|
-
}
|
|
461
|
-
]
|
|
462
|
-
};
|
|
463
|
-
} catch (err) {
|
|
464
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
465
|
-
return {
|
|
466
|
-
isError: true,
|
|
467
|
-
content: [{ type: "text", text: `Error checking render status: ${msg}` }]
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
);
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
// src/tools/ai.tools.ts
|
|
475
|
-
import { z as z4 } from "zod";
|
|
476
|
-
function registerAiTools(server2, client2) {
|
|
477
|
-
server2.tool(
|
|
478
|
-
"wevi_generate_storyboard",
|
|
479
|
-
"Generate tailored video script, headline, and copywriting variables for a Wevi template based on a user prompt or product URL.",
|
|
480
|
-
{
|
|
481
|
-
prompt: z4.string().describe("The marketing goal, product description, or topic for the video (e.g. '30-second SaaS promo highlighting AI-powered email writing')"),
|
|
482
|
-
templateId: z4.string().optional().describe("Optional template ID to shape the storyboard to specific scene layers"),
|
|
483
|
-
brandUrl: z4.string().url().optional().describe("Optional website URL to extract brand context from")
|
|
484
|
-
},
|
|
485
|
-
async (args) => {
|
|
486
|
-
try {
|
|
487
|
-
const result = await client2.generateStoryboard(args);
|
|
488
|
-
return {
|
|
489
|
-
content: [
|
|
490
|
-
{
|
|
491
|
-
type: "text",
|
|
492
|
-
text: JSON.stringify(result, null, 2)
|
|
493
|
-
}
|
|
494
|
-
]
|
|
495
|
-
};
|
|
496
|
-
} catch (err) {
|
|
497
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
498
|
-
return {
|
|
499
|
-
isError: true,
|
|
500
|
-
content: [{ type: "text", text: `Error generating storyboard: ${msg}` }]
|
|
501
|
-
};
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
);
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
// src/tools/browse.tools.ts
|
|
508
|
-
import { z as z5 } from "zod";
|
|
509
|
-
function registerBrowseTools(server2, client2) {
|
|
510
|
-
server2.tool(
|
|
511
|
-
"wevi_capture_web_ui",
|
|
512
|
-
"Capture a clean, high-resolution web screenshot asset from a website URL to use as an image layer in video templates.",
|
|
513
|
-
{
|
|
514
|
-
url: z5.string().url().describe("The website URL to capture (e.g. 'https://stripe.com')"),
|
|
515
|
-
selector: z5.string().optional().describe("Optional CSS selector to crop a specific component or hero element"),
|
|
516
|
-
viewport: z5.enum(["desktop", "mobile", "tablet"]).optional().default("desktop").describe("Target viewport size: 'desktop' (1440x900), 'tablet' (768x1024), or 'mobile' (375x812)")
|
|
517
|
-
},
|
|
518
|
-
async (args) => {
|
|
519
|
-
try {
|
|
520
|
-
const result = await client2.captureWebUi(args);
|
|
521
|
-
return {
|
|
522
|
-
content: [
|
|
523
|
-
{
|
|
524
|
-
type: "text",
|
|
525
|
-
text: JSON.stringify(result, null, 2)
|
|
526
|
-
}
|
|
527
|
-
]
|
|
528
|
-
};
|
|
529
|
-
} catch (err) {
|
|
530
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
531
|
-
return {
|
|
532
|
-
isError: true,
|
|
533
|
-
content: [{ type: "text", text: `Error capturing web UI: ${msg}` }]
|
|
534
|
-
};
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
);
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
// src/tools/index.ts
|
|
541
|
-
function registerAllTools(server2, client2) {
|
|
542
|
-
registerTemplateTools(server2, client2);
|
|
543
|
-
registerProjectTools(server2, client2);
|
|
544
|
-
registerRenderTools(server2, client2);
|
|
545
|
-
registerAiTools(server2, client2);
|
|
546
|
-
registerBrowseTools(server2, client2);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
// src/index.ts
|
|
550
12
|
dotenv.config();
|
|
551
13
|
var apiKey = process.env.WEVI_API_KEY;
|
|
552
14
|
var apiUrl = process.env.WEVI_API_URL || "https://api-v2.wevi.ai/api/v2";
|
|
@@ -559,10 +21,22 @@ var client = new WeviApiClient({
|
|
|
559
21
|
apiKey: apiKey || "",
|
|
560
22
|
apiUrl
|
|
561
23
|
});
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
24
|
+
if (client.isSandbox) {
|
|
25
|
+
process.stderr.write(
|
|
26
|
+
"[Wevi MCP] Sandbox key detected (wevi_test_): renders are watermarked, capped at 720p and do not use credits.\n"
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
var server = new McpServer(
|
|
30
|
+
{
|
|
31
|
+
name: "wevi",
|
|
32
|
+
version: "0.2.1"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
// Sent to the client on connect; assistants that honour MCP instructions
|
|
36
|
+
// learn what Wevi can and cannot make before the first tool call.
|
|
37
|
+
instructions: buildServerInstructions()
|
|
38
|
+
}
|
|
39
|
+
);
|
|
566
40
|
registerAllTools(server, client);
|
|
567
41
|
async function main() {
|
|
568
42
|
const transport = new StdioServerTransport();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/client/wevi-api-client.ts","../src/tools/templates.tools.ts","../src/tools/projects.tools.ts","../src/tools/renders.tools.ts","../src/tools/ai.tools.ts","../src/tools/browse.tools.ts","../src/tools/index.ts"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport dotenv from \"dotenv\";\nimport { WeviApiClient } from \"./client/wevi-api-client.js\";\nimport { registerAllTools } from \"./tools/index.js\";\n\ndotenv.config();\n\nconst apiKey = process.env.WEVI_API_KEY;\nconst apiUrl = process.env.WEVI_API_URL || \"https://api-v2.wevi.ai/api/v2\";\n\nif (!apiKey) {\n process.stderr.write(\n \"[Wevi MCP Warning] WEVI_API_KEY is not set. MCP tools will fail until an API key is provided in your MCP configuration.\\nGet your key at: https://app.wevi.ai/app/profile?id=api-keys\\n\",\n );\n}\n\nconst client = new WeviApiClient({\n apiKey: apiKey || \"\",\n apiUrl,\n});\n\nconst server = new McpServer({\n name: \"wevi\",\n version: \"0.1.0\",\n});\n\n// Register all video automation tools\nregisterAllTools(server, client);\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n process.stderr.write(`[Wevi MCP Server] Started successfully connected to ${apiUrl}\\n`);\n}\n\nmain().catch((error) => {\n process.stderr.write(`[Wevi MCP Server Fatal Error]: ${error}\\n`);\n process.exit(1);\n});\n","import {\n WeviConfig,\n WeviExportStatus,\n WeviProject,\n WeviTemplateSummary,\n} from \"../types/index.js\";\n\nexport class WeviApiClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n\n constructor(config: WeviConfig) {\n this.apiKey = config.apiKey.trim();\n this.baseUrl = config.apiUrl.replace(/\\/+$/, \"\");\n }\n\n private get headers(): Record<string, string> {\n return {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.apiKey,\n Authorization: `Bearer ${this.apiKey}`,\n \"User-Agent\": \"Wevi-MCP-Server/0.1.0\",\n };\n }\n\n private async request<T>(\n endpoint: string,\n options: RequestInit = {},\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint.startsWith(\"/\") ? \"\" : \"/\"}${endpoint}`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n ...options,\n headers: {\n ...this.headers,\n ...(options.headers || {}),\n },\n });\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(\n `Failed to connect to Wevi API at ${this.baseUrl}: ${msg}`,\n );\n }\n\n if (!response.ok) {\n let errorBody: Record<string, unknown> = {};\n try {\n errorBody = (await response.json()) as Record<string, unknown>;\n } catch {\n // non-JSON error\n }\n\n const errObj = errorBody.error;\n const message =\n (typeof errorBody.message === \"string\" && errorBody.message) ||\n (typeof errObj === \"string\" && errObj) ||\n (typeof errObj === \"object\" &&\n errObj !== null &&\n typeof (errObj as any).message === \"string\" &&\n (errObj as any).message) ||\n `Wevi API error (${response.status} ${response.statusText})`;\n\n if (response.status === 402) {\n throw new Error(\n `[402 Payment Required] Render credit limit reached. Please upgrade your plan at https://app.wevi.ai/settings/billing to continue rendering.\\nDetails: ${message}`,\n );\n }\n\n if (response.status === 401) {\n throw new Error(\n `[401 Unauthorized] Invalid or revoked Wevi API key. Please check your WEVI_API_KEY in settings at https://app.wevi.ai/settings/api-keys.`,\n );\n }\n\n throw new Error(`[Wevi API Error ${response.status}] ${message}`);\n }\n\n // 204 No Content\n if (response.status === 204) {\n return {} as T;\n }\n\n return (await response.json()) as T;\n }\n\n /**\n * Lists published templates with optional filtering.\n */\n async listTemplates(params?: {\n category?: string;\n aspectRatio?: string;\n search?: string;\n limit?: number;\n page?: number;\n }): Promise<{ items: WeviTemplateSummary[]; total: number }> {\n const query = new URLSearchParams();\n if (params?.category) query.set(\"category\", params.category);\n if (params?.aspectRatio) query.set(\"aspectRatio\", params.aspectRatio);\n if (params?.search) query.set(\"search\", params.search);\n if (params?.limit) query.set(\"limit\", String(params.limit));\n if (params?.page) query.set(\"page\", String(params.page));\n\n const qs = query.toString();\n const endpoint = `/templates${qs ? `?${qs}` : \"\"}`;\n const result = await this.request<any>(endpoint);\n\n const rawData = result?.data ?? result;\n const items: WeviTemplateSummary[] = Array.isArray(rawData)\n ? rawData\n : Array.isArray(rawData?.templates)\n ? rawData.templates\n : Array.isArray(rawData?.items)\n ? rawData.items\n : [];\n const total: number =\n rawData?.meta?.total ?? result?.total ?? (rawData as any)?.total ?? items.length;\n return { items, total };\n }\n\n /**\n * Retrieves full template details including editable dynamic layers.\n */\n async getTemplate(templateId: string): Promise<WeviTemplateSummary> {\n const res = await this.request<any>(\n `/templates/${encodeURIComponent(templateId)}`,\n );\n return res?.data ?? res;\n }\n\n /**\n * Creates a draft video project with template parameters.\n */\n async createProject(data: {\n templateId: string;\n title?: string;\n parameters?: Record<string, unknown>;\n }): Promise<WeviProject> {\n const res = await this.request<any>(\"/projects\", {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n return res?.data ?? res;\n }\n\n /**\n * Retrieves project details and current render state.\n */\n async getProject(projectId: string): Promise<WeviProject> {\n const res = await this.request<any>(\n `/projects/${encodeURIComponent(projectId)}`,\n );\n return res?.data?.project ?? res?.data ?? res;\n }\n\n /**\n * Triggers a high-definition video render export.\n */\n async triggerRender(projectId: string): Promise<{\n id: string;\n exportId: string;\n status: string;\n }> {\n const res = await this.request<any>(\n `/exports/projects/${encodeURIComponent(projectId)}`,\n {\n method: \"POST\",\n body: JSON.stringify({ quality: \"1080p\" }),\n },\n );\n\n const exportData = res?.data?.export ?? res?.export ?? res?.data ?? res;\n const exportId = exportData?.id ?? exportData?.exportId ?? \"\";\n const status = exportData?.status ?? \"QUEUED\";\n\n return {\n id: exportId,\n exportId,\n status,\n };\n }\n\n /**\n * Checks the status of an ongoing render export.\n */\n async getRenderStatus(exportId: string): Promise<WeviExportStatus> {\n const res = await this.request<any>(\n `/exports/${encodeURIComponent(exportId)}`,\n );\n return res?.data?.export ?? res?.data ?? res;\n }\n\n /**\n * Polls render export status until complete (SUCCESS or FAILED) or timed out.\n */\n async pollRenderUntilComplete(\n exportId: string,\n timeoutSeconds = 90,\n pollIntervalMs = 3000,\n ): Promise<WeviExportStatus> {\n const startTime = Date.now();\n const maxDurationMs = timeoutSeconds * 1000;\n\n while (Date.now() - startTime < maxDurationMs) {\n const status = await this.getRenderStatus(exportId);\n\n if (status.status === \"SUCCESS\" || status.status === \"FAILED\") {\n return status;\n }\n\n await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));\n }\n\n // Timed out while still processing\n const lastStatus = await this.getRenderStatus(exportId);\n return lastStatus;\n }\n\n /**\n * Generates an AI storyboard / copy for a template given a prompt.\n */\n async generateStoryboard(data: {\n prompt: string;\n templateId?: string;\n brandUrl?: string;\n }): Promise<Record<string, unknown>> {\n const res = await this.request<any>(\"/ai/storyboard/draft\", {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n return res?.data?.draft ?? res?.data ?? res;\n }\n\n /**\n * Captures a high-resolution screenshot from a live URL.\n */\n async captureWebUi(data: {\n url: string;\n selector?: string;\n viewport?: \"desktop\" | \"mobile\" | \"tablet\";\n }): Promise<{ screenshotUrl: string; title?: string }> {\n const res = await this.request<any>(\n \"/browse/capture\",\n {\n method: \"POST\",\n body: JSON.stringify(data),\n },\n );\n return res?.data ?? res;\n }\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { WeviApiClient } from \"../client/wevi-api-client.js\";\n\nexport function registerTemplateTools(server: McpServer, client: WeviApiClient) {\n // 1. wevi_list_templates\n server.tool(\n \"wevi_list_templates\",\n \"List and search available video templates on Wevi with category, aspect ratio, and keyword filters.\",\n {\n category: z\n .string()\n .optional()\n .describe(\"Category filter (e.g., 'SaaS', 'E-commerce', 'Social Media', 'Product Promo')\"),\n aspectRatio: z\n .enum([\"16:9\", \"16:12\", \"4:3\"])\n .optional()\n .describe(\"Target video aspect ratio: '16:9' (Widescreen landscape 1920x1080) or '16:12' (Desktop app focus frame 1920x1440 / 4:3)\"),\n search: z\n .string()\n .optional()\n .describe(\"Search keyword matching template titles, tags, or descriptions\"),\n limit: z\n .number()\n .min(1)\n .max(50)\n .optional()\n .default(20)\n .describe(\"Number of templates to return (default: 20)\"),\n },\n async (args) => {\n try {\n const result = await client.listTemplates(args);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n totalTemplates: result.total,\n templates: result.items.map((t) => ({\n id: t.id,\n name: t.name,\n slug: t.slug,\n description: t.description,\n aspectRatio: t.aspectRatio,\n durationSeconds: t.durationSeconds,\n tags: t.tags,\n previewVideoUrl: t.previewVideoUrl,\n thumbnailUrl: t.thumbnailUrl,\n })),\n },\n null,\n 2,\n ),\n },\n ],\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error listing templates: ${msg}` }],\n };\n }\n },\n );\n\n // 2. wevi_get_template_schema\n server.tool(\n \"wevi_get_template_schema\",\n \"Inspect the dynamic layer variables for a specific Wevi video template (e.g. text variables, color variables, logos, background videos). Use this before creating a project to know what parameters the template expects.\",\n {\n templateId: z\n .string()\n .describe(\"The unique ID or slug of the Wevi video template\"),\n },\n async (args) => {\n try {\n const template = await client.getTemplate(args.templateId);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n id: template.id,\n name: template.name,\n slug: template.slug,\n aspectRatio: template.aspectRatio,\n durationSeconds: template.durationSeconds,\n description: template.description,\n editableLayers: template.layers || [],\n },\n null,\n 2,\n ),\n },\n ],\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error fetching template schema: ${msg}` }],\n };\n }\n },\n );\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { WeviApiClient } from \"../client/wevi-api-client.js\";\n\nexport function registerProjectTools(server: McpServer, client: WeviApiClient) {\n // 3. wevi_create_project\n server.tool(\n \"wevi_create_project\",\n \"Create a new video project on Wevi using a chosen template ID and initial layer parameters (such as headlines, descriptions, colors, logos, and animation settings).\",\n {\n templateId: z\n .string()\n .describe(\"The ID of the template to base the project on\"),\n title: z\n .string()\n .optional()\n .describe(\"Optional project title (e.g., 'Product Promo Q3')\"),\n parameters: z\n .record(z.string(), z.any())\n .optional()\n .describe(\"Dynamic parameter key-value pairs matching the template's editable layers (e.g. { TXTTYPINGVAR: 'New AI Features', CLRTEXTTYPINGVAR: '#F8FAFC' })\"),\n },\n async (args) => {\n try {\n const project = await client.createProject(args);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n message: \"Project created successfully\",\n projectId: project.id,\n title: project.title,\n status: project.status,\n aspectRatio: project.aspectRatio,\n parameters: project.parameters,\n },\n null,\n 2,\n ),\n },\n ],\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error creating project: ${msg}` }],\n };\n }\n },\n );\n\n // 4. wevi_get_project\n server.tool(\n \"wevi_get_project\",\n \"Inspect an existing Wevi project's details, configuration parameters, and status.\",\n {\n projectId: z\n .string()\n .describe(\"The unique ID of the Wevi project\"),\n },\n async (args) => {\n try {\n const project = await client.getProject(args.projectId);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(project, null, 2),\n },\n ],\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error fetching project: ${msg}` }],\n };\n }\n },\n );\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { WeviApiClient } from \"../client/wevi-api-client.js\";\n\nexport function registerRenderTools(server: McpServer, client: WeviApiClient) {\n // 5. wevi_trigger_render\n server.tool(\n \"wevi_trigger_render\",\n \"Trigger high-quality video rendering for a Wevi project. Supports auto-polling so the tool can wait and return the final MP4 video link directly in one step.\",\n {\n projectId: z\n .string()\n .describe(\"The ID of the project to render\"),\n pollUntilComplete: z\n .boolean()\n .optional()\n .default(true)\n .describe(\"If true (default), waits for the render to complete before returning the final MP4 download URL.\"),\n timeoutSeconds: z\n .number()\n .min(10)\n .max(300)\n .optional()\n .default(90)\n .describe(\"Maximum seconds to wait if pollUntilComplete is true (default: 90)\"),\n },\n async (args) => {\n try {\n const triggerRes = await client.triggerRender(args.projectId);\n const exportId = triggerRes.exportId || triggerRes.id;\n\n if (!exportId) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(triggerRes, null, 2),\n },\n ],\n };\n }\n\n if (args.pollUntilComplete) {\n const finalStatus = await client.pollRenderUntilComplete(\n exportId,\n args.timeoutSeconds,\n );\n\n if (finalStatus.status === \"SUCCESS\") {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n status: \"SUCCESS\",\n message: \"Video rendered successfully!\",\n exportId: finalStatus.id,\n videoUrl: finalStatus.videoUrl,\n thumbnailUrl: finalStatus.thumbnailUrl,\n completedAt: finalStatus.completedAt,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n if (finalStatus.status === \"FAILED\") {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Render failed: ${finalStatus.errorMessage || \"Unknown render error\"}`,\n },\n ],\n };\n }\n\n // Still processing after timeout\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n status: finalStatus.status,\n message: \"Render is still processing in background. You can check status later using wevi_get_render_status.\",\n exportId: finalStatus.id,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n message: \"Render queued successfully\",\n exportId,\n status: triggerRes.status || \"QUEUED\",\n },\n null,\n 2,\n ),\n },\n ],\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error triggering render: ${msg}` }],\n };\n }\n },\n );\n\n // 6. wevi_get_render_status\n server.tool(\n \"wevi_get_render_status\",\n \"Check the real-time status and download URL of an active or completed video export.\",\n {\n exportId: z\n .string()\n .describe(\"The unique ID of the export render\"),\n },\n async (args) => {\n try {\n const status = await client.getRenderStatus(args.exportId);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(status, null, 2),\n },\n ],\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error checking render status: ${msg}` }],\n };\n }\n },\n );\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { WeviApiClient } from \"../client/wevi-api-client.js\";\n\nexport function registerAiTools(server: McpServer, client: WeviApiClient) {\n // 7. wevi_generate_storyboard\n server.tool(\n \"wevi_generate_storyboard\",\n \"Generate tailored video script, headline, and copywriting variables for a Wevi template based on a user prompt or product URL.\",\n {\n prompt: z\n .string()\n .describe(\"The marketing goal, product description, or topic for the video (e.g. '30-second SaaS promo highlighting AI-powered email writing')\"),\n templateId: z\n .string()\n .optional()\n .describe(\"Optional template ID to shape the storyboard to specific scene layers\"),\n brandUrl: z\n .string()\n .url()\n .optional()\n .describe(\"Optional website URL to extract brand context from\"),\n },\n async (args) => {\n try {\n const result = await client.generateStoryboard(args);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error generating storyboard: ${msg}` }],\n };\n }\n },\n );\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { WeviApiClient } from \"../client/wevi-api-client.js\";\n\nexport function registerBrowseTools(server: McpServer, client: WeviApiClient) {\n // 8. wevi_capture_web_ui\n server.tool(\n \"wevi_capture_web_ui\",\n \"Capture a clean, high-resolution web screenshot asset from a website URL to use as an image layer in video templates.\",\n {\n url: z\n .string()\n .url()\n .describe(\"The website URL to capture (e.g. 'https://stripe.com')\"),\n selector: z\n .string()\n .optional()\n .describe(\"Optional CSS selector to crop a specific component or hero element\"),\n viewport: z\n .enum([\"desktop\", \"mobile\", \"tablet\"])\n .optional()\n .default(\"desktop\")\n .describe(\"Target viewport size: 'desktop' (1440x900), 'tablet' (768x1024), or 'mobile' (375x812)\"),\n },\n async (args) => {\n try {\n const result = await client.captureWebUi(args);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error capturing web UI: ${msg}` }],\n };\n }\n },\n );\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { WeviApiClient } from \"../client/wevi-api-client.js\";\nimport { registerTemplateTools } from \"./templates.tools.js\";\nimport { registerProjectTools } from \"./projects.tools.js\";\nimport { registerRenderTools } from \"./renders.tools.js\";\nimport { registerAiTools } from \"./ai.tools.js\";\nimport { registerBrowseTools } from \"./browse.tools.js\";\n\nexport function registerAllTools(server: McpServer, client: WeviApiClient) {\n registerTemplateTools(server, client);\n registerProjectTools(server, client);\n registerRenderTools(server, client);\n registerAiTools(server, client);\n registerBrowseTools(server, client);\n}\n"],"mappings":"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","names":["server","client","z","server","client","z","server","client","z","server","client","z","server","client","server","client"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport dotenv from \"dotenv\";\nimport { WeviApiClient } from \"./client/wevi-api-client.js\";\nimport { registerAllTools } from \"./tools/index.js\";\nimport { buildServerInstructions } from \"./capabilities.js\";\n\ndotenv.config();\n\nconst apiKey = process.env.WEVI_API_KEY;\nconst apiUrl = process.env.WEVI_API_URL || \"https://api-v2.wevi.ai/api/v2\";\n\nif (!apiKey) {\n process.stderr.write(\n \"[Wevi MCP Warning] WEVI_API_KEY is not set. MCP tools will fail until an API key is provided in your MCP configuration.\\nGet your key at: https://app.wevi.ai/app/profile?id=api-keys\\n\",\n );\n}\n\nconst client = new WeviApiClient({\n apiKey: apiKey || \"\",\n apiUrl,\n});\n\nif (client.isSandbox) {\n process.stderr.write(\n \"[Wevi MCP] Sandbox key detected (wevi_test_): renders are watermarked, capped at 720p and do not use credits.\\n\",\n );\n}\n\nconst server = new McpServer(\n {\n name: \"wevi\",\n version: \"0.2.1\",\n },\n {\n // Sent to the client on connect; assistants that honour MCP instructions\n // learn what Wevi can and cannot make before the first tool call.\n instructions: buildServerInstructions(),\n },\n);\n\n// Register all video automation tools\nregisterAllTools(server, client);\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n process.stderr.write(`[Wevi MCP Server] Started successfully connected to ${apiUrl}\\n`);\n}\n\nmain().catch((error) => {\n process.stderr.write(`[Wevi MCP Server Fatal Error]: ${error}\\n`);\n process.exit(1);\n});\n"],"mappings":";;;;;;;;AAAA,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;AACrC,OAAO,YAAY;AAKnB,OAAO,OAAO;AAEd,IAAM,SAAS,QAAQ,IAAI;AAC3B,IAAM,SAAS,QAAQ,IAAI,gBAAgB;AAE3C,IAAI,CAAC,QAAQ;AACX,UAAQ,OAAO;AAAA,IACb;AAAA,EACF;AACF;AAEA,IAAM,SAAS,IAAI,cAAc;AAAA,EAC/B,QAAQ,UAAU;AAAA,EAClB;AACF,CAAC;AAED,IAAI,OAAO,WAAW;AACpB,UAAQ,OAAO;AAAA,IACb;AAAA,EACF;AACF;AAEA,IAAM,SAAS,IAAI;AAAA,EACjB;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,EACX;AAAA,EACA;AAAA;AAAA;AAAA,IAGE,cAAc,wBAAwB;AAAA,EACxC;AACF;AAGA,iBAAiB,QAAQ,MAAM;AAE/B,eAAe,OAAO;AACpB,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAC9B,UAAQ,OAAO,MAAM,uDAAuD,MAAM;AAAA,CAAI;AACxF;AAEA,KAAK,EAAE,MAAM,CAAC,UAAU;AACtB,UAAQ,OAAO,MAAM,kCAAkC,KAAK;AAAA,CAAI;AAChE,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
|