MCPMCP

MCP 设置、Tools 与安全

一次配置 stdio,先发现能力、免费规划,再显式确认付费执行。

API / MCP 成熟度

文档页面是公开的,但 API/MCP 能力是否可用由实时产品 Manifest 和账户权限决定。foundation / experimental 不等于稳定承诺。

Tool权限用途自动重试
myeq.capabilities.searchread发现制作能力429 / 502 / 503
myeq.production.planplan编译免费且可检查的计划绝不
myeq.production.preflightread验证 readiness 与预估成本429 / 502 / 503
myeq.storyboard.applymutate应用已批准的 Storyboard绝不
myeq.production.execute_stepspend执行一个已确认的计划步骤绝不
myeq.production.executespend启动已确认的持久制作绝不
myeq.job.statusread读取持久 Job 进度429 / 502 / 503
myeq.production.ledgerread读取 owner-scoped 执行 ledger429 / 502 / 503
myeq.production.verticalsread列出制作 recipes429 / 502 / 503
myeq.v2v.editspend使用 Studio 的 V2V gate 编辑源视频绝不
myeq.video.preflight_sceneread不花费积分,检查场景的准确 FPS 和费用429 / 502 / 503
myeq.video.generate_scenespend按准入 FPS 生成一个已确认场景绝不

通用 stdio 配置

构建 MCP package,提供 MYEQ_API_KEY 和 MYEQ_BASE_URL,并让 host 指向稳定 server entrypoint。

{
  "mcpServers": {
    "myeq": {
      "command": "node",
      "args": ["/absolute/path/to/myeq-full/mcp/dist/server.js"],
      "env": {
        "MYEQ_API_KEY": "your-key",
        "MYEQ_BASE_URL": "https://myeq.pro"
      }
    }
  }
}

从 Discovery 与 Plan 开始

先查询 capability,再 plan、preflight;只有获得用户授权后才 mutate/spend。

{
  "projectId": "project-123",
  "instruction": "Create a 60-second vertical trailer",
  "vertical": "ai_film",
  "sourceLanguage": "en",
  "responseLanguage": "es",
  "dialogueLanguage": "es",
  "visualPromptLanguage": "en"
}

通过 Job identity 恢复

稍后重连并读取 Job 状态;无需保持 chat 或 terminal 进程一直在线。

Studio、API 和 MCP 的 24 / 30 / 60 FPS

三个接口使用同一份已确认的场景 snapshot 和准入检查。保留请求的 FPS,不会自动回退到 24 FPS。可用性取决于已批准的 worker 和场景的准确条件。

START/END 画布为 704×1280、1280×704 或 960×960。I2V 可生成音频或无音频;A2V 要求有使用权限的源音频,并保留所选起始偏移。本表不代表 ingredients 或 V2V 支持高 FPS。seed 必须是 0–2147483647 的整数。 I2V 和 A2V 在已部署服务明确准入时,支持 24、30、60 FPS 的仅 END 输入。END 引导最后一帧,开头根据提示词生成。保持 start 为空,将图片放在 end 中。这不保证像素完全一致,也不会倒放视频。 A2V 始终需要有使用权限的源音频,以及至少一张 START 或 END 图片;不支持仅音频生成。

FPS可准入类别物理限制
24默认值;所选模态仍需通过自身检查时长、音频和参考取决于所选原生类别
30仅限已批准的 I2V / A2V720p · 2–10 整秒 · 9:16 / 16:9 / 1:1 · I2V/A2V:START、END 或两者;A2V 还需要源音频
60仅限已批准的 I2V / A2V720p · 2–10 整秒 · 9:16 / 16:9 / 1:1 · I2V/A2V:START、END 或两者;A2V 还需要源音频

保存、核对报价,再确认一个场景

创建或读取有权限的项目,通过 PATCH expectedVersion 保存场景,再将相同的 snapshot 和 targetSceneId 发送至 /api/v1/production/snapshots/preflight-scene。检查 data.ready、issues 和 estimatedCredits;此调用不创建 job 或预留积分。使用 confirm=true 和固定 Idempotency-Key 调用 /api/v1/production/snapshots/generate-scene,然后查询返回的 jobId。MCP 使用 myeq.video.preflight_scene 和 myeq.video.generate_scene,付费提交绝不自动重试。场景设置覆盖全局默认值;保留匹配的已确认 sceneContracts。

