@instavar/mcp-server 0.2.0 → 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/README.md +4 -0
- package/dist/index.js +139 -64
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @instavar/mcp-server
|
|
2
2
|
|
|
3
|
+
[](https://github.com/instavar/mcp-server/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@instavar/mcp-server)
|
|
5
|
+
[](https://glama.ai/mcp/servers/instavar/mcp-server)
|
|
6
|
+
|
|
3
7
|
Drive the full [Instavar Studio](https://instavar.com) video workflow —
|
|
4
8
|
**create → render → approve → publish → metrics** — from Claude Code or Codex,
|
|
5
9
|
without leaving your terminal.
|
package/dist/index.js
CHANGED
|
@@ -246,22 +246,33 @@ var editBriefShape = {
|
|
|
246
246
|
|
|
247
247
|
// src/tools.ts
|
|
248
248
|
var uuid = (desc) => z2.string().uuid().describe(desc);
|
|
249
|
+
var READ_ONLY = { readOnlyHint: true, openWorldHint: false };
|
|
250
|
+
var SAFE_WRITE = {
|
|
251
|
+
readOnlyHint: false,
|
|
252
|
+
destructiveHint: false,
|
|
253
|
+
idempotentHint: false,
|
|
254
|
+
openWorldHint: false
|
|
255
|
+
};
|
|
249
256
|
function registerTools(server) {
|
|
250
|
-
server.
|
|
257
|
+
server.registerTool(
|
|
251
258
|
"list_jobs",
|
|
252
|
-
"List recent video jobs for the current organization (newest first).",
|
|
253
259
|
{
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
"
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
260
|
+
title: "List jobs",
|
|
261
|
+
description: "List recent video jobs for the current organization (newest first). Start here to discover job IDs; for one job's full detail use get_job_status.",
|
|
262
|
+
inputSchema: {
|
|
263
|
+
limit: z2.number().int().min(1).max(50).default(10).describe("Number of jobs to return (default 10, max 50)"),
|
|
264
|
+
status: z2.enum([
|
|
265
|
+
"queued",
|
|
266
|
+
"rendering",
|
|
267
|
+
"draft_ready",
|
|
268
|
+
"approved",
|
|
269
|
+
"publish_requested",
|
|
270
|
+
"publishing",
|
|
271
|
+
"published",
|
|
272
|
+
"failed"
|
|
273
|
+
]).optional().describe("Filter by job status")
|
|
274
|
+
},
|
|
275
|
+
annotations: READ_ONLY
|
|
265
276
|
},
|
|
266
277
|
async ({ limit, status }) => {
|
|
267
278
|
const q = new URLSearchParams({ limit: String(limit) });
|
|
@@ -269,26 +280,38 @@ function registerTools(server) {
|
|
|
269
280
|
return runTool(() => apiGet(`/api/v1/jobs?${q.toString()}`));
|
|
270
281
|
}
|
|
271
282
|
);
|
|
272
|
-
server.
|
|
283
|
+
server.registerTool(
|
|
273
284
|
"get_job_status",
|
|
274
|
-
|
|
275
|
-
|
|
285
|
+
{
|
|
286
|
+
title: "Get job status",
|
|
287
|
+
description: "Get detailed status for a job: runs, artifacts, verifications, plus the current video and thumbnail URLs. The main polling target after create_video_brief or edit_video_brief; for post-publish engagement numbers use get_job_metrics instead.",
|
|
288
|
+
inputSchema: { jobId: uuid("The job ID to check") },
|
|
289
|
+
annotations: READ_ONLY
|
|
290
|
+
},
|
|
276
291
|
async ({ jobId }) => runTool(() => apiGet(`/api/v1/jobs/${encodeURIComponent(jobId)}`))
|
|
277
292
|
);
|
|
278
|
-
server.
|
|
293
|
+
server.registerTool(
|
|
279
294
|
"get_video_state",
|
|
280
|
-
|
|
281
|
-
|
|
295
|
+
{
|
|
296
|
+
title: "Get video state",
|
|
297
|
+
description: "Get the materialized video state for a job (composition decisions: scenes, duration, aspect ratio, etc.). Use it to inspect what the video contains; for pipeline progress and video URLs use get_job_status.",
|
|
298
|
+
inputSchema: { jobId: uuid("The job ID") },
|
|
299
|
+
annotations: READ_ONLY
|
|
300
|
+
},
|
|
282
301
|
async ({ jobId }) => runTool(
|
|
283
302
|
() => apiGet(`/api/v1/jobs/${encodeURIComponent(jobId)}/video-state`)
|
|
284
303
|
)
|
|
285
304
|
);
|
|
286
|
-
server.
|
|
305
|
+
server.registerTool(
|
|
287
306
|
"get_job_metrics",
|
|
288
|
-
"Get the latest platform engagement metric snapshots for a published job (newest first). Read-only.",
|
|
289
307
|
{
|
|
290
|
-
|
|
291
|
-
|
|
308
|
+
title: "Get job metrics",
|
|
309
|
+
description: "Get the latest platform engagement metric snapshots for a published job (newest first). Read-only. Only meaningful after publish_job; for render progress use get_job_status.",
|
|
310
|
+
inputSchema: {
|
|
311
|
+
jobId: uuid("The job ID"),
|
|
312
|
+
limit: z2.number().int().min(1).max(20).default(10).describe("Max metric snapshots (default 10, max 20)")
|
|
313
|
+
},
|
|
314
|
+
annotations: READ_ONLY
|
|
292
315
|
},
|
|
293
316
|
async ({ jobId, limit }) => runTool(
|
|
294
317
|
() => apiGet(
|
|
@@ -296,14 +319,18 @@ function registerTools(server) {
|
|
|
296
319
|
)
|
|
297
320
|
)
|
|
298
321
|
);
|
|
299
|
-
server.
|
|
322
|
+
server.registerTool(
|
|
300
323
|
"get_cost_summary",
|
|
301
|
-
"Query production infrastructure costs (Lambda, RunPod, R2, WaveSpeed, PoYo), optionally with reconciliation drift.",
|
|
302
324
|
{
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
325
|
+
title: "Get cost summary",
|
|
326
|
+
description: "Query production infrastructure costs (Lambda, RunPod, R2, WaveSpeed, PoYo), optionally with reconciliation drift. This is spend data, not engagement \u2014 for a published job's audience numbers use get_job_metrics.",
|
|
327
|
+
inputSchema: {
|
|
328
|
+
since: z2.string().optional().describe("ISO date \u2014 only include events after this date"),
|
|
329
|
+
provider: z2.enum(["runpod", "lambda", "r2", "wavespeed", "poyo", "all"]).default("all").describe("Filter by provider"),
|
|
330
|
+
groupBy: z2.enum(["provider", "job", "day"]).default("provider").describe("How to aggregate the summary"),
|
|
331
|
+
includeReconciliation: z2.boolean().default(false).describe("Include account-wide reconciliation events")
|
|
332
|
+
},
|
|
333
|
+
annotations: READ_ONLY
|
|
307
334
|
},
|
|
308
335
|
async ({ since, provider, groupBy, includeReconciliation }) => {
|
|
309
336
|
const q = new URLSearchParams({ provider, groupBy });
|
|
@@ -312,16 +339,24 @@ function registerTools(server) {
|
|
|
312
339
|
return runTool(() => apiGet(`/api/v1/cost-summary?${q.toString()}`));
|
|
313
340
|
}
|
|
314
341
|
);
|
|
315
|
-
server.
|
|
342
|
+
server.registerTool(
|
|
316
343
|
"create_video_brief",
|
|
317
|
-
|
|
318
|
-
|
|
344
|
+
{
|
|
345
|
+
title: "Create video brief",
|
|
346
|
+
description: "Create a new video job from a structured brief and trigger the render pipeline. Returns the job and run IDs immediately; rendering continues asynchronously (typically a few minutes) \u2014 poll get_job_status until draft_ready. Requires a key with write scope. To change an existing job, use edit_video_brief instead of creating a duplicate.",
|
|
347
|
+
inputSchema: createBriefShape,
|
|
348
|
+
annotations: SAFE_WRITE
|
|
349
|
+
},
|
|
319
350
|
async (input) => runTool(() => apiPost(`/api/v1/jobs`, input))
|
|
320
351
|
);
|
|
321
|
-
server.
|
|
352
|
+
server.registerTool(
|
|
322
353
|
"edit_video_brief",
|
|
323
|
-
|
|
324
|
-
|
|
354
|
+
{
|
|
355
|
+
title: "Edit video brief",
|
|
356
|
+
description: "Edit an existing job's brief (only provided fields change). Changing the script, caption, title, lessonTitle, objective, steps, scenes or aspectRatio triggers a re-render and returns the new run ID; objective also re-routes the composition. Changing only publishTarget updates the job's target platform without re-rendering. For a brand-new video use create_video_brief.",
|
|
357
|
+
inputSchema: editBriefShape,
|
|
358
|
+
annotations: SAFE_WRITE
|
|
359
|
+
},
|
|
325
360
|
async (input) => {
|
|
326
361
|
const { jobId, ...patch } = input;
|
|
327
362
|
return runTool(
|
|
@@ -329,52 +364,92 @@ function registerTools(server) {
|
|
|
329
364
|
);
|
|
330
365
|
}
|
|
331
366
|
);
|
|
332
|
-
server.
|
|
367
|
+
server.registerTool(
|
|
333
368
|
"approve_job",
|
|
334
|
-
|
|
335
|
-
|
|
369
|
+
{
|
|
370
|
+
title: "Approve job",
|
|
371
|
+
description: "Approve a rendered job so it becomes publishable (draft_ready/awaiting_review/needs_changes -> approved) and revoke active review links. Required before publish_job will accept the job.",
|
|
372
|
+
inputSchema: { jobId: uuid("The job ID to approve") },
|
|
373
|
+
annotations: {
|
|
374
|
+
readOnlyHint: false,
|
|
375
|
+
destructiveHint: false,
|
|
376
|
+
// Approving an already-approved job does not change state further.
|
|
377
|
+
idempotentHint: true,
|
|
378
|
+
openWorldHint: false
|
|
379
|
+
}
|
|
380
|
+
},
|
|
336
381
|
async ({ jobId }) => runTool(
|
|
337
382
|
() => apiPost(`/api/v1/jobs/${encodeURIComponent(jobId)}/approve`, {})
|
|
338
383
|
)
|
|
339
384
|
);
|
|
340
|
-
server.
|
|
385
|
+
server.registerTool(
|
|
341
386
|
"publish_job",
|
|
342
|
-
"Publish an APPROVED job to its connected social destination via the gated publish API. All production gates run (paid plan, ownership, abuse, QA, disclosure, destination, rights, moderation). For YouTube pass youtubePrivacyStatus:'private' for safe runs.",
|
|
343
387
|
{
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
"
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
388
|
+
title: "Publish job",
|
|
389
|
+
description: "Publish an APPROVED job to its connected social destination via the gated publish API. All production gates run (paid plan, ownership, abuse, QA, disclosure, destination, rights, moderation). Requires a key with publish scope; the post goes live on the external platform and cannot be recalled by the API. For YouTube pass youtubePrivacyStatus:'private' for safe runs.",
|
|
390
|
+
inputSchema: {
|
|
391
|
+
jobId: uuid("The approved job to publish"),
|
|
392
|
+
youtubePrivacyStatus: z2.enum(["private", "unlisted", "public"]).optional().describe("YouTube only. Use 'private' for safe dogfood runs."),
|
|
393
|
+
tiktokPostMode: z2.enum(["direct_publish", "draft_upload"]).optional().describe("TikTok only. Use 'draft_upload' for safe dogfood runs."),
|
|
394
|
+
connectedAccountDestinationId: z2.string().uuid().optional().describe(
|
|
395
|
+
"Specific destination when the org has multiple accounts for the provider."
|
|
396
|
+
),
|
|
397
|
+
confirmSyntheticDisclosure: z2.boolean().optional().describe(
|
|
398
|
+
"Set true when the job requires an AI synthetic-media disclosure."
|
|
399
|
+
),
|
|
400
|
+
confirmQaOverride: z2.boolean().optional().describe("Set true to override a non-passing QA gate.")
|
|
401
|
+
},
|
|
402
|
+
annotations: {
|
|
403
|
+
readOnlyHint: false,
|
|
404
|
+
// A live post on an external platform cannot be recalled by the API.
|
|
405
|
+
destructiveHint: true,
|
|
406
|
+
idempotentHint: false,
|
|
407
|
+
openWorldHint: true
|
|
408
|
+
}
|
|
352
409
|
},
|
|
353
410
|
async ({ jobId, ...rest }) => (
|
|
354
411
|
// NOTE: publish is NOT under /api/v1 — it is the gated /api/jobs route.
|
|
355
|
-
runTool(
|
|
412
|
+
runTool(
|
|
413
|
+
() => apiPost(`/api/jobs/${encodeURIComponent(jobId)}/publish`, rest)
|
|
414
|
+
)
|
|
356
415
|
)
|
|
357
416
|
);
|
|
358
|
-
server.
|
|
417
|
+
server.registerTool(
|
|
359
418
|
"connect_account",
|
|
360
|
-
"Start connecting a social account headlessly (no local browser needed). Returns an approve URL + a short confirm code: open the URL in a browser signed in to Instavar, check the code matches THIS terminal, and approve. Then poll connect_account_status with the returned pairingId until it reports 'connected'.",
|
|
361
419
|
{
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
420
|
+
title: "Connect social account",
|
|
421
|
+
description: "Start connecting a social account headlessly (no local browser needed). Returns an approve URL + a short confirm code: open the URL in a browser signed in to Instavar, check the code matches THIS terminal, and approve. Then poll connect_account_status with the returned pairingId until it reports 'connected'.",
|
|
422
|
+
inputSchema: {
|
|
423
|
+
provider: z2.enum([
|
|
424
|
+
"youtube",
|
|
425
|
+
"x",
|
|
426
|
+
"tiktok",
|
|
427
|
+
"linkedin",
|
|
428
|
+
"facebook",
|
|
429
|
+
"instagram",
|
|
430
|
+
"threads"
|
|
431
|
+
]).describe("The social platform to connect")
|
|
432
|
+
},
|
|
433
|
+
annotations: {
|
|
434
|
+
readOnlyHint: false,
|
|
435
|
+
destructiveHint: false,
|
|
436
|
+
idempotentHint: false,
|
|
437
|
+
// The pairing hands off to the platform's own OAuth flow.
|
|
438
|
+
openWorldHint: true
|
|
439
|
+
}
|
|
371
440
|
},
|
|
372
441
|
async ({ provider }) => runTool(() => apiPost(`/api/v1/connect/start`, { provider }))
|
|
373
442
|
);
|
|
374
|
-
server.
|
|
443
|
+
server.registerTool(
|
|
375
444
|
"connect_account_status",
|
|
376
|
-
|
|
377
|
-
|
|
445
|
+
{
|
|
446
|
+
title: "Check account connection",
|
|
447
|
+
description: "Poll a pending account connection started by connect_account. Returns status 'pending' | 'connected' | 'expired', plus the connected account label once connected.",
|
|
448
|
+
inputSchema: {
|
|
449
|
+
pairingId: uuid("The pairingId returned by connect_account")
|
|
450
|
+
},
|
|
451
|
+
annotations: READ_ONLY
|
|
452
|
+
},
|
|
378
453
|
async ({ pairingId }) => runTool(
|
|
379
454
|
() => apiGet(
|
|
380
455
|
`/api/v1/connect/poll?pairingId=${encodeURIComponent(pairingId)}`
|
|
@@ -386,7 +461,7 @@ function registerTools(server) {
|
|
|
386
461
|
// package.json
|
|
387
462
|
var package_default = {
|
|
388
463
|
name: "@instavar/mcp-server",
|
|
389
|
-
version: "0.2.
|
|
464
|
+
version: "0.2.2",
|
|
390
465
|
mcpName: "com.instavar/mcp-server",
|
|
391
466
|
description: "Instavar Studio MCP server \u2014 drive the full video create\u2192render\u2192approve\u2192publish\u2192metrics workflow from Claude Code or Codex with an API key.",
|
|
392
467
|
type: "module",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instavar/mcp-server",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"mcpName": "com.instavar/mcp-server",
|
|
5
5
|
"description": "Instavar Studio MCP server — drive the full video create→render→approve→publish→metrics workflow from Claude Code or Codex with an API key.",
|
|
6
6
|
"type": "module",
|