katto-mcp 0.3.1 → 0.4.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.
Files changed (2) hide show
  1. package/index.mjs +94 -1
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -135,9 +135,89 @@ const TOOLS = [
135
135
  "{ videos_used, videos_limit, videos_remaining }.",
136
136
  inputSchema: { type: "object", properties: {} },
137
137
  },
138
+ {
139
+ name: "katto_list_sources",
140
+ description:
141
+ "List the video platforms Katto can clip from, with an example URL for each. Use this to confirm a " +
142
+ "URL is supported before calling katto_create_clip_job.",
143
+ inputSchema: { type: "object", properties: {} },
144
+ },
145
+ {
146
+ name: "katto_list_clip_lengths",
147
+ description:
148
+ "List the valid values for the optional config.clipLength on katto_create_clip_job (target clip " +
149
+ "duration buckets).",
150
+ inputSchema: { type: "object", properties: {} },
151
+ },
152
+ {
153
+ name: "katto_rerender_clip",
154
+ description:
155
+ "Re-render one finished clip with a new reframe layout and/or caption style. Does NOT use video quota. " +
156
+ "Returns a rerender_id; poll katto_get_rerender for the new clip url.",
157
+ inputSchema: {
158
+ type: "object",
159
+ properties: {
160
+ id: { type: "string", description: "Job id from katto_create_clip_job." },
161
+ clip_index: { type: "number", description: "0-based index of the clip to re-render." },
162
+ layout_mode: {
163
+ type: "string",
164
+ enum: ["face_tracking", "wide", "split_screen", "stacked", "passthrough", "grid_3", "grid_4"],
165
+ },
166
+ caption_style: { type: "string", description: "A caption style preset name." },
167
+ },
168
+ required: ["id", "clip_index"],
169
+ },
170
+ },
171
+ {
172
+ name: "katto_dub_clip",
173
+ description:
174
+ "Re-render one finished clip dubbed into one or more languages (en, es, fr, it, pt, hi, ja, zh). Does " +
175
+ "NOT use video quota. Returns a rerender_id; poll katto_get_rerender for the result.",
176
+ inputSchema: {
177
+ type: "object",
178
+ properties: {
179
+ id: { type: "string", description: "Job id." },
180
+ clip_index: { type: "number", description: "0-based clip index." },
181
+ languages: {
182
+ type: "array",
183
+ items: { type: "string", enum: ["en", "es", "fr", "it", "pt", "hi", "ja", "zh"] },
184
+ },
185
+ },
186
+ required: ["id", "clip_index", "languages"],
187
+ },
188
+ },
189
+ {
190
+ name: "katto_get_rerender",
191
+ description:
192
+ "Poll a re-render started by katto_rerender_clip or katto_dub_clip. Returns { status, clip_url, captions_url }.",
193
+ inputSchema: {
194
+ type: "object",
195
+ properties: {
196
+ id: { type: "string", description: "Job id." },
197
+ rerender_id: { type: "string", description: "The rerender_id returned by rerender/dub." },
198
+ },
199
+ required: ["id", "rerender_id"],
200
+ },
201
+ },
202
+ ];
203
+
204
+ // Static reference data — returned by the list_* tools without an API call.
205
+ const SOURCES = [
206
+ { id: 'youtube', example: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' },
207
+ { id: 'twitch', example: 'https://www.twitch.tv/videos/123456789' },
208
+ { id: 'vimeo', example: 'https://vimeo.com/123456789' },
209
+ { id: 'rumble', example: 'https://rumble.com/v1a2b3c-title.html' },
210
+ { id: 'zoom', example: 'https://zoom.us/rec/share/abc123' },
211
+ { id: 'dailymotion', example: 'https://www.dailymotion.com/video/x8abcde' },
212
+ ];
213
+ const CLIP_LENGTHS = [
214
+ { value: 'lt30', label: 'Under 30 seconds' },
215
+ { value: '30_60', label: '30 to 60 seconds' },
216
+ { value: '60_90', label: '60 to 90 seconds' },
217
+ { value: '90_180', label: '90 to 180 seconds' },
138
218
  ];
139
219
 
140
- const server = new Server({ name: "katto", version: "0.3.1" }, { capabilities: { tools: {} } });
220
+ const server = new Server({ name: "katto", version: "0.4.0" }, { capabilities: { tools: {} } });
141
221
 
142
222
  server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
143
223
 
@@ -170,6 +250,19 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
170
250
  data = await api(`/api/v1/jobs/${encodeURIComponent(args.id)}`, { method: "DELETE" });
171
251
  } else if (name === "katto_get_account") {
172
252
  data = await api("/api/v1/me");
253
+ } else if (name === "katto_list_sources") {
254
+ data = { sources: SOURCES, note: "You can also clip a local file via the REST API (POST /v1/uploads)." };
255
+ } else if (name === "katto_list_clip_lengths") {
256
+ data = { clip_lengths: CLIP_LENGTHS };
257
+ } else if (name === "katto_rerender_clip") {
258
+ const b = {};
259
+ if (args.layout_mode) b.layout_mode = args.layout_mode;
260
+ if (args.caption_style) b.caption_style = args.caption_style;
261
+ data = await api(`/api/v1/jobs/${encodeURIComponent(args.id)}/clips/${encodeURIComponent(args.clip_index)}/rerender`, { method: "POST", body: JSON.stringify(b) });
262
+ } else if (name === "katto_dub_clip") {
263
+ data = await api(`/api/v1/jobs/${encodeURIComponent(args.id)}/clips/${encodeURIComponent(args.clip_index)}/rerender`, { method: "POST", body: JSON.stringify({ dub: args.languages || [] }) });
264
+ } else if (name === "katto_get_rerender") {
265
+ data = await api(`/api/v1/jobs/${encodeURIComponent(args.id)}/rerenders/${encodeURIComponent(args.rerender_id)}`);
173
266
  } else {
174
267
  throw new Error(`Unknown tool: ${name}`);
175
268
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "katto-mcp",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "mcpName": "io.github.miracleweasel/katto-mcp",
5
5
  "description": "MCP server for Katto — turn long videos into scored, captioned 9:16 clips from any MCP client (Claude, Cursor, ...).",
6
6
  "type": "module",