@wevi/mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +578 -0
- package/dist/index.js.map +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Wevi MCP Server (`@wevi/mcp`)
|
|
2
|
+
|
|
3
|
+
The official [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server for **[Wevi](https://wevi.ai)** — the AI Video Generation Platform.
|
|
4
|
+
|
|
5
|
+
Connect Claude Desktop, Claude Code, Cursor, or Windsurf directly to your Wevi account to create, customize, and render professional videos using natural language.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Features & Tools
|
|
10
|
+
|
|
11
|
+
* **`wevi_list_templates`**: Search and discover video templates by aspect ratio (`16:9`, `16:12`), category, or keywords.
|
|
12
|
+
* **`wevi_get_template_schema`**: Inspect dynamic editable layers (text, colors, images, animations).
|
|
13
|
+
* **`wevi_create_project`**: Create draft video projects and configure dynamic layer variables.
|
|
14
|
+
* **`wevi_get_project`**: Retrieve video configuration parameters and render status.
|
|
15
|
+
* **`wevi_trigger_render`**: Render high-definition MP4 videos on Plainly with automatic polling and preview links.
|
|
16
|
+
* **`wevi_get_render_status`**: Check export progress and fetch final download links.
|
|
17
|
+
* **`wevi_generate_storyboard`**: Generate AI copywriting and scripts tailored to Wevi video templates.
|
|
18
|
+
* **`wevi_capture_web_ui`**: Capture automated high-res web screenshots via Browserbase.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Setup & Quickstart
|
|
23
|
+
|
|
24
|
+
### 1. Get your Wevi API Key
|
|
25
|
+
1. Log in to [app.wevi.ai](https://app.wevi.ai).
|
|
26
|
+
2. Go to **Profile → API Keys & MCP** (or visit [app.wevi.ai/app/profile?id=api-keys](https://app.wevi.ai/app/profile?id=api-keys)).
|
|
27
|
+
3. Click **"Create New API Key"** and copy your secret key (`wevi_live_...`).
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
### 2. Configure Your AI Client
|
|
32
|
+
|
|
33
|
+
#### A. Claude Desktop
|
|
34
|
+
Add this to your Claude Desktop configuration file:
|
|
35
|
+
* **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
36
|
+
* **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"mcpServers": {
|
|
41
|
+
"wevi": {
|
|
42
|
+
"command": "npx",
|
|
43
|
+
"args": ["-y", "@wevi/mcp"],
|
|
44
|
+
"env": {
|
|
45
|
+
"WEVI_API_KEY": "wevi_live_YOUR_SECRET_KEY_HERE"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
#### B. Claude Code CLI
|
|
55
|
+
Run the following command in your terminal:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
claude mcp add wevi -- npx -y @wevi/mcp
|
|
59
|
+
```
|
|
60
|
+
*(When prompted or in your `.env`, provide `WEVI_API_KEY=wevi_live_...`)*
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
#### C. Cursor & Windsurf
|
|
65
|
+
Add to `.cursor/mcp.json` in your workspace:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"mcpServers": {
|
|
70
|
+
"wevi": {
|
|
71
|
+
"command": "npx",
|
|
72
|
+
"args": ["-y", "@wevi/mcp"],
|
|
73
|
+
"env": {
|
|
74
|
+
"WEVI_API_KEY": "wevi_live_YOUR_SECRET_KEY_HERE"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Example Prompts to Try in Claude
|
|
84
|
+
|
|
85
|
+
* *"Show me available 9:16 templates for social media ads."*
|
|
86
|
+
* *"Create a 15-second product promo video for our new feature launch called 'Wevi AI' and render it."*
|
|
87
|
+
* *"Take a screenshot of stripe.com and use it in our showcase video template."*
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Development
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
cd v2/mcp
|
|
95
|
+
npm install
|
|
96
|
+
npm run build
|
|
97
|
+
npm start
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## License
|
|
101
|
+
MIT © [Wevi AI](https://wevi.ai)
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
+
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 video render export on Plainly.
|
|
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 via Browserbase.
|
|
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 via Browserbase 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
|
+
dotenv.config();
|
|
551
|
+
var apiKey = process.env.WEVI_API_KEY;
|
|
552
|
+
var apiUrl = process.env.WEVI_API_URL || "https://api-v2.wevi.ai/api/v2";
|
|
553
|
+
if (!apiKey) {
|
|
554
|
+
process.stderr.write(
|
|
555
|
+
"[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"
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
var client = new WeviApiClient({
|
|
559
|
+
apiKey: apiKey || "",
|
|
560
|
+
apiUrl
|
|
561
|
+
});
|
|
562
|
+
var server = new McpServer({
|
|
563
|
+
name: "wevi",
|
|
564
|
+
version: "0.1.0"
|
|
565
|
+
});
|
|
566
|
+
registerAllTools(server, client);
|
|
567
|
+
async function main() {
|
|
568
|
+
const transport = new StdioServerTransport();
|
|
569
|
+
await server.connect(transport);
|
|
570
|
+
process.stderr.write(`[Wevi MCP Server] Started successfully connected to ${apiUrl}
|
|
571
|
+
`);
|
|
572
|
+
}
|
|
573
|
+
main().catch((error) => {
|
|
574
|
+
process.stderr.write(`[Wevi MCP Server Fatal Error]: ${error}
|
|
575
|
+
`);
|
|
576
|
+
process.exit(1);
|
|
577
|
+
});
|
|
578
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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 video render export on Plainly.\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 via Browserbase.\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 via Browserbase 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"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wevi/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Official Model Context Protocol (MCP) server for Wevi — AI Video Generation Platform",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"wevi-mcp": "dist/index.js",
|
|
8
|
+
"mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsup",
|
|
18
|
+
"prepublishOnly": "npm run build",
|
|
19
|
+
"dev": "tsup --watch",
|
|
20
|
+
"start": "node dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/wevi-HQ/mcp.git"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://wevi.ai",
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/wevi-HQ/mcp/issues"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"mcp",
|
|
32
|
+
"model-context-protocol",
|
|
33
|
+
"wevi",
|
|
34
|
+
"video-generation",
|
|
35
|
+
"claude",
|
|
36
|
+
"cursor"
|
|
37
|
+
],
|
|
38
|
+
"author": "Wevi AI <team@wevi.ai>",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@modelcontextprotocol/sdk": "^1.6.1",
|
|
42
|
+
"dotenv": "^16.4.7",
|
|
43
|
+
"zod": "^3.23.8"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^20.14.9",
|
|
47
|
+
"tsup": "^8.3.5",
|
|
48
|
+
"typescript": "^5.6.3"
|
|
49
|
+
}
|
|
50
|
+
}
|