navidrome-mcp 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +397 -0
  3. package/dist/capabilities.d.ts +20 -0
  4. package/dist/capabilities.d.ts.map +1 -0
  5. package/dist/capabilities.js +25 -0
  6. package/dist/capabilities.js.map +1 -0
  7. package/dist/client/auth-manager.d.ts +27 -0
  8. package/dist/client/auth-manager.d.ts.map +1 -0
  9. package/dist/client/auth-manager.js +54 -0
  10. package/dist/client/auth-manager.js.map +1 -0
  11. package/dist/client/navidrome-client.d.ts +28 -0
  12. package/dist/client/navidrome-client.d.ts.map +1 -0
  13. package/dist/client/navidrome-client.js +84 -0
  14. package/dist/client/navidrome-client.js.map +1 -0
  15. package/dist/config.d.ts +41 -0
  16. package/dist/config.d.ts.map +1 -0
  17. package/dist/config.js +132 -0
  18. package/dist/config.js.map +1 -0
  19. package/dist/constants/defaults.d.ts +29 -0
  20. package/dist/constants/defaults.d.ts.map +1 -0
  21. package/dist/constants/defaults.js +37 -0
  22. package/dist/constants/defaults.js.map +1 -0
  23. package/dist/constants/timeouts.d.ts +66 -0
  24. package/dist/constants/timeouts.d.ts.map +1 -0
  25. package/dist/constants/timeouts.js +66 -0
  26. package/dist/constants/timeouts.js.map +1 -0
  27. package/dist/index.d.ts +20 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +70 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/resources/index.d.ts +21 -0
  32. package/dist/resources/index.d.ts.map +1 -0
  33. package/dist/resources/index.js +83 -0
  34. package/dist/resources/index.js.map +1 -0
  35. package/dist/schemas/common.d.ts +68 -0
  36. package/dist/schemas/common.d.ts.map +1 -0
  37. package/dist/schemas/common.js +69 -0
  38. package/dist/schemas/common.js.map +1 -0
  39. package/dist/schemas/index.d.ts +21 -0
  40. package/dist/schemas/index.d.ts.map +1 -0
  41. package/dist/schemas/index.js +24 -0
  42. package/dist/schemas/index.js.map +1 -0
  43. package/dist/schemas/pagination.d.ts +153 -0
  44. package/dist/schemas/pagination.d.ts.map +1 -0
  45. package/dist/schemas/pagination.js +93 -0
  46. package/dist/schemas/pagination.js.map +1 -0
  47. package/dist/schemas/validation.d.ts +147 -0
  48. package/dist/schemas/validation.d.ts.map +1 -0
  49. package/dist/schemas/validation.js +143 -0
  50. package/dist/schemas/validation.js.map +1 -0
  51. package/dist/tools/handlers/lastfm-handlers.d.ts +5 -0
  52. package/dist/tools/handlers/lastfm-handlers.d.ts.map +1 -0
  53. package/dist/tools/handlers/lastfm-handlers.js +143 -0
  54. package/dist/tools/handlers/lastfm-handlers.js.map +1 -0
  55. package/dist/tools/handlers/lyrics-handlers.d.ts +5 -0
  56. package/dist/tools/handlers/lyrics-handlers.d.ts.map +1 -0
  57. package/dist/tools/handlers/lyrics-handlers.js +51 -0
  58. package/dist/tools/handlers/lyrics-handlers.js.map +1 -0
  59. package/dist/tools/handlers/playlist-handlers.d.ts +5 -0
  60. package/dist/tools/handlers/playlist-handlers.d.ts.map +1 -0
  61. package/dist/tools/handlers/playlist-handlers.js +316 -0
  62. package/dist/tools/handlers/playlist-handlers.js.map +1 -0
  63. package/dist/tools/handlers/queue-handlers.d.ts +5 -0
  64. package/dist/tools/handlers/queue-handlers.d.ts.map +1 -0
  65. package/dist/tools/handlers/queue-handlers.js +135 -0
  66. package/dist/tools/handlers/queue-handlers.js.map +1 -0
  67. package/dist/tools/handlers/radio-handlers.d.ts +5 -0
  68. package/dist/tools/handlers/radio-handlers.d.ts.map +1 -0
  69. package/dist/tools/handlers/radio-handlers.js +323 -0
  70. package/dist/tools/handlers/radio-handlers.js.map +1 -0
  71. package/dist/tools/handlers/registry.d.ts +26 -0
  72. package/dist/tools/handlers/registry.d.ts.map +1 -0
  73. package/dist/tools/handlers/registry.js +77 -0
  74. package/dist/tools/handlers/registry.js.map +1 -0
  75. package/dist/tools/handlers/search-handlers.d.ts +5 -0
  76. package/dist/tools/handlers/search-handlers.d.ts.map +1 -0
  77. package/dist/tools/handlers/search-handlers.js +125 -0
  78. package/dist/tools/handlers/search-handlers.js.map +1 -0
  79. package/dist/tools/handlers/tag-handlers.d.ts +5 -0
  80. package/dist/tools/handlers/tag-handlers.d.ts.map +1 -0
  81. package/dist/tools/handlers/tag-handlers.js +155 -0
  82. package/dist/tools/handlers/tag-handlers.js.map +1 -0
  83. package/dist/tools/handlers/user-preferences-handlers.d.ts +5 -0
  84. package/dist/tools/handlers/user-preferences-handlers.d.ts.map +1 -0
  85. package/dist/tools/handlers/user-preferences-handlers.js +155 -0
  86. package/dist/tools/handlers/user-preferences-handlers.js.map +1 -0
  87. package/dist/tools/index.d.ts +19 -0
  88. package/dist/tools/index.d.ts.map +1 -0
  89. package/dist/tools/index.js +20 -0
  90. package/dist/tools/index.js.map +1 -0
  91. package/dist/tools/lastfm-discovery.d.ts +107 -0
  92. package/dist/tools/lastfm-discovery.d.ts.map +1 -0
  93. package/dist/tools/lastfm-discovery.js +238 -0
  94. package/dist/tools/lastfm-discovery.js.map +1 -0
  95. package/dist/tools/library.d.ts +31 -0
  96. package/dist/tools/library.d.ts.map +1 -0
  97. package/dist/tools/library.js +272 -0
  98. package/dist/tools/library.js.map +1 -0
  99. package/dist/tools/listening-history.d.ts +51 -0
  100. package/dist/tools/listening-history.d.ts.map +1 -0
  101. package/dist/tools/listening-history.js +126 -0
  102. package/dist/tools/listening-history.js.map +1 -0
  103. package/dist/tools/lyrics.d.ts +35 -0
  104. package/dist/tools/lyrics.d.ts.map +1 -0
  105. package/dist/tools/lyrics.js +222 -0
  106. package/dist/tools/lyrics.js.map +1 -0
  107. package/dist/tools/media-library.d.ts +46 -0
  108. package/dist/tools/media-library.d.ts.map +1 -0
  109. package/dist/tools/media-library.js +179 -0
  110. package/dist/tools/media-library.js.map +1 -0
  111. package/dist/tools/playlist-management.d.ts +80 -0
  112. package/dist/tools/playlist-management.d.ts.map +1 -0
  113. package/dist/tools/playlist-management.js +384 -0
  114. package/dist/tools/playlist-management.js.map +1 -0
  115. package/dist/tools/queue-management.d.ts +48 -0
  116. package/dist/tools/queue-management.d.ts.map +1 -0
  117. package/dist/tools/queue-management.js +83 -0
  118. package/dist/tools/queue-management.js.map +1 -0
  119. package/dist/tools/radio-discovery.d.ts +95 -0
  120. package/dist/tools/radio-discovery.d.ts.map +1 -0
  121. package/dist/tools/radio-discovery.js +352 -0
  122. package/dist/tools/radio-discovery.js.map +1 -0
  123. package/dist/tools/radio-validation.d.ts +49 -0
  124. package/dist/tools/radio-validation.d.ts.map +1 -0
  125. package/dist/tools/radio-validation.js +463 -0
  126. package/dist/tools/radio-validation.js.map +1 -0
  127. package/dist/tools/radio.d.ts +38 -0
  128. package/dist/tools/radio.d.ts.map +1 -0
  129. package/dist/tools/radio.js +315 -0
  130. package/dist/tools/radio.js.map +1 -0
  131. package/dist/tools/search.d.ts +54 -0
  132. package/dist/tools/search.d.ts.map +1 -0
  133. package/dist/tools/search.js +165 -0
  134. package/dist/tools/search.js.map +1 -0
  135. package/dist/tools/tags.d.ts +63 -0
  136. package/dist/tools/tags.d.ts.map +1 -0
  137. package/dist/tools/tags.js +260 -0
  138. package/dist/tools/tags.js.map +1 -0
  139. package/dist/tools/test.d.ts +50 -0
  140. package/dist/tools/test.d.ts.map +1 -0
  141. package/dist/tools/test.js +121 -0
  142. package/dist/tools/test.js.map +1 -0
  143. package/dist/tools/user-preferences.d.ts +73 -0
  144. package/dist/tools/user-preferences.d.ts.map +1 -0
  145. package/dist/tools/user-preferences.js +231 -0
  146. package/dist/tools/user-preferences.js.map +1 -0
  147. package/dist/transformers/song-transformer.d.ts +122 -0
  148. package/dist/transformers/song-transformer.d.ts.map +1 -0
  149. package/dist/transformers/song-transformer.js +232 -0
  150. package/dist/transformers/song-transformer.js.map +1 -0
  151. package/dist/types/core.d.ts +147 -0
  152. package/dist/types/core.d.ts.map +1 -0
  153. package/dist/types/core.js +19 -0
  154. package/dist/types/core.js.map +1 -0
  155. package/dist/types/index.d.ts +23 -0
  156. package/dist/types/index.d.ts.map +1 -0
  157. package/dist/types/index.js +19 -0
  158. package/dist/types/index.js.map +1 -0
  159. package/dist/types/lyrics.d.ts +58 -0
  160. package/dist/types/lyrics.d.ts.map +1 -0
  161. package/dist/types/lyrics.js +19 -0
  162. package/dist/types/lyrics.js.map +1 -0
  163. package/dist/types/playlists.d.ts +150 -0
  164. package/dist/types/playlists.d.ts.map +1 -0
  165. package/dist/types/playlists.js +19 -0
  166. package/dist/types/playlists.js.map +1 -0
  167. package/dist/types/radio.d.ts +192 -0
  168. package/dist/types/radio.d.ts.map +1 -0
  169. package/dist/types/radio.js +19 -0
  170. package/dist/types/radio.js.map +1 -0
  171. package/dist/types/tags.d.ts +72 -0
  172. package/dist/types/tags.d.ts.map +1 -0
  173. package/dist/types/tags.js +19 -0
  174. package/dist/types/tags.js.map +1 -0
  175. package/dist/utils/cache.d.ts +32 -0
  176. package/dist/utils/cache.d.ts.map +1 -0
  177. package/dist/utils/cache.js +84 -0
  178. package/dist/utils/cache.js.map +1 -0
  179. package/dist/utils/error-formatter.d.ts +108 -0
  180. package/dist/utils/error-formatter.d.ts.map +1 -0
  181. package/dist/utils/error-formatter.js +161 -0
  182. package/dist/utils/error-formatter.js.map +1 -0
  183. package/dist/utils/logger.d.ts +33 -0
  184. package/dist/utils/logger.d.ts.map +1 -0
  185. package/dist/utils/logger.js +52 -0
  186. package/dist/utils/logger.js.map +1 -0
  187. package/dist/utils/message-manager.d.ts +74 -0
  188. package/dist/utils/message-manager.d.ts.map +1 -0
  189. package/dist/utils/message-manager.js +134 -0
  190. package/dist/utils/message-manager.js.map +1 -0
  191. package/dist/utils/version.d.ts +5 -0
  192. package/dist/utils/version.d.ts.map +1 -0
  193. package/dist/utils/version.js +19 -0
  194. package/dist/utils/version.js.map +1 -0
  195. package/package.json +78 -0
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Navidrome MCP Server - Playlist Management Tools
3
+ * Copyright (C) 2025
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU Affero General Public License as published
7
+ * by the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU Affero General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Affero General Public License
16
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+ import type { NavidromeClient } from '../client/navidrome-client.js';
19
+ import type { PlaylistDTO, PlaylistTrackDTO, AddTracksToPlaylistResponse, RemoveTracksFromPlaylistResponse, ReorderPlaylistTrackResponse } from '../types/index.js';
20
+ /**
21
+ * List all playlists accessible to the user
22
+ */
23
+ export declare function listPlaylists(client: NavidromeClient, args: unknown): Promise<{
24
+ playlists: PlaylistDTO[];
25
+ total: number;
26
+ offset: number;
27
+ limit: number;
28
+ }>;
29
+ /**
30
+ * Get a specific playlist by ID
31
+ */
32
+ export declare function getPlaylist(client: NavidromeClient, args: unknown): Promise<PlaylistDTO>;
33
+ /**
34
+ * Create a new playlist
35
+ */
36
+ export declare function createPlaylist(client: NavidromeClient, args: unknown): Promise<PlaylistDTO>;
37
+ /**
38
+ * Update a playlist's metadata
39
+ */
40
+ export declare function updatePlaylist(client: NavidromeClient, args: unknown): Promise<PlaylistDTO>;
41
+ /**
42
+ * Delete a playlist (owner or admin only)
43
+ */
44
+ export declare function deletePlaylist(client: NavidromeClient, args: unknown): Promise<{
45
+ success: boolean;
46
+ id: string;
47
+ message: string;
48
+ }>;
49
+ /**
50
+ * Get all tracks in a playlist
51
+ */
52
+ export declare function getPlaylistTracks(client: NavidromeClient, args: unknown): Promise<{
53
+ tracks: PlaylistTrackDTO[];
54
+ total: number;
55
+ offset: number;
56
+ limit: number;
57
+ playlistId: string;
58
+ format: string;
59
+ m3uContent?: string;
60
+ }>;
61
+ /**
62
+ * Add tracks to a playlist
63
+ */
64
+ export declare function addTracksToPlaylist(client: NavidromeClient, args: unknown): Promise<AddTracksToPlaylistResponse>;
65
+ /**
66
+ * Batch add multiple sets of tracks to a playlist
67
+ */
68
+ export declare function batchAddTracksToPlaylist(client: NavidromeClient, args: unknown): Promise<{
69
+ results: AddTracksToPlaylistResponse[];
70
+ summary: string;
71
+ }>;
72
+ /**
73
+ * Remove tracks from a playlist
74
+ */
75
+ export declare function removeTracksFromPlaylist(client: NavidromeClient, args: unknown): Promise<RemoveTracksFromPlaylistResponse>;
76
+ /**
77
+ * Reorder a track in the playlist
78
+ */
79
+ export declare function reorderPlaylistTrack(client: NavidromeClient, args: unknown): Promise<ReorderPlaylistTrackResponse>;
80
+ //# sourceMappingURL=playlist-management.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playlist-management.d.ts","sourceRoot":"","sources":["../../src/tools/playlist-management.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAOrE,OAAO,KAAK,EACV,WAAW,EACX,gBAAgB,EAIhB,2BAA2B,EAC3B,gCAAgC,EAEhC,4BAA4B,EAC7B,MAAM,mBAAmB,CAAC;AA2E3B;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACnF,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAyBD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAW9F;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAuCjG;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CA4CjG;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAkBvI;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACvF,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC,CAgDD;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,2BAA2B,CAAC,CA8DtH;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC;IAAE,OAAO,EAAE,2BAA2B,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAgEtE;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,gCAAgC,CAAC,CAsBhI;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAwBxH"}
@@ -0,0 +1,384 @@
1
+ /**
2
+ * Navidrome MCP Server - Playlist Management Tools
3
+ * Copyright (C) 2025
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU Affero General Public License as published
7
+ * by the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU Affero General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Affero General Public License
16
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+ import { transformPlaylistsToDTO, transformToPlaylistDTO, formatDuration, } from '../transformers/song-transformer.js';
19
+ import { PlaylistPaginationSchema, PlaylistTracksPaginationSchema, CreatePlaylistSchema, UpdatePlaylistSchema, AddTracksToPlaylistSchema, RemoveTracksFromPlaylistSchema, ReorderPlaylistTrackSchema, PlaylistIdSchema, } from '../schemas/index.js';
20
+ /**
21
+ * Transform raw playlist track data to DTO
22
+ */
23
+ function transformToPlaylistTrackDTO(rawTrack) {
24
+ const dto = {
25
+ id: rawTrack.id,
26
+ mediaFileId: rawTrack.mediaFileId || String(rawTrack.id),
27
+ playlistId: rawTrack.playlistId,
28
+ title: rawTrack.title || '',
29
+ album: rawTrack.album || '',
30
+ artist: rawTrack.artist || '',
31
+ duration: rawTrack.duration || 0,
32
+ durationFormatted: formatDuration(rawTrack.duration),
33
+ };
34
+ // Add optional fields only if they have values
35
+ if (rawTrack.albumArtist) {
36
+ dto.albumArtist = rawTrack.albumArtist;
37
+ }
38
+ if (rawTrack.bitRate !== undefined) {
39
+ dto.bitRate = rawTrack.bitRate;
40
+ }
41
+ if (rawTrack.path) {
42
+ dto.path = rawTrack.path;
43
+ }
44
+ if (rawTrack.trackNumber !== undefined) {
45
+ dto.trackNumber = rawTrack.trackNumber;
46
+ }
47
+ if (rawTrack.year !== undefined) {
48
+ dto.year = rawTrack.year;
49
+ }
50
+ if (rawTrack.genre) {
51
+ dto.genre = rawTrack.genre;
52
+ }
53
+ return dto;
54
+ }
55
+ /**
56
+ * List all playlists accessible to the user
57
+ */
58
+ export async function listPlaylists(client, args) {
59
+ const params = PlaylistPaginationSchema.parse(args);
60
+ try {
61
+ const queryParams = new URLSearchParams({
62
+ _start: params.offset.toString(),
63
+ _end: (params.offset + params.limit).toString(),
64
+ _sort: params.sort,
65
+ _order: params.order,
66
+ });
67
+ const rawPlaylists = await client.request(`/playlist?${queryParams.toString()}`);
68
+ const playlists = transformPlaylistsToDTO(rawPlaylists);
69
+ return {
70
+ playlists,
71
+ total: playlists.length,
72
+ offset: params.offset,
73
+ limit: params.limit,
74
+ };
75
+ }
76
+ catch (error) {
77
+ throw new Error(`Failed to fetch playlists: ${error instanceof Error ? error.message : 'Unknown error'}`);
78
+ }
79
+ }
80
+ /**
81
+ * Get a specific playlist by ID
82
+ */
83
+ export async function getPlaylist(client, args) {
84
+ const params = PlaylistIdSchema.parse(args);
85
+ try {
86
+ const rawPlaylist = await client.request(`/playlist/${params.id}`);
87
+ return transformToPlaylistDTO(rawPlaylist);
88
+ }
89
+ catch (error) {
90
+ throw new Error(`Failed to fetch playlist: ${error instanceof Error ? error.message : 'Unknown error'}`);
91
+ }
92
+ }
93
+ /**
94
+ * Create a new playlist
95
+ */
96
+ export async function createPlaylist(client, args) {
97
+ const params = CreatePlaylistSchema.parse(args);
98
+ try {
99
+ const requestBody = {
100
+ name: params.name,
101
+ public: params.public,
102
+ };
103
+ if (params.comment !== undefined) {
104
+ requestBody.comment = params.comment;
105
+ }
106
+ const rawPlaylist = await client.request('/playlist', {
107
+ method: 'POST',
108
+ headers: {
109
+ 'Content-Type': 'application/json',
110
+ },
111
+ body: JSON.stringify(requestBody),
112
+ });
113
+ const playlist = transformToPlaylistDTO(rawPlaylist);
114
+ // Fix the name if it's not properly returned from API
115
+ if (!playlist.name || playlist.name === 'Unknown Playlist') {
116
+ playlist.name = params.name;
117
+ }
118
+ // Fix the comment if it's not properly returned from API
119
+ if (params.comment && (!playlist.comment || playlist.comment === '')) {
120
+ playlist.comment = params.comment;
121
+ }
122
+ return playlist;
123
+ }
124
+ catch (error) {
125
+ throw new Error(`Failed to create playlist: ${error instanceof Error ? error.message : 'Unknown error'}`);
126
+ }
127
+ }
128
+ /**
129
+ * Update a playlist's metadata
130
+ */
131
+ export async function updatePlaylist(client, args) {
132
+ const params = UpdatePlaylistSchema.parse(args);
133
+ try {
134
+ const requestBody = {};
135
+ if (params.name !== undefined) {
136
+ requestBody.name = params.name;
137
+ }
138
+ if (params.comment !== undefined) {
139
+ requestBody.comment = params.comment;
140
+ }
141
+ if (params.public !== undefined) {
142
+ requestBody.public = params.public;
143
+ }
144
+ const rawPlaylist = await client.request(`/playlist/${params.id}`, {
145
+ method: 'PUT',
146
+ headers: {
147
+ 'Content-Type': 'application/json',
148
+ },
149
+ body: JSON.stringify(requestBody),
150
+ });
151
+ const playlist = transformToPlaylistDTO(rawPlaylist);
152
+ // Fix the name if it was updated but not properly returned from API
153
+ if (params.name && (!playlist.name || playlist.name === 'Unknown Playlist')) {
154
+ playlist.name = params.name;
155
+ }
156
+ // Fix the comment if it was updated but not properly returned from API
157
+ if (params.comment !== undefined && (!playlist.comment || playlist.comment === '')) {
158
+ playlist.comment = params.comment;
159
+ }
160
+ return playlist;
161
+ }
162
+ catch (error) {
163
+ throw new Error(`Failed to update playlist: ${error instanceof Error ? error.message : 'Unknown error'}`);
164
+ }
165
+ }
166
+ /**
167
+ * Delete a playlist (owner or admin only)
168
+ */
169
+ export async function deletePlaylist(client, args) {
170
+ const params = PlaylistIdSchema.parse(args);
171
+ try {
172
+ await client.request(`/playlist/${params.id}`, {
173
+ method: 'DELETE',
174
+ });
175
+ return {
176
+ success: true,
177
+ id: params.id,
178
+ message: `Successfully deleted playlist with ID: ${params.id}`,
179
+ };
180
+ }
181
+ catch (error) {
182
+ throw new Error(`Failed to delete playlist: ${error instanceof Error ? error.message : 'Unknown error'}`);
183
+ }
184
+ }
185
+ /**
186
+ * Get all tracks in a playlist
187
+ */
188
+ export async function getPlaylistTracks(client, args) {
189
+ const params = PlaylistTracksPaginationSchema.parse(args);
190
+ try {
191
+ const queryParams = new URLSearchParams({
192
+ _start: params.offset.toString(),
193
+ _end: (params.offset + params.limit).toString(),
194
+ });
195
+ const headers = {};
196
+ if (params.format === 'm3u') {
197
+ headers['Accept'] = 'audio/x-mpegurl';
198
+ }
199
+ const response = await client.request(`/playlist/${params.playlistId}/tracks?${queryParams.toString()}`, {
200
+ method: 'GET',
201
+ headers,
202
+ });
203
+ if (params.format === 'm3u') {
204
+ return {
205
+ tracks: [],
206
+ total: 0,
207
+ offset: params.offset,
208
+ limit: params.limit,
209
+ playlistId: params.playlistId,
210
+ format: 'm3u',
211
+ m3uContent: response,
212
+ };
213
+ }
214
+ const tracks = Array.isArray(response)
215
+ ? response.map((track) => transformToPlaylistTrackDTO(track))
216
+ : [];
217
+ return {
218
+ tracks,
219
+ total: tracks.length,
220
+ offset: params.offset,
221
+ limit: params.limit,
222
+ playlistId: params.playlistId,
223
+ format: 'json',
224
+ };
225
+ }
226
+ catch (error) {
227
+ throw new Error(`Failed to fetch playlist tracks: ${error instanceof Error ? error.message : 'Unknown error'}`);
228
+ }
229
+ }
230
+ /**
231
+ * Add tracks to a playlist
232
+ */
233
+ export async function addTracksToPlaylist(client, args) {
234
+ const params = AddTracksToPlaylistSchema.parse(args);
235
+ try {
236
+ // Get track count before adding
237
+ const tracksBefore = await getPlaylistTracks(client, {
238
+ playlistId: params.playlistId,
239
+ limit: 500,
240
+ offset: 0
241
+ });
242
+ const countBefore = tracksBefore.tracks.length;
243
+ const requestBody = {};
244
+ if (params.ids !== undefined) {
245
+ requestBody.ids = params.ids;
246
+ }
247
+ if (params.albumIds !== undefined) {
248
+ requestBody.albumIds = params.albumIds;
249
+ }
250
+ if (params.artistIds !== undefined) {
251
+ requestBody.artistIds = params.artistIds;
252
+ }
253
+ if (params.discs !== undefined) {
254
+ requestBody.discs = params.discs;
255
+ }
256
+ const response = await client.request(`/playlist/${params.playlistId}/tracks`, {
257
+ method: 'POST',
258
+ headers: {
259
+ 'Content-Type': 'application/json',
260
+ },
261
+ body: JSON.stringify(requestBody),
262
+ });
263
+ // Get track count after adding
264
+ const tracksAfter = await getPlaylistTracks(client, {
265
+ playlistId: params.playlistId,
266
+ limit: 500,
267
+ offset: 0
268
+ });
269
+ const countAfter = tracksAfter.tracks.length;
270
+ // Use actual count difference as fallback if API response is incorrect
271
+ const apiCount = response.added || 0;
272
+ const actualCount = countAfter - countBefore;
273
+ const addedCount = Math.max(apiCount, actualCount);
274
+ const success = addedCount > 0;
275
+ return {
276
+ added: addedCount,
277
+ message: `Successfully added ${addedCount} track${addedCount !== 1 ? 's' : ''} to playlist`,
278
+ success,
279
+ };
280
+ }
281
+ catch (error) {
282
+ throw new Error(`Failed to add tracks to playlist: ${error instanceof Error ? error.message : 'Unknown error'}`);
283
+ }
284
+ }
285
+ /**
286
+ * Batch add multiple sets of tracks to a playlist
287
+ */
288
+ export async function batchAddTracksToPlaylist(client, args) {
289
+ const params = args;
290
+ if (!params.playlistId) {
291
+ throw new Error('Playlist ID is required');
292
+ }
293
+ if (!params.trackSets || !Array.isArray(params.trackSets)) {
294
+ throw new Error('Track sets array is required');
295
+ }
296
+ if (params.trackSets.length === 0) {
297
+ throw new Error('At least one track set must be provided');
298
+ }
299
+ const results = [];
300
+ let totalAdded = 0;
301
+ let successCount = 0;
302
+ let failedCount = 0;
303
+ for (const trackSet of params.trackSets) {
304
+ try {
305
+ const result = await addTracksToPlaylist(client, {
306
+ playlistId: params.playlistId,
307
+ ...trackSet
308
+ });
309
+ results.push(result);
310
+ if (result.success) {
311
+ successCount++;
312
+ totalAdded += result.added;
313
+ }
314
+ else {
315
+ failedCount++;
316
+ }
317
+ }
318
+ catch (error) {
319
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
320
+ results.push({
321
+ added: 0,
322
+ message: `Failed to add tracks: ${errorMessage}`,
323
+ success: false
324
+ });
325
+ failedCount++;
326
+ }
327
+ }
328
+ let summary = `Successfully processed ${successCount} of ${params.trackSets.length} track sets. `;
329
+ summary += `Total tracks added: ${totalAdded}.`;
330
+ if (failedCount > 0) {
331
+ summary += ` ${failedCount} sets failed.`;
332
+ }
333
+ return {
334
+ results,
335
+ summary
336
+ };
337
+ }
338
+ /**
339
+ * Remove tracks from a playlist
340
+ */
341
+ export async function removeTracksFromPlaylist(client, args) {
342
+ const params = RemoveTracksFromPlaylistSchema.parse(args);
343
+ try {
344
+ const queryParams = new URLSearchParams();
345
+ params.trackIds.forEach(id => queryParams.append('id', id));
346
+ const response = await client.request(`/playlist/${params.playlistId}/tracks?${queryParams.toString()}`, {
347
+ method: 'DELETE',
348
+ });
349
+ const removedIds = response.ids || params.trackIds;
350
+ return {
351
+ ids: removedIds,
352
+ message: `Successfully removed ${removedIds.length} track${removedIds.length !== 1 ? 's' : ''} from playlist`,
353
+ success: removedIds.length > 0,
354
+ };
355
+ }
356
+ catch (error) {
357
+ throw new Error(`Failed to remove tracks from playlist: ${error instanceof Error ? error.message : 'Unknown error'}`);
358
+ }
359
+ }
360
+ /**
361
+ * Reorder a track in the playlist
362
+ */
363
+ export async function reorderPlaylistTrack(client, args) {
364
+ const params = ReorderPlaylistTrackSchema.parse(args);
365
+ try {
366
+ const requestBody = {
367
+ insert_before: params.insert_before.toString(),
368
+ };
369
+ const response = await client.request(`/playlist/${params.playlistId}/tracks/${params.trackId}`, {
370
+ method: 'PUT',
371
+ headers: {
372
+ 'Content-Type': 'application/json',
373
+ },
374
+ body: JSON.stringify(requestBody),
375
+ });
376
+ return {
377
+ id: response.id || parseInt(params.trackId, 10),
378
+ };
379
+ }
380
+ catch (error) {
381
+ throw new Error(`Failed to reorder playlist track: ${error instanceof Error ? error.message : 'Unknown error'}`);
382
+ }
383
+ }
384
+ //# sourceMappingURL=playlist-management.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playlist-management.js","sourceRoot":"","sources":["../../src/tools/playlist-management.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Navidrome MCP Server - Queue Management Tools
3
+ * Copyright (C) 2025
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU Affero General Public License as published
7
+ * by the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU Affero General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Affero General Public License
16
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+ import type { NavidromeClient } from '../client/navidrome-client.js';
19
+ export interface QueueTrack {
20
+ id: string;
21
+ title: string;
22
+ artist: string;
23
+ album: string;
24
+ duration: number;
25
+ }
26
+ export interface QueueResult {
27
+ current: number;
28
+ position: number;
29
+ trackCount: number;
30
+ tracks: QueueTrack[];
31
+ updatedAt?: string;
32
+ message?: string;
33
+ queue?: null;
34
+ }
35
+ export interface SetQueueResult {
36
+ success: boolean;
37
+ message: string;
38
+ trackCount: number;
39
+ current: number;
40
+ }
41
+ export interface ClearQueueResult {
42
+ success: boolean;
43
+ message: string;
44
+ }
45
+ export declare function getQueue(client: NavidromeClient, _args: unknown): Promise<QueueResult>;
46
+ export declare function setQueue(client: NavidromeClient, args: unknown): Promise<SetQueueResult>;
47
+ export declare function clearQueue(client: NavidromeClient, _args: unknown): Promise<ClearQueueResult>;
48
+ //# sourceMappingURL=queue-management.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-management.d.ts","sourceRoot":"","sources":["../../src/tools/queue-management.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAGrE,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,IAAI,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAgC5F;AAQD,wBAAsB,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAoB9F;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAWnG"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Navidrome MCP Server - Queue Management Tools
3
+ * Copyright (C) 2025
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU Affero General Public License as published
7
+ * by the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU Affero General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Affero General Public License
16
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+ import { z } from 'zod';
19
+ import { logger } from '../utils/logger.js';
20
+ export async function getQueue(client, _args) {
21
+ logger.info('Getting playback queue');
22
+ const response = await client.request('/queue');
23
+ if (!response || Object.keys(response).length === 0) {
24
+ return {
25
+ current: 0,
26
+ position: 0,
27
+ trackCount: 0,
28
+ tracks: [],
29
+ message: 'Queue is empty',
30
+ queue: null,
31
+ };
32
+ }
33
+ const result = {
34
+ current: response.current || 0,
35
+ position: response.position || 0,
36
+ trackCount: response.items?.length || 0,
37
+ tracks: (response.items || []).map((track) => ({
38
+ id: track.id,
39
+ title: track.title || '',
40
+ artist: track.artist || '',
41
+ album: track.album || '',
42
+ duration: track.duration || 0,
43
+ })),
44
+ };
45
+ if (response.updatedAt) {
46
+ result.updatedAt = response.updatedAt;
47
+ }
48
+ return result;
49
+ }
50
+ const SetQueueSchema = z.object({
51
+ songIds: z.array(z.string()),
52
+ current: z.number().min(0).optional().default(0),
53
+ position: z.number().min(0).optional().default(0),
54
+ });
55
+ export async function setQueue(client, args) {
56
+ const { songIds, current = 0, position = 0 } = SetQueueSchema.parse(args);
57
+ logger.info(`Setting queue with ${songIds.length} tracks`);
58
+ await client.request('/queue', {
59
+ method: 'POST',
60
+ body: JSON.stringify({
61
+ ids: songIds,
62
+ current,
63
+ position,
64
+ }),
65
+ });
66
+ return {
67
+ success: true,
68
+ message: `Queue set with ${songIds.length} tracks`,
69
+ trackCount: songIds.length,
70
+ current,
71
+ };
72
+ }
73
+ export async function clearQueue(client, _args) {
74
+ logger.info('Clearing playback queue');
75
+ await client.request('/queue', {
76
+ method: 'DELETE',
77
+ });
78
+ return {
79
+ success: true,
80
+ message: 'Queue cleared',
81
+ };
82
+ }
83
+ //# sourceMappingURL=queue-management.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-management.js","sourceRoot":"","sources":["../../src/tools/queue-management.ts"],"names":[],"mappings":"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"}