@soldy_ai/mcp 0.1.6

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 (47) hide show
  1. package/README.md +42 -0
  2. package/dist/client.d.ts +103 -0
  3. package/dist/client.js +165 -0
  4. package/dist/client.js.map +1 -0
  5. package/dist/errors.d.ts +5 -0
  6. package/dist/errors.js +22 -0
  7. package/dist/errors.js.map +1 -0
  8. package/dist/files.d.ts +6 -0
  9. package/dist/files.js +49 -0
  10. package/dist/files.js.map +1 -0
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.js +18 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/resources/brands.d.ts +3 -0
  15. package/dist/resources/brands.js +170 -0
  16. package/dist/resources/brands.js.map +1 -0
  17. package/dist/resources/materials.d.ts +3 -0
  18. package/dist/resources/materials.js +134 -0
  19. package/dist/resources/materials.js.map +1 -0
  20. package/dist/resources/messages.d.ts +3 -0
  21. package/dist/resources/messages.js +135 -0
  22. package/dist/resources/messages.js.map +1 -0
  23. package/dist/resources/projects.d.ts +3 -0
  24. package/dist/resources/projects.js +78 -0
  25. package/dist/resources/projects.js.map +1 -0
  26. package/dist/server.d.ts +6 -0
  27. package/dist/server.js +171 -0
  28. package/dist/server.js.map +1 -0
  29. package/dist/subscriptions.d.ts +45 -0
  30. package/dist/subscriptions.js +275 -0
  31. package/dist/subscriptions.js.map +1 -0
  32. package/dist/tools/brand.d.ts +3 -0
  33. package/dist/tools/brand.js +141 -0
  34. package/dist/tools/brand.js.map +1 -0
  35. package/dist/tools/material.d.ts +2 -0
  36. package/dist/tools/material.js +23 -0
  37. package/dist/tools/material.js.map +1 -0
  38. package/dist/tools/message.d.ts +3 -0
  39. package/dist/tools/message.js +241 -0
  40. package/dist/tools/message.js.map +1 -0
  41. package/dist/tools/project.d.ts +3 -0
  42. package/dist/tools/project.js +240 -0
  43. package/dist/tools/project.js.map +1 -0
  44. package/dist/tools/subscribe.d.ts +12 -0
  45. package/dist/tools/subscribe.js +74 -0
  46. package/dist/tools/subscribe.js.map +1 -0
  47. package/package.json +37 -0
