@viralspin/mcp 0.1.0 → 0.3.1

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 (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +79 -0
  3. package/dist/cli.js +40 -0
  4. package/dist/client.js +56 -9
  5. package/dist/engine.js +29 -0
  6. package/dist/hosted.js +159 -0
  7. package/dist/index.js +144 -2
  8. package/dist/local-render/kit.js +217 -0
  9. package/dist/local-render/login.js +138 -0
  10. package/dist/local-render/render.js +252 -0
  11. package/dist/local-render/tokens.js +201 -0
  12. package/dist/sanitize.js +22 -0
  13. package/dist/tools/assembly-adjust.js +194 -0
  14. package/dist/tools/carousel-video.js +197 -0
  15. package/dist/tools/color-grade.js +64 -0
  16. package/dist/tools/connections.js +23 -4
  17. package/dist/tools/edit-clip.js +136 -0
  18. package/dist/tools/engage.js +97 -0
  19. package/dist/tools/explainer-index.js +307 -0
  20. package/dist/tools/find-moments.js +140 -0
  21. package/dist/tools/folder-preview.js +71 -0
  22. package/dist/tools/ideas.js +158 -0
  23. package/dist/tools/image-ads.js +156 -0
  24. package/dist/tools/kinetic-text.js +122 -0
  25. package/dist/tools/local-index.js +84 -0
  26. package/dist/tools/local-mode.js +84 -0
  27. package/dist/tools/photo-picker.js +31 -0
  28. package/dist/tools/profile.js +56 -0
  29. package/dist/tools/publish.js +119 -12
  30. package/dist/tools/relight-clip.js +98 -0
  31. package/dist/tools/render-locally.js +158 -0
  32. package/dist/tools/review.js +103 -0
  33. package/dist/tools/timeline-edit.js +367 -0
  34. package/dist/tools/video-assembly.js +310 -0
  35. package/package.json +16 -3
  36. package/src/client.ts +0 -80
  37. package/src/index.ts +0 -60
  38. package/src/tools/captions.ts +0 -32
  39. package/src/tools/connections.ts +0 -27
  40. package/src/tools/posts.ts +0 -58
  41. package/src/tools/publish.ts +0 -158
  42. package/tsconfig.json +0 -15
@@ -1,158 +0,0 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import { post, uploadFiles, deleteFiles } from "../client.js";
4
-
5
- const IMAGE_EXTS = new Set([".jpg", ".jpeg", ".png", ".gif", ".webp"]);
6
- const VIDEO_EXTS = new Set([".mp4", ".mov", ".webm", ".avi"]);
7
-
8
- function detectMediaType(filePaths: string[]): "video" | "carousel" {
9
- if (filePaths.length > 1) return "carousel";
10
- const ext = path.extname(filePaths[0]).toLowerCase();
11
- return IMAGE_EXTS.has(ext) ? "carousel" : "video";
12
- }
13
-
14
- /** Expand a folder path into individual file paths (images/videos only, sorted) */
15
- function expandPaths(inputs: string[]): string[] {
16
- const result: string[] = [];
17
- for (const p of inputs) {
18
- const stat = fs.statSync(p, { throwIfNoEntry: false });
19
- if (!stat) throw new Error(`Path not found: ${p}`);
20
- if (stat.isDirectory()) {
21
- const files = fs.readdirSync(p)
22
- .filter((f) => {
23
- const ext = path.extname(f).toLowerCase();
24
- return IMAGE_EXTS.has(ext) || VIDEO_EXTS.has(ext);
25
- })
26
- .sort()
27
- .map((f) => path.join(p, f));
28
- result.push(...files);
29
- } else {
30
- result.push(p);
31
- }
32
- }
33
- return result;
34
- }
35
-
36
- interface PublishResult {
37
- post: { id: string; status: string; platform_post_ids: Record<string, string>; failed_reason?: string };
38
- }
39
-
40
- const publishSchema = {
41
- type: "object",
42
- properties: {
43
- paths: {
44
- type: "array",
45
- items: { type: "string" },
46
- description: "Local file path(s) or a folder path. Single video → video post. Multiple images or image folder → carousel.",
47
- },
48
- platforms: {
49
- type: "array",
50
- items: { type: "string", enum: ["tiktok", "instagram", "youtube"] },
51
- description: "Platforms to publish to. Must be connected.",
52
- },
53
- caption: { type: "string", description: "Post caption." },
54
- hashtags: {
55
- type: "array",
56
- items: { type: "string" },
57
- description: "Hashtags without # prefix.",
58
- },
59
- },
60
- required: ["paths", "platforms", "caption"],
61
- };
62
-
63
- export const publishNowTool = {
64
- name: "publish_now",
65
- description: "Upload local file(s) and publish immediately to TikTok, Instagram, and/or YouTube. Pass a folder path to publish all images in it as a carousel.",
66
- inputSchema: publishSchema,
67
-
68
- async execute(args: { paths: string[]; platforms: string[]; caption: string; hashtags?: string[] }) {
69
- const filePaths = expandPaths(args.paths);
70
- if (!filePaths.length) throw new Error("No media files found in the provided paths.");
71
-
72
- const mediaType = detectMediaType(filePaths);
73
- if (mediaType === "carousel" && filePaths.length > 10) {
74
- throw new Error(`Instagram supports max 10 images per carousel. Found ${filePaths.length} files.`);
75
- }
76
-
77
- // Upload files
78
- const { urls, storage_paths } = await uploadFiles(filePaths);
79
-
80
- let result: PublishResult;
81
- try {
82
- result = await post<PublishResult>("/v1/publish/schedule", {
83
- media_urls: urls,
84
- media_type: mediaType,
85
- platforms: args.platforms,
86
- caption: args.caption,
87
- hashtags: args.hashtags ?? [],
88
- publish_now: true,
89
- });
90
- } finally {
91
- // Always clean up uploaded files
92
- await deleteFiles(storage_paths).catch(() => {});
93
- }
94
-
95
- const { status, platform_post_ids, failed_reason } = result.post;
96
- const published = Object.keys(platform_post_ids);
97
- let summary = `Status: ${status}\n`;
98
- if (published.length) summary += `Published to: ${published.join(", ")}\n`;
99
- if (failed_reason) summary += `Errors: ${failed_reason}`;
100
- return summary.trim();
101
- },
102
- };
103
-
104
- export const schedulePostTool = {
105
- name: "schedule_post",
106
- description: "Upload local file(s) and schedule a post for a future time. Pass a folder path to schedule all images as a carousel.",
107
- inputSchema: {
108
- type: "object",
109
- properties: {
110
- ...publishSchema.properties,
111
- scheduled_time: {
112
- type: "string",
113
- description: "ISO 8601 datetime string for when to publish (e.g. '2026-05-10T09:00:00'). Uses your local timezone if no timezone offset provided.",
114
- },
115
- timezone: {
116
- type: "string",
117
- description: "IANA timezone name (e.g. 'America/New_York'). Defaults to UTC.",
118
- },
119
- },
120
- required: ["paths", "platforms", "caption", "scheduled_time"],
121
- },
122
-
123
- async execute(args: {
124
- paths: string[];
125
- platforms: string[];
126
- caption: string;
127
- hashtags?: string[];
128
- scheduled_time: string;
129
- timezone?: string;
130
- }) {
131
- const filePaths = expandPaths(args.paths);
132
- if (!filePaths.length) throw new Error("No media files found in the provided paths.");
133
-
134
- const mediaType = detectMediaType(filePaths);
135
-
136
- // Upload files (storage URLs remain valid for 1 hour; cron will publish before then if scheduled soon,
137
- // otherwise the cron route will fail — advise scheduling within the hour for now)
138
- const { urls, storage_paths } = await uploadFiles(filePaths);
139
-
140
- const result = await post<PublishResult>("/v1/publish/schedule", {
141
- media_urls: urls,
142
- media_type: mediaType,
143
- platforms: args.platforms,
144
- caption: args.caption,
145
- hashtags: args.hashtags ?? [],
146
- scheduled_time: args.scheduled_time,
147
- timezone: args.timezone,
148
- publish_now: false,
149
- });
150
-
151
- // Note: storage_paths are NOT deleted here — the cron job needs the URLs to stay valid.
152
- // They expire after 1 hour. For posts scheduled further out, re-upload closer to publish time.
153
- void storage_paths;
154
-
155
- const { post: p } = result;
156
- return `Scheduled post ${p.id}\nPlatforms: ${args.platforms.join(", ")}\nTime: ${args.scheduled_time}\nStatus: ${p.status}`;
157
- },
158
- };
package/tsconfig.json DELETED
@@ -1,15 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "commonjs",
5
- "lib": ["ES2020"],
6
- "outDir": "./dist",
7
- "rootDir": "./src",
8
- "strict": true,
9
- "esModuleInterop": true,
10
- "skipLibCheck": true,
11
- "resolveJsonModule": true
12
- },
13
- "include": ["src/**/*"],
14
- "exclude": ["node_modules", "dist"]
15
- }