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,231 @@
1
+ /**
2
+ * Navidrome MCP Server - User Preferences 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 { logger } from '../utils/logger.js';
19
+ import { transformSongsToDTO, transformAlbumsToDTO, transformArtistsToDTO } from '../transformers/song-transformer.js';
20
+ import { StarItemSchema, SetRatingSchema, StarredItemsPaginationSchema, TopRatedItemsPaginationSchema, } from '../schemas/index.js';
21
+ // Helper function to parse duration from MM:SS format to seconds
22
+ function parseDuration(durationFormatted) {
23
+ const parts = durationFormatted.split(':');
24
+ if (parts.length === 2) {
25
+ const minutes = parseInt(parts[0] || '0', 10);
26
+ const seconds = parseInt(parts[1] || '0', 10);
27
+ return minutes * 60 + seconds;
28
+ }
29
+ return 0;
30
+ }
31
+ // Helper function to extract starredAt timestamp from raw data
32
+ function extractStarredAt(item) {
33
+ // The transformers don't currently include starredAt, so we need to check the raw data
34
+ // This is a limitation that should be addressed in the transformers later
35
+ if (typeof item === 'object' && item !== null && 'starredAt' in item) {
36
+ const starredAt = item.starredAt;
37
+ return typeof starredAt === 'string' ? starredAt : undefined;
38
+ }
39
+ return undefined;
40
+ }
41
+ export async function starItem(client, _config, args) {
42
+ const { id, type } = StarItemSchema.parse(args);
43
+ logger.info(`Starring ${type}: ${id}`);
44
+ // Use Subsonic REST API for starring
45
+ const response = await client.subsonicRequest('/star', { id });
46
+ logger.debug('Star response:', response);
47
+ return {
48
+ success: true,
49
+ message: `Successfully starred ${type}`,
50
+ id,
51
+ type,
52
+ };
53
+ }
54
+ export async function unstarItem(client, _config, args) {
55
+ const { id, type } = StarItemSchema.parse(args);
56
+ logger.info(`Unstarring ${type}: ${id}`);
57
+ // Use Subsonic REST API for unstarring
58
+ const response = await client.subsonicRequest('/unstar', { id });
59
+ logger.debug('Unstar response:', response);
60
+ return {
61
+ success: true,
62
+ message: `Successfully unstarred ${type}`,
63
+ id,
64
+ type,
65
+ };
66
+ }
67
+ export async function setRating(client, _config, args) {
68
+ const { id, type, rating } = SetRatingSchema.parse(args);
69
+ logger.info(`Setting rating ${rating} for ${type}: ${id}`);
70
+ // Use Subsonic REST API for setting rating
71
+ const response = await client.subsonicRequest('/setRating', {
72
+ id,
73
+ rating: rating.toString()
74
+ });
75
+ logger.debug('Set rating response:', response);
76
+ return {
77
+ success: true,
78
+ message: rating > 0 ? `Successfully set rating to ${rating} stars` : 'Successfully removed rating',
79
+ id,
80
+ type,
81
+ rating,
82
+ };
83
+ }
84
+ export async function listStarredItems(client, args) {
85
+ const { type, limit, offset } = StarredItemsPaginationSchema.parse(args);
86
+ logger.info(`Listing starred ${type}`);
87
+ const endpoint = type === 'songs' ? '/song' : type === 'albums' ? '/album' : '/artist';
88
+ // Fetch more items to account for client-side filtering
89
+ const fetchLimit = Math.min(limit * 5, 500); // Fetch 5x requested or max 500
90
+ const response = await client.request(`${endpoint}?_start=${offset}&_end=${offset + fetchLimit}&_sort=starredAt&_order=DESC`);
91
+ // Transform using the appropriate transformer
92
+ let transformedItems;
93
+ if (type === 'songs') {
94
+ const songs = transformSongsToDTO(response);
95
+ transformedItems = songs
96
+ .filter(song => song.starred) // Filter on client side to ensure we only get starred items
97
+ .map(song => {
98
+ const item = { id: song.id };
99
+ if (song.title)
100
+ item.title = song.title;
101
+ if (song.artist)
102
+ item.artist = song.artist;
103
+ if (song.album)
104
+ item.album = song.album;
105
+ if (song.durationFormatted) {
106
+ item.duration = parseDuration(song.durationFormatted);
107
+ }
108
+ const starredAt = extractStarredAt(song);
109
+ if (starredAt)
110
+ item.starredAt = starredAt;
111
+ return item;
112
+ });
113
+ }
114
+ else if (type === 'albums') {
115
+ const albums = transformAlbumsToDTO(response);
116
+ transformedItems = albums
117
+ .filter(album => album.starred)
118
+ .map(album => {
119
+ const item = { id: album.id };
120
+ if (album.name)
121
+ item.name = album.name;
122
+ if (album.artist)
123
+ item.artist = album.artist;
124
+ if (album.releaseYear)
125
+ item.year = album.releaseYear;
126
+ item.songCount = album.songCount; // Always present in albums
127
+ const starredAt = extractStarredAt(album);
128
+ if (starredAt)
129
+ item.starredAt = starredAt;
130
+ return item;
131
+ });
132
+ }
133
+ else {
134
+ const artists = transformArtistsToDTO(response);
135
+ transformedItems = artists
136
+ .filter(artist => artist.starred)
137
+ .map(artist => {
138
+ const item = { id: artist.id };
139
+ if (artist.name)
140
+ item.name = artist.name;
141
+ item.albumCount = artist.albumCount; // Always present
142
+ item.songCount = artist.songCount; // Always present
143
+ const starredAt = extractStarredAt(artist);
144
+ if (starredAt)
145
+ item.starredAt = starredAt;
146
+ return item;
147
+ });
148
+ }
149
+ return {
150
+ type,
151
+ count: transformedItems.length,
152
+ items: transformedItems,
153
+ };
154
+ }
155
+ export async function listTopRated(client, args) {
156
+ const { type, minRating, limit, offset } = TopRatedItemsPaginationSchema.parse(args);
157
+ logger.info(`Listing top rated ${type} (min rating: ${minRating})`);
158
+ const endpoint = type === 'songs' ? '/song' : type === 'albums' ? '/album' : '/artist';
159
+ // Fetch more items to account for filtering by minRating
160
+ // We'll fetch 3x the requested amount to ensure we have enough after filtering
161
+ const fetchLimit = limit * 3;
162
+ const response = await client.request(`${endpoint}?_sort=rating&_order=DESC&_start=${offset}&_end=${offset + fetchLimit}`);
163
+ // Transform using the appropriate transformer
164
+ let transformedItems;
165
+ if (type === 'songs') {
166
+ const songs = transformSongsToDTO(response);
167
+ transformedItems = songs
168
+ .filter(song => (song.rating || 0) >= minRating) // Filter on client side
169
+ .map(song => {
170
+ const item = {
171
+ id: song.id,
172
+ rating: song.rating || 0
173
+ };
174
+ if (song.title)
175
+ item.title = song.title;
176
+ if (song.artist)
177
+ item.artist = song.artist;
178
+ if (song.album)
179
+ item.album = song.album;
180
+ if (song.playCount)
181
+ item.playCount = song.playCount;
182
+ return item;
183
+ })
184
+ .slice(0, limit);
185
+ }
186
+ else if (type === 'albums') {
187
+ const albums = transformAlbumsToDTO(response);
188
+ transformedItems = albums
189
+ .filter(album => (album.rating || 0) >= minRating)
190
+ .map(album => {
191
+ const item = {
192
+ id: album.id,
193
+ rating: album.rating || 0
194
+ };
195
+ if (album.name)
196
+ item.name = album.name;
197
+ if (album.artist)
198
+ item.artist = album.artist;
199
+ if (album.releaseYear)
200
+ item.year = album.releaseYear;
201
+ if (album.playCount)
202
+ item.playCount = album.playCount;
203
+ return item;
204
+ })
205
+ .slice(0, limit);
206
+ }
207
+ else {
208
+ const artists = transformArtistsToDTO(response);
209
+ transformedItems = artists
210
+ .filter(artist => (artist.rating || 0) >= minRating)
211
+ .map(artist => {
212
+ const item = {
213
+ id: artist.id,
214
+ rating: artist.rating || 0
215
+ };
216
+ if (artist.name)
217
+ item.name = artist.name;
218
+ item.albumCount = artist.albumCount;
219
+ item.songCount = artist.songCount;
220
+ return item;
221
+ })
222
+ .slice(0, limit);
223
+ }
224
+ return {
225
+ type,
226
+ minRating,
227
+ count: transformedItems.length,
228
+ items: transformedItems,
229
+ };
230
+ }
231
+ //# sourceMappingURL=user-preferences.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-preferences.js","sourceRoot":"","sources":["../../src/tools/user-preferences.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Navidrome MCP Server - Song Data Transformers
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 { SongDTO, AlbumDTO, ArtistDTO, GenreDTO, PlaylistDTO } from '../types/index.js';
19
+ /**
20
+ * Raw song data from Navidrome API
21
+ */
22
+ export interface RawSong {
23
+ id: string;
24
+ title: string;
25
+ artist: string;
26
+ artistId: string;
27
+ album: string;
28
+ albumId: string;
29
+ albumArtist?: string;
30
+ albumArtistId?: string;
31
+ genre?: string;
32
+ genres?: Array<{
33
+ id: string;
34
+ name: string;
35
+ }>;
36
+ year?: number;
37
+ duration?: number;
38
+ trackNumber?: number;
39
+ playCount?: number;
40
+ rating?: number;
41
+ starred?: boolean;
42
+ createdAt?: string;
43
+ path?: string;
44
+ [key: string]: unknown;
45
+ }
46
+ export interface RawAlbum {
47
+ id: string;
48
+ name: string;
49
+ artist: string;
50
+ artistId: string;
51
+ albumArtist?: string;
52
+ albumArtistId?: string;
53
+ releaseYear?: number;
54
+ genre?: string;
55
+ genres?: Array<{
56
+ id: string;
57
+ name: string;
58
+ }>;
59
+ songCount: number;
60
+ duration?: number;
61
+ compilation?: boolean;
62
+ playCount?: number;
63
+ rating?: number;
64
+ starred?: boolean;
65
+ [key: string]: unknown;
66
+ }
67
+ export interface RawArtist {
68
+ id: string;
69
+ name: string;
70
+ albumCount: number;
71
+ songCount: number;
72
+ genres?: string[];
73
+ biography?: string;
74
+ playCount?: number;
75
+ rating?: number;
76
+ starred?: boolean;
77
+ [key: string]: unknown;
78
+ }
79
+ export interface RawGenre {
80
+ id: string;
81
+ name: string;
82
+ songCount?: number;
83
+ albumCount?: number;
84
+ [key: string]: unknown;
85
+ }
86
+ export interface RawPlaylist {
87
+ id: string;
88
+ name: string;
89
+ comment?: string;
90
+ public: boolean;
91
+ songCount: number;
92
+ duration?: number;
93
+ owner: string;
94
+ [key: string]: unknown;
95
+ }
96
+ /**
97
+ * Format duration from seconds to MM:SS format
98
+ * @param seconds Duration in seconds
99
+ * @returns Formatted string like "3:45"
100
+ */
101
+ export declare function formatDuration(seconds?: number): string;
102
+ /**
103
+ * Transform a raw song from Navidrome API to a clean DTO
104
+ * @param rawSong Raw song data from API
105
+ * @returns Clean song DTO for LLM consumption
106
+ */
107
+ export declare function transformToSongDTO(rawSong: RawSong): SongDTO;
108
+ /**
109
+ * Transform an array of raw songs to DTOs
110
+ * @param rawSongs Array of raw song data
111
+ * @returns Array of clean song DTOs
112
+ */
113
+ export declare function transformSongsToDTO(rawSongs: unknown): SongDTO[];
114
+ export declare function transformToAlbumDTO(rawAlbum: RawAlbum): AlbumDTO;
115
+ export declare function transformAlbumsToDTO(rawAlbums: unknown): AlbumDTO[];
116
+ export declare function transformToArtistDTO(rawArtist: RawArtist): ArtistDTO;
117
+ export declare function transformArtistsToDTO(rawArtists: unknown): ArtistDTO[];
118
+ export declare function transformToGenreDTO(rawGenre: RawGenre): GenreDTO;
119
+ export declare function transformGenresToDTO(rawGenres: unknown): GenreDTO[];
120
+ export declare function transformToPlaylistDTO(rawPlaylist: RawPlaylist): PlaylistDTO;
121
+ export declare function transformPlaylistsToDTO(rawPlaylists: unknown): PlaylistDTO[];
122
+ //# sourceMappingURL=song-transformer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"song-transformer.d.ts","sourceRoot":"","sources":["../../src/transformers/song-transformer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Navidrome MCP Server - Song Data Transformers
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
+ /**
19
+ * Format duration from seconds to MM:SS format
20
+ * @param seconds Duration in seconds
21
+ * @returns Formatted string like "3:45"
22
+ */
23
+ export function formatDuration(seconds) {
24
+ if (!seconds || seconds <= 0) {
25
+ return '0:00';
26
+ }
27
+ const minutes = Math.floor(seconds / 60);
28
+ const remainingSeconds = Math.floor(seconds % 60);
29
+ return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
30
+ }
31
+ /**
32
+ * Extract the primary genre from various formats
33
+ * @param rawSong The raw song data
34
+ * @returns The primary genre name or undefined
35
+ */
36
+ function extractGenre(rawSong) {
37
+ // Try genres array first (newer format)
38
+ if (rawSong.genres && Array.isArray(rawSong.genres) && rawSong.genres.length > 0) {
39
+ const firstGenre = rawSong.genres[0];
40
+ if (firstGenre) {
41
+ return firstGenre.name;
42
+ }
43
+ }
44
+ // Fall back to genre string
45
+ if (rawSong.genre) {
46
+ return rawSong.genre;
47
+ }
48
+ return undefined;
49
+ }
50
+ /**
51
+ * Extract all genres from the raw song data
52
+ * @param rawSong The raw song data
53
+ * @returns Array of genre names or undefined
54
+ */
55
+ function extractAllGenres(rawSong) {
56
+ // Try genres array first (newer format)
57
+ if (rawSong.genres && Array.isArray(rawSong.genres) && rawSong.genres.length > 0) {
58
+ return rawSong.genres.map(g => g.name).filter(Boolean);
59
+ }
60
+ // Fall back to single genre string as array
61
+ if (rawSong.genre) {
62
+ return [rawSong.genre];
63
+ }
64
+ return undefined;
65
+ }
66
+ /**
67
+ * Transform a raw song from Navidrome API to a clean DTO
68
+ * @param rawSong Raw song data from API
69
+ * @returns Clean song DTO for LLM consumption
70
+ */
71
+ export function transformToSongDTO(rawSong) {
72
+ const dto = {
73
+ id: rawSong.id,
74
+ title: rawSong.title || '',
75
+ artist: rawSong.artist || '',
76
+ artistId: rawSong.artistId,
77
+ album: rawSong.album || '',
78
+ albumId: rawSong.albumId,
79
+ durationFormatted: formatDuration(rawSong.duration),
80
+ addedDate: rawSong.createdAt || new Date().toISOString(),
81
+ };
82
+ // Add optional fields only if they have values
83
+ const genre = extractGenre(rawSong);
84
+ if (genre !== undefined) {
85
+ dto.genre = genre;
86
+ }
87
+ const genres = extractAllGenres(rawSong);
88
+ if (genres !== undefined) {
89
+ dto.genres = genres;
90
+ }
91
+ if (rawSong.year !== undefined) {
92
+ dto.year = rawSong.year;
93
+ }
94
+ if (rawSong.path !== undefined) {
95
+ dto.path = rawSong.path;
96
+ }
97
+ if (rawSong.trackNumber !== undefined) {
98
+ dto.trackNumber = rawSong.trackNumber;
99
+ }
100
+ if (rawSong.playCount !== undefined) {
101
+ dto.playCount = rawSong.playCount;
102
+ }
103
+ if (rawSong.rating !== undefined) {
104
+ dto.rating = rawSong.rating;
105
+ }
106
+ if (rawSong.starred !== undefined) {
107
+ dto.starred = rawSong.starred;
108
+ }
109
+ return dto;
110
+ }
111
+ /**
112
+ * Transform an array of raw songs to DTOs
113
+ * @param rawSongs Array of raw song data
114
+ * @returns Array of clean song DTOs
115
+ */
116
+ export function transformSongsToDTO(rawSongs) {
117
+ if (!Array.isArray(rawSongs)) {
118
+ return [];
119
+ }
120
+ return rawSongs.map((song) => transformToSongDTO(song));
121
+ }
122
+ export function transformToAlbumDTO(rawAlbum) {
123
+ const dto = {
124
+ id: rawAlbum.id,
125
+ name: rawAlbum.name || '',
126
+ artist: rawAlbum.artist || '',
127
+ artistId: rawAlbum.artistId,
128
+ songCount: rawAlbum.songCount || 0,
129
+ durationFormatted: formatDuration(rawAlbum.duration),
130
+ };
131
+ if (rawAlbum.albumArtist !== undefined) {
132
+ dto.albumArtist = rawAlbum.albumArtist;
133
+ }
134
+ if (rawAlbum.albumArtistId !== undefined) {
135
+ dto.albumArtistId = rawAlbum.albumArtistId;
136
+ }
137
+ if (rawAlbum.releaseYear !== undefined) {
138
+ dto.releaseYear = rawAlbum.releaseYear;
139
+ }
140
+ const genre = extractGenre(rawAlbum);
141
+ if (genre !== undefined) {
142
+ dto.genre = genre;
143
+ }
144
+ const genres = extractAllGenres(rawAlbum);
145
+ if (genres !== undefined) {
146
+ dto.genres = genres;
147
+ }
148
+ if (rawAlbum.compilation !== undefined) {
149
+ dto.compilation = rawAlbum.compilation;
150
+ }
151
+ if (rawAlbum.playCount !== undefined) {
152
+ dto.playCount = rawAlbum.playCount;
153
+ }
154
+ if (rawAlbum.rating !== undefined) {
155
+ dto.rating = rawAlbum.rating;
156
+ }
157
+ if (rawAlbum.starred !== undefined) {
158
+ dto.starred = rawAlbum.starred;
159
+ }
160
+ return dto;
161
+ }
162
+ export function transformAlbumsToDTO(rawAlbums) {
163
+ if (!Array.isArray(rawAlbums)) {
164
+ return [];
165
+ }
166
+ return rawAlbums.map((album) => transformToAlbumDTO(album));
167
+ }
168
+ export function transformToArtistDTO(rawArtist) {
169
+ const dto = {
170
+ id: rawArtist.id,
171
+ name: rawArtist.name || '',
172
+ albumCount: rawArtist.albumCount || 0,
173
+ songCount: rawArtist.songCount || 0,
174
+ };
175
+ if (rawArtist.genres !== undefined) {
176
+ dto.genres = rawArtist.genres;
177
+ }
178
+ if (rawArtist.biography !== undefined) {
179
+ dto.biography = rawArtist.biography;
180
+ }
181
+ if (rawArtist.playCount !== undefined) {
182
+ dto.playCount = rawArtist.playCount;
183
+ }
184
+ if (rawArtist.rating !== undefined) {
185
+ dto.rating = rawArtist.rating;
186
+ }
187
+ if (rawArtist.starred !== undefined) {
188
+ dto.starred = rawArtist.starred;
189
+ }
190
+ return dto;
191
+ }
192
+ export function transformArtistsToDTO(rawArtists) {
193
+ if (!Array.isArray(rawArtists)) {
194
+ return [];
195
+ }
196
+ return rawArtists.map((artist) => transformToArtistDTO(artist));
197
+ }
198
+ export function transformToGenreDTO(rawGenre) {
199
+ return {
200
+ id: rawGenre.id,
201
+ name: rawGenre.name || '',
202
+ songCount: rawGenre.songCount || 0,
203
+ albumCount: rawGenre.albumCount || 0,
204
+ };
205
+ }
206
+ export function transformGenresToDTO(rawGenres) {
207
+ if (!Array.isArray(rawGenres)) {
208
+ return [];
209
+ }
210
+ return rawGenres.map((genre) => transformToGenreDTO(genre));
211
+ }
212
+ export function transformToPlaylistDTO(rawPlaylist) {
213
+ const dto = {
214
+ id: rawPlaylist.id,
215
+ name: rawPlaylist.name || '',
216
+ public: rawPlaylist.public || false,
217
+ songCount: rawPlaylist.songCount || 0,
218
+ durationFormatted: formatDuration(rawPlaylist.duration),
219
+ owner: rawPlaylist.owner || '',
220
+ };
221
+ if (rawPlaylist.comment !== undefined) {
222
+ dto.comment = rawPlaylist.comment;
223
+ }
224
+ return dto;
225
+ }
226
+ export function transformPlaylistsToDTO(rawPlaylists) {
227
+ if (!Array.isArray(rawPlaylists)) {
228
+ return [];
229
+ }
230
+ return rawPlaylists.map((playlist) => transformToPlaylistDTO(playlist));
231
+ }
232
+ //# sourceMappingURL=song-transformer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"song-transformer.js","sourceRoot":"","sources":["../../src/transformers/song-transformer.ts"],"names":[],"mappings":"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"}