roon-mcp 0.1.0 → 0.2.0

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.
@@ -0,0 +1,253 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { TransportService } from "./TransportService.js";
4
+ import { RoonMcpError } from "./types.js";
5
+ import { ZoneService } from "./ZoneService.js";
6
+ function zone(partial) {
7
+ return {
8
+ display_name: partial.zone_id,
9
+ state: "stopped",
10
+ outputs: [{ output_id: `o:${partial.zone_id}`, zone_id: partial.zone_id, display_name: partial.zone_id }],
11
+ ...partial,
12
+ };
13
+ }
14
+ /** Builds a TransportService backed by a stub RoonClient with the given zones. */
15
+ function serviceWith(zones, defaultZone) {
16
+ const controlCalls = [];
17
+ const volumeCalls = [];
18
+ const muteCalls = [];
19
+ const stub = {
20
+ waitForCore: async () => undefined,
21
+ getTransport: () => ({
22
+ get_zones: (cb) => cb(false, { zones }),
23
+ subscribe_zones: () => { },
24
+ control: (zoneOrOutput, control, cb) => {
25
+ controlCalls.push({ zone: zoneOrOutput, control });
26
+ cb?.(false);
27
+ },
28
+ change_volume: (output, how, value, cb) => {
29
+ const outputId = typeof output === "string" ? output : output.output_id;
30
+ volumeCalls.push({ outputId, how, value });
31
+ cb?.(false);
32
+ },
33
+ mute: (output, how, cb) => {
34
+ const outputId = typeof output === "string" ? output : output.output_id;
35
+ muteCalls.push({ outputId, how });
36
+ cb?.(false);
37
+ },
38
+ }),
39
+ };
40
+ const zoneSvc = new ZoneService(stub, undefined, defaultZone);
41
+ const svc = new TransportService(stub, zoneSvc);
42
+ return { svc, controlCalls, volumeCalls, muteCalls };
43
+ }
44
+ test("getNowPlaying returns a structured snapshot of a playing zone", async () => {
45
+ const { svc } = serviceWith([
46
+ zone({
47
+ zone_id: "z1",
48
+ display_name: "Office",
49
+ state: "playing",
50
+ now_playing: {
51
+ three_line: { line1: "A Walk", line2: "Tycho", line3: "Dive" },
52
+ seek_position: 42,
53
+ length: 240,
54
+ image_key: "img:1",
55
+ },
56
+ }),
57
+ ]);
58
+ const info = await svc.getNowPlaying();
59
+ assert.deepEqual(info, {
60
+ zoneId: "z1",
61
+ displayName: "Office",
62
+ state: "playing",
63
+ title: "A Walk",
64
+ artist: "Tycho",
65
+ album: "Dive",
66
+ imageKey: "img:1",
67
+ lengthSec: 240,
68
+ seekPositionSec: 42,
69
+ });
70
+ });
71
+ test("getNowPlaying falls back through three/two/one line displays", async () => {
72
+ // Two-line only — `album` should be undefined.
73
+ const two = await serviceWith([
74
+ zone({
75
+ zone_id: "z1",
76
+ state: "playing",
77
+ now_playing: { two_line: { line1: "Strobe", line2: "deadmau5" } },
78
+ }),
79
+ ]).svc.getNowPlaying();
80
+ assert.deepEqual(two, {
81
+ zoneId: "z1",
82
+ displayName: "z1",
83
+ state: "playing",
84
+ title: "Strobe",
85
+ artist: "deadmau5",
86
+ album: undefined,
87
+ imageKey: undefined,
88
+ lengthSec: undefined,
89
+ seekPositionSec: undefined,
90
+ });
91
+ // One-line only — both `artist` and `album` should be undefined.
92
+ const one = await serviceWith([
93
+ zone({
94
+ zone_id: "z2",
95
+ state: "playing",
96
+ now_playing: { one_line: { line1: "Track 1" } },
97
+ }),
98
+ ]).svc.getNowPlaying();
99
+ assert.equal(one?.title, "Track 1");
100
+ assert.equal(one?.artist, undefined);
101
+ assert.equal(one?.album, undefined);
102
+ });
103
+ test("getNowPlaying reports the zone state when nothing is playing", async () => {
104
+ const { svc } = serviceWith([zone({ zone_id: "z1", state: "stopped" })]);
105
+ const info = await svc.getNowPlaying();
106
+ // Zone exists, so the snapshot is returned with `title` undefined to signal
107
+ // "no track" (rather than throwing or returning null).
108
+ assert.equal(info?.state, "stopped");
109
+ assert.equal(info?.title, undefined);
110
+ assert.equal(info?.artist, undefined);
111
+ });
112
+ test("getNowPlaying rejects an unknown zone id with ZONE_NOT_FOUND", async () => {
113
+ const { svc } = serviceWith([zone({ zone_id: "z1" })]);
114
+ await assert.rejects(svc.getNowPlaying("nope"), (e) => e instanceof RoonMcpError && e.code === "ZONE_NOT_FOUND");
115
+ });
116
+ test("control rejects an unknown action with BROWSE_FAILED", async () => {
117
+ const { svc } = serviceWith([zone({ zone_id: "z1", state: "playing" })]);
118
+ await assert.rejects(svc.control(undefined, "rewind"), (e) => e instanceof RoonMcpError && e.code === "BROWSE_FAILED" && /unknown action/i.test(e.message));
119
+ });
120
+ test("control('pause') issues transport.control(zoneId, 'pause')", async () => {
121
+ const { svc, controlCalls } = serviceWith([
122
+ zone({ zone_id: "z1", state: "playing", is_pause_allowed: true }),
123
+ ]);
124
+ const out = await svc.control("z1", "pause");
125
+ assert.equal(out.ok, true);
126
+ assert.equal(out.zoneId, "z1");
127
+ assert.equal(out.action, "pause");
128
+ assert.deepEqual(controlCalls, [{ zone: "z1", control: "pause" }]);
129
+ });
130
+ test("control('resume') maps to Roon's 'play' verb", async () => {
131
+ const { svc, controlCalls } = serviceWith([
132
+ zone({ zone_id: "z1", state: "paused", is_play_allowed: true }),
133
+ ]);
134
+ await svc.control("z1", "resume");
135
+ assert.deepEqual(controlCalls, [{ zone: "z1", control: "play" }]);
136
+ });
137
+ test("control('next') is refused when is_next_allowed is false", async () => {
138
+ const { svc, controlCalls } = serviceWith([
139
+ zone({ zone_id: "z1", state: "playing", is_next_allowed: false }),
140
+ ]);
141
+ await assert.rejects(svc.control("z1", "next"), (e) => e instanceof RoonMcpError && e.code === "BROWSE_FAILED");
142
+ assert.deepEqual(controlCalls, []);
143
+ });
144
+ test("control('stop') bypasses the allowed-flag check", async () => {
145
+ // Roon doesn't expose is_stop_allowed; `stop` should never be refused.
146
+ const { svc, controlCalls } = serviceWith([
147
+ zone({ zone_id: "z1", state: "playing" }),
148
+ ]);
149
+ await svc.control("z1", "stop");
150
+ assert.deepEqual(controlCalls, [{ zone: "z1", control: "stop" }]);
151
+ });
152
+ test("control resolves an omitted zoneId via ZoneService", async () => {
153
+ const { svc, controlCalls } = serviceWith([
154
+ zone({ zone_id: "z1", state: "playing", is_pause_allowed: true }),
155
+ ]);
156
+ await svc.control(undefined, "pause");
157
+ assert.deepEqual(controlCalls, [{ zone: "z1", control: "pause" }]);
158
+ });
159
+ test("setVolume rejects out-of-range levels", async () => {
160
+ const { svc } = serviceWith([zone({ zone_id: "z1" })]);
161
+ for (const bad of [-1, 101, Number.NaN]) {
162
+ await assert.rejects(svc.setVolume("z1", bad), (e) => e instanceof RoonMcpError && e.code === "BROWSE_FAILED");
163
+ }
164
+ });
165
+ test("setVolume rescales 0..100 to each output's native min/max", async () => {
166
+ // Output with 0..60 numeric range and a step of 5 → 50% maps to 30.
167
+ const { svc, volumeCalls } = serviceWith([
168
+ zone({
169
+ zone_id: "z1",
170
+ outputs: [
171
+ {
172
+ output_id: "o1",
173
+ zone_id: "z1",
174
+ display_name: "Office",
175
+ volume: { min: 0, max: 60, step: 5 },
176
+ },
177
+ ],
178
+ }),
179
+ ]);
180
+ const out = await svc.setVolume("z1", 50);
181
+ assert.equal(out.applied.length, 1);
182
+ assert.deepEqual(volumeCalls, [{ outputId: "o1", how: "absolute", value: 30 }]);
183
+ });
184
+ test("setVolume fans out across multiple outputs in a grouped zone", async () => {
185
+ const { svc, volumeCalls } = serviceWith([
186
+ zone({
187
+ zone_id: "z1",
188
+ outputs: [
189
+ { output_id: "o1", zone_id: "z1", display_name: "L", volume: { min: 0, max: 100 } },
190
+ { output_id: "o2", zone_id: "z1", display_name: "R", volume: { min: 0, max: 100 } },
191
+ ],
192
+ }),
193
+ ]);
194
+ const out = await svc.setVolume("z1", 25);
195
+ assert.equal(out.applied.length, 2);
196
+ assert.deepEqual(volumeCalls.sort((a, b) => a.outputId.localeCompare(b.outputId)), [
197
+ { outputId: "o1", how: "absolute", value: 25 },
198
+ { outputId: "o2", how: "absolute", value: 25 },
199
+ ]);
200
+ });
201
+ test("setVolume skips incremental outputs and applies to the rest", async () => {
202
+ const { svc, volumeCalls } = serviceWith([
203
+ zone({
204
+ zone_id: "z1",
205
+ outputs: [
206
+ { output_id: "o1", zone_id: "z1", display_name: "Speaker", volume: { min: 0, max: 100 } },
207
+ // No min/max — incremental IR-blaster style.
208
+ { output_id: "o2", zone_id: "z1", display_name: "IR", volume: { type: "incremental" } },
209
+ ],
210
+ }),
211
+ ]);
212
+ const out = await svc.setVolume("z1", 50);
213
+ assert.deepEqual(out.applied, ["o1"]);
214
+ assert.deepEqual(out.skipped, ["o2"]);
215
+ assert.equal(volumeCalls.length, 1);
216
+ });
217
+ test("setVolume throws when every output is incremental", async () => {
218
+ const { svc } = serviceWith([
219
+ zone({
220
+ zone_id: "z1",
221
+ outputs: [
222
+ { output_id: "o1", zone_id: "z1", display_name: "IR", volume: { type: "incremental" } },
223
+ ],
224
+ }),
225
+ ]);
226
+ await assert.rejects(svc.setVolume("z1", 50), (e) => e instanceof RoonMcpError &&
227
+ e.code === "BROWSE_FAILED" &&
228
+ /incremental/i.test(e.message));
229
+ });
230
+ test("mute fans out to every output with the requested how", async () => {
231
+ const { svc, muteCalls } = serviceWith([
232
+ zone({
233
+ zone_id: "z1",
234
+ outputs: [
235
+ { output_id: "o1", zone_id: "z1", display_name: "L" },
236
+ { output_id: "o2", zone_id: "z1", display_name: "R" },
237
+ ],
238
+ }),
239
+ ]);
240
+ const out = await svc.mute("z1", true);
241
+ assert.equal(out.muted, true);
242
+ assert.deepEqual(muteCalls.sort((a, b) => a.outputId.localeCompare(b.outputId)), [
243
+ { outputId: "o1", how: "mute" },
244
+ { outputId: "o2", how: "mute" },
245
+ ]);
246
+ await svc.mute("z1", false);
247
+ assert.equal(muteCalls.length, 4);
248
+ assert.deepEqual(muteCalls.slice(2), [
249
+ { outputId: "o1", how: "unmute" },
250
+ { outputId: "o2", how: "unmute" },
251
+ ]);
252
+ });
253
+ //# sourceMappingURL=TransportService.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TransportService.test.js","sourceRoot":"","sources":["../src/TransportService.test.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ import { RoonClient } from "./RoonClient.js";
6
6
  import { RoonMcpServer } from "./RoonMcpServer.js";
