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,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":"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"}
@@ -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"}