freebeat-mcp 0.1.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 (78) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +210 -0
  3. package/dist/capabilities/assets/register.d.ts +3 -0
  4. package/dist/capabilities/assets/register.js +7 -0
  5. package/dist/capabilities/assets/register.js.map +1 -0
  6. package/dist/capabilities/assets/tools/upload-audio.d.ts +3 -0
  7. package/dist/capabilities/assets/tools/upload-audio.js +70 -0
  8. package/dist/capabilities/assets/tools/upload-audio.js.map +1 -0
  9. package/dist/capabilities/assets/tools/upload-image.d.ts +3 -0
  10. package/dist/capabilities/assets/tools/upload-image.js +67 -0
  11. package/dist/capabilities/assets/tools/upload-image.js.map +1 -0
  12. package/dist/capabilities/effects/register.d.ts +3 -0
  13. package/dist/capabilities/effects/register.js +7 -0
  14. package/dist/capabilities/effects/register.js.map +1 -0
  15. package/dist/capabilities/effects/task-type.d.ts +1 -0
  16. package/dist/capabilities/effects/task-type.js +2 -0
  17. package/dist/capabilities/effects/task-type.js.map +1 -0
  18. package/dist/capabilities/effects/tools/generate-effect.d.ts +3 -0
  19. package/dist/capabilities/effects/tools/generate-effect.js +81 -0
  20. package/dist/capabilities/effects/tools/generate-effect.js.map +1 -0
  21. package/dist/capabilities/effects/tools/list-effects.d.ts +3 -0
  22. package/dist/capabilities/effects/tools/list-effects.js +55 -0
  23. package/dist/capabilities/effects/tools/list-effects.js.map +1 -0
  24. package/dist/capabilities/mv/register.d.ts +3 -0
  25. package/dist/capabilities/mv/register.js +5 -0
  26. package/dist/capabilities/mv/register.js.map +1 -0
  27. package/dist/capabilities/mv/task-type.d.ts +1 -0
  28. package/dist/capabilities/mv/task-type.js +2 -0
  29. package/dist/capabilities/mv/task-type.js.map +1 -0
  30. package/dist/capabilities/mv/tools/generate-music-video.d.ts +3 -0
  31. package/dist/capabilities/mv/tools/generate-music-video.js +116 -0
  32. package/dist/capabilities/mv/tools/generate-music-video.js.map +1 -0
  33. package/dist/capabilities/tasks/register.d.ts +3 -0
  34. package/dist/capabilities/tasks/register.js +7 -0
  35. package/dist/capabilities/tasks/register.js.map +1 -0
  36. package/dist/capabilities/tasks/task-type.d.ts +1 -0
  37. package/dist/capabilities/tasks/task-type.js +2 -0
  38. package/dist/capabilities/tasks/task-type.js.map +1 -0
  39. package/dist/capabilities/tasks/tools/get-task-result.d.ts +3 -0
  40. package/dist/capabilities/tasks/tools/get-task-result.js +93 -0
  41. package/dist/capabilities/tasks/tools/get-task-result.js.map +1 -0
  42. package/dist/capabilities/tasks/tools/get-task-status.d.ts +3 -0
  43. package/dist/capabilities/tasks/tools/get-task-status.js +63 -0
  44. package/dist/capabilities/tasks/tools/get-task-status.js.map +1 -0
  45. package/dist/core/config.d.ts +4 -0
  46. package/dist/core/config.js +11 -0
  47. package/dist/core/config.js.map +1 -0
  48. package/dist/core/errors.d.ts +6 -0
  49. package/dist/core/errors.js +35 -0
  50. package/dist/core/errors.js.map +1 -0
  51. package/dist/core/prompt.d.ts +1 -0
  52. package/dist/core/prompt.js +12 -0
  53. package/dist/core/prompt.js.map +1 -0
  54. package/dist/core/response.d.ts +14 -0
  55. package/dist/core/response.js +26 -0
  56. package/dist/core/response.js.map +1 -0
  57. package/dist/core/task-types.d.ts +6 -0
  58. package/dist/core/task-types.js +20 -0
  59. package/dist/core/task-types.js.map +1 -0
  60. package/dist/core/tasks.d.ts +1 -0
  61. package/dist/core/tasks.js +2 -0
  62. package/dist/core/tasks.js.map +1 -0
  63. package/dist/core/tool-schemas.d.ts +7 -0
  64. package/dist/core/tool-schemas.js +64 -0
  65. package/dist/core/tool-schemas.js.map +1 -0
  66. package/dist/index.d.ts +2 -0
  67. package/dist/index.js +26 -0
  68. package/dist/index.js.map +1 -0
  69. package/dist/services/freebeat-api.d.ts +117 -0
  70. package/dist/services/freebeat-api.js +188 -0
  71. package/dist/services/freebeat-api.js.map +1 -0
  72. package/dist/services/upload-service.d.ts +13 -0
  73. package/dist/services/upload-service.js +22 -0
  74. package/dist/services/upload-service.js.map +1 -0
  75. package/dist/utils/file.d.ts +5 -0
  76. package/dist/utils/file.js +69 -0
  77. package/dist/utils/file.js.map +1 -0
  78. package/package.json +48 -0
