mr-magic-mcp-server 0.3.1 → 0.3.3
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 +53 -52
- package/package.json +3 -3
- package/src/transport/http-server.js +1 -1
- package/src/transport/mcp-http-server.js +4 -0
- package/src/utils/config.js +6 -2
package/README.md
CHANGED
|
@@ -76,6 +76,7 @@ config. Token fetch scripts, the Playwright workflow, and local export storage a
|
|
|
76
76
|
| CLI | `node src/bin/cli.js --help` |
|
|
77
77
|
|
|
78
78
|
Or use the npm scripts:
|
|
79
|
+
|
|
79
80
|
```bash
|
|
80
81
|
npm run server:mcp # MCP stdio
|
|
81
82
|
npm run server:mcp:http # MCP Streamable HTTP & SSE — 127.0.0.1:3444
|
|
@@ -154,8 +155,8 @@ GENIUS_CLIENT_ID=your_id \
|
|
|
154
155
|
|
|
155
156
|
#### npx reference — all entrypoints
|
|
156
157
|
|
|
157
|
-
| What you want | Command
|
|
158
|
-
| -------------------------------- |
|
|
158
|
+
| What you want | Command |
|
|
159
|
+
| -------------------------------- | --------------------------------------------------------- |
|
|
159
160
|
| MCP stdio | `npx -y --package mr-magic-mcp-server mcp-server` |
|
|
160
161
|
| MCP Streamable HTTP & SSE (+SSE) | `npx -y --package mr-magic-mcp-server mcp-http-server` |
|
|
161
162
|
| JSON HTTP automation | `npx -y --package mr-magic-mcp-server http-server` |
|
|
@@ -255,11 +256,11 @@ grouped below by purpose.
|
|
|
255
256
|
|
|
256
257
|
### Genius credentials
|
|
257
258
|
|
|
258
|
-
| Variable | Description
|
|
259
|
-
| ---------------------- |
|
|
259
|
+
| Variable | Description |
|
|
260
|
+
| ---------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
260
261
|
| `GENIUS_CLIENT_ID` | OAuth client ID for auto-refresh (recommended). Get from [genius.com/api-clients](https://genius.com/api-clients). |
|
|
261
|
-
| `GENIUS_CLIENT_SECRET` | OAuth client secret for auto-refresh (recommended).
|
|
262
|
-
| `GENIUS_DIRECT_TOKEN` | Static direct bearer token. Used when client credentials are unavailable.
|
|
262
|
+
| `GENIUS_CLIENT_SECRET` | OAuth client secret for auto-refresh (recommended). |
|
|
263
|
+
| `GENIUS_DIRECT_TOKEN` | Static direct bearer token. Used when client credentials are unavailable. |
|
|
263
264
|
|
|
264
265
|
Token resolution order (first match wins):
|
|
265
266
|
|
|
@@ -271,8 +272,8 @@ Token resolution order (first match wins):
|
|
|
271
272
|
|
|
272
273
|
### Musixmatch credentials
|
|
273
274
|
|
|
274
|
-
| Variable | Description
|
|
275
|
-
| --------------------------------- |
|
|
275
|
+
| Variable | Description |
|
|
276
|
+
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
|
|
276
277
|
| `MUSIXMATCH_DIRECT_TOKEN` | Static bearer token. Recommended for production / ephemeral hosts. Also used as push source by `push:musixmatch-token`. |
|
|
277
278
|
| `MUSIXMATCH_TOKEN_KV_KEY` | KV key name for the token store. Default: `mr-magic:musixmatch-token`. |
|
|
278
279
|
| `MUSIXMATCH_TOKEN_KV_TTL_SECONDS` | Token TTL in the KV store (seconds). Default: `2592000` (30 days). |
|
|
@@ -287,36 +288,36 @@ Token resolution order (first match wins):
|
|
|
287
288
|
|
|
288
289
|
### Export and storage
|
|
289
290
|
|
|
290
|
-
| Variable | Default | Description
|
|
291
|
-
| ----------------------------------- | ---------- |
|
|
291
|
+
| Variable | Default | Description |
|
|
292
|
+
| ----------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
292
293
|
| `MR_MAGIC_EXPORT_BACKEND` | `local` | Storage backend: `local` \| `inline` \| `redis`. |
|
|
293
|
-
| `MR_MAGIC_EXPORT_DIR` | `exports/` | Absolute path for local exports. Required when backend is `local`.
|
|
294
|
-
| `MR_MAGIC_EXPORT_TTL_SECONDS` | `3600` | TTL for `local` and `redis` backends (ignored for `inline`).
|
|
295
|
-
| `MR_MAGIC_DOWNLOAD_BASE_URL` | _(none)_ | Public base URL for download links, e.g. `https://lyrics.example.com`.
|
|
294
|
+
| `MR_MAGIC_EXPORT_DIR` | `exports/` | Absolute path for local exports. Required when backend is `local`. |
|
|
295
|
+
| `MR_MAGIC_EXPORT_TTL_SECONDS` | `3600` | TTL for `local` and `redis` backends (ignored for `inline`). |
|
|
296
|
+
| `MR_MAGIC_DOWNLOAD_BASE_URL` | _(none)_ | Public base URL for download links, e.g. `https://lyrics.example.com`. |
|
|
296
297
|
| `MR_MAGIC_INLINE_PAYLOAD_MAX_CHARS` | `1500` | Character threshold at which `build_catalog_payload` auto-promotes to `reference` transport when `omitInlineLyrics` is `true`. |
|
|
297
298
|
| `UPSTASH_REDIS_REST_URL` | — | Upstash Redis KV backend URL. Also used by the export backend when `MR_MAGIC_EXPORT_BACKEND=redis` — set once, used for both. |
|
|
298
299
|
| `UPSTASH_REDIS_REST_TOKEN` | — | Upstash Redis KV bearer token. Takes precedence over Cloudflare KV when both are set. |
|
|
299
300
|
| `CF_API_TOKEN` | — | Cloudflare API token with `KV:Edit` permission (Cloudflare KV backend). |
|
|
300
|
-
| `CF_ACCOUNT_ID` | — | Cloudflare account ID (Cloudflare KV backend).
|
|
301
|
-
| `CF_KV_NAMESPACE_ID` | — | Cloudflare KV namespace ID (Cloudflare KV backend).
|
|
301
|
+
| `CF_ACCOUNT_ID` | — | Cloudflare account ID (Cloudflare KV backend). |
|
|
302
|
+
| `CF_KV_NAMESPACE_ID` | — | Cloudflare KV namespace ID (Cloudflare KV backend). |
|
|
302
303
|
|
|
303
304
|
### Server and runtime
|
|
304
305
|
|
|
305
|
-
| Variable | Default | Description
|
|
306
|
-
| -------------------------- | ---------------- |
|
|
307
|
-
| `PORT` | `3444` / `3333` | Override server port. On Render this is set automatically (default `10000`).
|
|
306
|
+
| Variable | Default | Description |
|
|
307
|
+
| -------------------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
308
|
+
| `PORT` | `3444` / `3333` | Override server port. On Render this is set automatically (default `10000`). |
|
|
308
309
|
| `LOG_LEVEL` | `info` | Verbosity: `error` \| `warn` \| `info` \| `debug`. |
|
|
309
|
-
| `MR_MAGIC_QUIET_STDIO` | `0` | Set to `1` to suppress non-error stdout logs (forces `LOG_LEVEL=error`). Recommended under stdio MCP clients.
|
|
310
|
-
| `MR_MAGIC_HTTP_TIMEOUT_MS` | `10000` | Global outbound HTTP timeout in milliseconds.
|
|
311
|
-
| `MR_MAGIC_ROOT` | _(project root)_ | Override the project root used for `.env` and `.cache` path resolution.
|
|
310
|
+
| `MR_MAGIC_QUIET_STDIO` | `0` | Set to `1` to suppress non-error stdout logs (forces `LOG_LEVEL=error`). Recommended under stdio MCP clients. |
|
|
311
|
+
| `MR_MAGIC_HTTP_TIMEOUT_MS` | `10000` | Global outbound HTTP timeout in milliseconds. |
|
|
312
|
+
| `MR_MAGIC_ROOT` | _(project root)_ | Override the project root used for `.env` and `.cache` path resolution. |
|
|
312
313
|
| `MR_MAGIC_ENV_PATH` | _(auto)_ | Point to a specific `.env` file instead of `<project root>/.env`. |
|
|
313
|
-
| `MR_MAGIC_ALLOWED_HOSTS` | _(empty)_ | Comma-separated extra hostnames allowed for DNS rebinding protection when binding to `0.0.0.0`. `RENDER_EXTERNAL_HOSTNAME` is included automatically on Render. Only needed for custom domains.
|
|
314
|
+
| `MR_MAGIC_ALLOWED_HOSTS` | _(empty)_ | Comma-separated extra hostnames allowed for DNS rebinding protection when binding to `0.0.0.0`. `RENDER_EXTERNAL_HOSTNAME` is included automatically on Render. Only needed for custom domains. |
|
|
314
315
|
| `MR_MAGIC_SESSIONLESS` | `0` | Set to `1` to force **sessionless mode** on the MCP Streamable HTTP & SSE server — each request is handled by a fresh, temporary server/transport with no in-memory session state. Auto-enabled on Render (see below). |
|
|
315
316
|
|
|
316
317
|
### Airtable
|
|
317
318
|
|
|
318
|
-
| Variable | Description
|
|
319
|
-
| -------------------------------- |
|
|
319
|
+
| Variable | Description |
|
|
320
|
+
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
320
321
|
| `AIRTABLE_PERSONAL_ACCESS_TOKEN` | Required for `push_catalog_to_airtable`. Generate at [airtable.com/create/tokens](https://airtable.com/create/tokens) with `data.records:write` scope. |
|
|
321
322
|
|
|
322
323
|
### Melon
|
|
@@ -508,12 +509,12 @@ a similar load-balanced, stateless deployment is used.
|
|
|
508
509
|
|
|
509
510
|
### Transport selection
|
|
510
511
|
|
|
511
|
-
| Transport
|
|
512
|
-
|
|
|
513
|
-
| MCP stdio
|
|
514
|
-
| MCP Streamable HTTP & SSE
|
|
515
|
-
| JSON HTTP automation
|
|
516
|
-
| CLI
|
|
512
|
+
| Transport | Command | Use case |
|
|
513
|
+
| ------------------------- | ------------------------- | ----------------------------------- |
|
|
514
|
+
| MCP stdio | `npm run server:mcp` | Local MCP clients that speak stdio |
|
|
515
|
+
| MCP Streamable HTTP & SSE | `npm run server:mcp:http` | Remote MCP clients |
|
|
516
|
+
| JSON HTTP automation | `npm run server:http` | Container / remote automations |
|
|
517
|
+
| CLI | `npm run cli` | Ad-hoc / SSH / CI one-shot commands |
|
|
517
518
|
|
|
518
519
|
## HTTP Endpoints
|
|
519
520
|
|
|
@@ -770,12 +771,12 @@ Mr. Magic supports two connection modes depending on where the MCP client runs:
|
|
|
770
771
|
|
|
771
772
|
The right way to supply environment variables depends on how the server is launched:
|
|
772
773
|
|
|
773
|
-
| Config mode | How it starts
|
|
774
|
-
| ---------------------------------------------------------------------- |
|
|
775
|
-
| **Local source**
|
|
776
|
-
| **Local npx**
|
|
777
|
-
| **Persistent server** (VPS, global install, Docker with persistent FS) | `mcp-server` binary or `npm run server:mcp:http`
|
|
778
|
-
| **Ephemeral server** (Render free tier, containers, serverless) | `npx` or process started fresh each time
|
|
774
|
+
| Config mode | How it starts | How to pass env vars | `.env` file read? |
|
|
775
|
+
| ---------------------------------------------------------------------- | ------------------------------------------------------------- | ----------------------------------------------------------------- | ----------------- |
|
|
776
|
+
| **Local source** | `node src/bin/mcp-server.js` or `npm run server:mcp` | `.env` in project root, or shell exports | ✅ yes |
|
|
777
|
+
| **Local npx** | `npx --package mr-magic-mcp-server mcp-server` via MCP client | `env` block in MCP client config (see below) | ❌ no |
|
|
778
|
+
| **Persistent server** (VPS, global install, Docker with persistent FS) | `mcp-server` binary or `npm run server:mcp:http` | `.env` file **or** platform environment variables | ✅ if present |
|
|
779
|
+
| **Ephemeral server** (Render free tier, containers, serverless) | `npx` or process started fresh each time | Platform environment variables (Render Dashboard, Docker `--env`) | ❌ no |
|
|
779
780
|
|
|
780
781
|
> **`npx` and MCP clients:** When a local MCP client (Cline, Claude Desktop, etc.) starts the
|
|
781
782
|
> server via `npx`, the spawned process has **no access to your `.env` file** — your
|
|
@@ -788,16 +789,16 @@ The right way to supply environment variables depends on how the server is launc
|
|
|
788
789
|
|
|
789
790
|
These variables should be passed explicitly — the server cannot fall back to `.env` or on-disk caches:
|
|
790
791
|
|
|
791
|
-
| Variable
|
|
792
|
-
|
|
|
793
|
-
| `GENIUS_CLIENT_ID` + `GENIUS_CLIENT_SECRET`
|
|
794
|
-
| `GENIUS_DIRECT_TOKEN`
|
|
795
|
-
| `MUSIXMATCH_DIRECT_TOKEN`
|
|
796
|
-
| `UPSTASH_REDIS_REST_URL` + `UPSTASH_REDIS_REST_TOKEN`
|
|
797
|
-
| `MR_MAGIC_EXPORT_BACKEND`
|
|
798
|
-
| `MR_MAGIC_DOWNLOAD_BASE_URL`
|
|
799
|
-
| `AIRTABLE_PERSONAL_ACCESS_TOKEN`
|
|
800
|
-
| `MR_MAGIC_QUIET_STDIO`
|
|
792
|
+
| Variable | Purpose | Required when |
|
|
793
|
+
| ----------------------------------------------------- | ---------------------------------------------------- | -------------------------------------------------------- |
|
|
794
|
+
| `GENIUS_CLIENT_ID` + `GENIUS_CLIENT_SECRET` | Genius auto-refresh (recommended) | Using Genius |
|
|
795
|
+
| `GENIUS_DIRECT_TOKEN` | Static Genius token (alternative) | Using Genius without OAuth credentials |
|
|
796
|
+
| `MUSIXMATCH_DIRECT_TOKEN` | Musixmatch token (highest priority) | Using Musixmatch |
|
|
797
|
+
| `UPSTASH_REDIS_REST_URL` + `UPSTASH_REDIS_REST_TOKEN` | KV store for Musixmatch token + Redis export backend | Musixmatch via KV **or** `MR_MAGIC_EXPORT_BACKEND=redis` |
|
|
798
|
+
| `MR_MAGIC_EXPORT_BACKEND` | Storage backend for exports (`inline` or `redis`) | Exporting lyrics; use `inline` if no Redis |
|
|
799
|
+
| `MR_MAGIC_DOWNLOAD_BASE_URL` | Base URL for download links | `MR_MAGIC_EXPORT_BACKEND=redis` only |
|
|
800
|
+
| `AIRTABLE_PERSONAL_ACCESS_TOKEN` | Airtable push tool | Using `push_catalog_to_airtable` |
|
|
801
|
+
| `MR_MAGIC_QUIET_STDIO` | Suppress non-error stdout (set to `1`) | stdio MCP clients — avoids JSON-RPC parse errors |
|
|
801
802
|
|
|
802
803
|
> 💡 **Musixmatch on ephemeral hosts:** The on-disk token cache (`.cache/musixmatch-token.json`)
|
|
803
804
|
> is **not** available when running via `npx` or on ephemeral servers. Use `MUSIXMATCH_DIRECT_TOKEN`
|
|
@@ -809,11 +810,11 @@ These variables should be passed explicitly — the server cannot fall back to `
|
|
|
809
810
|
|
|
810
811
|
In addition to the provider credentials above, local and persistent deployments can also use:
|
|
811
812
|
|
|
812
|
-
| Variable | Purpose
|
|
813
|
-
| ------------------------------------- |
|
|
814
|
-
| `MR_MAGIC_EXPORT_BACKEND=local` | Write export files to disk (default; not usable on ephemeral hosts)
|
|
815
|
-
| `MR_MAGIC_EXPORT_DIR` | Directory to write local exports into
|
|
816
|
-
| `MR_MAGIC_ROOT` / `MR_MAGIC_ENV_PATH` | Override project root / `.env` path resolution
|
|
813
|
+
| Variable | Purpose |
|
|
814
|
+
| ------------------------------------- | ------------------------------------------------------------------------------ |
|
|
815
|
+
| `MR_MAGIC_EXPORT_BACKEND=local` | Write export files to disk (default; not usable on ephemeral hosts) |
|
|
816
|
+
| `MR_MAGIC_EXPORT_DIR` | Directory to write local exports into |
|
|
817
|
+
| `MR_MAGIC_ROOT` / `MR_MAGIC_ENV_PATH` | Override project root / `.env` path resolution |
|
|
817
818
|
| `MUSIXMATCH_AUTO_FETCH` | Auto re-run the Playwright fetch script when no token found (requires browser) |
|
|
818
819
|
|
|
819
820
|
On-disk token caches (`.cache/genius-token.json`, `.cache/musixmatch-token.json`) are also
|
|
@@ -997,7 +998,6 @@ Any client that accepts a plain MCP endpoint URL:
|
|
|
997
998
|
https://your-server.com/mcp
|
|
998
999
|
```
|
|
999
1000
|
|
|
1000
|
-
|
|
1001
1001
|
#### Legacy SSE clients
|
|
1002
1002
|
|
|
1003
1003
|
Some older MCP clients use the pre-Streamable HTTP & SSE SSE protocol instead of `POST /mcp`.
|
|
@@ -1355,6 +1355,7 @@ npm run server:http # JSON HTTP automation — port 3333
|
|
|
1355
1355
|
# Terminal 2
|
|
1356
1356
|
npm run server:mcp:http # Streamable HTTP & SSE MCP — port 3444
|
|
1357
1357
|
```
|
|
1358
|
+
|
|
1358
1359
|
> **Note:** Running both is **not** required for Redis exports. The MCP HTTP server
|
|
1359
1360
|
> (`server:mcp:http`) includes its own `/downloads/:id/:ext` route, so a single
|
|
1360
1361
|
> `server:mcp:http` instance is self-sufficient for Redis-backed download links.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mr-magic-mcp-server",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Lyrics MCP server connecting LRCLIB, Genius, Musixmatch, and Melon",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -59,11 +59,11 @@
|
|
|
59
59
|
"node": ">=20"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
+
"@dotenvx/dotenvx": "^1.55.1",
|
|
62
63
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
63
64
|
"axios": "^1.13.6",
|
|
64
65
|
"cheerio": "^1.2.0",
|
|
65
|
-
"commander": "^14.0.3"
|
|
66
|
-
"dotenv": "^17.3.1"
|
|
66
|
+
"commander": "^14.0.3"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"eslint": "^10.0.3",
|
|
@@ -71,7 +71,7 @@ export function startHttpServer(options = {}) {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
if (req.method === 'GET' && req.url === '/health') {
|
|
74
|
+
if (req.method === 'GET' && (req.url === '/' || req.url === '/health')) {
|
|
75
75
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
76
76
|
res.end(
|
|
77
77
|
JSON.stringify({
|
|
@@ -129,6 +129,10 @@ export async function startMcpHttpServer(options = {}) {
|
|
|
129
129
|
const app = createMcpExpressApp({ host, ...(allowedHosts ? { allowedHosts } : {}) });
|
|
130
130
|
|
|
131
131
|
// ── Health check ─────────────────────────────────────────────────────────────
|
|
132
|
+
app.get('/', async (_req, res) => {
|
|
133
|
+
res.json({ status: 'ok', providers: await getProviderStatus() });
|
|
134
|
+
});
|
|
135
|
+
|
|
132
136
|
app.get('/health', async (_req, res) => {
|
|
133
137
|
res.json({ status: 'ok', providers: await getProviderStatus() });
|
|
134
138
|
});
|
package/src/utils/config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import dotenvx from '@dotenvx/dotenvx';
|
|
5
5
|
|
|
6
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
7
|
const __dirname = path.dirname(__filename);
|
|
@@ -9,7 +9,11 @@ const projectRoot = path.resolve(__dirname, '..', '..');
|
|
|
9
9
|
const resolvedRoot = process.env.MR_MAGIC_ROOT || projectRoot;
|
|
10
10
|
const resolvedEnvPath = process.env.MR_MAGIC_ENV_PATH || path.join(resolvedRoot, '.env');
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
// Only load .env on local instances — skip on any known server environment
|
|
13
|
+
// (Render sets RENDER automatically; NODE_ENV=production covers other platforms).
|
|
14
|
+
if (!process.env.RENDER && process.env.NODE_ENV !== 'production') {
|
|
15
|
+
dotenvx.config({ path: resolvedEnvPath });
|
|
16
|
+
}
|
|
13
17
|
|
|
14
18
|
export function getProjectRoot() {
|
|
15
19
|
return resolvedRoot;
|