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.
- package/LICENSE +661 -0
- package/README.md +397 -0
- package/dist/capabilities.d.ts +20 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +25 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/client/auth-manager.d.ts +27 -0
- package/dist/client/auth-manager.d.ts.map +1 -0
- package/dist/client/auth-manager.js +54 -0
- package/dist/client/auth-manager.js.map +1 -0
- package/dist/client/navidrome-client.d.ts +28 -0
- package/dist/client/navidrome-client.d.ts.map +1 -0
- package/dist/client/navidrome-client.js +84 -0
- package/dist/client/navidrome-client.js.map +1 -0
- package/dist/config.d.ts +41 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +132 -0
- package/dist/config.js.map +1 -0
- package/dist/constants/defaults.d.ts +29 -0
- package/dist/constants/defaults.d.ts.map +1 -0
- package/dist/constants/defaults.js +37 -0
- package/dist/constants/defaults.js.map +1 -0
- package/dist/constants/timeouts.d.ts +66 -0
- package/dist/constants/timeouts.d.ts.map +1 -0
- package/dist/constants/timeouts.js +66 -0
- package/dist/constants/timeouts.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +70 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/index.d.ts +21 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +83 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/schemas/common.d.ts +68 -0
- package/dist/schemas/common.d.ts.map +1 -0
- package/dist/schemas/common.js +69 -0
- package/dist/schemas/common.js.map +1 -0
- package/dist/schemas/index.d.ts +21 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +24 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/pagination.d.ts +153 -0
- package/dist/schemas/pagination.d.ts.map +1 -0
- package/dist/schemas/pagination.js +93 -0
- package/dist/schemas/pagination.js.map +1 -0
- package/dist/schemas/validation.d.ts +147 -0
- package/dist/schemas/validation.d.ts.map +1 -0
- package/dist/schemas/validation.js +143 -0
- package/dist/schemas/validation.js.map +1 -0
- package/dist/tools/handlers/lastfm-handlers.d.ts +5 -0
- package/dist/tools/handlers/lastfm-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/lastfm-handlers.js +143 -0
- package/dist/tools/handlers/lastfm-handlers.js.map +1 -0
- package/dist/tools/handlers/lyrics-handlers.d.ts +5 -0
- package/dist/tools/handlers/lyrics-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/lyrics-handlers.js +51 -0
- package/dist/tools/handlers/lyrics-handlers.js.map +1 -0
- package/dist/tools/handlers/playlist-handlers.d.ts +5 -0
- package/dist/tools/handlers/playlist-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/playlist-handlers.js +316 -0
- package/dist/tools/handlers/playlist-handlers.js.map +1 -0
- package/dist/tools/handlers/queue-handlers.d.ts +5 -0
- package/dist/tools/handlers/queue-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/queue-handlers.js +135 -0
- package/dist/tools/handlers/queue-handlers.js.map +1 -0
- package/dist/tools/handlers/radio-handlers.d.ts +5 -0
- package/dist/tools/handlers/radio-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/radio-handlers.js +323 -0
- package/dist/tools/handlers/radio-handlers.js.map +1 -0
- package/dist/tools/handlers/registry.d.ts +26 -0
- package/dist/tools/handlers/registry.d.ts.map +1 -0
- package/dist/tools/handlers/registry.js +77 -0
- package/dist/tools/handlers/registry.js.map +1 -0
- package/dist/tools/handlers/search-handlers.d.ts +5 -0
- package/dist/tools/handlers/search-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/search-handlers.js +125 -0
- package/dist/tools/handlers/search-handlers.js.map +1 -0
- package/dist/tools/handlers/tag-handlers.d.ts +5 -0
- package/dist/tools/handlers/tag-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/tag-handlers.js +155 -0
- package/dist/tools/handlers/tag-handlers.js.map +1 -0
- package/dist/tools/handlers/user-preferences-handlers.d.ts +5 -0
- package/dist/tools/handlers/user-preferences-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/user-preferences-handlers.js +155 -0
- package/dist/tools/handlers/user-preferences-handlers.js.map +1 -0
- package/dist/tools/index.d.ts +19 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +20 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/lastfm-discovery.d.ts +107 -0
- package/dist/tools/lastfm-discovery.d.ts.map +1 -0
- package/dist/tools/lastfm-discovery.js +238 -0
- package/dist/tools/lastfm-discovery.js.map +1 -0
- package/dist/tools/library.d.ts +31 -0
- package/dist/tools/library.d.ts.map +1 -0
- package/dist/tools/library.js +272 -0
- package/dist/tools/library.js.map +1 -0
- package/dist/tools/listening-history.d.ts +51 -0
- package/dist/tools/listening-history.d.ts.map +1 -0
- package/dist/tools/listening-history.js +126 -0
- package/dist/tools/listening-history.js.map +1 -0
- package/dist/tools/lyrics.d.ts +35 -0
- package/dist/tools/lyrics.d.ts.map +1 -0
- package/dist/tools/lyrics.js +222 -0
- package/dist/tools/lyrics.js.map +1 -0
- package/dist/tools/media-library.d.ts +46 -0
- package/dist/tools/media-library.d.ts.map +1 -0
- package/dist/tools/media-library.js +179 -0
- package/dist/tools/media-library.js.map +1 -0
- package/dist/tools/playlist-management.d.ts +80 -0
- package/dist/tools/playlist-management.d.ts.map +1 -0
- package/dist/tools/playlist-management.js +384 -0
- package/dist/tools/playlist-management.js.map +1 -0
- package/dist/tools/queue-management.d.ts +48 -0
- package/dist/tools/queue-management.d.ts.map +1 -0
- package/dist/tools/queue-management.js +83 -0
- package/dist/tools/queue-management.js.map +1 -0
- package/dist/tools/radio-discovery.d.ts +95 -0
- package/dist/tools/radio-discovery.d.ts.map +1 -0
- package/dist/tools/radio-discovery.js +352 -0
- package/dist/tools/radio-discovery.js.map +1 -0
- package/dist/tools/radio-validation.d.ts +49 -0
- package/dist/tools/radio-validation.d.ts.map +1 -0
- package/dist/tools/radio-validation.js +463 -0
- package/dist/tools/radio-validation.js.map +1 -0
- package/dist/tools/radio.d.ts +38 -0
- package/dist/tools/radio.d.ts.map +1 -0
- package/dist/tools/radio.js +315 -0
- package/dist/tools/radio.js.map +1 -0
- package/dist/tools/search.d.ts +54 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +165 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/tags.d.ts +63 -0
- package/dist/tools/tags.d.ts.map +1 -0
- package/dist/tools/tags.js +260 -0
- package/dist/tools/tags.js.map +1 -0
- package/dist/tools/test.d.ts +50 -0
- package/dist/tools/test.d.ts.map +1 -0
- package/dist/tools/test.js +121 -0
- package/dist/tools/test.js.map +1 -0
- package/dist/tools/user-preferences.d.ts +73 -0
- package/dist/tools/user-preferences.d.ts.map +1 -0
- package/dist/tools/user-preferences.js +231 -0
- package/dist/tools/user-preferences.js.map +1 -0
- package/dist/transformers/song-transformer.d.ts +122 -0
- package/dist/transformers/song-transformer.d.ts.map +1 -0
- package/dist/transformers/song-transformer.js +232 -0
- package/dist/transformers/song-transformer.js.map +1 -0
- package/dist/types/core.d.ts +147 -0
- package/dist/types/core.d.ts.map +1 -0
- package/dist/types/core.js +19 -0
- package/dist/types/core.js.map +1 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +19 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/lyrics.d.ts +58 -0
- package/dist/types/lyrics.d.ts.map +1 -0
- package/dist/types/lyrics.js +19 -0
- package/dist/types/lyrics.js.map +1 -0
- package/dist/types/playlists.d.ts +150 -0
- package/dist/types/playlists.d.ts.map +1 -0
- package/dist/types/playlists.js +19 -0
- package/dist/types/playlists.js.map +1 -0
- package/dist/types/radio.d.ts +192 -0
- package/dist/types/radio.d.ts.map +1 -0
- package/dist/types/radio.js +19 -0
- package/dist/types/radio.js.map +1 -0
- package/dist/types/tags.d.ts +72 -0
- package/dist/types/tags.d.ts.map +1 -0
- package/dist/types/tags.js +19 -0
- package/dist/types/tags.js.map +1 -0
- package/dist/utils/cache.d.ts +32 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +84 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/error-formatter.d.ts +108 -0
- package/dist/utils/error-formatter.d.ts.map +1 -0
- package/dist/utils/error-formatter.js +161 -0
- package/dist/utils/error-formatter.js.map +1 -0
- package/dist/utils/logger.d.ts +33 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +52 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/message-manager.d.ts +74 -0
- package/dist/utils/message-manager.d.ts.map +1 -0
- package/dist/utils/message-manager.js +134 -0
- package/dist/utils/message-manager.js.map +1 -0
- package/dist/utils/version.d.ts +5 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +19 -0
- package/dist/utils/version.js.map +1 -0
- 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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"}
|