7
7
  import { SearchService } from "./SearchService.js";
8
8
  import { TrackExpansionService } from "./TrackExpansionService.js";
9
+ import { TransportService } from "./TransportService.js";
9
10
  import { ZoneService } from "./ZoneService.js";
10
11
  import { createStderrLogger } from "./logger.js";
11
12
  // node-roon-api logs discovery chatter via console.log. On a stdio MCP server
@@ -29,7 +30,8 @@ async function main() {
29
30
  const tracks = new TrackExpansionService(browse);
30
31
  const search = new SearchService(browse, genres, tracks);
31
32
  const playback = new PlaybackService(browse, zones, roon, tracks, logger);
32
- const server = new RoonMcpServer(roon, zones, search, tracks, playback);
33
+ const transport = new TransportService(roon, zones, logger);
34
+ const server = new RoonMcpServer(roon, zones, search, tracks, playback, transport);
33
35
  const shutdown = () => {
34
36
  void server.stop().finally(() => process.exit(0));
35
37
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,8EAA8E;AAC9E,0EAA0E;AAC1E,KAAK,MAAM,MAAM,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAU,EAAE,CAAC;IAC/D,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE;QACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,2EAA2E;IAC3E,+DAA+D;IAC/D,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,UAAU,EAAE,CAAC;IAC9B,2EAA2E;IAC3E,yCAAyC;IACzC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IACvE,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,IAAI,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1E,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAExE,MAAM,QAAQ,GAAG,GAAG,EAAE;QACpB,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAEhC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACtF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -85,6 +85,43 @@ export interface EnqueueAndPlayOutput extends PlaybackResult {
85
85
  /** Number of item keys the caller asked to queue. */
86
86
  requested: number;
87
87
  }
88
+ /** Verb for the `control_playback` tool. `resume` maps to Roon's `play`. */
89
+ export type TransportAction = "pause" | "resume" | "next" | "previous" | "stop";
90
+ export interface ControlPlaybackInput {
91
+ /** Zone or output id from `list_zones`; resolves like `play_now` when omitted. */
92
+ zoneId?: string;
93
+ action: TransportAction;
94
+ }
95
+ export interface SetVolumeInput {
96
+ zoneId?: string;
97
+ /**
98
+ * Target volume in percent (0 = silent, 100 = max). The server rescales
99
+ * to each output's native range, so a single value works across mixed
100
+ * devices in a grouped zone.
101
+ */
102
+ level: number;
103
+ }
104
+ export interface MuteInput {
105
+ zoneId?: string;
106
+ /** `true` to mute, `false` to unmute. */
107
+ muted: boolean;
108
+ }
109
+ /**
110
+ * Structured snapshot of a zone's current playback. Fields are populated
111
+ * only when Roon reports them (e.g. `artist`/`album` are empty when only a
112
+ * one-line display is available, or when nothing is playing at all).
113
+ */
114
+ export interface NowPlayingInfo {
115
+ zoneId: string;
116
+ displayName: string;
117
+ state: ZoneState;
118
+ title?: string;
119
+ artist?: string;
120
+ album?: string;
121
+ imageKey?: string;
122
+ lengthSec?: number;
123
+ seekPositionSec?: number;
124
+ }
88
125
  export type RoonMcpErrorCode = "NO_CORE_PAIRED" | "ZONE_NOT_FOUND" | "ZONE_AMBIGUOUS" | "BROWSE_FAILED" | "INVALID_ITEM_KEY" | "NO_SEARCH_RESULTS" | "NO_PLAYABLE_ITEMS" | "NO_PLAY_ACTION" | "ACTION_FAILED" | "PARTIAL_QUEUE";
89
126
  export declare class RoonMcpError extends Error {
90
127
  readonly code: RoonMcpErrorCode;
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,qEAAqE;AAmHrE,MAAM,OAAO,YAAa,SAAQ,KAAK;IAEnB;IAEA;IAHlB,YACkB,IAAsB,EACtC,OAAe,EACC,OAAiB;QAEjC,KAAK,CAAC,OAAO,CAAC,CAAC;QAJC,SAAI,GAAJ,IAAI,CAAkB;QAEtB,YAAO,GAAP,OAAO,CAAU;QAGjC,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,qEAAqE;AA6JrE,MAAM,OAAO,YAAa,SAAQ,KAAK;IAEnB;IAEA;IAHlB,YACkB,IAAsB,EACtC,OAAe,EACC,OAAiB;QAEjC,KAAK,CAAC,OAAO,CAAC,CAAC;QAJC,SAAI,GAAJ,IAAI,CAAkB;QAEtB,YAAO,GAAP,OAAO,CAAU;QAGjC,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roon-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "An MCP server to control the Roon music player.",
5
5
  "license": "MIT",
6
6
  "author": "Christoph Halang",