@@ -0,0 +1,117 @@
1
+ import { z } from "zod";
2
+ import { SessionType } from "../core/task-types.js";
3
+ declare const preSignedUrlItemSchema: z.ZodObject<{
4
+ signURL: z.ZodString;
5
+ finalStaticUrl: z.ZodString;
6
+ }, "strip", z.ZodTypeAny, {
7
+ signURL: string;
8
+ finalStaticUrl: string;
9
+ }, {
10
+ signURL: string;
11
+ finalStaticUrl: string;
12
+ }>;
13
+ declare const taskStartResponseSchema: z.ZodObject<{
14
+ task_id: z.ZodString;
15
+ status: z.ZodString;
16
+ task_type: z.ZodString;
17
+ }, "strip", z.ZodTypeAny, {
18
+ status: string;
19
+ task_id: string;
20
+ task_type: string;
21
+ }, {
22
+ status: string;
23
+ task_id: string;
24
+ task_type: string;
25
+ }>;
26
+ declare const effectListItemSchema: z.ZodObject<{
27
+ aspectRatio: z.ZodString;
28
+ coverUrl: z.ZodString;
29
+ effectsDisplayName: z.ZodString;
30
+ effectsName: z.ZodString;
31
+ effectsTypeId: z.ZodNumber;
32
+ height: z.ZodNumber;
33
+ id: z.ZodNumber;
34
+ musicId: z.ZodNumber;
35
+ musicName: z.ZodString;
36
+ musicUrl: z.ZodString;
37
+ videoUrl: z.ZodString;
38
+ width: z.ZodNumber;
39
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
40
+ aspectRatio: z.ZodString;
41
+ coverUrl: z.ZodString;
42
+ effectsDisplayName: z.ZodString;
43
+ effectsName: z.ZodString;
44
+ effectsTypeId: z.ZodNumber;
45
+ height: z.ZodNumber;
46
+ id: z.ZodNumber;
47
+ musicId: z.ZodNumber;
48
+ musicName: z.ZodString;
49
+ musicUrl: z.ZodString;
50
+ videoUrl: z.ZodString;
51
+ width: z.ZodNumber;
52
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
53
+ aspectRatio: z.ZodString;
54
+ coverUrl: z.ZodString;
55
+ effectsDisplayName: z.ZodString;
56
+ effectsName: z.ZodString;
57
+ effectsTypeId: z.ZodNumber;
58
+ height: z.ZodNumber;
59
+ id: z.ZodNumber;
60
+ musicId: z.ZodNumber;
61
+ musicName: z.ZodString;
62
+ musicUrl: z.ZodString;
63
+ videoUrl: z.ZodString;
64
+ width: z.ZodNumber;
65
+ }, z.ZodTypeAny, "passthrough">>;
66
+ type PreSignedUrlResponse = z.infer<typeof preSignedUrlItemSchema>;
67
+ export type TaskStartResponse = z.infer<typeof taskStartResponseSchema>;
68
+ export interface TaskStatusResponse {
69
+ task_id: string;
70
+ status: string;
71
+ type: SessionType;
72
+ error_message?: string;
73
+ error_code?: number | string;
74
+ }
75
+ export interface TaskResultResponse {
76
+ task_id: string;
77
+ status: string;
78
+ type: SessionType;
79
+ error_message?: string;
80
+ error_code?: number | string;
81
+ result_payload?: string;
82
+ }
83
+ export type EffectListItem = z.infer<typeof effectListItemSchema>;
84
+ export interface GenerateMusicVideoParams {
85
+ music_id: number;
86
+ prompt: string;
87
+ aspect_ratio?: string;
88
+ resolution?: number;
89
+ start_ms?: number;
90
+ end_ms?: number;
91
+ reference_image_urls?: string[];
92
+ mv_type?: "abstract" | "singing" | "storytelling";
93
+ style?: string;
94
+ watermark?: boolean;
95
+ }
96
+ export interface GenerateEffectParams {
97
+ effect_id: number;
98
+ music_id: number;
99
+ prompt: string;
100
+ watermark?: boolean;
101
+ reference_image_urls: string[];
102
+ }
103
+ export declare class FreebeatApiClient {
104
+ private httpClient;
105
+ constructor(baseUrl: string, apiKey: string);
106
+ private unwrapApiEnvelope;
107
+ private postAndUnwrap;
108
+ createUploadUrl(key: string, fileName: string, bucketName?: string): Promise<PreSignedUrlResponse>;
109
+ uploadToPreSignedUrl(signURL: string, fileBuffer: Buffer, contentType: string): Promise<void>;
110
+ saveMusicSource(copyUrl: string): Promise<number>;
111
+ listEffects(): Promise<EffectListItem[]>;
112
+ generateMusicVideo(params: GenerateMusicVideoParams): Promise<TaskStartResponse>;
113
+ generateEffect(params: GenerateEffectParams): Promise<TaskStartResponse>;
114
+ getTaskStatus(taskId: string): Promise<TaskStatusResponse>;
115
+ getTaskResult(taskId: string): Promise<TaskResultResponse>;
116
+ }
117
+ export {};
@@ -0,0 +1,188 @@
1
+ import axios from "axios";
2
+ import { z } from "zod";
3
+ import { AppError } from "../core/errors.js";
4
+ import { EFFECT_SESSION_TYPE, EFFECT_TASK_TYPE, MUSIC_VIDEO_SESSION_TYPE, MUSIC_VIDEO_TASK_TYPE, } from "../core/task-types.js";
5
+ const preSignedUrlItemSchema = z.object({
6
+ signURL: z.string(),
7
+ finalStaticUrl: z.string(),
8
+ });
9
+ const apiResponseEnvelopeSchema = z.object({
10
+ code: z.number(),
11
+ msg: z.string().optional(),
12
+ data: z.unknown().optional(),
13
+ });
14
+ const preSignedUrlListSchema = z.array(preSignedUrlItemSchema).min(1);
15
+ const taskStartResponseSchema = z.object({
16
+ task_id: z.string(),
17
+ status: z.string(),
18
+ task_type: z.string(),
19
+ });
20
+ const trackIdResponseSchema = z.object({
21
+ trackId: z.string(),
22
+ });
23
+ const sessionTypeSchema = z.union([z.number(), z.string()]);
24
+ const errorCodeSchema = z.union([z.number().int(), z.string()]);
25
+ const querySessionStatusResponseSchema = z.object({
26
+ status: z.string(),
27
+ trackId: z.string().optional(),
28
+ type: sessionTypeSchema,
29
+ errorMsg: z.string().optional(),
30
+ errorCode: errorCodeSchema.optional(),
31
+ }).passthrough();
32
+ const querySessionResultResponseSchema = querySessionStatusResponseSchema.extend({
33
+ resultPayload: z.string().optional(),
34
+ }).passthrough();
35
+ const effectListItemSchema = z.object({
36
+ aspectRatio: z.string(),
37
+ coverUrl: z.string(),
38
+ effectsDisplayName: z.string(),
39
+ effectsName: z.string(),
40
+ effectsTypeId: z.number(),
41
+ height: z.number(),
42
+ id: z.number(),
43
+ musicId: z.number(),
44
+ musicName: z.string(),
45
+ musicUrl: z.string(),
46
+ videoUrl: z.string(),
47
+ width: z.number(),
48
+ }).passthrough();
49
+ const effectListResponseSchema = z.object({
50
+ anchor: z.union([z.string(), z.number()]).optional(),
51
+ end: z.boolean().optional(),
52
+ list: z.array(effectListItemSchema),
53
+ });
54
+ export class FreebeatApiClient {
55
+ httpClient;
56
+ constructor(baseUrl, apiKey) {
57
+ this.httpClient = axios.create({
58
+ baseURL: baseUrl,
59
+ timeout: 30_000,
60
+ headers: {
61
+ Authorization: apiKey,
62
+ },
63
+ });
64
+ }
65
+ unwrapApiEnvelope(payload, dataSchema, action, invalidDataMessage = `${action}: unexpected response format`) {
66
+ const envelope = apiResponseEnvelopeSchema.safeParse(payload);
67
+ if (!envelope.success) {
68
+ throw new AppError(`${action}: unexpected response format`, "INVALID_RESPONSE");
69
+ }
70
+ if (envelope.data.code !== 0) {
71
+ throw new AppError(`${action} failed: ${envelope.data.msg ?? "unknown error"}`, "API_ERROR");
72
+ }
73
+ if (envelope.data.data === undefined) {
74
+ throw new AppError(invalidDataMessage, "INVALID_RESPONSE");
75
+ }
76
+ const parsedData = dataSchema.safeParse(envelope.data.data);
77
+ if (!parsedData.success) {
78
+ throw new AppError(invalidDataMessage, "INVALID_RESPONSE");
79
+ }
80
+ return parsedData.data;
81
+ }
82
+ async postAndUnwrap(path, body, dataSchema, action, invalidDataMessage = `${action}: unexpected response format`) {
83
+ const response = await this.httpClient.post(path, body);
84
+ return this.unwrapApiEnvelope(response.data, dataSchema, action, invalidDataMessage);
85
+ }
86
+ async createUploadUrl(key, fileName, bucketName = "") {
87
+ const list = await this.postAndUnwrap("/v1/mcp/agent/genUploadSignUrl", { reqList: [{ key, fileName, bucketName }] }, preSignedUrlListSchema, "createUploadUrl");
88
+ return list[0];
89
+ }
90
+ async uploadToPreSignedUrl(signURL, fileBuffer, contentType) {
91
+ const uploadHeaders = {
92
+ "Content-Type": contentType,
93
+ };
94
+ const signedHeaders = new URL(signURL).searchParams
95
+ .get("X-Amz-SignedHeaders")
96
+ ?.split(";")
97
+ .map((header) => header.trim().toLowerCase()) ?? [];
98
+ if (signedHeaders.includes("x-amz-acl")) {
99
+ uploadHeaders["x-amz-acl"] = "public-read";
100
+ }
101
+ await axios.put(signURL, fileBuffer, {
102
+ headers: uploadHeaders,
103
+ timeout: 300_000,
104
+ });
105
+ }
106
+ async saveMusicSource(copyUrl) {
107
+ return this.postAndUnwrap("/v1/mcp/agent/saveMusicV3", { copyUrl }, z.number(), "saveMusicSource");
108
+ }
109
+ async listEffects() {
110
+ const result = await this.postAndUnwrap("/v1/mcp/agent/getAiAgentVeEffectsVideoList", {
111
+ anchor: 1,
112
+ limit: 1000,
113
+ effectsTypeIdList: [],
114
+ maxTypeCount: 1,
115
+ }, effectListResponseSchema, "listEffects");
116
+ return result.list;
117
+ }
118
+ async generateMusicVideo(params) {
119
+ if (!Number.isInteger(params.music_id)) {
120
+ throw new AppError("generateMusicVideo: music_id must be an integer", "INVALID_PARAMS");
121
+ }
122
+ if (params.resolution !== undefined && ![720, 1080].includes(params.resolution)) {
123
+ throw new AppError("generateMusicVideo: resolution must be either 720 or 1080", "INVALID_PARAMS");
124
+ }
125
+ const response = await this.postAndUnwrap("/v1/mcp/openMv/createSession", {
126
+ type: MUSIC_VIDEO_SESSION_TYPE,
127
+ mvMode: "fast",
128
+ mvType: params.mv_type,
129
+ style: params.style,
130
+ musicId: params.music_id,
131
+ musicStartMs: params.start_ms,
132
+ musicEndMs: params.end_ms,
133
+ prompt: params.prompt,
134
+ aspectRatio: params.aspect_ratio,
135
+ resolution: params.resolution,
136
+ watermark: params.watermark,
137
+ personaImgUrls: params.reference_image_urls,
138
+ }, trackIdResponseSchema, "generateMusicVideo", "generateMusicVideo: missing trackId in response");
139
+ return {
140
+ task_id: response.trackId,
141
+ task_type: MUSIC_VIDEO_TASK_TYPE,
142
+ status: "pending",
143
+ };
144
+ }
145
+ async generateEffect(params) {
146
+ if (!Number.isInteger(params.effect_id)) {
147
+ throw new AppError("generateEffect: effect_id must be an integer", "INVALID_PARAMS");
148
+ }
149
+ if (!Number.isInteger(params.music_id)) {
150
+ throw new AppError("generateEffect: music_id must be an integer", "INVALID_PARAMS");
151
+ }
152
+ const response = await this.postAndUnwrap("/v1/mcp/openMv/createSession", {
153
+ type: EFFECT_SESSION_TYPE,
154
+ effectsTypeId: params.effect_id,
155
+ musicId: params.music_id,
156
+ prompt: params.prompt,
157
+ watermark: params.watermark,
158
+ personaImgUrls: params.reference_image_urls,
159
+ }, trackIdResponseSchema, "generateEffect", "generateEffect: missing trackId in response");
160
+ return {
161
+ task_id: response.trackId,
162
+ task_type: EFFECT_TASK_TYPE,
163
+ status: "pending",
164
+ };
165
+ }
166
+ async getTaskStatus(taskId) {
167
+ const parsed = await this.postAndUnwrap("/v1/mcp/openMv/querySessionStatus", { trackId: taskId }, querySessionStatusResponseSchema, "getTaskStatus", "getTaskStatus: unexpected session status response");
168
+ return {
169
+ task_id: parsed.trackId ?? taskId,
170
+ status: parsed.status,
171
+ type: parsed.type,
172
+ error_message: parsed.errorMsg,
173
+ error_code: parsed.errorCode,
174
+ };
175
+ }
176
+ async getTaskResult(taskId) {
177
+ const parsed = await this.postAndUnwrap("/v1/mcp/openMv/querySessionResult", { trackId: taskId }, querySessionResultResponseSchema, "getTaskResult", "getTaskResult: unexpected session result response");
178
+ return {
179
+ task_id: parsed.trackId ?? taskId,
180
+ status: parsed.status,
181
+ type: parsed.type,
182
+ error_message: parsed.errorMsg,
183
+ error_code: parsed.errorCode,
184
+ result_payload: parsed.resultPayload,
185
+ };
186
+ }
187
+ }
188
+ //# sourceMappingURL=freebeat-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"freebeat-api.js","sourceRoot":"","sources":["../../src/services/freebeat-api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { FreebeatApiClient } from "./freebeat-api.js";
2
+ export interface UploadLocalFileParams {
3
+ filePath: string;
4
+ keyPrefix: string;
5
+ bucketName?: string;
6
+ contentType: string;
7
+ keySuffix?: string;
8
+ }
9
+ export declare class UploadService {
10
+ private readonly client;
11
+ constructor(client: Pick<FreebeatApiClient, "createUploadUrl" | "uploadToPreSignedUrl">);
12
+ uploadLocalFile({ filePath, keyPrefix, bucketName, contentType, keySuffix, }: UploadLocalFileParams): Promise<string>;
13
+ }
@@ -0,0 +1,22 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { safeExtension } from "../utils/file.js";
4
+ export class UploadService {
5
+ client;
6
+ constructor(client) {
7
+ this.client = client;
8
+ }
9
+ async uploadLocalFile({ filePath, keyPrefix, bucketName = "freebeat-static", contentType, keySuffix, }) {
10
+ const filename = path.basename(filePath);
11
+ const ext = safeExtension(filePath);
12
+ const timestamp = Date.now();
13
+ const rand = Math.random().toString(36).slice(2, 8);
14
+ const suffix = keySuffix ? `_${keySuffix}` : "";
15
+ const key = `${keyPrefix}/${timestamp}${suffix}_${rand}.${ext}`;
16
+ const { signURL, finalStaticUrl } = await this.client.createUploadUrl(key, filename, bucketName);
17
+ const fileBuffer = await fs.promises.readFile(filePath);
18
+ await this.client.uploadToPreSignedUrl(signURL, fileBuffer, contentType);
19
+ return finalStaticUrl;
20
+ }
21
+ }
22
+ //# sourceMappingURL=upload-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-service.js","sourceRoot":"","sources":["../../src/services/upload-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAUjD,MAAM,OAAO,aAAa;IACK;IAA7B,YAA6B,MAG5B;QAH4B,WAAM,GAAN,MAAM,CAGlC;IAAG,CAAC;IAEL,KAAK,CAAC,eAAe,CAAC,EACpB,QAAQ,EACR,SAAS,EACT,UAAU,GAAG,iBAAiB,EAC9B,WAAW,EACX,SAAS,GACa;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QACpC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChD,MAAM,GAAG,GAAG,GAAG,SAAS,IAAI,SAAS,GAAG,MAAM,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC;QAEhE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,eAAe,CACnE,GAAG,EACH,QAAQ,EACR,UAAU,CACX,CAAC;QAEF,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACxD,MAAM,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;QAEzE,OAAO,cAAc,CAAC;IACxB,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ export declare function detectAudioMimeType(filePath: string): string;
2
+ export declare function detectImageMimeType(filePath: string): string;
3
+ export declare function safeExtension(filePath: string): string;
4
+ export declare function validateAudioFile(filePath: string): void;
5
+ export declare function validateImageFile(filePath: string): void;
@@ -0,0 +1,69 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import mime from "mime-types";
4
+ import { AppError } from "../core/errors.js";
5
+ const AUDIO_CONFIG = {
6
+ acceptedTypes: [
7
+ "audio/mpeg",
8
+ "audio/wav",
9
+ "audio/ogg",
10
+ "audio/flac",
11
+ "audio/aac",
12
+ ],
13
+ normalizeMap: {
14
+ "audio/wave": "audio/wav",
15
+ "audio/x-flac": "audio/flac",
16
+ "audio/x-aac": "audio/aac",
17
+ },
18
+ maxSize: 50 * 1024 * 1024,
19
+ label: "audio",
20
+ };
21
+ const IMAGE_CONFIG = {
22
+ acceptedTypes: ["image/png", "image/jpeg"],
23
+ normalizeMap: {
24
+ "image/jpg": "image/jpeg",
25
+ },
26
+ maxSize: 10 * 1024 * 1024,
27
+ label: "image",
28
+ };
29
+ function detectMime(filePath, normalizeMap) {
30
+ const mimeType = mime.lookup(filePath);
31
+ if (!mimeType) {
32
+ throw new AppError(`Cannot detect MIME type for file: ${filePath}`, "INVALID_PARAMS");
33
+ }
34
+ return normalizeMap[mimeType] ?? mimeType;
35
+ }
36
+ function validateFile(filePath, config) {
37
+ if (!fs.existsSync(filePath)) {
38
+ throw new AppError(`File not found: ${filePath}`, "FILE_NOT_FOUND");
39
+ }
40
+ const mimeType = detectMime(filePath, config.normalizeMap);
41
+ if (!config.acceptedTypes.includes(mimeType)) {
42
+ throw new AppError(`Unsupported ${config.label} type: ${mimeType}. Accepted: ${config.acceptedTypes.join(", ")}`, "UNSUPPORTED_TYPE");
43
+ }
44
+ const stats = fs.statSync(filePath);
45
+ if (stats.size > config.maxSize) {
46
+ const maxMB = config.maxSize / 1024 / 1024;
47
+ throw new AppError(`File too large: ${(stats.size / 1024 / 1024).toFixed(2)}MB. Max: ${maxMB}MB`, "FILE_TOO_LARGE");
48
+ }
49
+ }
50
+ export function detectAudioMimeType(filePath) {
51
+ return detectMime(filePath, AUDIO_CONFIG.normalizeMap);
52
+ }
53
+ export function detectImageMimeType(filePath) {
54
+ return detectMime(filePath, IMAGE_CONFIG.normalizeMap);
55
+ }
56
+ export function safeExtension(filePath) {
57
+ const ext = path.extname(filePath).slice(1).toLowerCase();
58
+ if (!/^[a-z0-9]+$/.test(ext)) {
59
+ throw new AppError(`Invalid file extension: ${ext}`, "INVALID_PARAMS");
60
+ }
61
+ return ext;
62
+ }
63
+ export function validateAudioFile(filePath) {
64
+ validateFile(filePath, AUDIO_CONFIG);
65
+ }
66
+ export function validateImageFile(filePath) {
67
+ validateFile(filePath, IMAGE_CONFIG);
68
+ }
69
+ //# sourceMappingURL=file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.js","sourceRoot":"","sources":["../../src/utils/file.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "freebeat-mcp",
3
+ "version": "0.1.0",
4
+ "description": "Freebeat MCP Server",
5
+ "type": "module",
6
+ "bin": {
7
+ "freebeat-mcp": "./dist/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/index.js",
13
+ "dev": "tsx src/index.ts",
14
+ "pretest": "npm run build",
15
+ "test": "vitest run",
16
+ "test:watch": "vitest",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "keywords": ["mcp", "freebeat", "ai", "music-video"],
20
+ "author": "Freebeat",
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/freebeatfit/freebeat-mcp.git"
25
+ },
26
+ "homepage": "https://github.com/freebeatfit/freebeat-mcp#readme",
27
+ "bugs": {
28
+ "url": "https://github.com/freebeatfit/freebeat-mcp/issues"
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "README.md",
33
+ "LICENSE"
34
+ ],
35
+ "dependencies": {
36
+ "@modelcontextprotocol/sdk": "^1.25.0",
37
+ "axios": "^1.7.0",
38
+ "mime-types": "^2.1.35",
39
+ "zod": "^3.23.0"
40
+ },
41
+ "devDependencies": {
42
+ "@types/mime-types": "^2.1.4",
43
+ "@types/node": "^20.0.0",
44
+ "tsx": "^4.0.0",
45
+ "typescript": "^5.5.0",
46
+ "vitest": "^3.0.0"
47
+ }
48
+ }