From 8410bef158dc42f66d2eb85613498dbe90d823d5 Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Sat, 13 Dec 2025 12:40:32 -0500 Subject: [PATCH 1/3] MCP - get_spotify_album --- lib/mcp/getToolErrorResponse.ts | 21 +++++++ lib/mcp/getToolSuccessResponse.ts | 22 +++++++ .../catalogs/registerGetCatalogSongsTool.ts | 10 +-- .../tools/catalogs/registerGetCatalogsTool.ts | 11 +--- .../registerInsertCatalogSongsTool.ts | 11 +--- lib/mcp/tools/images/registerEditImageTool.ts | 13 ++-- .../tools/images/registerGenerateImageTool.ts | 10 +-- lib/mcp/tools/registerContactTeamTool.ts | 12 +--- lib/mcp/tools/registerGetArtistSocialsTool.ts | 3 +- lib/mcp/tools/registerGetLocalTimeTool.ts | 3 +- .../tools/sora2/registerGenerateVideoTool.ts | 11 +--- .../sora2/registerRetrieveVideoContentTool.ts | 11 +--- .../tools/sora2/registerRetrieveVideoTool.ts | 11 +--- lib/mcp/tools/spotify/index.ts | 2 + .../spotify/registerGetSpotifyAlbumTool.ts | 61 +++++++++++++++++++ .../registerGetSpotifyArtistAlbumsTool.ts | 50 +++------------ .../registerGetSpotifyArtistTopTracksTool.ts | 50 +++------------ .../spotify/registerGetSpotifySearchTool.ts | 49 +++------------ lib/mcp/tools/tasks/registerCreateTaskTool.ts | 10 +-- lib/mcp/tools/tasks/registerDeleteTaskTool.ts | 10 +-- lib/mcp/tools/tasks/registerGetTasksTool.ts | 11 +--- lib/mcp/tools/tasks/registerUpdateTaskTool.ts | 10 +-- 22 files changed, 162 insertions(+), 240 deletions(-) create mode 100644 lib/mcp/getToolErrorResponse.ts create mode 100644 lib/mcp/getToolSuccessResponse.ts create mode 100644 lib/mcp/tools/spotify/registerGetSpotifyAlbumTool.ts diff --git a/lib/mcp/getToolErrorResponse.ts b/lib/mcp/getToolErrorResponse.ts new file mode 100644 index 000000000..da6ac0a93 --- /dev/null +++ b/lib/mcp/getToolErrorResponse.ts @@ -0,0 +1,21 @@ +import { CallToolResult } from "./getToolSuccessResponse"; + +/** + * Creates a standardized error response for MCP tools. + * + * @param message - The error message to return + * @returns An MCP tool response with error content + */ +export function getToolErrorResponse(message: string): CallToolResult { + return { + content: [ + { + type: "text" as const, + text: JSON.stringify({ + success: false, + message, + }), + }, + ], + }; +} diff --git a/lib/mcp/getToolSuccessResponse.ts b/lib/mcp/getToolSuccessResponse.ts new file mode 100644 index 000000000..d7635bf07 --- /dev/null +++ b/lib/mcp/getToolSuccessResponse.ts @@ -0,0 +1,22 @@ +import { TextContent } from "@modelcontextprotocol/sdk/types.js"; + +export type CallToolResult = { + content: TextContent[]; +}; + +/** + * Creates a standardized success response for MCP tools. + * + * @param data - The data to return + * @returns An MCP tool response with success content + */ +export function getToolSuccessResponse(data: unknown): CallToolResult { + return { + content: [ + { + type: "text" as const, + text: JSON.stringify(data), + }, + ], + }; +} diff --git a/lib/mcp/tools/catalogs/registerGetCatalogSongsTool.ts b/lib/mcp/tools/catalogs/registerGetCatalogSongsTool.ts index 64e9d1a28..f5b6c5378 100644 --- a/lib/mcp/tools/catalogs/registerGetCatalogSongsTool.ts +++ b/lib/mcp/tools/catalogs/registerGetCatalogSongsTool.ts @@ -4,6 +4,7 @@ import { getCatalogSongsQuerySchema, type GetCatalogSongsQuery, } from "@/lib/catalog/validateGetCatalogSongsQuery"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; /** * Registers the "select_catalog_songs" tool on the MCP server. @@ -41,14 +42,7 @@ export function registerGetCatalogSongsTool(server: McpServer): void { criteria: args.criteria, }); - return { - content: [ - { - type: "text", - text: JSON.stringify(response), - }, - ], - }; + return getToolSuccessResponse(response); }, ); } diff --git a/lib/mcp/tools/catalogs/registerGetCatalogsTool.ts b/lib/mcp/tools/catalogs/registerGetCatalogsTool.ts index 2ee114a26..4de99e35b 100644 --- a/lib/mcp/tools/catalogs/registerGetCatalogsTool.ts +++ b/lib/mcp/tools/catalogs/registerGetCatalogsTool.ts @@ -4,6 +4,7 @@ import { type GetCatalogsQuery, } from "@/lib/catalog/validateGetCatalogsQuery"; import { selectAccountCatalogs } from "@/lib/supabase/account_catalogs/selectAccountCatalogs"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; /** * Registers the "select_catalogs" tool on the MCP server. * Retrieves catalogs associated with the current account for ANY music recommendation request. @@ -28,15 +29,7 @@ export function registerGetCatalogsTool(server: McpServer): void { }, async (args: GetCatalogsQuery) => { const data = await selectAccountCatalogs({ accountIds: [args.account_id] }); - - return { - content: [ - { - type: "text", - text: JSON.stringify(data), - }, - ], - }; + return getToolSuccessResponse(data); }, ); } diff --git a/lib/mcp/tools/catalogs/registerInsertCatalogSongsTool.ts b/lib/mcp/tools/catalogs/registerInsertCatalogSongsTool.ts index 15d66436b..44e12553c 100644 --- a/lib/mcp/tools/catalogs/registerInsertCatalogSongsTool.ts +++ b/lib/mcp/tools/catalogs/registerInsertCatalogSongsTool.ts @@ -4,6 +4,7 @@ import { insertCatalogSongsQuerySchema, type InsertCatalogSongsQuery, } from "@/lib/catalog/validateInsertCatalogSongsQuery"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; /** * Registers the "insert_catalog_songs" tool on the MCP server. @@ -33,15 +34,7 @@ export function registerInsertCatalogSongsTool(server: McpServer): void { }, async (args: InsertCatalogSongsQuery) => { const response = await insertCatalogSongsFunction(args.songs); - - return { - content: [ - { - type: "text", - text: JSON.stringify(response), - }, - ], - }; + return getToolSuccessResponse(response); }, ); } diff --git a/lib/mcp/tools/images/registerEditImageTool.ts b/lib/mcp/tools/images/registerEditImageTool.ts index e7a00cfd2..2e4132d44 100644 --- a/lib/mcp/tools/images/registerEditImageTool.ts +++ b/lib/mcp/tools/images/registerEditImageTool.ts @@ -4,6 +4,8 @@ import { type GenerateAndProcessImageResult, } from "@/lib/image/generateAndProcessImage"; import { editImageQuerySchema, type EditImageQuery } from "@/lib/image/validateEditImageQuery"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { CallToolResult } from "@/lib/mcp/getToolSuccessResponse"; /** * Registers the "edit_image" tool on the MCP server. @@ -18,7 +20,7 @@ export function registerEditImageTool(server: McpServer): void { inputSchema: editImageQuerySchema, description: "Edit existing images.", }, - async (args: EditImageQuery): Promise<{ content: Array<{ type: "text"; text: string }> }> => { + async (args: EditImageQuery): Promise => { const result: GenerateAndProcessImageResult = await generateAndProcessImage( args.prompt, args.account_id, @@ -30,14 +32,7 @@ export function registerEditImageTool(server: McpServer): void { ], ); - return { - content: [ - { - type: "text", - text: JSON.stringify(result), - }, - ], - }; + return getToolSuccessResponse(result); }, ); } diff --git a/lib/mcp/tools/images/registerGenerateImageTool.ts b/lib/mcp/tools/images/registerGenerateImageTool.ts index 363874f5c..4b6c696cd 100644 --- a/lib/mcp/tools/images/registerGenerateImageTool.ts +++ b/lib/mcp/tools/images/registerGenerateImageTool.ts @@ -7,6 +7,7 @@ import { generateImageQuerySchema, type GenerateImageQuery, } from "@/lib/image/validateGenerateImageQuery"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; /** * Registers the "generate_image" tool on the MCP server. @@ -27,14 +28,7 @@ export function registerGenerateImageTool(server: McpServer): void { args.account_id, ); - return { - content: [ - { - type: "text", - text: JSON.stringify(result), - }, - ], - }; + return getToolSuccessResponse(result); }, ); } diff --git a/lib/mcp/tools/registerContactTeamTool.ts b/lib/mcp/tools/registerContactTeamTool.ts index 2e81369b2..1c43370d1 100644 --- a/lib/mcp/tools/registerContactTeamTool.ts +++ b/lib/mcp/tools/registerContactTeamTool.ts @@ -4,6 +4,7 @@ import { contactTeamQuerySchema, type ContactTeamQuery, } from "@/lib/contact/validateContactTeamQuery"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; /** * Registers the "contact_team" tool on the MCP server. @@ -21,16 +22,7 @@ export function registerContactTeamTool(server: McpServer): void { }, async (args: ContactTeamQuery) => { const result = await contactTeam(args); - - return { - content: [ - { - type: "text", - text: JSON.stringify(result), - }, - ], - }; + return getToolSuccessResponse(result); }, ); } - diff --git a/lib/mcp/tools/registerGetArtistSocialsTool.ts b/lib/mcp/tools/registerGetArtistSocialsTool.ts index 804d007d9..ab5b31c9f 100644 --- a/lib/mcp/tools/registerGetArtistSocialsTool.ts +++ b/lib/mcp/tools/registerGetArtistSocialsTool.ts @@ -4,6 +4,7 @@ import { ArtistSocialsQuery, artistSocialsQuerySchema, } from "@/lib/artist/validateArtistSocialsQuery"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; /** * Registers the "get_artist_socials" tool on the MCP server. @@ -21,7 +22,7 @@ export function registerGetArtistSocialsTool(server: McpServer): void { }, async (args: ArtistSocialsQuery) => { const result = await getArtistSocials(args); - return { content: [{ type: "text", text: JSON.stringify(result) }] }; + return getToolSuccessResponse(result); }, ); } diff --git a/lib/mcp/tools/registerGetLocalTimeTool.ts b/lib/mcp/tools/registerGetLocalTimeTool.ts index 2be82876c..35b2afda7 100644 --- a/lib/mcp/tools/registerGetLocalTimeTool.ts +++ b/lib/mcp/tools/registerGetLocalTimeTool.ts @@ -1,6 +1,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { getLocalTime } from "@/lib/time/getLocalTime"; import { GetLocalTimeQuery, getLocalTimeQuerySchema } from "@/lib/time/validateGetLocalTimeQuery"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; /** * Registers the "get_local_time" tool on the MCP server. @@ -18,7 +19,7 @@ export function registerGetLocalTimeTool(server: McpServer): void { }, async (args: GetLocalTimeQuery) => { const result = await getLocalTime(args); - return { content: [{ type: "text", text: JSON.stringify(result) }] }; + return getToolSuccessResponse(result); }, ); } diff --git a/lib/mcp/tools/sora2/registerGenerateVideoTool.ts b/lib/mcp/tools/sora2/registerGenerateVideoTool.ts index 62e3213d3..b15ab3eab 100644 --- a/lib/mcp/tools/sora2/registerGenerateVideoTool.ts +++ b/lib/mcp/tools/sora2/registerGenerateVideoTool.ts @@ -4,6 +4,7 @@ import { generateVideoQuerySchema, type GenerateVideoQuery, } from "@/lib/video/validateGenerateVideoQuery"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; /** * Registers the "generate_sora_2_video" tool on the MCP server. @@ -28,15 +29,7 @@ export function registerGenerateVideoTool(server: McpServer): void { }, async (args: GenerateVideoQuery) => { const result = await generateVideoFunction(args); - - return { - content: [ - { - type: "text", - text: JSON.stringify(result), - }, - ], - }; + return getToolSuccessResponse(result); }, ); } diff --git a/lib/mcp/tools/sora2/registerRetrieveVideoContentTool.ts b/lib/mcp/tools/sora2/registerRetrieveVideoContentTool.ts index 84d997d40..cf1c4b848 100644 --- a/lib/mcp/tools/sora2/registerRetrieveVideoContentTool.ts +++ b/lib/mcp/tools/sora2/registerRetrieveVideoContentTool.ts @@ -4,6 +4,7 @@ import { retrieveVideoQuerySchema, type RetrieveVideoQuery, } from "@/lib/video/validateRetrieveVideoQuery"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; /** * Registers the "retrieve_sora_2_video_content" tool on the MCP server. @@ -31,15 +32,7 @@ export function registerRetrieveVideoContentTool(server: McpServer): void { }, async (args: RetrieveVideoQuery) => { const result = await retrieveVideoContentFunction(args); - - return { - content: [ - { - type: "text", - text: JSON.stringify(result), - }, - ], - }; + return getToolSuccessResponse(result); }, ); } diff --git a/lib/mcp/tools/sora2/registerRetrieveVideoTool.ts b/lib/mcp/tools/sora2/registerRetrieveVideoTool.ts index d1391e4b3..ec665678f 100644 --- a/lib/mcp/tools/sora2/registerRetrieveVideoTool.ts +++ b/lib/mcp/tools/sora2/registerRetrieveVideoTool.ts @@ -4,6 +4,7 @@ import { retrieveVideoQuerySchema, type RetrieveVideoQuery, } from "@/lib/video/validateRetrieveVideoQuery"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; /** * Registers the "retrieve_sora_2_video" tool on the MCP server. @@ -30,15 +31,7 @@ export function registerRetrieveVideoTool(server: McpServer): void { }, async (args: RetrieveVideoQuery) => { const result = await retrieveVideoFunction(args); - - return { - content: [ - { - type: "text", - text: JSON.stringify(result), - }, - ], - }; + return getToolSuccessResponse(result); }, ); } diff --git a/lib/mcp/tools/spotify/index.ts b/lib/mcp/tools/spotify/index.ts index 1bfab1dea..dabfe128e 100644 --- a/lib/mcp/tools/spotify/index.ts +++ b/lib/mcp/tools/spotify/index.ts @@ -2,6 +2,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { registerGetSpotifySearchTool } from "./registerGetSpotifySearchTool"; import { registerGetSpotifyArtistTopTracksTool } from "./registerGetSpotifyArtistTopTracksTool"; import { registerGetSpotifyArtistAlbumsTool } from "./registerGetSpotifyArtistAlbumsTool"; +import { registerGetSpotifyAlbumTool } from "./registerGetSpotifyAlbumTool"; /** * Registers all Spotify-related MCP tools on the server. @@ -12,4 +13,5 @@ export const registerAllSpotifyTools = (server: McpServer): void => { registerGetSpotifySearchTool(server); registerGetSpotifyArtistTopTracksTool(server); registerGetSpotifyArtistAlbumsTool(server); + registerGetSpotifyAlbumTool(server); }; diff --git a/lib/mcp/tools/spotify/registerGetSpotifyAlbumTool.ts b/lib/mcp/tools/spotify/registerGetSpotifyAlbumTool.ts new file mode 100644 index 000000000..a384dc59f --- /dev/null +++ b/lib/mcp/tools/spotify/registerGetSpotifyAlbumTool.ts @@ -0,0 +1,61 @@ +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { z } from "zod"; +import generateAccessToken from "@/lib/spotify/generateAccessToken"; +import getAlbum from "@/lib/spotify/getAlbum"; +import { getToolErrorResponse } from "@/lib/mcp/getToolErrorResponse"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; + +// Zod schema for the MCP tool - matches the original tool interface +const getSpotifyAlbumSchema = z.object({ + id: z.string().min(1, "Album ID is required"), + market: z.string().length(2).optional().describe("ISO 3166-1 alpha-2 country code"), +}); + +type GetSpotifyAlbumArgs = z.infer; + +/** + * Registers the "get_spotify_album" tool on the MCP server. + * Retrieve Spotify catalog information for a single album. + * You should call get_spotify_artist_albums or get_spotify_search first in order to get an album ID to use in the tool call. + * + * @param server - The MCP server instance to register the tool on. + */ +export function registerGetSpotifyAlbumTool(server: McpServer): void { + server.registerTool( + "get_spotify_album", + { + description: + "Retrieve Spotify catalog information for a single album. You should call get_spotify_artist_albums or get_spotify_search first in order to get an album ID to use in the tool call.", + inputSchema: getSpotifyAlbumSchema, + }, + async (args: GetSpotifyAlbumArgs) => { + try { + // Generate Spotify access token + const tokenResult = await generateAccessToken(); + + if (!tokenResult || tokenResult.error || !tokenResult.access_token) { + return getToolErrorResponse("Failed to generate Spotify access token"); + } + + // Call Spotify API to get album + const { album, error } = await getAlbum({ + id: args.id, + market: args.market, + accessToken: tokenResult.access_token, + }); + + if (error || !album) { + return getToolErrorResponse(error?.message || "Failed to fetch Spotify album"); + } + + // Return the album data directly + return getToolSuccessResponse(album); + } catch (error) { + console.error("Error fetching Spotify album:", error); + return getToolErrorResponse( + error instanceof Error ? error.message : "Failed to fetch Spotify album", + ); + } + }, + ); +} diff --git a/lib/mcp/tools/spotify/registerGetSpotifyArtistAlbumsTool.ts b/lib/mcp/tools/spotify/registerGetSpotifyArtistAlbumsTool.ts index 294d243c8..bdfefa55d 100644 --- a/lib/mcp/tools/spotify/registerGetSpotifyArtistAlbumsTool.ts +++ b/lib/mcp/tools/spotify/registerGetSpotifyArtistAlbumsTool.ts @@ -2,6 +2,8 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import generateAccessToken from "@/lib/spotify/generateAccessToken"; import getArtistAlbums from "@/lib/spotify/getArtistAlbums"; +import { getToolErrorResponse } from "@/lib/mcp/getToolErrorResponse"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; // Zod schema for the MCP tool - matches the original tool interface const getSpotifyArtistAlbumsSchema = z.object({ @@ -38,17 +40,7 @@ export function registerGetSpotifyArtistAlbumsTool(server: McpServer): void { const tokenResult = await generateAccessToken(); if (!tokenResult || tokenResult.error || !tokenResult.access_token) { - return { - content: [ - { - type: "text", - text: JSON.stringify({ - success: false, - message: "Failed to generate Spotify access token", - }), - }, - ], - }; + return getToolErrorResponse("Failed to generate Spotify access token"); } // Call Spotify API to get artist albums @@ -62,42 +54,16 @@ export function registerGetSpotifyArtistAlbumsTool(server: McpServer): void { }); if (error || !data) { - return { - content: [ - { - type: "text", - text: JSON.stringify({ - success: false, - message: error?.message || "Failed to fetch Spotify artist albums", - }), - }, - ], - }; + return getToolErrorResponse(error?.message || "Failed to fetch Spotify artist albums"); } // Return the data directly (Spotify API returns paginated album list) - return { - content: [ - { - type: "text", - text: JSON.stringify(data), - }, - ], - }; + return getToolSuccessResponse(data); } catch (error) { console.error("Error fetching Spotify artist albums:", error); - return { - content: [ - { - type: "text", - text: JSON.stringify({ - success: false, - message: - error instanceof Error ? error.message : "Failed to fetch Spotify artist albums", - }), - }, - ], - }; + return getToolErrorResponse( + error instanceof Error ? error.message : "Failed to fetch Spotify artist albums", + ); } }, ); diff --git a/lib/mcp/tools/spotify/registerGetSpotifyArtistTopTracksTool.ts b/lib/mcp/tools/spotify/registerGetSpotifyArtistTopTracksTool.ts index 45ed54ba7..b73def31b 100644 --- a/lib/mcp/tools/spotify/registerGetSpotifyArtistTopTracksTool.ts +++ b/lib/mcp/tools/spotify/registerGetSpotifyArtistTopTracksTool.ts @@ -2,6 +2,8 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import generateAccessToken from "@/lib/spotify/generateAccessToken"; import getArtistTopTracks from "@/lib/spotify/getArtistTopTracks"; +import { getToolErrorResponse } from "@/lib/mcp/getToolErrorResponse"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; // Zod schema for the MCP tool - matches the original tool interface const getSpotifyArtistTopTracksSchema = z.object({ @@ -32,17 +34,7 @@ export function registerGetSpotifyArtistTopTracksTool(server: McpServer): void { const tokenResult = await generateAccessToken(); if (!tokenResult || tokenResult.error || !tokenResult.access_token) { - return { - content: [ - { - type: "text", - text: JSON.stringify({ - success: false, - message: "Failed to generate Spotify access token", - }), - }, - ], - }; + return getToolErrorResponse("Failed to generate Spotify access token"); } // Call Spotify API to get artist top tracks @@ -53,42 +45,16 @@ export function registerGetSpotifyArtistTopTracksTool(server: McpServer): void { }); if (error || !data) { - return { - content: [ - { - type: "text", - text: JSON.stringify({ - success: false, - message: error?.message || "Failed to fetch artist top tracks", - }), - }, - ], - }; + return getToolErrorResponse(error?.message || "Failed to fetch artist top tracks"); } // Return the data directly (Spotify API returns { tracks: [...] }) - return { - content: [ - { - type: "text", - text: JSON.stringify(data), - }, - ], - }; + return getToolSuccessResponse(data); } catch (error) { console.error("Error fetching artist top tracks:", error); - return { - content: [ - { - type: "text", - text: JSON.stringify({ - success: false, - message: - error instanceof Error ? error.message : "Failed to fetch artist top tracks", - }), - }, - ], - }; + return getToolErrorResponse( + error instanceof Error ? error.message : "Failed to fetch artist top tracks", + ); } }, ); diff --git a/lib/mcp/tools/spotify/registerGetSpotifySearchTool.ts b/lib/mcp/tools/spotify/registerGetSpotifySearchTool.ts index d664e6d12..8431f839f 100644 --- a/lib/mcp/tools/spotify/registerGetSpotifySearchTool.ts +++ b/lib/mcp/tools/spotify/registerGetSpotifySearchTool.ts @@ -2,6 +2,8 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import generateAccessToken from "@/lib/spotify/generateAccessToken"; import getSearch from "@/lib/spotify/getSearch"; +import { getToolErrorResponse } from "@/lib/mcp/getToolErrorResponse"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; // Supported Spotify search types const SPOTIFY_TYPES = [ @@ -44,17 +46,7 @@ export function registerGetSpotifySearchTool(server: McpServer): void { const tokenResult = await generateAccessToken(); if (!tokenResult || tokenResult.error || !tokenResult.access_token) { - return { - content: [ - { - type: "text", - text: JSON.stringify({ - success: false, - message: "Failed to generate Spotify access token", - }), - }, - ], - }; + return getToolErrorResponse("Failed to generate Spotify access token"); } // Convert type array to comma-separated string for API @@ -69,17 +61,7 @@ export function registerGetSpotifySearchTool(server: McpServer): void { }); if (error || !data) { - return { - content: [ - { - type: "text", - text: JSON.stringify({ - success: false, - message: error?.message || "Failed to search Spotify", - }), - }, - ], - }; + return getToolErrorResponse(error?.message || "Failed to search Spotify"); } // Filter results to only include requested types (matching original tool behavior) @@ -91,27 +73,12 @@ export function registerGetSpotifySearchTool(server: McpServer): void { } } - return { - content: [ - { - type: "text", - text: JSON.stringify(result), - }, - ], - }; + return getToolSuccessResponse(result); } catch (error) { console.error("Error searching Spotify:", error); - return { - content: [ - { - type: "text", - text: JSON.stringify({ - success: false, - message: error instanceof Error ? error.message : "Failed to search Spotify", - }), - }, - ], - }; + return getToolErrorResponse( + error instanceof Error ? error.message : "Failed to search Spotify", + ); } }, ); diff --git a/lib/mcp/tools/tasks/registerCreateTaskTool.ts b/lib/mcp/tools/tasks/registerCreateTaskTool.ts index 0e19e2914..a14de70c4 100644 --- a/lib/mcp/tools/tasks/registerCreateTaskTool.ts +++ b/lib/mcp/tools/tasks/registerCreateTaskTool.ts @@ -1,6 +1,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { createTask } from "@/lib/tasks/createTask"; import { createTaskBodySchema, type CreateTaskBody } from "@/lib/tasks/validateCreateTaskBody"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; /** * Registers the "create_task" tool on the MCP server. @@ -17,14 +18,7 @@ export function registerCreateTaskTool(server: McpServer): void { }, async (args: CreateTaskBody) => { const result = await createTask(args); - return { - content: [ - { - type: "text", - text: JSON.stringify(result), - }, - ], - }; + return getToolSuccessResponse(result); }, ); } diff --git a/lib/mcp/tools/tasks/registerDeleteTaskTool.ts b/lib/mcp/tools/tasks/registerDeleteTaskTool.ts index 0a764eba0..3e42cd010 100644 --- a/lib/mcp/tools/tasks/registerDeleteTaskTool.ts +++ b/lib/mcp/tools/tasks/registerDeleteTaskTool.ts @@ -2,6 +2,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { deleteTask } from "@/lib/tasks/deleteTask"; import { selectScheduledActions } from "@/lib/supabase/scheduled_actions/selectScheduledActions"; import { deleteTaskBodySchema, type DeleteTaskBody } from "@/lib/tasks/validateDeleteTaskBody"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; /** * Registers the "delete_task" tool on the MCP server. @@ -24,14 +25,7 @@ export function registerDeleteTaskTool(server: McpServer): void { // Delete the task await deleteTask(args); - return { - content: [ - { - type: "text", - text: JSON.stringify(taskToDelete), - }, - ], - }; + return getToolSuccessResponse(taskToDelete); }, ); } diff --git a/lib/mcp/tools/tasks/registerGetTasksTool.ts b/lib/mcp/tools/tasks/registerGetTasksTool.ts index 58005582d..9f5f98d82 100644 --- a/lib/mcp/tools/tasks/registerGetTasksTool.ts +++ b/lib/mcp/tools/tasks/registerGetTasksTool.ts @@ -1,6 +1,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { selectScheduledActions } from "@/lib/supabase/scheduled_actions/selectScheduledActions"; import { GetTasksQuery, getTasksQuerySchema } from "@/lib/tasks/validateGetTasksQuery"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; /** * Registers the "get_tasks" tool on the MCP server. @@ -17,15 +18,7 @@ export function registerGetTasksTool(server: McpServer): void { }, async (args: GetTasksQuery) => { const tasks = await selectScheduledActions(args); - - return { - content: [ - { - type: "text", - text: JSON.stringify(tasks), - }, - ], - }; + return getToolSuccessResponse(tasks); }, ); } diff --git a/lib/mcp/tools/tasks/registerUpdateTaskTool.ts b/lib/mcp/tools/tasks/registerUpdateTaskTool.ts index 9e29132a7..0882adb97 100644 --- a/lib/mcp/tools/tasks/registerUpdateTaskTool.ts +++ b/lib/mcp/tools/tasks/registerUpdateTaskTool.ts @@ -1,6 +1,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { updateTask } from "@/lib/tasks/updateTask"; import { updateTaskBodySchema, type UpdateTaskBody } from "@/lib/tasks/validateUpdateTaskBody"; +import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; /** * Registers the "update_task" tool on the MCP server. @@ -19,14 +20,7 @@ Omitting a field leaves the existing value unchanged.`, }, async (args: UpdateTaskBody) => { const result = await updateTask(args); - return { - content: [ - { - type: "text", - text: JSON.stringify(result), - }, - ], - }; + return getToolSuccessResponse(result); }, ); } From f2337fe251b33ae7097aa32fed4c8e3e3ebda5e2 Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Sat, 13 Dec 2025 12:48:00 -0500 Subject: [PATCH 2/3] refactor helper libs to match type name. --- ...getToolErrorResponse.ts => getToolResultError.ts} | 4 ++-- ...oolSuccessResponse.ts => getToolResultSuccess.ts} | 2 +- .../tools/catalogs/registerGetCatalogSongsTool.ts | 4 ++-- lib/mcp/tools/catalogs/registerGetCatalogsTool.ts | 4 ++-- .../tools/catalogs/registerInsertCatalogSongsTool.ts | 4 ++-- lib/mcp/tools/images/registerEditImageTool.ts | 5 ++--- lib/mcp/tools/images/registerGenerateImageTool.ts | 4 ++-- lib/mcp/tools/registerContactTeamTool.ts | 4 ++-- lib/mcp/tools/registerGetArtistSocialsTool.ts | 4 ++-- lib/mcp/tools/registerGetLocalTimeTool.ts | 4 ++-- lib/mcp/tools/sora2/registerGenerateVideoTool.ts | 4 ++-- .../tools/sora2/registerRetrieveVideoContentTool.ts | 4 ++-- lib/mcp/tools/sora2/registerRetrieveVideoTool.ts | 4 ++-- lib/mcp/tools/spotify/registerGetSpotifyAlbumTool.ts | 12 ++++++------ .../spotify/registerGetSpotifyArtistAlbumsTool.ts | 12 ++++++------ .../spotify/registerGetSpotifyArtistTopTracksTool.ts | 12 ++++++------ .../tools/spotify/registerGetSpotifySearchTool.ts | 12 ++++++------ lib/mcp/tools/tasks/registerCreateTaskTool.ts | 4 ++-- lib/mcp/tools/tasks/registerDeleteTaskTool.ts | 4 ++-- lib/mcp/tools/tasks/registerGetTasksTool.ts | 4 ++-- lib/mcp/tools/tasks/registerUpdateTaskTool.ts | 4 ++-- 21 files changed, 57 insertions(+), 58 deletions(-) rename lib/mcp/{getToolErrorResponse.ts => getToolResultError.ts} (72%) rename lib/mcp/{getToolSuccessResponse.ts => getToolResultSuccess.ts} (85%) diff --git a/lib/mcp/getToolErrorResponse.ts b/lib/mcp/getToolResultError.ts similarity index 72% rename from lib/mcp/getToolErrorResponse.ts rename to lib/mcp/getToolResultError.ts index da6ac0a93..138d138a5 100644 --- a/lib/mcp/getToolErrorResponse.ts +++ b/lib/mcp/getToolResultError.ts @@ -1,4 +1,4 @@ -import { CallToolResult } from "./getToolSuccessResponse"; +import { CallToolResult } from "./getToolResultSuccess"; /** * Creates a standardized error response for MCP tools. @@ -6,7 +6,7 @@ import { CallToolResult } from "./getToolSuccessResponse"; * @param message - The error message to return * @returns An MCP tool response with error content */ -export function getToolErrorResponse(message: string): CallToolResult { +export function getToolResultError(message: string): CallToolResult { return { content: [ { diff --git a/lib/mcp/getToolSuccessResponse.ts b/lib/mcp/getToolResultSuccess.ts similarity index 85% rename from lib/mcp/getToolSuccessResponse.ts rename to lib/mcp/getToolResultSuccess.ts index d7635bf07..43ecf1c4d 100644 --- a/lib/mcp/getToolSuccessResponse.ts +++ b/lib/mcp/getToolResultSuccess.ts @@ -10,7 +10,7 @@ export type CallToolResult = { * @param data - The data to return * @returns An MCP tool response with success content */ -export function getToolSuccessResponse(data: unknown): CallToolResult { +export function getToolResultSuccess(data: unknown): CallToolResult { return { content: [ { diff --git a/lib/mcp/tools/catalogs/registerGetCatalogSongsTool.ts b/lib/mcp/tools/catalogs/registerGetCatalogSongsTool.ts index f5b6c5378..4af5a91ac 100644 --- a/lib/mcp/tools/catalogs/registerGetCatalogSongsTool.ts +++ b/lib/mcp/tools/catalogs/registerGetCatalogSongsTool.ts @@ -4,7 +4,7 @@ import { getCatalogSongsQuerySchema, type GetCatalogSongsQuery, } from "@/lib/catalog/validateGetCatalogSongsQuery"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; /** * Registers the "select_catalog_songs" tool on the MCP server. @@ -42,7 +42,7 @@ export function registerGetCatalogSongsTool(server: McpServer): void { criteria: args.criteria, }); - return getToolSuccessResponse(response); + return getToolResultSuccess(response); }, ); } diff --git a/lib/mcp/tools/catalogs/registerGetCatalogsTool.ts b/lib/mcp/tools/catalogs/registerGetCatalogsTool.ts index 4de99e35b..fdea636b8 100644 --- a/lib/mcp/tools/catalogs/registerGetCatalogsTool.ts +++ b/lib/mcp/tools/catalogs/registerGetCatalogsTool.ts @@ -4,7 +4,7 @@ import { type GetCatalogsQuery, } from "@/lib/catalog/validateGetCatalogsQuery"; import { selectAccountCatalogs } from "@/lib/supabase/account_catalogs/selectAccountCatalogs"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; /** * Registers the "select_catalogs" tool on the MCP server. * Retrieves catalogs associated with the current account for ANY music recommendation request. @@ -29,7 +29,7 @@ export function registerGetCatalogsTool(server: McpServer): void { }, async (args: GetCatalogsQuery) => { const data = await selectAccountCatalogs({ accountIds: [args.account_id] }); - return getToolSuccessResponse(data); + return getToolResultSuccess(data); }, ); } diff --git a/lib/mcp/tools/catalogs/registerInsertCatalogSongsTool.ts b/lib/mcp/tools/catalogs/registerInsertCatalogSongsTool.ts index 44e12553c..1518f0b8e 100644 --- a/lib/mcp/tools/catalogs/registerInsertCatalogSongsTool.ts +++ b/lib/mcp/tools/catalogs/registerInsertCatalogSongsTool.ts @@ -4,7 +4,7 @@ import { insertCatalogSongsQuerySchema, type InsertCatalogSongsQuery, } from "@/lib/catalog/validateInsertCatalogSongsQuery"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; /** * Registers the "insert_catalog_songs" tool on the MCP server. @@ -34,7 +34,7 @@ export function registerInsertCatalogSongsTool(server: McpServer): void { }, async (args: InsertCatalogSongsQuery) => { const response = await insertCatalogSongsFunction(args.songs); - return getToolSuccessResponse(response); + return getToolResultSuccess(response); }, ); } diff --git a/lib/mcp/tools/images/registerEditImageTool.ts b/lib/mcp/tools/images/registerEditImageTool.ts index 2e4132d44..1afe94638 100644 --- a/lib/mcp/tools/images/registerEditImageTool.ts +++ b/lib/mcp/tools/images/registerEditImageTool.ts @@ -4,8 +4,7 @@ import { type GenerateAndProcessImageResult, } from "@/lib/image/generateAndProcessImage"; import { editImageQuerySchema, type EditImageQuery } from "@/lib/image/validateEditImageQuery"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; -import { CallToolResult } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultSuccess, CallToolResult } from "@/lib/mcp/getToolResultSuccess"; /** * Registers the "edit_image" tool on the MCP server. @@ -32,7 +31,7 @@ export function registerEditImageTool(server: McpServer): void { ], ); - return getToolSuccessResponse(result); + return getToolResultSuccess(result); }, ); } diff --git a/lib/mcp/tools/images/registerGenerateImageTool.ts b/lib/mcp/tools/images/registerGenerateImageTool.ts index 4b6c696cd..0f150c08d 100644 --- a/lib/mcp/tools/images/registerGenerateImageTool.ts +++ b/lib/mcp/tools/images/registerGenerateImageTool.ts @@ -7,7 +7,7 @@ import { generateImageQuerySchema, type GenerateImageQuery, } from "@/lib/image/validateGenerateImageQuery"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; /** * Registers the "generate_image" tool on the MCP server. @@ -28,7 +28,7 @@ export function registerGenerateImageTool(server: McpServer): void { args.account_id, ); - return getToolSuccessResponse(result); + return getToolResultSuccess(result); }, ); } diff --git a/lib/mcp/tools/registerContactTeamTool.ts b/lib/mcp/tools/registerContactTeamTool.ts index 1c43370d1..a5f6bd2f4 100644 --- a/lib/mcp/tools/registerContactTeamTool.ts +++ b/lib/mcp/tools/registerContactTeamTool.ts @@ -4,7 +4,7 @@ import { contactTeamQuerySchema, type ContactTeamQuery, } from "@/lib/contact/validateContactTeamQuery"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; /** * Registers the "contact_team" tool on the MCP server. @@ -22,7 +22,7 @@ export function registerContactTeamTool(server: McpServer): void { }, async (args: ContactTeamQuery) => { const result = await contactTeam(args); - return getToolSuccessResponse(result); + return getToolResultSuccess(result); }, ); } diff --git a/lib/mcp/tools/registerGetArtistSocialsTool.ts b/lib/mcp/tools/registerGetArtistSocialsTool.ts index ab5b31c9f..4fe6b10c1 100644 --- a/lib/mcp/tools/registerGetArtistSocialsTool.ts +++ b/lib/mcp/tools/registerGetArtistSocialsTool.ts @@ -4,7 +4,7 @@ import { ArtistSocialsQuery, artistSocialsQuerySchema, } from "@/lib/artist/validateArtistSocialsQuery"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; /** * Registers the "get_artist_socials" tool on the MCP server. @@ -22,7 +22,7 @@ export function registerGetArtistSocialsTool(server: McpServer): void { }, async (args: ArtistSocialsQuery) => { const result = await getArtistSocials(args); - return getToolSuccessResponse(result); + return getToolResultSuccess(result); }, ); } diff --git a/lib/mcp/tools/registerGetLocalTimeTool.ts b/lib/mcp/tools/registerGetLocalTimeTool.ts index 35b2afda7..8d5db480d 100644 --- a/lib/mcp/tools/registerGetLocalTimeTool.ts +++ b/lib/mcp/tools/registerGetLocalTimeTool.ts @@ -1,7 +1,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { getLocalTime } from "@/lib/time/getLocalTime"; import { GetLocalTimeQuery, getLocalTimeQuerySchema } from "@/lib/time/validateGetLocalTimeQuery"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; /** * Registers the "get_local_time" tool on the MCP server. @@ -19,7 +19,7 @@ export function registerGetLocalTimeTool(server: McpServer): void { }, async (args: GetLocalTimeQuery) => { const result = await getLocalTime(args); - return getToolSuccessResponse(result); + return getToolResultSuccess(result); }, ); } diff --git a/lib/mcp/tools/sora2/registerGenerateVideoTool.ts b/lib/mcp/tools/sora2/registerGenerateVideoTool.ts index b15ab3eab..d4e5c0b24 100644 --- a/lib/mcp/tools/sora2/registerGenerateVideoTool.ts +++ b/lib/mcp/tools/sora2/registerGenerateVideoTool.ts @@ -4,7 +4,7 @@ import { generateVideoQuerySchema, type GenerateVideoQuery, } from "@/lib/video/validateGenerateVideoQuery"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; /** * Registers the "generate_sora_2_video" tool on the MCP server. @@ -29,7 +29,7 @@ export function registerGenerateVideoTool(server: McpServer): void { }, async (args: GenerateVideoQuery) => { const result = await generateVideoFunction(args); - return getToolSuccessResponse(result); + return getToolResultSuccess(result); }, ); } diff --git a/lib/mcp/tools/sora2/registerRetrieveVideoContentTool.ts b/lib/mcp/tools/sora2/registerRetrieveVideoContentTool.ts index cf1c4b848..7328f0136 100644 --- a/lib/mcp/tools/sora2/registerRetrieveVideoContentTool.ts +++ b/lib/mcp/tools/sora2/registerRetrieveVideoContentTool.ts @@ -4,7 +4,7 @@ import { retrieveVideoQuerySchema, type RetrieveVideoQuery, } from "@/lib/video/validateRetrieveVideoQuery"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; /** * Registers the "retrieve_sora_2_video_content" tool on the MCP server. @@ -32,7 +32,7 @@ export function registerRetrieveVideoContentTool(server: McpServer): void { }, async (args: RetrieveVideoQuery) => { const result = await retrieveVideoContentFunction(args); - return getToolSuccessResponse(result); + return getToolResultSuccess(result); }, ); } diff --git a/lib/mcp/tools/sora2/registerRetrieveVideoTool.ts b/lib/mcp/tools/sora2/registerRetrieveVideoTool.ts index ec665678f..e59bb2005 100644 --- a/lib/mcp/tools/sora2/registerRetrieveVideoTool.ts +++ b/lib/mcp/tools/sora2/registerRetrieveVideoTool.ts @@ -4,7 +4,7 @@ import { retrieveVideoQuerySchema, type RetrieveVideoQuery, } from "@/lib/video/validateRetrieveVideoQuery"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; /** * Registers the "retrieve_sora_2_video" tool on the MCP server. @@ -31,7 +31,7 @@ export function registerRetrieveVideoTool(server: McpServer): void { }, async (args: RetrieveVideoQuery) => { const result = await retrieveVideoFunction(args); - return getToolSuccessResponse(result); + return getToolResultSuccess(result); }, ); } diff --git a/lib/mcp/tools/spotify/registerGetSpotifyAlbumTool.ts b/lib/mcp/tools/spotify/registerGetSpotifyAlbumTool.ts index a384dc59f..75ab2701b 100644 --- a/lib/mcp/tools/spotify/registerGetSpotifyAlbumTool.ts +++ b/lib/mcp/tools/spotify/registerGetSpotifyAlbumTool.ts @@ -2,8 +2,8 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import generateAccessToken from "@/lib/spotify/generateAccessToken"; import getAlbum from "@/lib/spotify/getAlbum"; -import { getToolErrorResponse } from "@/lib/mcp/getToolErrorResponse"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultError } from "@/lib/mcp/getToolResultError"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; // Zod schema for the MCP tool - matches the original tool interface const getSpotifyAlbumSchema = z.object({ @@ -34,7 +34,7 @@ export function registerGetSpotifyAlbumTool(server: McpServer): void { const tokenResult = await generateAccessToken(); if (!tokenResult || tokenResult.error || !tokenResult.access_token) { - return getToolErrorResponse("Failed to generate Spotify access token"); + return getToolResultError("Failed to generate Spotify access token"); } // Call Spotify API to get album @@ -45,14 +45,14 @@ export function registerGetSpotifyAlbumTool(server: McpServer): void { }); if (error || !album) { - return getToolErrorResponse(error?.message || "Failed to fetch Spotify album"); + return getToolResultError(error?.message || "Failed to fetch Spotify album"); } // Return the album data directly - return getToolSuccessResponse(album); + return getToolResultSuccess(album); } catch (error) { console.error("Error fetching Spotify album:", error); - return getToolErrorResponse( + return getToolResultError( error instanceof Error ? error.message : "Failed to fetch Spotify album", ); } diff --git a/lib/mcp/tools/spotify/registerGetSpotifyArtistAlbumsTool.ts b/lib/mcp/tools/spotify/registerGetSpotifyArtistAlbumsTool.ts index bdfefa55d..ff4b06b29 100644 --- a/lib/mcp/tools/spotify/registerGetSpotifyArtistAlbumsTool.ts +++ b/lib/mcp/tools/spotify/registerGetSpotifyArtistAlbumsTool.ts @@ -2,8 +2,8 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import generateAccessToken from "@/lib/spotify/generateAccessToken"; import getArtistAlbums from "@/lib/spotify/getArtistAlbums"; -import { getToolErrorResponse } from "@/lib/mcp/getToolErrorResponse"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultError } from "@/lib/mcp/getToolResultError"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; // Zod schema for the MCP tool - matches the original tool interface const getSpotifyArtistAlbumsSchema = z.object({ @@ -40,7 +40,7 @@ export function registerGetSpotifyArtistAlbumsTool(server: McpServer): void { const tokenResult = await generateAccessToken(); if (!tokenResult || tokenResult.error || !tokenResult.access_token) { - return getToolErrorResponse("Failed to generate Spotify access token"); + return getToolResultError("Failed to generate Spotify access token"); } // Call Spotify API to get artist albums @@ -54,14 +54,14 @@ export function registerGetSpotifyArtistAlbumsTool(server: McpServer): void { }); if (error || !data) { - return getToolErrorResponse(error?.message || "Failed to fetch Spotify artist albums"); + return getToolResultError(error?.message || "Failed to fetch Spotify artist albums"); } // Return the data directly (Spotify API returns paginated album list) - return getToolSuccessResponse(data); + return getToolResultSuccess(data); } catch (error) { console.error("Error fetching Spotify artist albums:", error); - return getToolErrorResponse( + return getToolResultError( error instanceof Error ? error.message : "Failed to fetch Spotify artist albums", ); } diff --git a/lib/mcp/tools/spotify/registerGetSpotifyArtistTopTracksTool.ts b/lib/mcp/tools/spotify/registerGetSpotifyArtistTopTracksTool.ts index b73def31b..0d89e0293 100644 --- a/lib/mcp/tools/spotify/registerGetSpotifyArtistTopTracksTool.ts +++ b/lib/mcp/tools/spotify/registerGetSpotifyArtistTopTracksTool.ts @@ -2,8 +2,8 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import generateAccessToken from "@/lib/spotify/generateAccessToken"; import getArtistTopTracks from "@/lib/spotify/getArtistTopTracks"; -import { getToolErrorResponse } from "@/lib/mcp/getToolErrorResponse"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultError } from "@/lib/mcp/getToolResultError"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; // Zod schema for the MCP tool - matches the original tool interface const getSpotifyArtistTopTracksSchema = z.object({ @@ -34,7 +34,7 @@ export function registerGetSpotifyArtistTopTracksTool(server: McpServer): void { const tokenResult = await generateAccessToken(); if (!tokenResult || tokenResult.error || !tokenResult.access_token) { - return getToolErrorResponse("Failed to generate Spotify access token"); + return getToolResultError("Failed to generate Spotify access token"); } // Call Spotify API to get artist top tracks @@ -45,14 +45,14 @@ export function registerGetSpotifyArtistTopTracksTool(server: McpServer): void { }); if (error || !data) { - return getToolErrorResponse(error?.message || "Failed to fetch artist top tracks"); + return getToolResultError(error?.message || "Failed to fetch artist top tracks"); } // Return the data directly (Spotify API returns { tracks: [...] }) - return getToolSuccessResponse(data); + return getToolResultSuccess(data); } catch (error) { console.error("Error fetching artist top tracks:", error); - return getToolErrorResponse( + return getToolResultError( error instanceof Error ? error.message : "Failed to fetch artist top tracks", ); } diff --git a/lib/mcp/tools/spotify/registerGetSpotifySearchTool.ts b/lib/mcp/tools/spotify/registerGetSpotifySearchTool.ts index 8431f839f..512d42472 100644 --- a/lib/mcp/tools/spotify/registerGetSpotifySearchTool.ts +++ b/lib/mcp/tools/spotify/registerGetSpotifySearchTool.ts @@ -2,8 +2,8 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import generateAccessToken from "@/lib/spotify/generateAccessToken"; import getSearch from "@/lib/spotify/getSearch"; -import { getToolErrorResponse } from "@/lib/mcp/getToolErrorResponse"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultError } from "@/lib/mcp/getToolResultError"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; // Supported Spotify search types const SPOTIFY_TYPES = [ @@ -46,7 +46,7 @@ export function registerGetSpotifySearchTool(server: McpServer): void { const tokenResult = await generateAccessToken(); if (!tokenResult || tokenResult.error || !tokenResult.access_token) { - return getToolErrorResponse("Failed to generate Spotify access token"); + return getToolResultError("Failed to generate Spotify access token"); } // Convert type array to comma-separated string for API @@ -61,7 +61,7 @@ export function registerGetSpotifySearchTool(server: McpServer): void { }); if (error || !data) { - return getToolErrorResponse(error?.message || "Failed to search Spotify"); + return getToolResultError(error?.message || "Failed to search Spotify"); } // Filter results to only include requested types (matching original tool behavior) @@ -73,10 +73,10 @@ export function registerGetSpotifySearchTool(server: McpServer): void { } } - return getToolSuccessResponse(result); + return getToolResultSuccess(result); } catch (error) { console.error("Error searching Spotify:", error); - return getToolErrorResponse( + return getToolResultError( error instanceof Error ? error.message : "Failed to search Spotify", ); } diff --git a/lib/mcp/tools/tasks/registerCreateTaskTool.ts b/lib/mcp/tools/tasks/registerCreateTaskTool.ts index a14de70c4..1c88e3718 100644 --- a/lib/mcp/tools/tasks/registerCreateTaskTool.ts +++ b/lib/mcp/tools/tasks/registerCreateTaskTool.ts @@ -1,7 +1,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { createTask } from "@/lib/tasks/createTask"; import { createTaskBodySchema, type CreateTaskBody } from "@/lib/tasks/validateCreateTaskBody"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; /** * Registers the "create_task" tool on the MCP server. @@ -18,7 +18,7 @@ export function registerCreateTaskTool(server: McpServer): void { }, async (args: CreateTaskBody) => { const result = await createTask(args); - return getToolSuccessResponse(result); + return getToolResultSuccess(result); }, ); } diff --git a/lib/mcp/tools/tasks/registerDeleteTaskTool.ts b/lib/mcp/tools/tasks/registerDeleteTaskTool.ts index 3e42cd010..5e036c964 100644 --- a/lib/mcp/tools/tasks/registerDeleteTaskTool.ts +++ b/lib/mcp/tools/tasks/registerDeleteTaskTool.ts @@ -2,7 +2,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { deleteTask } from "@/lib/tasks/deleteTask"; import { selectScheduledActions } from "@/lib/supabase/scheduled_actions/selectScheduledActions"; import { deleteTaskBodySchema, type DeleteTaskBody } from "@/lib/tasks/validateDeleteTaskBody"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; /** * Registers the "delete_task" tool on the MCP server. @@ -25,7 +25,7 @@ export function registerDeleteTaskTool(server: McpServer): void { // Delete the task await deleteTask(args); - return getToolSuccessResponse(taskToDelete); + return getToolResultSuccess(taskToDelete); }, ); } diff --git a/lib/mcp/tools/tasks/registerGetTasksTool.ts b/lib/mcp/tools/tasks/registerGetTasksTool.ts index 9f5f98d82..e69caf447 100644 --- a/lib/mcp/tools/tasks/registerGetTasksTool.ts +++ b/lib/mcp/tools/tasks/registerGetTasksTool.ts @@ -1,7 +1,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { selectScheduledActions } from "@/lib/supabase/scheduled_actions/selectScheduledActions"; import { GetTasksQuery, getTasksQuerySchema } from "@/lib/tasks/validateGetTasksQuery"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; /** * Registers the "get_tasks" tool on the MCP server. @@ -18,7 +18,7 @@ export function registerGetTasksTool(server: McpServer): void { }, async (args: GetTasksQuery) => { const tasks = await selectScheduledActions(args); - return getToolSuccessResponse(tasks); + return getToolResultSuccess(tasks); }, ); } diff --git a/lib/mcp/tools/tasks/registerUpdateTaskTool.ts b/lib/mcp/tools/tasks/registerUpdateTaskTool.ts index 0882adb97..1cf2deaf5 100644 --- a/lib/mcp/tools/tasks/registerUpdateTaskTool.ts +++ b/lib/mcp/tools/tasks/registerUpdateTaskTool.ts @@ -1,7 +1,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { updateTask } from "@/lib/tasks/updateTask"; import { updateTaskBodySchema, type UpdateTaskBody } from "@/lib/tasks/validateUpdateTaskBody"; -import { getToolSuccessResponse } from "@/lib/mcp/getToolSuccessResponse"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; /** * Registers the "update_task" tool on the MCP server. @@ -20,7 +20,7 @@ Omitting a field leaves the existing value unchanged.`, }, async (args: UpdateTaskBody) => { const result = await updateTask(args); - return getToolSuccessResponse(result); + return getToolResultSuccess(result); }, ); } From 1ad1b2f7385c87ba8d4424d5b1c19b710fc5f713 Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Sat, 13 Dec 2025 12:52:02 -0500 Subject: [PATCH 3/3] DRY - getCallToolResult --- lib/mcp/getCallToolResult.ts | 22 +++++++++++++++++++ lib/mcp/getToolResultError.ts | 19 ++++++---------- lib/mcp/getToolResultSuccess.ts | 15 ++----------- lib/mcp/tools/images/registerEditImageTool.ts | 3 ++- 4 files changed, 33 insertions(+), 26 deletions(-) create mode 100644 lib/mcp/getCallToolResult.ts diff --git a/lib/mcp/getCallToolResult.ts b/lib/mcp/getCallToolResult.ts new file mode 100644 index 000000000..1da12049c --- /dev/null +++ b/lib/mcp/getCallToolResult.ts @@ -0,0 +1,22 @@ +import { TextContent } from "@modelcontextprotocol/sdk/types.js"; + +export type CallToolResult = { + content: TextContent[]; +}; + +/** + * Creates the base structure for an MCP tool result. + * + * @param text - The text content to include in the response + * @returns An MCP tool response structure + */ +export function getCallToolResult(text: string): CallToolResult { + return { + content: [ + { + type: "text" as const, + text, + }, + ], + }; +} diff --git a/lib/mcp/getToolResultError.ts b/lib/mcp/getToolResultError.ts index 138d138a5..a3240dda6 100644 --- a/lib/mcp/getToolResultError.ts +++ b/lib/mcp/getToolResultError.ts @@ -1,4 +1,4 @@ -import { CallToolResult } from "./getToolResultSuccess"; +import { CallToolResult, getCallToolResult } from "./getCallToolResult"; /** * Creates a standardized error response for MCP tools. @@ -7,15 +7,10 @@ import { CallToolResult } from "./getToolResultSuccess"; * @returns An MCP tool response with error content */ export function getToolResultError(message: string): CallToolResult { - return { - content: [ - { - type: "text" as const, - text: JSON.stringify({ - success: false, - message, - }), - }, - ], - }; + return getCallToolResult( + JSON.stringify({ + success: false, + message, + }), + ); } diff --git a/lib/mcp/getToolResultSuccess.ts b/lib/mcp/getToolResultSuccess.ts index 43ecf1c4d..961df744a 100644 --- a/lib/mcp/getToolResultSuccess.ts +++ b/lib/mcp/getToolResultSuccess.ts @@ -1,8 +1,4 @@ -import { TextContent } from "@modelcontextprotocol/sdk/types.js"; - -export type CallToolResult = { - content: TextContent[]; -}; +import { CallToolResult, getCallToolResult } from "./getCallToolResult"; /** * Creates a standardized success response for MCP tools. @@ -11,12 +7,5 @@ export type CallToolResult = { * @returns An MCP tool response with success content */ export function getToolResultSuccess(data: unknown): CallToolResult { - return { - content: [ - { - type: "text" as const, - text: JSON.stringify(data), - }, - ], - }; + return getCallToolResult(JSON.stringify(data)); } diff --git a/lib/mcp/tools/images/registerEditImageTool.ts b/lib/mcp/tools/images/registerEditImageTool.ts index 1afe94638..f0e0a0511 100644 --- a/lib/mcp/tools/images/registerEditImageTool.ts +++ b/lib/mcp/tools/images/registerEditImageTool.ts @@ -4,7 +4,8 @@ import { type GenerateAndProcessImageResult, } from "@/lib/image/generateAndProcessImage"; import { editImageQuerySchema, type EditImageQuery } from "@/lib/image/validateEditImageQuery"; -import { getToolResultSuccess, CallToolResult } from "@/lib/mcp/getToolResultSuccess"; +import { getToolResultSuccess } from "@/lib/mcp/getToolResultSuccess"; +import { CallToolResult } from "@/lib/mcp/getCallToolResult"; /** * Registers the "edit_image" tool on the MCP server.