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,116 @@
1
+ import { z } from "zod";
2
+ import { AppError } from "../../../core/errors.js";
3
+ import { normalizeGenerationPrompt } from "../../../core/prompt.js";
4
+ import { formatToolError, jsonContent } from "../../../core/response.js";
5
+ export function registerGenerateMusicVideoTool(server, client) {
6
+ server.registerTool("generate_music_video", {
7
+ description: "Start AI music video generation from a music_id returned by upload_audio. Recommended flow: upload_audio -> optional upload_image -> generate_music_video -> get_task_status -> get_task_result. Only call get_task_result after get_task_status returns completed.",
8
+ outputSchema: {
9
+ success: z
10
+ .literal(true)
11
+ .describe("Whether the music video task was created successfully."),
12
+ task_id: z
13
+ .string()
14
+ .describe("The asynchronous task ID for status and result lookups."),
15
+ task_type: z
16
+ .string()
17
+ .describe("The task category returned by Freebeat."),
18
+ status: z
19
+ .string()
20
+ .describe("The initial task status, typically pending."),
21
+ message: z
22
+ .string()
23
+ .describe("A human-readable summary of the task creation result."),
24
+ },
25
+ inputSchema: {
26
+ music_id: z.number().int().describe("Integer audio ID returned by upload_audio."),
27
+ prompt: z
28
+ .string()
29
+ .trim()
30
+ .min(1, "prompt must not be empty or whitespace only")
31
+ .max(2000, "prompt must be at most 2000 characters after trimming")
32
+ .describe("Required task instruction. After trimming whitespace it must be 1 to 2000 characters and should describe how you want the MV task to be done."),
33
+ mv_type: z
34
+ .enum(["abstract", "singing", "storytelling"])
35
+ .optional()
36
+ .default("abstract")
37
+ .describe("MV type. Supported values: abstract, singing, storytelling."),
38
+ style: z
39
+ .string()
40
+ .optional()
41
+ .default("")
42
+ .describe("Optional MV style string, for example Ghibli or cyberpunk."),
43
+ aspect_ratio: z
44
+ .enum(["9:16", "16:9", "1:1", "4:3", "3:4"])
45
+ .optional()
46
+ .default("16:9")
47
+ .describe("Video aspect ratio (default: 16:9)"),
48
+ resolution: z
49
+ .union([z.literal(720), z.literal(1080), z.literal("720p"), z.literal("1080p")])
50
+ .optional()
51
+ .default(720)
52
+ .describe("Video resolution (default: 720). Supported values: 720, 1080."),
53
+ watermark: z
54
+ .boolean()
55
+ .optional()
56
+ .default(false)
57
+ .describe("Whether to apply a watermark to the generated MV."),
58
+ start_ms: z
59
+ .number()
60
+ .int()
61
+ .nonnegative()
62
+ .optional()
63
+ .describe("Audio start time in milliseconds"),
64
+ end_ms: z
65
+ .number()
66
+ .int()
67
+ .nonnegative()
68
+ .optional()
69
+ .describe("Audio end time in milliseconds"),
70
+ reference_image_urls: z
71
+ .array(z
72
+ .string()
73
+ .describe("A reference image URL returned by upload_image."))
74
+ .max(2)
75
+ .optional()
76
+ .describe("Optional reference image URLs from upload_image for character consistency."),
77
+ },
78
+ }, async ({ music_id, prompt, mv_type, style, aspect_ratio, resolution, watermark, start_ms, end_ms, reference_image_urls, }) => {
79
+ try {
80
+ const normalizedPrompt = normalizeGenerationPrompt(prompt);
81
+ if (!Number.isInteger(music_id)) {
82
+ return formatToolError(new AppError("music_id must be an integer", "INVALID_PARAMS"));
83
+ }
84
+ if (start_ms !== undefined && end_ms !== undefined && end_ms <= start_ms) {
85
+ return formatToolError(new AppError("end_ms must be greater than start_ms", "INVALID_PARAMS"));
86
+ }
87
+ const result = await client.generateMusicVideo({
88
+ music_id,
89
+ prompt: normalizedPrompt,
90
+ mv_type: mv_type ?? "abstract",
91
+ style: style ?? "",
92
+ aspect_ratio: aspect_ratio ?? "16:9",
93
+ resolution: resolution === "720p"
94
+ ? 720
95
+ : resolution === "1080p"
96
+ ? 1080
97
+ : (resolution ?? 720),
98
+ watermark: watermark ?? false,
99
+ start_ms,
100
+ end_ms,
101
+ reference_image_urls,
102
+ });
103
+ return jsonContent({
104
+ success: true,
105
+ task_id: result.task_id,
106
+ task_type: result.task_type,
107
+ status: result.status,
108
+ message: `Music video generation queued. Use get_task_status with task_id="${result.task_id}" to check status.`,
109
+ });
110
+ }
111
+ catch (error) {
112
+ return formatToolError(error);
113
+ }
114
+ });
115
+ }
116
+ //# sourceMappingURL=generate-music-video.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-music-video.js","sourceRoot":"","sources":["../../../../src/capabilities/mv/tools/generate-music-video.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { FreebeatApiClient } from "../../services/freebeat-api.js";
3
+ export declare function registerTaskTools(server: McpServer, client: FreebeatApiClient): void;
@@ -0,0 +1,7 @@
1
+ import { registerGetTaskResultTool } from "./tools/get-task-result.js";
2
+ import { registerGetTaskStatusTool } from "./tools/get-task-status.js";
3
+ export function registerTaskTools(server, client) {
4
+ registerGetTaskStatusTool(server, client);
5
+ registerGetTaskResultTool(server, client);
6
+ }
7
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../../src/capabilities/tasks/register.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAEvE,MAAM,UAAU,iBAAiB,CAC/B,MAAiB,EACjB,MAAyB;IAEzB,yBAAyB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,yBAAyB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1 @@
1
+ export { EFFECT_SESSION_TYPE, MUSIC_VIDEO_SESSION_TYPE, mapSessionTypeToTaskType, } from "../../core/task-types.js";
@@ -0,0 +1,2 @@
1
+ export { EFFECT_SESSION_TYPE, MUSIC_VIDEO_SESSION_TYPE, mapSessionTypeToTaskType, } from "../../core/task-types.js";
2
+ //# sourceMappingURL=task-type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-type.js","sourceRoot":"","sources":["../../../src/capabilities/tasks/task-type.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { FreebeatApiClient } from "../../../services/freebeat-api.js";
3
+ export declare function registerGetTaskResultTool(server: McpServer, client: Pick<FreebeatApiClient, "getTaskResult">): void;
@@ -0,0 +1,93 @@
1
+ import { z } from "zod";
2
+ import { AppError } from "../../../core/errors.js";
3
+ import { formatToolError, jsonContent } from "../../../core/response.js";
4
+ import { EFFECT_TASK_TYPE } from "../../effects/task-type.js";
5
+ import { MUSIC_VIDEO_TASK_TYPE } from "../../mv/task-type.js";
6
+ import { mapSessionTypeToTaskType } from "../task-type.js";
7
+ const videoResultSchema = z.object({
8
+ video_url: z
9
+ .string()
10
+ .describe("The final generated video URL."),
11
+ cover_url: z
12
+ .string()
13
+ .describe("The cover image URL for the generated video."),
14
+ }).passthrough();
15
+ function normalizeVideoResult(payload) {
16
+ const parsedResult = videoResultSchema.safeParse(payload);
17
+ return parsedResult.success ? parsedResult.data : null;
18
+ }
19
+ function parseRawResultPayload(payload) {
20
+ try {
21
+ return JSON.parse(payload);
22
+ }
23
+ catch {
24
+ throw new AppError("getTaskResult: resultPayload is not valid JSON", "INVALID_RESPONSE");
25
+ }
26
+ }
27
+ function normalizeTaskResult(result) {
28
+ const task_type = mapSessionTypeToTaskType(result.type);
29
+ const normalizedStatus = result.status.trim().toLowerCase();
30
+ const rawPayload = result.result_payload;
31
+ if (normalizedStatus === "failed") {
32
+ throw new AppError(result.error_message
33
+ ? `Task failed: ${result.error_message}`
34
+ : "Task failed.", "API_ERROR");
35
+ }
36
+ if (normalizedStatus !== "completed") {
37
+ throw new AppError(`Task is not completed yet. Current status: ${result.status}. Call get_task_status until status is completed before calling get_task_result.`, "TASK_NOT_COMPLETED");
38
+ }
39
+ if (task_type !== MUSIC_VIDEO_TASK_TYPE && task_type !== EFFECT_TASK_TYPE) {
40
+ throw new AppError(`getTaskResult: unsupported task type ${task_type}`, "UNSUPPORTED_TYPE");
41
+ }
42
+ if (rawPayload === undefined) {
43
+ throw new AppError("getTaskResult: missing result payload in response", "INVALID_RESPONSE");
44
+ }
45
+ const parsedPayload = parseRawResultPayload(rawPayload);
46
+ const normalizedVideoResult = normalizeVideoResult(parsedPayload);
47
+ if (!normalizedVideoResult) {
48
+ throw new AppError("getTaskResult: resultPayload missing required video_url or cover_url", "INVALID_RESPONSE");
49
+ }
50
+ return {
51
+ success: true,
52
+ task_id: result.task_id,
53
+ task_type,
54
+ status: result.status,
55
+ result: normalizedVideoResult,
56
+ message: `Task result ready. Video: ${normalizedVideoResult.video_url}`,
57
+ };
58
+ }
59
+ export function registerGetTaskResultTool(server, client) {
60
+ server.registerTool("get_task_result", {
61
+ description: "Retrieve the output for a completed Freebeat task. Only call after get_task_status returns completed. Current supported completed MV and effect results return result.video_url and result.cover_url. If the task is still pending or running, this tool returns TASK_NOT_COMPLETED. If the task failed, this tool surfaces the backend failure.",
62
+ outputSchema: {
63
+ success: z
64
+ .literal(true)
65
+ .describe("Whether the task result was retrieved successfully."),
66
+ task_id: z
67
+ .string()
68
+ .describe("The completed asynchronous task ID."),
69
+ task_type: z
70
+ .string()
71
+ .describe("The task category returned by Freebeat."),
72
+ status: z
73
+ .string()
74
+ .describe("The current backend result-query status, for example pending, running, completed, failed, or legacy uppercase variants."),
75
+ result: videoResultSchema.describe("The structured output payload for the completed task. Current supported MV and effect tasks return video_url and cover_url."),
76
+ message: z
77
+ .string()
78
+ .describe("A human-readable summary of the completed task result."),
79
+ },
80
+ inputSchema: {
81
+ task_id: z.string().describe("Task ID returned by a generation tool"),
82
+ },
83
+ }, async ({ task_id }) => {
84
+ try {
85
+ const result = await client.getTaskResult(task_id);
86
+ return jsonContent(normalizeTaskResult(result));
87
+ }
88
+ catch (error) {
89
+ return formatToolError(error);
90
+ }
91
+ });
92
+ }
93
+ //# sourceMappingURL=get-task-result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-task-result.js","sourceRoot":"","sources":["../../../../src/capabilities/tasks/tools/get-task-result.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { FreebeatApiClient } from "../../../services/freebeat-api.js";
3
+ export declare function registerGetTaskStatusTool(server: McpServer, client: Pick<FreebeatApiClient, "getTaskStatus">): void;
@@ -0,0 +1,63 @@
1
+ import { z } from "zod";
2
+ import { formatToolError, jsonContent } from "../../../core/response.js";
3
+ import { mapSessionTypeToTaskType } from "../task-type.js";
4
+ export function registerGetTaskStatusTool(server, client) {
5
+ server.registerTool("get_task_status", {
6
+ description: "Check asynchronous Freebeat task status. Backends may return lowercase status values such as pending, completed, and failed, or legacy uppercase variants. Continue polling until the task reaches a terminal state. Only call get_task_result after status is completed.",
7
+ outputSchema: {
8
+ success: z
9
+ .literal(true)
10
+ .describe("Whether the task status was retrieved successfully."),
11
+ task_id: z
12
+ .string()
13
+ .describe("The asynchronous task ID being queried."),
14
+ task_type: z
15
+ .string()
16
+ .describe("The normalized task category derived from the Freebeat session type."),
17
+ status: z
18
+ .string()
19
+ .describe("The current backend task state, for example pending, running, completed, failed, or legacy uppercase variants."),
20
+ error_message: z
21
+ .string()
22
+ .optional()
23
+ .describe("Backend failure message when the task status is failed."),
24
+ error_code: z
25
+ .union([z.number(), z.string()])
26
+ .optional()
27
+ .describe("Backend failure code when the task status is failed."),
28
+ message: z
29
+ .string()
30
+ .optional()
31
+ .describe("A human-readable summary of the current task state."),
32
+ },
33
+ inputSchema: {
34
+ task_id: z.string().describe("Task ID returned by a generation tool"),
35
+ },
36
+ }, async ({ task_id }) => {
37
+ try {
38
+ const result = await client.getTaskStatus(task_id);
39
+ const task_type = mapSessionTypeToTaskType(result.type);
40
+ const normalizedStatus = result.status.trim().toLowerCase();
41
+ let message;
42
+ if (normalizedStatus === "completed") {
43
+ message = "Task completed. Use get_task_result with task_id to retrieve the output.";
44
+ }
45
+ else if (normalizedStatus === "failed") {
46
+ message = result.error_message ?? "Task failed.";
47
+ }
48
+ return jsonContent({
49
+ success: true,
50
+ task_id: result.task_id,
51
+ task_type,
52
+ status: result.status,
53
+ error_message: result.error_message,
54
+ error_code: result.error_code,
55
+ message,
56
+ });
57
+ }
58
+ catch (error) {
59
+ return formatToolError(error);
60
+ }
61
+ });
62
+ }
63
+ //# sourceMappingURL=get-task-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-task-status.js","sourceRoot":"","sources":["../../../../src/capabilities/tasks/tools/get-task-status.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAEzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,MAAM,UAAU,yBAAyB,CACvC,MAAiB,EACjB,MAAgD;IAEhD,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,WAAW,EACT,2QAA2Q;QAC7Q,YAAY,EAAE;YACZ,OAAO,EAAE,CAAC;iBACP,OAAO,CAAC,IAAI,CAAC;iBACb,QAAQ,CAAC,qDAAqD,CAAC;YAClE,OAAO,EAAE,CAAC;iBACP,MAAM,EAAE;iBACR,QAAQ,CAAC,yCAAyC,CAAC;YACtD,SAAS,EAAE,CAAC;iBACT,MAAM,EAAE;iBACR,QAAQ,CAAC,sEAAsE,CAAC;YACnF,MAAM,EAAE,CAAC;iBACN,MAAM,EAAE;iBACR,QAAQ,CACP,gHAAgH,CACjH;YACH,aAAa,EAAE,CAAC;iBACb,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,yDAAyD,CAAC;YACtE,UAAU,EAAE,CAAC;iBACV,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;iBAC/B,QAAQ,EAAE;iBACV,QAAQ,CAAC,sDAAsD,CAAC;YACnE,OAAO,EAAE,CAAC;iBACP,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,qDAAqD,CAAC;SACnE;QACD,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;SACtE;KACF,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QACpB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YACnD,MAAM,SAAS,GAAG,wBAAwB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACxD,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YAE5D,IAAI,OAA2B,CAAC;YAChC,IAAI,gBAAgB,KAAK,WAAW,EAAE,CAAC;gBACrC,OAAO,GAAG,0EAA0E,CAAC;YACvF,CAAC;iBAAM,IAAI,gBAAgB,KAAK,QAAQ,EAAE,CAAC;gBACzC,OAAO,GAAG,MAAM,CAAC,aAAa,IAAI,cAAc,CAAC;YACnD,CAAC;YAED,OAAO,WAAW,CAAC;gBACjB,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,SAAS;gBACT,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,aAAa,EAAE,MAAM,CAAC,aAAa;gBACnC,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,OAAO;aACR,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function loadConfig(): {
2
+ apiKey: string;
3
+ apiHost: string;
4
+ };
@@ -0,0 +1,11 @@
1
+ export function loadConfig() {
2
+ const apiKey = process.env.FREEBEAT_API_KEY;
3
+ if (!apiKey) {
4
+ throw new Error("FREEBEAT_API_KEY environment variable is required");
5
+ }
6
+ return {
7
+ apiKey,
8
+ apiHost: process.env.FREEBEAT_API_HOST || "https://api.freebeatfit.com",
9
+ };
10
+ }
11
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,UAAU;IACxB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,OAAO;QACL,MAAM;QACN,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,6BAA6B;KACxE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ export type ErrorCode = "INVALID_PARAMS" | "TASK_NOT_COMPLETED" | "FILE_NOT_FOUND" | "UNSUPPORTED_TYPE" | "FILE_TOO_LARGE" | "INVALID_RESPONSE" | "NETWORK_ERROR" | "AUTH_ERROR" | "NOT_FOUND" | "RATE_LIMITED" | "SERVER_ERROR" | "API_ERROR" | "UNKNOWN_ERROR";
2
+ export declare class AppError extends Error {
3
+ readonly code: ErrorCode;
4
+ constructor(message: string, code: ErrorCode);
5
+ }
6
+ export declare function classifyErrorCode(error: unknown): ErrorCode;
@@ -0,0 +1,35 @@
1
+ import axios from "axios";
2
+ export class AppError extends Error {
3
+ code;
4
+ constructor(message, code) {
5
+ super(message);
6
+ this.code = code;
7
+ this.name = "AppError";
8
+ }
9
+ }
10
+ export function classifyErrorCode(error) {
11
+ if (error instanceof AppError) {
12
+ return error.code;
13
+ }
14
+ if (axios.isAxiosError(error)) {
15
+ if (!error.response) {
16
+ return "NETWORK_ERROR";
17
+ }
18
+ const status = error.response.status;
19
+ if (status === 401 || status === 403) {
20
+ return "AUTH_ERROR";
21
+ }
22
+ if (status === 404) {
23
+ return "NOT_FOUND";
24
+ }
25
+ if (status === 429) {
26
+ return "RATE_LIMITED";
27
+ }
28
+ if (status >= 500) {
29
+ return "SERVER_ERROR";
30
+ }
31
+ return "API_ERROR";
32
+ }
33
+ return "UNKNOWN_ERROR";
34
+ }
35
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAiB1B,MAAM,OAAO,QAAS,SAAQ,KAAK;IACY;IAA7C,YAAY,OAAe,EAAkB,IAAe;QAC1D,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,SAAI,GAAJ,IAAI,CAAW;QAE1D,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IAED,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACpB,OAAO,eAAe,CAAC;QACzB,CAAC;QAED,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QACrC,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACrC,OAAO,YAAY,CAAC;QACtB,CAAC;QACD,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,OAAO,WAAW,CAAC;QACrB,CAAC;QACD,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,OAAO,cAAc,CAAC;QACxB,CAAC;QACD,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;YAClB,OAAO,cAAc,CAAC;QACxB,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,OAAO,eAAe,CAAC;AACzB,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function normalizeGenerationPrompt(prompt: string): string;
@@ -0,0 +1,12 @@
1
+ import { AppError } from "./errors.js";
2
+ export function normalizeGenerationPrompt(prompt) {
3
+ const normalizedPrompt = prompt.trim();
4
+ if (normalizedPrompt.length === 0) {
5
+ throw new AppError("prompt must not be empty or whitespace only", "INVALID_PARAMS");
6
+ }
7
+ if (normalizedPrompt.length > 2000) {
8
+ throw new AppError("prompt must be at most 2000 characters after trimming", "INVALID_PARAMS");
9
+ }
10
+ return normalizedPrompt;
11
+ }
12
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/core/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,MAAM,UAAU,yBAAyB,CAAC,MAAc;IACtD,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAEvC,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,QAAQ,CAChB,6CAA6C,EAC7C,gBAAgB,CACjB,CAAC;IACJ,CAAC;IAED,IAAI,gBAAgB,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QACnC,MAAM,IAAI,QAAQ,CAChB,uDAAuD,EACvD,gBAAgB,CACjB,CAAC;IACJ,CAAC;IAED,OAAO,gBAAgB,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,14 @@
1
+ export declare function formatToolError(error: unknown): {
2
+ content: [{
3
+ type: "text";
4
+ text: string;
5
+ }];
6
+ isError: true;
7
+ };
8
+ export declare function jsonContent<T extends Record<string, unknown>>(payload: T): {
9
+ content: [{
10
+ type: "text";
11
+ text: string;
12
+ }];
13
+ structuredContent: T;
14
+ };
@@ -0,0 +1,26 @@
1
+ import { classifyErrorCode } from "./errors.js";
2
+ export function formatToolError(error) {
3
+ const message = error instanceof Error ? error.message : String(error);
4
+ const code = classifyErrorCode(error);
5
+ return {
6
+ content: [
7
+ {
8
+ type: "text",
9
+ text: JSON.stringify({ success: false, error: message, code }),
10
+ },
11
+ ],
12
+ isError: true,
13
+ };
14
+ }
15
+ export function jsonContent(payload) {
16
+ return {
17
+ content: [
18
+ {
19
+ type: "text",
20
+ text: JSON.stringify(payload),
21
+ },
22
+ ],
23
+ structuredContent: payload,
24
+ };
25
+ }
26
+ //# sourceMappingURL=response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/core/response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,UAAU,eAAe,CAAC,KAAc;IAI5C,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAEtC,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;aAC/D;SACF;QACD,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAoC,OAAU;IAIvE,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;aAC9B;SACF;QACD,iBAAiB,EAAE,OAAO;KAC3B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare const MUSIC_VIDEO_SESSION_TYPE = 0;
2
+ export declare const EFFECT_SESSION_TYPE = 3;
3
+ export declare const MUSIC_VIDEO_TASK_TYPE = "music_video_generation";
4
+ export declare const EFFECT_TASK_TYPE = "effect_generation";
5
+ export type SessionType = number | string;
6
+ export declare function mapSessionTypeToTaskType(type: SessionType): string;
@@ -0,0 +1,20 @@
1
+ export const MUSIC_VIDEO_SESSION_TYPE = 0;
2
+ export const EFFECT_SESSION_TYPE = 3;
3
+ export const MUSIC_VIDEO_TASK_TYPE = "music_video_generation";
4
+ export const EFFECT_TASK_TYPE = "effect_generation";
5
+ export function mapSessionTypeToTaskType(type) {
6
+ const normalizedType = typeof type === "string"
7
+ ? type.trim().toLowerCase()
8
+ : type;
9
+ if (normalizedType === MUSIC_VIDEO_SESSION_TYPE ||
10
+ normalizedType === MUSIC_VIDEO_TASK_TYPE) {
11
+ return MUSIC_VIDEO_TASK_TYPE;
12
+ }
13
+ if (normalizedType === EFFECT_SESSION_TYPE ||
14
+ normalizedType === EFFECT_TASK_TYPE ||
15
+ normalizedType === "effects_generation") {
16
+ return EFFECT_TASK_TYPE;
17
+ }
18
+ return typeof type === "string" ? type : `unknown_${type}`;
19
+ }
20
+ //# sourceMappingURL=task-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-types.js","sourceRoot":"","sources":["../../src/core/task-types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAC1C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC,MAAM,CAAC,MAAM,qBAAqB,GAAG,wBAAwB,CAAC;AAC9D,MAAM,CAAC,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AAIpD,MAAM,UAAU,wBAAwB,CAAC,IAAiB;IACxD,MAAM,cAAc,GAClB,OAAO,IAAI,KAAK,QAAQ;QACtB,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;QAC3B,CAAC,CAAC,IAAI,CAAC;IAEX,IACE,cAAc,KAAK,wBAAwB;QAC3C,cAAc,KAAK,qBAAqB,EACxC,CAAC;QACD,OAAO,qBAAqB,CAAC;IAC/B,CAAC;IAED,IACE,cAAc,KAAK,mBAAmB;QACtC,cAAc,KAAK,gBAAgB;QACnC,cAAc,KAAK,oBAAoB,EACvC,CAAC;QACD,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC;AAC7D,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const MUSIC_VIDEO_TASK_TYPE = "music_video_generation";
@@ -0,0 +1,2 @@
1
+ export const MUSIC_VIDEO_TASK_TYPE = "music_video_generation";
2
+ //# sourceMappingURL=tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/core/tasks.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG,wBAAwB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ interface ToolSchemaOverride {
3
+ inputSchema?: Record<string, unknown>;
4
+ outputSchema?: Record<string, unknown>;
5
+ }
6
+ export declare function overrideToolSchemas(server: McpServer, toolName: string, override: ToolSchemaOverride): void;
7
+ export {};
@@ -0,0 +1,64 @@
1
+ import { toJsonSchemaCompat } from "@modelcontextprotocol/sdk/server/zod-json-schema-compat.js";
2
+ import { normalizeObjectSchema } from "@modelcontextprotocol/sdk/server/zod-compat.js";
3
+ import { ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
4
+ const EMPTY_OBJECT_JSON_SCHEMA = {
5
+ type: "object",
6
+ properties: {},
7
+ };
8
+ const CUSTOM_TOOL_SCHEMAS = Symbol("custom-tool-schemas");
9
+ function toInputJsonSchema(schema) {
10
+ const objectSchema = normalizeObjectSchema(schema);
11
+ if (!objectSchema) {
12
+ return EMPTY_OBJECT_JSON_SCHEMA;
13
+ }
14
+ return toJsonSchemaCompat(objectSchema, {
15
+ strictUnions: true,
16
+ pipeStrategy: "input",
17
+ });
18
+ }
19
+ function toOutputJsonSchema(schema) {
20
+ const objectSchema = normalizeObjectSchema(schema);
21
+ if (!objectSchema) {
22
+ return undefined;
23
+ }
24
+ return toJsonSchemaCompat(objectSchema, {
25
+ strictUnions: true,
26
+ pipeStrategy: "output",
27
+ });
28
+ }
29
+ export function overrideToolSchemas(server, toolName, override) {
30
+ const internalServer = server;
31
+ const registeredTools = internalServer._registeredTools;
32
+ if (!registeredTools) {
33
+ return;
34
+ }
35
+ internalServer[CUSTOM_TOOL_SCHEMAS] = {
36
+ ...internalServer[CUSTOM_TOOL_SCHEMAS],
37
+ [toolName]: {
38
+ ...internalServer[CUSTOM_TOOL_SCHEMAS]?.[toolName],
39
+ ...override,
40
+ },
41
+ };
42
+ server.server.setRequestHandler(ListToolsRequestSchema, () => ({
43
+ tools: Object.entries(registeredTools)
44
+ .filter(([, tool]) => tool.enabled)
45
+ .map(([name, tool]) => {
46
+ const schemaOverride = internalServer[CUSTOM_TOOL_SCHEMAS]?.[name];
47
+ const toolDefinition = {
48
+ name,
49
+ title: tool.title,
50
+ description: tool.description,
51
+ inputSchema: schemaOverride?.inputSchema ?? toInputJsonSchema(tool.inputSchema),
52
+ annotations: tool.annotations,
53
+ execution: tool.execution,
54
+ _meta: tool._meta,
55
+ };
56
+ const outputSchema = schemaOverride?.outputSchema ?? toOutputJsonSchema(tool.outputSchema);
57
+ if (outputSchema) {
58
+ toolDefinition.outputSchema = outputSchema;
59
+ }
60
+ return toolDefinition;
61
+ }),
62
+ }));
63
+ }
64
+ //# sourceMappingURL=tool-schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-schemas.js","sourceRoot":"","sources":["../../src/core/tool-schemas.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4DAA4D,CAAC;AAChG,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAE5E,MAAM,wBAAwB,GAAG;IAC/B,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE,EAAE;CACf,CAAC;AAEF,MAAM,mBAAmB,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAwB1D,SAAS,iBAAiB,CAAC,MAAe;IACxC,MAAM,YAAY,GAAG,qBAAqB,CAAC,MAAe,CAAC,CAAC;IAC5D,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,wBAAwB,CAAC;IAClC,CAAC;IAED,OAAO,kBAAkB,CAAC,YAAY,EAAE;QACtC,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,OAAO;KACtB,CAA4B,CAAC;AAChC,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAe;IACzC,MAAM,YAAY,GAAG,qBAAqB,CAAC,MAAe,CAAC,CAAC;IAC5D,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,kBAAkB,CAAC,YAAY,EAAE;QACtC,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,QAAQ;KACvB,CAA4B,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,MAAiB,EACjB,QAAgB,EAChB,QAA4B;IAE5B,MAAM,cAAc,GAAG,MAA4C,CAAC;IACpE,MAAM,eAAe,GAAG,cAAc,CAAC,gBAAgB,CAAC;IACxD,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,OAAO;IACT,CAAC;IAED,cAAc,CAAC,mBAAmB,CAAC,GAAG;QACpC,GAAG,cAAc,CAAC,mBAAmB,CAAC;QACtC,CAAC,QAAQ,CAAC,EAAE;YACV,GAAG,cAAc,CAAC,mBAAmB,CAAC,EAAE,CAAC,QAAQ,CAAC;YAClD,GAAG,QAAQ;SACZ;KACF,CAAC;IAEF,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7D,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC;aACnC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;aAClC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;YACpB,MAAM,cAAc,GAAG,cAAc,CAAC,mBAAmB,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YACnE,MAAM,cAAc,GAA4B;gBAC9C,IAAI;gBACJ,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,WAAW,EAAE,cAAc,EAAE,WAAW,IAAI,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC;gBAC/E,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,KAAK,EAAE,IAAI,CAAC,KAAK;aAClB,CAAC;YAEF,MAAM,YAAY,GAAG,cAAc,EAAE,YAAY,IAAI,kBAAkB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC3F,IAAI,YAAY,EAAE,CAAC;gBACjB,cAAc,CAAC,YAAY,GAAG,YAAY,CAAC;YAC7C,CAAC;YAED,OAAO,cAAc,CAAC;QACxB,CAAC,CAAC;KACL,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from "module";
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { registerAssetTools } from "./capabilities/assets/register.js";
6
+ import { registerEffectTools } from "./capabilities/effects/register.js";
7
+ import { registerMvTools } from "./capabilities/mv/register.js";
8
+ import { registerTaskTools } from "./capabilities/tasks/register.js";
9
+ import { loadConfig } from "./core/config.js";
10
+ import { FreebeatApiClient } from "./services/freebeat-api.js";
11
+ const require = createRequire(import.meta.url);
12
+ const { version } = require("../package.json");
13
+ const server = new McpServer({
14
+ name: "freebeat-mcp",
15
+ version,
16
+ });
17
+ const { apiHost, apiKey } = loadConfig();
18
+ const client = new FreebeatApiClient(apiHost, apiKey);
19
+ registerAssetTools(server, client);
20
+ registerEffectTools(server, client);
21
+ registerMvTools(server, client);
22
+ registerTaskTools(server, client);
23
+ const transport = new StdioServerTransport();
24
+ await server.connect(transport);
25
+ console.error("freebeat-mcp server running on stdio");
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAE/D,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAwB,CAAC;AAEtE,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,cAAc;IACpB,OAAO;CACR,CAAC,CAAC;AAEH,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;AACzC,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AAEtD,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACnC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACpC,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAChC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAElC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAEhC,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC"}