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,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Navidrome MCP Server - Radio Discovery 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 type { ExternalRadioStationDTO, DiscoverRadioStationsResponse, RadioFiltersResponse, ClickRadioStationResponse, VoteRadioStationResponse } from '../types/index.js';
|
|
20
|
+
import type { Config } from '../config.js';
|
|
21
|
+
import type { NavidromeClient } from '../client/navidrome-client.js';
|
|
22
|
+
/**
|
|
23
|
+
* Schema for discovering radio stations
|
|
24
|
+
*/
|
|
25
|
+
export declare const DiscoverRadioStationsArgsSchema: z.ZodObject<{
|
|
26
|
+
query: z.ZodOptional<z.ZodString>;
|
|
27
|
+
tag: z.ZodOptional<z.ZodString>;
|
|
28
|
+
countryCode: z.ZodOptional<z.ZodString>;
|
|
29
|
+
language: z.ZodOptional<z.ZodString>;
|
|
30
|
+
codec: z.ZodOptional<z.ZodString>;
|
|
31
|
+
bitrateMin: z.ZodOptional<z.ZodNumber>;
|
|
32
|
+
isHttps: z.ZodOptional<z.ZodBoolean>;
|
|
33
|
+
order: z.ZodDefault<z.ZodEnum<{
|
|
34
|
+
name: "name";
|
|
35
|
+
votes: "votes";
|
|
36
|
+
clickcount: "clickcount";
|
|
37
|
+
bitrate: "bitrate";
|
|
38
|
+
lastcheckok: "lastcheckok";
|
|
39
|
+
random: "random";
|
|
40
|
+
}>>;
|
|
41
|
+
reverse: z.ZodDefault<z.ZodBoolean>;
|
|
42
|
+
offset: z.ZodOptional<z.ZodNumber>;
|
|
43
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
44
|
+
hideBroken: z.ZodDefault<z.ZodBoolean>;
|
|
45
|
+
}, z.core.$strip>;
|
|
46
|
+
/**
|
|
47
|
+
* Schema for getting radio filter options
|
|
48
|
+
*/
|
|
49
|
+
export declare const GetRadioFiltersArgsSchema: z.ZodObject<{
|
|
50
|
+
kinds: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
51
|
+
tags: "tags";
|
|
52
|
+
countries: "countries";
|
|
53
|
+
languages: "languages";
|
|
54
|
+
codecs: "codecs";
|
|
55
|
+
}>>>;
|
|
56
|
+
}, z.core.$strip>;
|
|
57
|
+
/**
|
|
58
|
+
* Schema for getting station by UUID
|
|
59
|
+
*/
|
|
60
|
+
export declare const GetStationByUuidArgsSchema: z.ZodObject<{
|
|
61
|
+
stationUuid: z.ZodString;
|
|
62
|
+
}, z.core.$strip>;
|
|
63
|
+
/**
|
|
64
|
+
* Schema for clicking a station
|
|
65
|
+
*/
|
|
66
|
+
export declare const ClickStationArgsSchema: z.ZodObject<{
|
|
67
|
+
stationUuid: z.ZodString;
|
|
68
|
+
}, z.core.$strip>;
|
|
69
|
+
/**
|
|
70
|
+
* Schema for voting for a station
|
|
71
|
+
*/
|
|
72
|
+
export declare const VoteStationArgsSchema: z.ZodObject<{
|
|
73
|
+
stationUuid: z.ZodString;
|
|
74
|
+
}, z.core.$strip>;
|
|
75
|
+
/**
|
|
76
|
+
* Discover radio stations via Radio Browser API
|
|
77
|
+
*/
|
|
78
|
+
export declare function discoverRadioStations(config: Config, client: NavidromeClient, args: unknown): Promise<DiscoverRadioStationsResponse>;
|
|
79
|
+
/**
|
|
80
|
+
* Get available filter options for radio station discovery
|
|
81
|
+
*/
|
|
82
|
+
export declare function getRadioFilters(config: Config, args: unknown): Promise<RadioFiltersResponse>;
|
|
83
|
+
/**
|
|
84
|
+
* Get a specific radio station by UUID
|
|
85
|
+
*/
|
|
86
|
+
export declare function getStationByUuid(config: Config, args: unknown): Promise<ExternalRadioStationDTO>;
|
|
87
|
+
/**
|
|
88
|
+
* Register a play click for a station (helps with popularity metrics)
|
|
89
|
+
*/
|
|
90
|
+
export declare function clickStation(config: Config, args: unknown): Promise<ClickRadioStationResponse>;
|
|
91
|
+
/**
|
|
92
|
+
* Vote for a radio station
|
|
93
|
+
*/
|
|
94
|
+
export declare function voteStation(config: Config, args: unknown): Promise<VoteRadioStationResponse>;
|
|
95
|
+
//# sourceMappingURL=radio-discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radio-discovery.d.ts","sourceRoot":"","sources":["../../src/tools/radio-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EACV,uBAAuB,EACvB,6BAA6B,EAC7B,oBAAoB,EACpB,yBAAyB,EACzB,wBAAwB,EACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAI3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAuFrE;;GAEG;AACH,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;iBAa1C,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;;;;iBAEpC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,0BAA0B;;iBAErC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,sBAAsB;;iBAEjC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,qBAAqB;;iBAEhC,CAAC;AA8EH;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,6BAA6B,CAAC,CA4DxC;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA+ElG;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAgCtG;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,yBAAyB,CAAC,CA2BpG;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,wBAAwB,CAAC,CA0BlG"}
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Navidrome MCP Server - Radio Discovery 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 { validateRadioStream } from './radio-validation.js';
|
|
20
|
+
import { DISCOVERY_VALIDATION_TIMEOUT } from '../constants/timeouts.js';
|
|
21
|
+
import { DEFAULT_VALUES } from '../constants/defaults.js';
|
|
22
|
+
import { ErrorFormatter } from '../utils/error-formatter.js';
|
|
23
|
+
const MAX_LIMIT = 500;
|
|
24
|
+
/**
|
|
25
|
+
* Schema for discovering radio stations
|
|
26
|
+
*/
|
|
27
|
+
export const DiscoverRadioStationsArgsSchema = z.object({
|
|
28
|
+
query: z.string().optional(),
|
|
29
|
+
tag: z.string().optional(),
|
|
30
|
+
countryCode: z.string().optional(),
|
|
31
|
+
language: z.string().optional(),
|
|
32
|
+
codec: z.string().optional(),
|
|
33
|
+
bitrateMin: z.number().min(0).optional(),
|
|
34
|
+
isHttps: z.boolean().optional(),
|
|
35
|
+
order: z.enum(['name', 'votes', 'clickcount', 'bitrate', 'lastcheckok', 'random']).default('votes'),
|
|
36
|
+
reverse: z.boolean().default(true),
|
|
37
|
+
offset: z.number().min(0).optional(),
|
|
38
|
+
limit: z.number().min(1).max(MAX_LIMIT).default(DEFAULT_VALUES.RADIO_DISCOVERY_LIMIT),
|
|
39
|
+
hideBroken: z.boolean().default(true)
|
|
40
|
+
});
|
|
41
|
+
/**
|
|
42
|
+
* Schema for getting radio filter options
|
|
43
|
+
*/
|
|
44
|
+
export const GetRadioFiltersArgsSchema = z.object({
|
|
45
|
+
kinds: z.array(z.enum(['tags', 'countries', 'languages', 'codecs'])).default(['tags', 'countries', 'languages', 'codecs'])
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* Schema for getting station by UUID
|
|
49
|
+
*/
|
|
50
|
+
export const GetStationByUuidArgsSchema = z.object({
|
|
51
|
+
stationUuid: z.string()
|
|
52
|
+
});
|
|
53
|
+
/**
|
|
54
|
+
* Schema for clicking a station
|
|
55
|
+
*/
|
|
56
|
+
export const ClickStationArgsSchema = z.object({
|
|
57
|
+
stationUuid: z.string()
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* Schema for voting for a station
|
|
61
|
+
*/
|
|
62
|
+
export const VoteStationArgsSchema = z.object({
|
|
63
|
+
stationUuid: z.string()
|
|
64
|
+
});
|
|
65
|
+
/**
|
|
66
|
+
* Convert Radio Browser API response to our DTO
|
|
67
|
+
*/
|
|
68
|
+
function mapStationToDTO(station) {
|
|
69
|
+
const dto = {
|
|
70
|
+
stationUuid: station.stationuuid,
|
|
71
|
+
name: station.name,
|
|
72
|
+
playUrl: station.url_resolved || station.url,
|
|
73
|
+
tags: station.tags ? station.tags.split(',').filter((t) => t.trim()) : [],
|
|
74
|
+
languageCodes: station.languagecodes ? station.languagecodes.split(',').filter((l) => l.trim()) : [],
|
|
75
|
+
hls: Boolean(station.hls),
|
|
76
|
+
votes: station.votes || 0,
|
|
77
|
+
clickCount: station.clickcount || 0
|
|
78
|
+
};
|
|
79
|
+
// Only include essential fields for cleaner LLM context
|
|
80
|
+
if (station.homepage)
|
|
81
|
+
dto.homepage = station.homepage;
|
|
82
|
+
if (station.countrycode)
|
|
83
|
+
dto.countryCode = station.countrycode;
|
|
84
|
+
if (station.codec)
|
|
85
|
+
dto.codec = station.codec;
|
|
86
|
+
if (station.bitrate !== undefined)
|
|
87
|
+
dto.bitrate = station.bitrate;
|
|
88
|
+
// Skip favicon and lastCheckTime to reduce context size
|
|
89
|
+
return dto;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Validate discovered radio stations
|
|
93
|
+
*/
|
|
94
|
+
async function validateDiscoveredStations(client, stations) {
|
|
95
|
+
// Validate up to 8 stations with individual timeouts to handle rate limiting
|
|
96
|
+
const maxValidations = Math.min(stations.length, 8);
|
|
97
|
+
const stationsToValidate = stations.slice(0, maxValidations);
|
|
98
|
+
const remainingStations = stations.slice(maxValidations);
|
|
99
|
+
// Process validations with individual timeouts, not in parallel to avoid rate limiting
|
|
100
|
+
const validatedStations = [];
|
|
101
|
+
for (const station of stationsToValidate) {
|
|
102
|
+
try {
|
|
103
|
+
// Each validation gets its own timeout - no overall time limit
|
|
104
|
+
const validationResult = await validateRadioStream(client, {
|
|
105
|
+
url: station.playUrl,
|
|
106
|
+
timeout: DISCOVERY_VALIDATION_TIMEOUT
|
|
107
|
+
});
|
|
108
|
+
const validation = {
|
|
109
|
+
validated: true,
|
|
110
|
+
isValid: validationResult.success,
|
|
111
|
+
status: validationResult.success ? 'OK' : 'FAIL',
|
|
112
|
+
duration: validationResult.testDuration
|
|
113
|
+
};
|
|
114
|
+
validatedStations.push({
|
|
115
|
+
...station,
|
|
116
|
+
validation
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// If validation fails, mark as failed but include the station
|
|
121
|
+
validatedStations.push({
|
|
122
|
+
...station,
|
|
123
|
+
validation: {
|
|
124
|
+
validated: true,
|
|
125
|
+
isValid: false,
|
|
126
|
+
status: 'FAIL',
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Add remaining stations without validation
|
|
132
|
+
return [...validatedStations, ...remainingStations];
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Discover radio stations via Radio Browser API
|
|
136
|
+
*/
|
|
137
|
+
export async function discoverRadioStations(config, client, args) {
|
|
138
|
+
const params = DiscoverRadioStationsArgsSchema.parse(args);
|
|
139
|
+
try {
|
|
140
|
+
const url = new URL('/json/stations/search', config.radioBrowserBase);
|
|
141
|
+
// Map parameters to Radio Browser API format
|
|
142
|
+
if (params.query)
|
|
143
|
+
url.searchParams.set('name', params.query);
|
|
144
|
+
if (params.tag)
|
|
145
|
+
url.searchParams.set('tag', params.tag);
|
|
146
|
+
if (params.countryCode)
|
|
147
|
+
url.searchParams.set('countrycode', params.countryCode);
|
|
148
|
+
if (params.language)
|
|
149
|
+
url.searchParams.set('language', params.language);
|
|
150
|
+
if (params.codec)
|
|
151
|
+
url.searchParams.set('codec', params.codec);
|
|
152
|
+
if (params.bitrateMin !== undefined)
|
|
153
|
+
url.searchParams.set('bitrateMin', String(params.bitrateMin));
|
|
154
|
+
if (params.isHttps !== undefined)
|
|
155
|
+
url.searchParams.set('is_https', params.isHttps ? 'true' : 'false');
|
|
156
|
+
if (params.order)
|
|
157
|
+
url.searchParams.set('order', params.order);
|
|
158
|
+
if (params.reverse !== undefined)
|
|
159
|
+
url.searchParams.set('reverse', params.reverse ? 'true' : 'false');
|
|
160
|
+
if (params.offset !== undefined)
|
|
161
|
+
url.searchParams.set('offset', String(params.offset));
|
|
162
|
+
url.searchParams.set('limit', String(params.limit));
|
|
163
|
+
url.searchParams.set('hidebroken', params.hideBroken ? 'true' : 'false');
|
|
164
|
+
const response = await fetch(url.toString(), {
|
|
165
|
+
headers: {
|
|
166
|
+
'User-Agent': config.radioBrowserUserAgent || 'Navidrome-MCP/1.0',
|
|
167
|
+
'Accept': 'application/json'
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
if (!response.ok) {
|
|
171
|
+
throw new Error(ErrorFormatter.radioBrowserApi(response));
|
|
172
|
+
}
|
|
173
|
+
const data = await response.json();
|
|
174
|
+
const stations = data.map(mapStationToDTO);
|
|
175
|
+
// Automatically validate all discovered stations
|
|
176
|
+
const validatedStations = await validateDiscoveredStations(client, stations);
|
|
177
|
+
// Create validation summary
|
|
178
|
+
const validatedCount = validatedStations.filter(s => s.validation?.validated).length;
|
|
179
|
+
const workingCount = validatedStations.filter(s => s.validation?.isValid).length;
|
|
180
|
+
const result = {
|
|
181
|
+
stations: validatedStations,
|
|
182
|
+
source: 'radio-browser',
|
|
183
|
+
mirrorUsed: config.radioBrowserBase
|
|
184
|
+
};
|
|
185
|
+
if (validatedCount > 0) {
|
|
186
|
+
result.validationSummary = {
|
|
187
|
+
totalStations: stations.length,
|
|
188
|
+
validatedStations: validatedCount,
|
|
189
|
+
workingStations: workingCount,
|
|
190
|
+
message: `Auto-validated first ${validatedCount} stations: ${workingCount} working, ${validatedCount - workingCount} not working.`
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
throw new Error(ErrorFormatter.toolExecution('discoverRadioStations', error));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Get available filter options for radio station discovery
|
|
201
|
+
*/
|
|
202
|
+
export async function getRadioFilters(config, args) {
|
|
203
|
+
const params = GetRadioFiltersArgsSchema.parse(args);
|
|
204
|
+
const result = {};
|
|
205
|
+
try {
|
|
206
|
+
const fetchPromises = [];
|
|
207
|
+
if (params.kinds.includes('tags')) {
|
|
208
|
+
fetchPromises.push(fetch(`${config.radioBrowserBase}/json/tags`, {
|
|
209
|
+
headers: { 'User-Agent': config.radioBrowserUserAgent || 'Navidrome-MCP/1.0', 'Accept': 'application/json' }
|
|
210
|
+
})
|
|
211
|
+
.then(res => res.json())
|
|
212
|
+
.then((data) => {
|
|
213
|
+
result.tags = data
|
|
214
|
+
.slice(0, 100)
|
|
215
|
+
.map(t => ({ name: t.name, stationCount: t.stationcount }));
|
|
216
|
+
}));
|
|
217
|
+
}
|
|
218
|
+
if (params.kinds.includes('countries')) {
|
|
219
|
+
fetchPromises.push(fetch(`${config.radioBrowserBase}/json/countries`, {
|
|
220
|
+
headers: { 'User-Agent': config.radioBrowserUserAgent || 'Navidrome-MCP/1.0', 'Accept': 'application/json' }
|
|
221
|
+
})
|
|
222
|
+
.then(res => res.json())
|
|
223
|
+
.then((data) => {
|
|
224
|
+
result.countries = data
|
|
225
|
+
.slice(0, 100)
|
|
226
|
+
.map(c => ({
|
|
227
|
+
code: c.iso_3166_1,
|
|
228
|
+
name: c.name,
|
|
229
|
+
stationCount: c.stationcount
|
|
230
|
+
}));
|
|
231
|
+
}));
|
|
232
|
+
}
|
|
233
|
+
if (params.kinds.includes('languages')) {
|
|
234
|
+
fetchPromises.push(fetch(`${config.radioBrowserBase}/json/languages`, {
|
|
235
|
+
headers: { 'User-Agent': config.radioBrowserUserAgent || 'Navidrome-MCP/1.0', 'Accept': 'application/json' }
|
|
236
|
+
})
|
|
237
|
+
.then(res => res.json())
|
|
238
|
+
.then((data) => {
|
|
239
|
+
result.languages = data
|
|
240
|
+
.slice(0, 100)
|
|
241
|
+
.map(l => ({
|
|
242
|
+
code: l.iso_639 || l.name,
|
|
243
|
+
name: l.name,
|
|
244
|
+
stationCount: l.stationcount
|
|
245
|
+
}));
|
|
246
|
+
}));
|
|
247
|
+
}
|
|
248
|
+
if (params.kinds.includes('codecs')) {
|
|
249
|
+
fetchPromises.push(fetch(`${config.radioBrowserBase}/json/codecs`, {
|
|
250
|
+
headers: { 'User-Agent': config.radioBrowserUserAgent || 'Navidrome-MCP/1.0', 'Accept': 'application/json' }
|
|
251
|
+
})
|
|
252
|
+
.then(res => res.json())
|
|
253
|
+
.then((data) => {
|
|
254
|
+
result.codecs = data
|
|
255
|
+
.slice(0, 50)
|
|
256
|
+
.map(c => ({
|
|
257
|
+
name: c.name,
|
|
258
|
+
stationCount: c.stationcount
|
|
259
|
+
}));
|
|
260
|
+
}));
|
|
261
|
+
}
|
|
262
|
+
await Promise.all(fetchPromises);
|
|
263
|
+
return result;
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
throw new Error(ErrorFormatter.toolExecution('getRadioFilters', error));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Get a specific radio station by UUID
|
|
271
|
+
*/
|
|
272
|
+
export async function getStationByUuid(config, args) {
|
|
273
|
+
const params = GetStationByUuidArgsSchema.parse(args);
|
|
274
|
+
try {
|
|
275
|
+
const url = `${config.radioBrowserBase}/json/stations/byuuid?uuids=${encodeURIComponent(params.stationUuid)}`;
|
|
276
|
+
const response = await fetch(url, {
|
|
277
|
+
headers: {
|
|
278
|
+
'User-Agent': config.radioBrowserUserAgent || 'Navidrome-MCP/1.0',
|
|
279
|
+
'Accept': 'application/json'
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
if (!response.ok) {
|
|
283
|
+
throw new Error(ErrorFormatter.radioBrowserApi(response));
|
|
284
|
+
}
|
|
285
|
+
const data = await response.json();
|
|
286
|
+
if (!data || data.length === 0) {
|
|
287
|
+
throw new Error(ErrorFormatter.notFound('Station', params.stationUuid));
|
|
288
|
+
}
|
|
289
|
+
const firstStation = data[0];
|
|
290
|
+
if (!firstStation) {
|
|
291
|
+
throw new Error(ErrorFormatter.notFound('Station', params.stationUuid));
|
|
292
|
+
}
|
|
293
|
+
return mapStationToDTO(firstStation);
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
throw new Error(ErrorFormatter.toolExecution('getStationByUuid', error));
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Register a play click for a station (helps with popularity metrics)
|
|
301
|
+
*/
|
|
302
|
+
export async function clickStation(config, args) {
|
|
303
|
+
const params = ClickStationArgsSchema.parse(args);
|
|
304
|
+
try {
|
|
305
|
+
const url = `${config.radioBrowserBase}/json/url/${encodeURIComponent(params.stationUuid)}`;
|
|
306
|
+
const response = await fetch(url, {
|
|
307
|
+
headers: {
|
|
308
|
+
'User-Agent': config.radioBrowserUserAgent || 'Navidrome-MCP/1.0',
|
|
309
|
+
'Accept': 'application/json'
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
if (!response.ok) {
|
|
313
|
+
throw new Error(ErrorFormatter.radioBrowserApi(response));
|
|
314
|
+
}
|
|
315
|
+
const data = await response.json();
|
|
316
|
+
return {
|
|
317
|
+
ok: Boolean(data.ok),
|
|
318
|
+
playUrl: data.url || '',
|
|
319
|
+
message: data.message || 'Click registered successfully'
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
throw new Error(ErrorFormatter.toolExecution('clickStation', error));
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Vote for a radio station
|
|
328
|
+
*/
|
|
329
|
+
export async function voteStation(config, args) {
|
|
330
|
+
const params = VoteStationArgsSchema.parse(args);
|
|
331
|
+
try {
|
|
332
|
+
const url = `${config.radioBrowserBase}/json/vote/${encodeURIComponent(params.stationUuid)}`;
|
|
333
|
+
const response = await fetch(url, {
|
|
334
|
+
headers: {
|
|
335
|
+
'User-Agent': config.radioBrowserUserAgent || 'Navidrome-MCP/1.0',
|
|
336
|
+
'Accept': 'application/json'
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
if (!response.ok) {
|
|
340
|
+
throw new Error(ErrorFormatter.radioBrowserApi(response));
|
|
341
|
+
}
|
|
342
|
+
const data = await response.json();
|
|
343
|
+
return {
|
|
344
|
+
ok: Boolean(data.ok),
|
|
345
|
+
message: data.message || 'Vote registered successfully'
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
catch (error) {
|
|
349
|
+
throw new Error(ErrorFormatter.toolExecution('voteStation', error));
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
//# sourceMappingURL=radio-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radio-discovery.js","sourceRoot":"","sources":["../../src/tools/radio-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,MAAM,SAAS,GAAG,GAAG,CAAC;AAqFtB;;GAEG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC,MAAM,CAAC;IACtD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACxC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC/B,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACnG,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACpC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,qBAAqB,CAAC;IACrF,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CACtC,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;CAC3H,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;CACxB,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;CACxB,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;CACxB,CAAC,CAAC;AAEH;;GAEG;AACH,SAAS,eAAe,CAAC,OAA4B;IACnD,MAAM,GAAG,GAA4B;QACnC,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,OAAO,EAAE,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG;QAC5C,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;QACjF,aAAa,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;QAC5G,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC;QACzB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QACzB,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,CAAC;KACpC,CAAC;IAEF,wDAAwD;IACxD,IAAI,OAAO,CAAC,QAAQ;QAAE,GAAG,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IACtD,IAAI,OAAO,CAAC,WAAW;QAAE,GAAG,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAC/D,IAAI,OAAO,CAAC,KAAK;QAAE,GAAG,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC7C,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS;QAAE,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IACjE,wDAAwD;IAExD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,0BAA0B,CACvC,MAAuB,EACvB,QAAmC;IAEnC,6EAA6E;IAC7E,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACpD,MAAM,kBAAkB,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;IAC7D,MAAM,iBAAiB,GAAG,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAEzD,uFAAuF;IACvF,MAAM,iBAAiB,GAA8B,EAAE,CAAC;IAExD,KAAK,MAAM,OAAO,IAAI,kBAAkB,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,+DAA+D;YAC/D,MAAM,gBAAgB,GAAG,MAAM,mBAAmB,CAAC,MAAM,EAAE;gBACzD,GAAG,EAAE,OAAO,CAAC,OAAO;gBACpB,OAAO,EAAE,4BAA4B;aACtC,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG;gBACjB,SAAS,EAAE,IAAI;gBACf,OAAO,EAAE,gBAAgB,CAAC,OAAO;gBACjC,MAAM,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM;gBAChD,QAAQ,EAAE,gBAAgB,CAAC,YAAY;aACxC,CAAC;YAEF,iBAAiB,CAAC,IAAI,CAAC;gBACrB,GAAG,OAAO;gBACV,UAAU;aACX,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,8DAA8D;YAC9D,iBAAiB,CAAC,IAAI,CAAC;gBACrB,GAAG,OAAO;gBACV,UAAU,EAAE;oBACV,SAAS,EAAE,IAAI;oBACf,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,MAAM;iBACf;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,4CAA4C;IAC5C,OAAO,CAAC,GAAG,iBAAiB,EAAE,GAAG,iBAAiB,CAAC,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAc,EACd,MAAuB,EACvB,IAAa;IAEb,MAAM,MAAM,GAAG,+BAA+B,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE3D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,uBAAuB,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAEtE,6CAA6C;QAC7C,IAAI,MAAM,CAAC,KAAK;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC7D,IAAI,MAAM,CAAC,GAAG;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;QACxD,IAAI,MAAM,CAAC,WAAW;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAChF,IAAI,MAAM,CAAC,QAAQ;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACvE,IAAI,MAAM,CAAC,KAAK;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9D,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;QACnG,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACtG,IAAI,MAAM,CAAC,KAAK;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9D,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACrG,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACvF,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACpD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAEzE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;YAC3C,OAAO,EAAE;gBACP,YAAY,EAAE,MAAM,CAAC,qBAAqB,IAAI,mBAAmB;gBACjE,QAAQ,EAAE,kBAAkB;aAC7B;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAA2B,CAAC;QAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAE3C,iDAAiD;QACjD,MAAM,iBAAiB,GAAG,MAAM,0BAA0B,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAE7E,4BAA4B;QAC5B,MAAM,cAAc,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC;QACrF,MAAM,YAAY,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC;QAEjF,MAAM,MAAM,GAAkC;YAC5C,QAAQ,EAAE,iBAAiB;YAC3B,MAAM,EAAE,eAAe;YACvB,UAAU,EAAE,MAAM,CAAC,gBAAgB;SACpC,CAAC;QAEF,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,CAAC,iBAAiB,GAAG;gBACzB,aAAa,EAAE,QAAQ,CAAC,MAAM;gBAC9B,iBAAiB,EAAE,cAAc;gBACjC,eAAe,EAAE,YAAY;gBAC7B,OAAO,EAAE,wBAAwB,cAAc,cAAc,YAAY,aAAa,cAAc,GAAG,YAAY,eAAe;aACnI,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,aAAa,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC,CAAC;IAChF,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAc,EAAE,IAAa;IACjE,MAAM,MAAM,GAAG,yBAAyB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,MAAM,GAAyB,EAAE,CAAC;IAExC,IAAI,CAAC;QACH,MAAM,aAAa,GAAoB,EAAE,CAAC;QAE1C,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAClC,aAAa,CAAC,IAAI,CAChB,KAAK,CAAC,GAAG,MAAM,CAAC,gBAAgB,YAAY,EAAE;gBAC5C,OAAO,EAAE,EAAE,YAAY,EAAE,MAAM,CAAC,qBAAqB,IAAI,mBAAmB,EAAE,QAAQ,EAAE,kBAAkB,EAAE;aAC7G,CAAC;iBACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;iBACvB,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;gBACb,MAAM,CAAC,IAAI,GAAI,IAA0B;qBACtC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;qBACb,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;YAChE,CAAC,CAAC,CACH,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACvC,aAAa,CAAC,IAAI,CAChB,KAAK,CAAC,GAAG,MAAM,CAAC,gBAAgB,iBAAiB,EAAE;gBACjD,OAAO,EAAE,EAAE,YAAY,EAAE,MAAM,CAAC,qBAAqB,IAAI,mBAAmB,EAAE,QAAQ,EAAE,kBAAkB,EAAE;aAC7G,CAAC;iBACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;iBACvB,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;gBACb,MAAM,CAAC,SAAS,GAAI,IAA8B;qBAC/C,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;qBACb,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBACT,IAAI,EAAE,CAAC,CAAC,UAAU;oBAClB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,YAAY,EAAE,CAAC,CAAC,YAAY;iBAC7B,CAAC,CAAC,CAAC;YACR,CAAC,CAAC,CACH,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACvC,aAAa,CAAC,IAAI,CAChB,KAAK,CAAC,GAAG,MAAM,CAAC,gBAAgB,iBAAiB,EAAE;gBACjD,OAAO,EAAE,EAAE,YAAY,EAAE,MAAM,CAAC,qBAAqB,IAAI,mBAAmB,EAAE,QAAQ,EAAE,kBAAkB,EAAE;aAC7G,CAAC;iBACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;iBACvB,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;gBACb,MAAM,CAAC,SAAS,GAAI,IAA+B;qBAChD,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;qBACb,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBACT,IAAI,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI;oBACzB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,YAAY,EAAE,CAAC,CAAC,YAAY;iBAC7B,CAAC,CAAC,CAAC;YACR,CAAC,CAAC,CACH,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpC,aAAa,CAAC,IAAI,CAChB,KAAK,CAAC,GAAG,MAAM,CAAC,gBAAgB,cAAc,EAAE;gBAC9C,OAAO,EAAE,EAAE,YAAY,EAAE,MAAM,CAAC,qBAAqB,IAAI,mBAAmB,EAAE,QAAQ,EAAE,kBAAkB,EAAE;aAC7G,CAAC;iBACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;iBACvB,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;gBACb,MAAM,CAAC,MAAM,GAAI,IAA4B;qBAC1C,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;qBACZ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBACT,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,YAAY,EAAE,CAAC,CAAC,YAAY;iBAC7B,CAAC,CAAC,CAAC;YACR,CAAC,CAAC,CACH,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACjC,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,aAAa,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAc,EAAE,IAAa;IAClE,MAAM,MAAM,GAAG,0BAA0B,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEtD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,gBAAgB,+BAA+B,kBAAkB,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QAE9G,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,OAAO,EAAE;gBACP,YAAY,EAAE,MAAM,CAAC,qBAAqB,IAAI,mBAAmB;gBACjE,QAAQ,EAAE,kBAAkB;aAC7B;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAA2B,CAAC;QAE5D,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;QAC1E,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;QAC1E,CAAC;QAED,OAAO,eAAe,CAAC,YAAY,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,aAAa,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAc,EAAE,IAAa;IAC9D,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,gBAAgB,aAAa,kBAAkB,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QAE5F,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,OAAO,EAAE;gBACP,YAAY,EAAE,MAAM,CAAC,qBAAqB,IAAI,mBAAmB;gBACjE,QAAQ,EAAE,kBAAkB;aAC7B;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAgC,CAAC;QAEjE,OAAO;YACL,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACpB,OAAO,EAAE,IAAI,CAAC,GAAG,IAAI,EAAE;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,+BAA+B;SACzD,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,aAAa,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAc,EAAE,IAAa;IAC7D,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEjD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,gBAAgB,cAAc,kBAAkB,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QAE7F,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,OAAO,EAAE;gBACP,YAAY,EAAE,MAAM,CAAC,qBAAqB,IAAI,mBAAmB;gBACjE,QAAQ,EAAE,kBAAkB;aAC7B;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAgC,CAAC;QAEjE,OAAO;YACL,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACpB,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,8BAA8B;SACxD,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,aAAa,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC;IACtE,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Navidrome MCP Server - Radio Stream Validation Tool
|
|
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
|
+
interface AudioDetectionResult {
|
|
20
|
+
readonly detected: boolean;
|
|
21
|
+
readonly format?: string;
|
|
22
|
+
readonly mime?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface StreamValidationResult {
|
|
25
|
+
success: boolean;
|
|
26
|
+
url: string;
|
|
27
|
+
finalUrl?: string;
|
|
28
|
+
status: 'valid' | 'invalid' | 'error';
|
|
29
|
+
httpStatus?: number;
|
|
30
|
+
contentType?: string;
|
|
31
|
+
streamingHeaders: Record<string, string>;
|
|
32
|
+
audioFormat?: AudioDetectionResult;
|
|
33
|
+
validation: {
|
|
34
|
+
httpAccessible: boolean;
|
|
35
|
+
hasAudioContentType: boolean;
|
|
36
|
+
hasStreamingHeaders: boolean;
|
|
37
|
+
audioDataDetected: boolean;
|
|
38
|
+
};
|
|
39
|
+
errors: string[];
|
|
40
|
+
warnings: string[];
|
|
41
|
+
recommendations: string[];
|
|
42
|
+
testDuration: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Validate a radio stream URL
|
|
46
|
+
*/
|
|
47
|
+
export declare function validateRadioStream(_client: NavidromeClient, args: unknown): Promise<StreamValidationResult>;
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=radio-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radio-validation.d.ts","sourceRoot":"","sources":["../../src/tools/radio-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAgBrE,UAAU,oBAAoB;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAWD,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,WAAW,CAAC,EAAE,oBAAoB,CAAC;IACnC,UAAU,EAAE;QACV,cAAc,EAAE,OAAO,CAAC;QACxB,mBAAmB,EAAE,OAAO,CAAC;QAC7B,mBAAmB,EAAE,OAAO,CAAC;QAC7B,iBAAiB,EAAE,OAAO,CAAC;KAC5B,CAAC;IACF,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;CACtB;AA8SD;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,sBAAsB,CAAC,CAuLjC"}
|