@darrenjaws/spotify-mcp 0.2.0 → 0.3.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.
- package/README.md +16 -11
- package/build/index.js +8 -0
- package/build/index.js.map +1 -1
- package/build/tools/system.d.ts +6 -0
- package/build/tools/system.d.ts.map +1 -0
- package/build/tools/system.js +138 -0
- package/build/tools/system.js.map +1 -0
- package/build/types.d.ts +3 -0
- package/build/types.d.ts.map +1 -1
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Spotify MCP Server
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@darrenjaws/spotify-mcp)
|
|
4
|
+
[](https://www.npmjs.com/package/@darrenjaws/spotify-mcp)
|
|
5
|
+
[](https://github.com/darrenjaworski/spotify-mcp/blob/main/LICENSE)
|
|
6
|
+
|
|
3
7
|
A Model Context Protocol (MCP) server that provides seamless integration with Spotify's API, enabling AI assistants to control and interact with Spotify playback, manage playlists, search for music, and retrieve user listening data.
|
|
4
8
|
|
|
5
9
|
## Table of Contents
|
|
@@ -17,7 +21,7 @@ A Model Context Protocol (MCP) server that provides seamless integration with Sp
|
|
|
17
21
|
- [Environment Variables](#environment-variables)
|
|
18
22
|
- [MCP Configuration](#mcp-configuration)
|
|
19
23
|
- [Usage](#usage)
|
|
20
|
-
- [Available Tools (
|
|
24
|
+
- [Available Tools (15 total)](#available-tools-15-total)
|
|
21
25
|
- [Playback](#playback)
|
|
22
26
|
- [Search & Discovery](#search--discovery)
|
|
23
27
|
- [Library Management](#library-management)
|
|
@@ -314,32 +318,33 @@ Once configured, you can interact with Spotify through natural language:
|
|
|
314
318
|
- "Search for songs by The Beatles"
|
|
315
319
|
- "Add this song to my liked songs"
|
|
316
320
|
|
|
317
|
-
## Available Tools (
|
|
321
|
+
## Available Tools (15 total)
|
|
318
322
|
|
|
319
|
-
### Playback
|
|
323
|
+
### Playback (6 tools)
|
|
320
324
|
- `spotify_play` - Start or resume playback of tracks, albums, playlists, or artists
|
|
321
325
|
- `spotify_pause` - Pause playback
|
|
322
326
|
- `spotify_next` - Skip to next track
|
|
323
327
|
- `spotify_previous` - Skip to previous track
|
|
324
|
-
- `spotify_set_volume` - Adjust volume level
|
|
328
|
+
- `spotify_set_volume` - Adjust volume level (0-100)
|
|
325
329
|
- `spotify_get_playback_state` - Get current playback information
|
|
326
330
|
|
|
327
|
-
### Search
|
|
331
|
+
### Search (1 tool)
|
|
328
332
|
- `spotify_search` - Search for tracks, albums, artists, or playlists
|
|
329
|
-
- `spotify_get_recommendations` - Get song recommendations based on seeds
|
|
330
333
|
|
|
331
|
-
###
|
|
334
|
+
### Playlist Management (4 tools)
|
|
332
335
|
- `spotify_get_playlists` - Get user's playlists
|
|
333
336
|
- `spotify_get_playlist` - Get specific playlist details
|
|
334
337
|
- `spotify_create_playlist` - Create a new playlist
|
|
335
338
|
- `spotify_add_to_playlist` - Add tracks to a playlist
|
|
336
|
-
- `spotify_get_saved_tracks` - Get user's saved tracks
|
|
337
339
|
|
|
338
|
-
### User Data
|
|
340
|
+
### User Data (3 tools)
|
|
339
341
|
- `spotify_get_user_profile` - Get user profile information
|
|
340
342
|
- `spotify_get_top_items` - Get user's top artists or tracks
|
|
341
343
|
- `spotify_get_recently_played` - Get recently played tracks
|
|
342
344
|
|
|
345
|
+
### System (1 tool)
|
|
346
|
+
- `spotify_open` - Open the Spotify desktop app (supports macOS, Windows, Linux)
|
|
347
|
+
|
|
343
348
|
## Local Development
|
|
344
349
|
|
|
345
350
|
### Prerequisites
|
|
@@ -421,7 +426,7 @@ DEBUG=true npx @modelcontextprotocol/inspector node build/bin.js
|
|
|
421
426
|
```
|
|
422
427
|
|
|
423
428
|
**Benefits:**
|
|
424
|
-
- ✅ Interactive UI to test all
|
|
429
|
+
- ✅ Interactive UI to test all 15 tools
|
|
425
430
|
- ✅ See JSON-RPC messages in real-time
|
|
426
431
|
- ✅ No need to configure Claude Desktop during development
|
|
427
432
|
- ✅ Quickly iterate on tool implementations
|
|
@@ -514,7 +519,7 @@ npm run test:coverage # Generate coverage report
|
|
|
514
519
|
|
|
515
520
|
**Test Coverage:**
|
|
516
521
|
- ✅ 30 tests covering tool registration
|
|
517
|
-
- ✅ Validates all
|
|
522
|
+
- ✅ Validates all 15 tools are registered correctly
|
|
518
523
|
- ✅ Verifies tool naming conventions
|
|
519
524
|
- ✅ Checks input schema validation with Zod
|
|
520
525
|
- ✅ Integration tests for MCP server setup
|
package/build/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import * as playbackTools from "./tools/playback.js";
|
|
|
7
7
|
import * as searchTools from "./tools/search.js";
|
|
8
8
|
import * as playlistTools from "./tools/playlists.js";
|
|
9
9
|
import * as userTools from "./tools/user.js";
|
|
10
|
+
import * as systemTools from "./tools/system.js";
|
|
10
11
|
// Load environment variables
|
|
11
12
|
dotenv.config();
|
|
12
13
|
// Validate required environment variables
|
|
@@ -123,6 +124,13 @@ server.registerTool("spotify_get_recently_played", {
|
|
|
123
124
|
limit: z.number().min(1).max(50).optional().describe("Number of tracks to return (default: 20)"),
|
|
124
125
|
},
|
|
125
126
|
}, async ({ limit }) => userTools.getRecentlyPlayed({ limit }));
|
|
127
|
+
// Register system tools
|
|
128
|
+
server.registerTool("spotify_open", {
|
|
129
|
+
description: "Open the Spotify desktop app on this machine",
|
|
130
|
+
inputSchema: {
|
|
131
|
+
wait_seconds: z.number().min(0).max(30).optional().describe("Seconds to wait after opening for Spotify to initialize (0-30)"),
|
|
132
|
+
},
|
|
133
|
+
}, async ({ wait_seconds }) => systemTools.openSpotify({ wait_seconds }));
|
|
126
134
|
// Handle shutdown signals
|
|
127
135
|
const cleanup = async () => {
|
|
128
136
|
logger.info("Shutting down Spotify MCP server");
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,KAAK,aAAa,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,aAAa,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../src/tools/system.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA4FjE,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CA2D9E"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System-level tools (non-API, local machine operations)
|
|
3
|
+
*/
|
|
4
|
+
import { spawn } from "child_process";
|
|
5
|
+
import { logger } from "../utils/logger.js";
|
|
6
|
+
const SUPPORTED_PLATFORMS = ["darwin", "win32", "linux"];
|
|
7
|
+
function isSupportedPlatform(platform) {
|
|
8
|
+
return SUPPORTED_PLATFORMS.includes(platform);
|
|
9
|
+
}
|
|
10
|
+
function isSpotifyRunning() {
|
|
11
|
+
const platform = process.platform;
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
let cmd;
|
|
14
|
+
let args;
|
|
15
|
+
if (platform === "darwin") {
|
|
16
|
+
cmd = "pgrep";
|
|
17
|
+
args = ["-x", "Spotify"];
|
|
18
|
+
}
|
|
19
|
+
else if (platform === "win32") {
|
|
20
|
+
cmd = "tasklist";
|
|
21
|
+
args = ["/FI", "IMAGENAME eq Spotify.exe", "/NH"];
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
// linux
|
|
25
|
+
cmd = "pgrep";
|
|
26
|
+
args = ["-x", "spotify"];
|
|
27
|
+
}
|
|
28
|
+
const child = spawn(cmd, args, { shell: false });
|
|
29
|
+
let stdout = "";
|
|
30
|
+
child.stdout.on("data", (data) => {
|
|
31
|
+
stdout += data.toString();
|
|
32
|
+
});
|
|
33
|
+
child.on("error", () => {
|
|
34
|
+
resolve(false);
|
|
35
|
+
});
|
|
36
|
+
child.on("close", (code) => {
|
|
37
|
+
if (platform === "win32") {
|
|
38
|
+
resolve(stdout.toLowerCase().includes("spotify.exe"));
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
resolve(code === 0);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function openSpotifyApp() {
|
|
47
|
+
const platform = process.platform;
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
let cmd;
|
|
50
|
+
let args;
|
|
51
|
+
if (platform === "darwin") {
|
|
52
|
+
cmd = "open";
|
|
53
|
+
args = ["-a", "Spotify"];
|
|
54
|
+
}
|
|
55
|
+
else if (platform === "win32") {
|
|
56
|
+
cmd = "cmd";
|
|
57
|
+
args = ["/c", "start", "spotify:"];
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// linux
|
|
61
|
+
cmd = "spotify";
|
|
62
|
+
args = [];
|
|
63
|
+
}
|
|
64
|
+
const child = spawn(cmd, args, { shell: false, detached: true, stdio: "ignore" });
|
|
65
|
+
child.on("error", (err) => {
|
|
66
|
+
reject(new Error(`Failed to launch Spotify: ${err.message}`));
|
|
67
|
+
});
|
|
68
|
+
// On macOS/Linux, `open`/`spotify` exits quickly after launching.
|
|
69
|
+
// On Windows, `cmd /c start` also exits quickly.
|
|
70
|
+
child.on("close", (code) => {
|
|
71
|
+
if (code === 0 || code === null) {
|
|
72
|
+
resolve();
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
reject(new Error(`Failed to launch Spotify (exit code ${code})`));
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
child.unref();
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function sleep(seconds) {
|
|
82
|
+
return new Promise((resolve) => setTimeout(resolve, seconds * 1000));
|
|
83
|
+
}
|
|
84
|
+
export async function openSpotify(args) {
|
|
85
|
+
const platform = process.platform;
|
|
86
|
+
if (!isSupportedPlatform(platform)) {
|
|
87
|
+
return {
|
|
88
|
+
content: [
|
|
89
|
+
{
|
|
90
|
+
type: "text",
|
|
91
|
+
text: `Unsupported platform: ${platform}. Supported platforms: macOS, Windows, Linux.`,
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
isError: true,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const running = await isSpotifyRunning();
|
|
98
|
+
if (running) {
|
|
99
|
+
return {
|
|
100
|
+
content: [
|
|
101
|
+
{
|
|
102
|
+
type: "text",
|
|
103
|
+
text: "Spotify is already running.",
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
logger.info("Opening Spotify application");
|
|
109
|
+
try {
|
|
110
|
+
await openSpotifyApp();
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
logger.error("Failed to open Spotify:", error);
|
|
114
|
+
return {
|
|
115
|
+
content: [
|
|
116
|
+
{
|
|
117
|
+
type: "text",
|
|
118
|
+
text: "Failed to open Spotify. Please make sure Spotify is installed.",
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
isError: true,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
if (args.wait_seconds && args.wait_seconds > 0) {
|
|
125
|
+
await sleep(args.wait_seconds);
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
content: [
|
|
129
|
+
{
|
|
130
|
+
type: "text",
|
|
131
|
+
text: args.wait_seconds
|
|
132
|
+
? `Spotify opened. Waited ${args.wait_seconds} seconds for it to initialize.`
|
|
133
|
+
: "Spotify opened.",
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.js","sourceRoot":"","sources":["../../src/tools/system.ts"],"names":[],"mappings":"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"}
|
package/build/types.d.ts
CHANGED
package/build/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC3B,UAAU,CAAC,EAAE,YAAY,GAAG,aAAa,GAAG,WAAW,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC3B,UAAU,CAAC,EAAE,YAAY,GAAG,aAAa,GAAG,WAAW,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@darrenjaws/spotify-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Model Context Protocol server for Spotify integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
"prepublishOnly": "npm run build && npm test",
|
|
15
15
|
"test": "vitest run",
|
|
16
16
|
"test:watch": "vitest",
|
|
17
|
-
"test:coverage": "vitest run --coverage",
|
|
18
17
|
"lint": "eslint src --ext .ts",
|
|
19
18
|
"lint:fix": "eslint src --ext .ts --fix"
|
|
20
19
|
},
|
|
@@ -59,9 +58,9 @@
|
|
|
59
58
|
"@types/spotify-web-api-node": "^5.0.11",
|
|
60
59
|
"@typescript-eslint/eslint-plugin": "^8.19.1",
|
|
61
60
|
"@typescript-eslint/parser": "^8.19.1",
|
|
62
|
-
"@vitest/coverage-v8": "^4.0.18",
|
|
63
61
|
"eslint": "^9.17.0",
|
|
64
62
|
"typescript": "^5.7.2",
|
|
63
|
+
"typescript-eslint": "^8.55.0",
|
|
65
64
|
"vitest": "^4.0.18"
|
|
66
65
|
},
|
|
67
66
|
"engines": {
|