@@ -0,0 +1,241 @@
1
+ import { z } from "zod";
2
+ import { formatApiError } from "../errors.js";
3
+ import { resolveUrls } from "../files.js";
4
+ export function registerMessageTools(server, client) {
5
+ server.tool("send_message", `Send a message to the project agent to start or continue generation.
6
+
7
+ Required: ratio — the video aspect ratio. Choose based on target platform:
8
+ - 9:16 → TikTok, Reels, Shorts (vertical)
9
+ - 16:9 → YouTube, landscape video
10
+ - 1:1 → Instagram, square
11
+ - 4:3, 3:4, 3:2, 2:3, 21:9 → other formats
12
+
13
+ Also supports:
14
+ - material_urls: local file paths (auto-uploaded), GCS URLs, or external http URLs
15
+ - brand_id: pass for brand-aware generation (get from list_brands or extract_brand)
16
+
17
+ The agent starts processing and project status becomes "running".
18
+ After sending, use watch_project(project_id) to subscribe for real-time status/message/material updates. Alternatively, poll get_project_status.`, {
19
+ project_id: z.string(),
20
+ content: z
21
+ .string()
22
+ .describe("Message to the agent describing what to generate or modify"),
23
+ material_urls: z
24
+ .array(z.string())
25
+ .optional()
26
+ .describe("Image/video/audio URLs or local file paths"),
27
+ ratio: z
28
+ .enum(["9:16", "16:9", "1:1", "4:3", "3:4", "3:2", "2:3", "21:9"])
29
+ .describe("Video aspect ratio (required). Common: '9:16' (TikTok/Reels/Shorts), '16:9' (YouTube/landscape), '1:1' (Instagram/square), '4:3'/'3:4', '3:2'/'2:3', '21:9' (ultra-wide)"),
30
+ brand_id: z
31
+ .string()
32
+ .optional()
33
+ .describe("Brand ID for generation context. Get from list_brands or extract_brand."),
34
+ }, async ({ project_id, content, material_urls, ratio, brand_id }) => {
35
+ let resolvedUrls;
36
+ if (material_urls?.length) {
37
+ try {
38
+ resolvedUrls = await resolveUrls(client, material_urls);
39
+ }
40
+ catch (err) {
41
+ return {
42
+ content: [
43
+ {
44
+ type: "text",
45
+ text: `Failed to process materials: ${err instanceof Error ? err.message : String(err)}`,
46
+ },
47
+ ],
48
+ isError: true,
49
+ };
50
+ }
51
+ }
52
+ const body = {
53
+ project_id,
54
+ content,
55
+ options: {
56
+ ratio,
57
+ ...(brand_id ? { brand_id } : {}),
58
+ },
59
+ };
60
+ if (resolvedUrls?.length)
61
+ body.material_urls = resolvedUrls;
62
+ const resp = await client.post("/public/project/message/send", body);
63
+ if (resp.code !== 0 || !resp.data) {
64
+ return {
65
+ content: [{ type: "text", text: formatApiError(resp) }],
66
+ isError: true,
67
+ };
68
+ }
69
+ const matInfo = resolvedUrls?.length
70
+ ? ` with ${resolvedUrls.length} material(s)`
71
+ : "";
72
+ const brandInfo = brand_id ? ` (brand: ${brand_id})` : "";
73
+ return {
74
+ content: [
75
+ {
76
+ type: "text",
77
+ text: `Message sent${matInfo}${brandInfo}, ratio: ${ratio}. Status: ${resp.data.status}\nUse watch_project to subscribe for updates, or poll with get_project_status.`,
78
+ },
79
+ ],
80
+ };
81
+ });
82
+ server.tool("pause_project", "Pause the currently running agent generation. Use when the user wants to stop the agent temporarily without losing progress.", { project_id: z.string(), run_id: z.string().optional() }, async ({ project_id, run_id }) => {
83
+ const resp = await client.post("/public/project/pause", {
84
+ project_id,
85
+ run_id: run_id ?? "",
86
+ });
87
+ if (resp.code !== 0)
88
+ return {
89
+ content: [{ type: "text", text: formatApiError(resp) }],
90
+ isError: true,
91
+ };
92
+ return {
93
+ content: [
94
+ {
95
+ type: "text",
96
+ text: "Project paused. Use continue_project to resume.",
97
+ },
98
+ ],
99
+ };
100
+ });
101
+ server.tool("continue_project", "Resume a paused project. Use after pause_project or when the agent paused due to credits/approval. If paused for credits, ensure the account has been topped up first.", {
102
+ project_id: z.string(),
103
+ run_id: z.string().optional(),
104
+ should_remind: z
105
+ .boolean()
106
+ .optional()
107
+ .describe("Set to false to skip future pause reminders for this project"),
108
+ }, async ({ project_id, run_id, should_remind }) => {
109
+ const body = { project_id };
110
+ if (run_id)
111
+ body.run_id = run_id;
112
+ if (should_remind !== undefined)
113
+ body.should_remind = should_remind;
114
+ const resp = await client.post("/public/project/continue", body);
115
+ if (resp.code !== 0 || !resp.data)
116
+ return {
117
+ content: [{ type: "text", text: formatApiError(resp) }],
118
+ isError: true,
119
+ };
120
+ return {
121
+ content: [
122
+ {
123
+ type: "text",
124
+ text: `Project resumed. Status: ${resp.data.status}\nPoll with get_project_status.`,
125
+ },
126
+ ],
127
+ };
128
+ });
129
+ server.tool("stop_project", "Stop a running or paused project completely. The project can be restarted later with send_message.", { project_id: z.string() }, async ({ project_id }) => {
130
+ const resp = await client.post("/public/project/stop", { project_id });
131
+ if (resp.code !== 0)
132
+ return {
133
+ content: [{ type: "text", text: formatApiError(resp) }],
134
+ isError: true,
135
+ };
136
+ return {
137
+ content: [
138
+ {
139
+ type: "text",
140
+ text: "Project stopped. Use send_message to start a new run.",
141
+ },
142
+ ],
143
+ };
144
+ });
145
+ server.tool("list_messages", "Get conversation history for a project. Shows messages with role, content, materials, and tool calls.", {
146
+ project_id: z.string(),
147
+ page: z.number().optional(),
148
+ page_size: z.number().optional(),
149
+ }, async ({ project_id, page, page_size }) => {
150
+ const params = { project_id };
151
+ if (page)
152
+ params.page = String(page);
153
+ if (page_size)
154
+ params.page_size = String(page_size);
155
+ const resp = await client.get("/public/project/message/list", params);
156
+ if (resp.code !== 0)
157
+ return {
158
+ content: [{ type: "text", text: formatApiError(resp) }],
159
+ isError: true,
160
+ };
161
+ const messages = resp.data ?? [];
162
+ if (messages.length === 0) {
163
+ return {
164
+ content: [
165
+ {
166
+ type: "text",
167
+ text: "No messages. Use send_message to start.",
168
+ },
169
+ ],
170
+ };
171
+ }
172
+ const total = resp.page?.total_count ?? messages.length;
173
+ const lines = [`Page ${page ?? 1} (${total} total)\n`];
174
+ for (const msg of messages) {
175
+ const role = msg.role === "user" ? "[user]" : "[agent]";
176
+ const time = msg.created_at?.slice(11, 16) ?? "";
177
+ let line = `${time} ${role}`;
178
+ if (msg.event && msg.event !== "ClientProjectMessage")
179
+ line += ` (${msg.event})`;
180
+ if (msg.content) {
181
+ const preview = msg.content.length > 120
182
+ ? `${msg.content.slice(0, 120)}...`
183
+ : msg.content;
184
+ line += ` ${preview}`;
185
+ }
186
+ if (msg.tool?.name)
187
+ line += `\n Tool: ${msg.tool.name}`;
188
+ if (msg.materials?.length) {
189
+ const counts = {};
190
+ for (const m of msg.materials)
191
+ counts[m.type] = (counts[m.type] ?? 0) + 1;
192
+ line += `\n Materials: ${Object.entries(counts)
193
+ .map(([t, n]) => `${n} ${t}`)
194
+ .join(", ")}`;
195
+ }
196
+ // Show pause reason if present
197
+ if (msg.event === "RunPaused" && msg.metadata) {
198
+ const reason = msg.metadata.reason;
199
+ if (reason)
200
+ line += `\n Pause reason: ${reason}`;
201
+ }
202
+ lines.push(line);
203
+ }
204
+ return { content: [{ type: "text", text: lines.join("\n") }] };
205
+ });
206
+ server.tool("get_project_materials", "Get all generated assets (videos, images, audio, documents). Use after generation completes to see deliverables.", { project_id: z.string() }, async ({ project_id }) => {
207
+ const resp = await client.get("/public/project/materials", {
208
+ project_id,
209
+ });
210
+ if (resp.code !== 0)
211
+ return {
212
+ content: [{ type: "text", text: formatApiError(resp) }],
213
+ isError: true,
214
+ };
215
+ const materials = resp.data ?? [];
216
+ if (materials.length === 0) {
217
+ return {
218
+ content: [
219
+ {
220
+ type: "text",
221
+ text: "No materials yet. Check get_project_status for progress.",
222
+ },
223
+ ],
224
+ };
225
+ }
226
+ const lines = [`${materials.length} material(s):\n`];
227
+ for (let i = 0; i < materials.length; i++) {
228
+ const m = materials[i];
229
+ let line = `${i + 1}. [${m.type}] ${m.url}`;
230
+ if (m.thumbnail)
231
+ line += `\n Thumbnail: ${m.thumbnail}`;
232
+ if (m.display_title)
233
+ line += `\n Title: ${m.display_title}`;
234
+ if (m.asset_category)
235
+ line += `\n Category: ${m.asset_category}`;
236
+ lines.push(line);
237
+ }
238
+ return { content: [{ type: "text", text: lines.join("\n") }] };
239
+ });
240
+ }
241
+ //# sourceMappingURL=message.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message.js","sourceRoot":"","sources":["../../src/tools/message.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { SoldyAPIClient } from "../client.js";
3
+ export declare function registerProjectTools(server: McpServer, client: SoldyAPIClient): void;
@@ -0,0 +1,240 @@
1
+ import { z } from "zod";
2
+ import { formatApiError } from "../errors.js";
3
+ export function registerProjectTools(server, client) {
4
+ server.tool("create_project", "Create a conversation project. After creation, use send_message to start generating.", {
5
+ name: z.string(),
6
+ brand_id: z.string().optional(),
7
+ ratio: z
8
+ .enum(["9:16", "16:9", "1:1", "4:3", "3:4", "3:2", "2:3", "21:9"])
9
+ .optional()
10
+ .describe("Default video ratio. Can be overridden per message in send_message."),
11
+ description: z.string().optional(),
12
+ }, async ({ name, brand_id, ratio, description }) => {
13
+ const wsId = await client.getDefaultWorkspaceId();
14
+ const resp = await client.post("/public/project", {
15
+ name,
16
+ slug: name
17
+ .toLowerCase()
18
+ .replace(/\s+/g, "-")
19
+ .replace(/[^a-z0-9-]/g, ""),
20
+ description: description ?? "",
21
+ ratio: ratio ?? "9:16",
22
+ workspace_id: wsId,
23
+ });
24
+ if (resp.code !== 0 || !resp.data)
25
+ return {
26
+ content: [{ type: "text", text: formatApiError(resp) }],
27
+ isError: true,
28
+ };
29
+ const p = resp.data;
30
+ // Link brand if provided
31
+ if (brand_id) {
32
+ await client
33
+ .post("/public/project/brand", { project_id: p.id, brand_id })
34
+ .catch(() => { });
35
+ }
36
+ return {
37
+ content: [
38
+ {
39
+ type: "text",
40
+ text: `Project created: **${p.name}** (ID: \`${p.id}\`, status: ${p.status})\nUse send_message to start generating.\nWeb: https://soldy.ai/app/chat/${p.id}`,
41
+ },
42
+ ],
43
+ };
44
+ });
45
+ server.tool("get_project", "Get project details including name, status, ratio, brand, timestamps.", { project_id: z.string() }, async ({ project_id }) => {
46
+ const resp = await client.get("/public/project", {
47
+ id: project_id,
48
+ });
49
+ if (resp.code !== 0 || !resp.data)
50
+ return {
51
+ content: [{ type: "text", text: formatApiError(resp) }],
52
+ isError: true,
53
+ };
54
+ const p = resp.data;
55
+ return {
56
+ content: [
57
+ {
58
+ type: "text",
59
+ text: `| Field | Value |\n|---|---|\n| ID | \`${p.id}\` |\n| Name | ${p.name} |\n| Status | ${p.status} |\n| Ratio | ${p.ratio} |\n| Created | ${p.created_at} |\n\nWeb: https://soldy.ai/app/chat/${p.id}`,
60
+ },
61
+ ],
62
+ };
63
+ });
64
+ server.tool("list_projects", "List all projects with status.", { page: z.number().optional(), page_size: z.number().optional() }, async ({ page, page_size }) => {
65
+ const wsId = await client.getDefaultWorkspaceId();
66
+ const params = { workspace_id: wsId };
67
+ if (page)
68
+ params.page = String(page);
69
+ if (page_size)
70
+ params.page_size = String(page_size);
71
+ const resp = await client.get("/public/project/list", params);
72
+ if (resp.code !== 0)
73
+ return {
74
+ content: [{ type: "text", text: formatApiError(resp) }],
75
+ isError: true,
76
+ };
77
+ const projects = resp.data ?? [];
78
+ if (projects.length === 0) {
79
+ return {
80
+ content: [
81
+ {
82
+ type: "text",
83
+ text: "No projects yet. Use create_project to start.",
84
+ },
85
+ ],
86
+ };
87
+ }
88
+ const total = resp.page?.total_count ?? projects.length;
89
+ const lines = [
90
+ `Total: ${total} (page ${page ?? 1})\n`,
91
+ "| Name | ID | Status | Created |",
92
+ "|---|---|---|---|",
93
+ ];
94
+ for (const p of projects) {
95
+ lines.push(`| ${p.name} | \`${p.id}\` | ${p.status} | ${p.created_at?.slice(0, 16)} |`);
96
+ }
97
+ return { content: [{ type: "text", text: lines.join("\n") }] };
98
+ });
99
+ server.tool("get_project_status", `Get project status and latest run activity.
100
+
101
+ For long-running jobs, prefer watch_project(project_id) to subscribe for real-time status updates via resource notifications instead of polling this tool. You can also read the resource URI soldy://project/{project_id}/status directly.
102
+
103
+ Status meanings:
104
+ - ready: waiting for send_message
105
+ - running: agent is processing
106
+ - completed: generation finished — use get_project_materials or read soldy://project/{id}/materials
107
+ - pause: agent paused (credits or approval needed) — use continue_project to resume
108
+ - error: generation failed — use send_message to retry`, { project_id: z.string() }, async ({ project_id }) => {
109
+ const [projResp, msgResp] = await Promise.all([
110
+ client.get("/public/project", { id: project_id }),
111
+ client.get("/public/project/message/list", {
112
+ project_id,
113
+ page: "1",
114
+ page_size: "30",
115
+ sort: "created_at desc",
116
+ }),
117
+ ]);
118
+ if (projResp.code !== 0 || !projResp.data) {
119
+ return {
120
+ content: [{ type: "text", text: formatApiError(projResp) }],
121
+ isError: true,
122
+ };
123
+ }
124
+ const p = projResp.data;
125
+ const messages = msgResp.data ?? [];
126
+ let output = `**${p.name}** — Status: ${p.status}\n`;
127
+ // Add actionable guidance per status
128
+ switch (p.status) {
129
+ case "pause":
130
+ output += "⏸ Agent paused. Use continue_project to resume.\n";
131
+ break;
132
+ case "error":
133
+ output +=
134
+ "❌ Generation failed. Use send_message to start a new run.\n";
135
+ break;
136
+ case "completed":
137
+ output +=
138
+ "✅ Complete. Use get_project_materials to view results, or send_message to iterate.\n";
139
+ break;
140
+ case "running":
141
+ output += "⏳ Processing. Poll again in a few seconds.\n";
142
+ break;
143
+ }
144
+ if (messages.length > 0) {
145
+ let latestRunId = "";
146
+ for (const msg of messages) {
147
+ if (msg.run_id) {
148
+ latestRunId = msg.run_id;
149
+ break;
150
+ }
151
+ }
152
+ if (latestRunId) {
153
+ const runMsgs = messages
154
+ .filter((m) => m.run_id === latestRunId)
155
+ .reverse();
156
+ if (runMsgs.length > 0) {
157
+ output += `\nLatest run (${runMsgs.length} events):\n`;
158
+ for (const msg of runMsgs) {
159
+ output += formatMessage(msg);
160
+ }
161
+ }
162
+ }
163
+ }
164
+ output += `\nWeb: https://soldy.ai/app/chat/${project_id}`;
165
+ return { content: [{ type: "text", text: output }] };
166
+ });
167
+ }
168
+ const eventMap = {
169
+ RunStarted: "Started processing",
170
+ TeamRunStarted: "Started processing",
171
+ ToolCallStarted: "Tool",
172
+ ToolCallCompleted: "Tool completed",
173
+ TeamToolCallStarted: "Tool",
174
+ TeamToolCallCompleted: "Tool completed",
175
+ RunContent: "",
176
+ RunContentCompleted: "",
177
+ RunCompleted: "Generation complete",
178
+ TeamRunCompleted: "Generation complete",
179
+ RunError: "Error",
180
+ TeamRunError: "Error",
181
+ RunPaused: "⏸ Paused",
182
+ RunCancelled: "🚫 Cancelled",
183
+ AgentSystemError: "⚠️ System error",
184
+ };
185
+ function formatMessage(msg) {
186
+ const role = msg.role === "user" ? "[user]" : "[agent]";
187
+ // Tool call events
188
+ if (msg.event === "ToolCallStarted" || msg.event === "TeamToolCallStarted") {
189
+ const toolName = msg.tool?.name ?? "unknown";
190
+ return ` 🔧 ${toolName}\n`;
191
+ }
192
+ if (msg.event === "ToolCallCompleted" ||
193
+ msg.event === "TeamToolCallCompleted") {
194
+ if (msg.content)
195
+ return ` ✓ ${msg.content.slice(0, 120)}\n`;
196
+ return "";
197
+ }
198
+ // Pause with reason
199
+ if (msg.event === "RunPaused") {
200
+ let pauseInfo = "⏸ Paused";
201
+ if (msg.metadata) {
202
+ const reason = msg.metadata.reason ?? msg.metadata.paused_reason;
203
+ if (reason)
204
+ pauseInfo += ` — ${reason}`;
205
+ }
206
+ return `${pauseInfo}\n → Use continue_project to resume\n`;
207
+ }
208
+ // Status events
209
+ const mapped = eventMap[msg.event];
210
+ if (mapped === "") {
211
+ if (msg.content) {
212
+ const preview = msg.content.length > 200
213
+ ? `${msg.content.slice(0, 200)}...`
214
+ : msg.content;
215
+ return `${role} ${preview}\n`;
216
+ }
217
+ return "";
218
+ }
219
+ if (mapped) {
220
+ const extra = msg.content ? `: ${msg.content.slice(0, 100)}` : "";
221
+ return `${mapped}${extra}\n`;
222
+ }
223
+ // Materials
224
+ if (msg.materials?.length > 0) {
225
+ const counts = {};
226
+ for (const m of msg.materials)
227
+ counts[m.type] = (counts[m.type] ?? 0) + 1;
228
+ return ` 📎 ${Object.entries(counts)
229
+ .map(([t, n]) => `${n} ${t}`)
230
+ .join(", ")}\n`;
231
+ }
232
+ if (msg.content) {
233
+ const preview = msg.content.length > 200
234
+ ? `${msg.content.slice(0, 200)}...`
235
+ : msg.content;
236
+ return `${role} ${preview}\n`;
237
+ }
238
+ return "";
239
+ }
240
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/tools/project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { SubscriptionBridge } from "../subscriptions.js";
3
+ /**
4
+ * Registers subscription tools that expose MCP resource subscriptions
5
+ * as discoverable tools for agents.
6
+ *
7
+ * Agents can only see tools in the tool list — MCP resources and their
8
+ * subscribe capability are invisible at the tool level. These tools
9
+ * bridge that gap by letting agents subscribe to real-time updates
10
+ * instead of polling.
11
+ */
12
+ export declare function registerSubscribeTools(server: McpServer, bridge: SubscriptionBridge): void;
@@ -0,0 +1,74 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Registers subscription tools that expose MCP resource subscriptions
4
+ * as discoverable tools for agents.
5
+ *
6
+ * Agents can only see tools in the tool list — MCP resources and their
7
+ * subscribe capability are invisible at the tool level. These tools
8
+ * bridge that gap by letting agents subscribe to real-time updates
9
+ * instead of polling.
10
+ */
11
+ export function registerSubscribeTools(server, bridge) {
12
+ server.tool("watch_project", `Subscribe to real-time updates for a project. Returns immediately and pushes notifications when project status, messages, or materials change.
13
+
14
+ **Use this instead of polling get_project_status in a loop.** After calling watch_project, you will receive resource update notifications for:
15
+ - \`soldy://project/{project_id}/status\` — when status changes (running → completed, paused, error)
16
+ - \`soldy://project/{project_id}/messages\` — when new messages arrive
17
+ - \`soldy://project/{project_id}/materials\` — when new assets are generated
18
+ - \`soldy://project/{project_id}/runs/{run_id}/messages\` — per-run message updates
19
+ - \`soldy://project/{project_id}/runs/{run_id}/materials\` — per-run material updates
20
+
21
+ When you receive a notification, read the corresponding resource URI to get updated data.
22
+
23
+ Typical flow: send_message → watch_project → wait for notifications → read resources when notified.`, {
24
+ project_id: z.string().describe("Project ID to watch for updates"),
25
+ }, async ({ project_id }) => {
26
+ try {
27
+ await bridge.subscribeProject(project_id);
28
+ return {
29
+ content: [
30
+ {
31
+ type: "text",
32
+ text: `Watching project \`${project_id}\`. You will receive resource update notifications when status, messages, or materials change.\n\nAvailable resource URIs:\n- soldy://project/${project_id}/status\n- soldy://project/${project_id}/messages\n- soldy://project/${project_id}/materials`,
33
+ },
34
+ ],
35
+ };
36
+ }
37
+ catch (err) {
38
+ return {
39
+ content: [
40
+ {
41
+ type: "text",
42
+ text: `Failed to watch project: ${err instanceof Error ? err.message : String(err)}`,
43
+ },
44
+ ],
45
+ isError: true,
46
+ };
47
+ }
48
+ });
49
+ server.tool("watch_brand_task", `Subscribe to real-time updates for a brand extraction task. Returns immediately and pushes notifications when task status changes.
50
+
51
+ **Use this instead of polling get_brand_task_result in a loop.** After calling watch_brand_task, you will receive resource update notifications for:
52
+ - \`soldy://brand/task/{task_id}\` — when task progress or status changes (running → finished/failed)
53
+
54
+ When the task finishes, you will also receive notifications for:
55
+ - \`soldy://brands\` — brand list updated with newly extracted brand
56
+ - \`soldy://brand/{brand_id}\` — new brand details available
57
+
58
+ Polling automatically stops when the task completes or fails.
59
+
60
+ Typical flow: extract_brand → watch_brand_task → wait for notification → read resource to get brand_id.`, {
61
+ task_id: z.string().describe("Brand extraction task ID to watch"),
62
+ }, async ({ task_id }) => {
63
+ bridge.subscribeBrandTask(task_id);
64
+ return {
65
+ content: [
66
+ {
67
+ type: "text",
68
+ text: `Watching brand task \`${task_id}\`. You will receive a resource update notification when the extraction completes or fails.\n\nResource URI: soldy://brand/task/${task_id}`,
69
+ },
70
+ ],
71
+ };
72
+ });
73
+ }
74
+ //# sourceMappingURL=subscribe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscribe.js","sourceRoot":"","sources":["../../src/tools/subscribe.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAAiB,EACjB,MAA0B;IAE1B,MAAM,CAAC,IAAI,CACT,eAAe,EACf;;;;;;;;;;;oGAWgG,EAChG;QACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;KACnE,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;QACvB,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;YAC1C,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,sBAAsB,UAAU,iJAAiJ,UAAU,8BAA8B,UAAU,gCAAgC,UAAU,YAAY;qBAChS;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,4BAA4B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;qBACrF;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB;;;;;;;;;;;wGAWoG,EACpG;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;KAClE,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QACpB,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACnC,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,yBAAyB,OAAO,mIAAmI,OAAO,EAAE;iBACnL;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@soldy_ai/mcp",
3
+ "version": "0.1.6",
4
+ "description": "Soldy AI MCP Server — video ad generation via Claude Desktop, Cursor, Claude Code",
5
+ "type": "module",
6
+ "bin": {
7
+ "soldy-mcp": "./dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "dev": "tsx src/index.ts",
12
+ "start": "node dist/index.js",
13
+ "pack:dist": "npm run build && npm pack --pack-destination ../web/public/mcp",
14
+ "lint": "biome check src/",
15
+ "lint:fix": "biome check --write src/"
16
+ },
17
+ "dependencies": {
18
+ "@modelcontextprotocol/sdk": "^1.29.0",
19
+ "@types/node": "^22.0.0",
20
+ "typescript": "^5.7.0",
21
+ "zod": "^4.0.0"
22
+ },
23
+ "devDependencies": {
24
+ "tsx": "^4.19.0"
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "README.md"
29
+ ],
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/solgers/soldy-mcp.git"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ }
37
+ }