旧 /video/start、/video/create、/video/create-job 和 /video/preflight 已退役:默认/24 返回 410;30/60 返回 422,要求迁移到 snapshot。25/48/50 不受支持。preflight 失败不会更改 FPS 或收费。检查成功也不预留可用资源或账户余额。

const base = process.env.MYEQ_BASE_URL || 'https://myeq.pro';
const headers = { Authorization: 'Bearer ' + process.env.MYEQ_API_KEY, 'Content-Type': 'application/json' };
async function api(path, method, body, extra = {}) {
  const response = await fetch(base + path, { method, headers: { ...headers, ...extra },
    ...(body === undefined ? {} : { body: JSON.stringify(body) }) });
  const value = await response.json();
  if (!response.ok) throw new Error(JSON.stringify(value));
  return value;
}
const project = await api('/api/v1/projects', 'POST', { title: '60 FPS', aspectRatio: '9:16', duration: 4 });
const sourceAudioUrl = process.env.SOURCE_AUDIO_URL;
const generationInputs = { videoProvider: 'myeq_v2', videoModelSelection: 'myeq_v2',
  inputModality: sourceAudioUrl ? 'audio_to_video' : 'image_to_video', durationSeconds: 4,
  fps: 60, outputResolution: '720p', includeAudio: Boolean(sourceAudioUrl), seed: 12345,
  ...(sourceAudioUrl ? { sourceAudioUrl, sourceAudioStartTime: 0 } : {}) };
const scene = { id: 'scene-1', prompt: 'A slow camera move. Preserve the subject.',
  settings: { fps: 60, durationSeconds: 4 },
  start: process.env.START_URL ? [{ name: 'START', url: process.env.START_URL }] : [],
  end: process.env.END_URL ? [{ name: 'END', url: process.env.END_URL }] : [], context: [], avatar: [] };
const snapshot = { id: crypto.randomUUID(), version: 1, projectId: project.id,
  ownerId: project.ownerUserId, sourceEditorStateVersion: project.version + 1,
  createdAt: new Date().toISOString(), projectTitle: project.title,
  aspectRatio: '9:16', resolution: '720p', durationSeconds: 4, fps: 60,
  generationInputs, scenes: [scene], avatars: [], assetsSummary: [],
  sourceAudio: sourceAudioUrl ? { url: sourceAudioUrl, durationSeconds: null } : null, provenance: { source: 'ui' } };
await api('/api/v1/projects/' + project.id, 'PATCH', { expectedVersion: project.version,
  editorState: { ...project.editorState, generationInputs,
    sceneStoryboard: { scenes: [scene] }, productionSnapshot: snapshot } });
const input = { snapshot, targetSceneId: scene.id };
const quote = await api('/api/v1/production/snapshots/preflight-scene', 'POST', input);
console.log(quote);
if (quote.data?.ready && process.env.CONFIRM_PAID === 'true') {
  const idempotencyKey = process.env.SAVED_IDEMPOTENCY_KEY;
  if (!idempotencyKey) throw new Error('Persist one stable key before submitting');
  const result = await api('/api/v1/production/snapshots/generate-scene', 'POST',
    { ...input, confirm: true }, { 'Idempotency-Key': idempotencyKey });
  console.log(result);
  const jobId = result.data?.pendingTake?.orchestrationJobId || result.data?.asset?.metadata?.jobId;
  if (jobId) console.log(await api('/api/v1/production/jobs/' + encodeURIComponent(jobId), 'GET'));
}

MCP · 24 / 30 / 60 FPS

// Reuse the full saved snapshot from the API example.
{ name: 'myeq.video.preflight_scene', arguments: { snapshot, targetSceneId: 'scene-1' } }
// Review data.ready, issues and estimatedCredits before confirming.
{ name: 'myeq.video.generate_scene', arguments: {
  snapshot, targetSceneId: 'scene-1', confirm: true,
  idempotencyKey: 'persisted-scene-request-0001'
} }
{ name: 'myeq.job.status', arguments: { jobId: 'returned-orchestration-job-id' } }
Workspace · Project · Asset · Entity · Storyboard · Plan · Job已生成 ≠ 已认证