mr-magic-mcp-server 0.1.13 → 0.1.14

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 CHANGED
@@ -233,18 +233,30 @@ The `MR_MAGIC_EXPORT_BACKEND` variable controls where formatted lyrics are store
233
233
  `UPSTASH_REDIS_REST_TOKEN`, and `MR_MAGIC_DOWNLOAD_BASE_URL`.
234
234
 
235
235
  For Redis exports, `MR_MAGIC_DOWNLOAD_BASE_URL` must be the publicly reachable base URL
236
- of your HTTP automation server (not the Upstash URL), e.g. `https://lyrics.example.com`.
237
- Download links are built as `{base_url}/downloads/{id}/{ext}`.
236
+ of the server that will serve the download links (not the Upstash URL),
237
+ e.g. `https://lyrics.example.com`. Download links are built as
238
+ `{base_url}/downloads/{id}/{ext}`.
238
239
 
239
- For local testing:
240
+ Both HTTP servers serve `/downloads/:id/:ext` routes:
241
+
242
+ - **`server:mcp:http`** (port `3444`) — the Streamable HTTP MCP server includes its
243
+ own `/downloads` route. If you are already running this server, no additional HTTP
244
+ server is needed for Redis exports on Render or any remote deployment.
245
+ - **`server:http`** (port `3333`) — the JSON HTTP automation server also exposes the
246
+ same route and remains the right choice if you are running `server:mcp` (stdio) only
247
+ or want a standalone HTTP service for download links.
248
+
249
+ For local testing against the MCP HTTP server:
240
250
 
241
251
  ```bash
242
- MR_MAGIC_DOWNLOAD_BASE_URL=http://127.0.0.1:3333
252
+ MR_MAGIC_DOWNLOAD_BASE_URL=http://127.0.0.1:3444
243
253
  ```
244
254
 
245
- > Even when using only the stdio MCP server, you still need the HTTP automation
246
- > server running to serve `/downloads/:id/:ext` routes when the `redis` backend
247
- > is enabled.
255
+ Or against the JSON HTTP server:
256
+
257
+ ```bash
258
+ MR_MAGIC_DOWNLOAD_BASE_URL=http://127.0.0.1:3333
259
+ ```
248
260
 
249
261
  ## Local Deployment
250
262
 
@@ -844,16 +856,23 @@ curl -sS -X POST http://127.0.0.1:3444/mcp \
844
856
 
845
857
  ### Running both servers side-by-side
846
858
 
847
- For Redis-backed download scenarios, run both servers in separate terminals:
859
+ You may want both servers running at the same time — for example, to serve JSON HTTP
860
+ automations (`server:http`) alongside MCP tool calls (`server:mcp:http`), or to expose
861
+ both a REST API and an MCP endpoint under one deployment.
848
862
 
849
863
  ```bash
850
864
  # Terminal 1
851
- npm run server:http
865
+ npm run server:http # JSON HTTP automation — port 3333
852
866
 
853
867
  # Terminal 2
854
- npm run server:mcp:http
868
+ npm run server:mcp:http # Streamable HTTP MCP — port 3444
855
869
  ```
856
870
 
871
+ > **Note:** Running both is **not** required for Redis exports. The MCP HTTP server
872
+ > (`server:mcp:http`) includes its own `/downloads/:id/:ext` route, so a single
873
+ > `server:mcp:http` instance is self-sufficient for Redis-backed download links.
874
+ > Only run `server:http` alongside it if you also need the JSON HTTP automation API.
875
+
857
876
  ## Provider Notes
858
877
 
859
878
  - **LRCLIB** — Public API with synced lyric coverage. No auth required.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mr-magic-mcp-server",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "Lyrics MCP server connecting LRCLIB, Genius, Musixmatch, and Melon",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -8,6 +8,7 @@ import { createMcpExpressApp } from '@modelcontextprotocol/sdk/server/express.js
8
8
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
9
9
 
10
10
  import { createLogger } from '../utils/logger.js';
11
+ import { getSharedRedisClient } from '../utils/export-storage/shared-redis-client.js';
11
12
 
12
13
  import { mcpToolDefinitions, handleMcpTool } from './mcp-tools.js';
13
14
  import { buildMcpResponse } from './mcp-response.js';
@@ -111,10 +112,35 @@ export async function startMcpHttpServer(options = {}) {
111
112
  : undefined;
112
113
 
113
114
  const app = createMcpExpressApp({ host, ...(allowedHosts ? { allowedHosts } : {}) });
115
+
114
116
  app.get('/health', async (_req, res) => {
115
117
  res.json({ status: 'ok', providers: await getProviderStatus() });
116
118
  });
117
119
 
120
+ app.get('/downloads/:downloadId/*', async (req, res) => {
121
+ const { downloadId } = req.params;
122
+ const extension = req.params[0] || '';
123
+ if (!downloadId || !extension) {
124
+ res.status(400).json({ error: 'Invalid download path' });
125
+ return;
126
+ }
127
+ try {
128
+ const redis = getSharedRedisClient({ context: 'mcp-http-download' });
129
+ const key = `mr-magic:${downloadId}:${extension}`;
130
+ const content = await redis.get(key);
131
+ if (!content) {
132
+ logger.warn('Export download missing', { context: 'mcp-http-download', key, downloadId, extension });
133
+ res.status(404).json({ error: 'Export expired or missing' });
134
+ return;
135
+ }
136
+ res.status(200).type('text/plain').send(content);
137
+ logger.info('Export download served', { context: 'mcp-http-download', key, downloadId, extension, bytes: Buffer.byteLength(content) });
138
+ } catch (error) {
139
+ logger.error('Download lookup failed', { error, url: req.originalUrl });
140
+ res.status(500).json({ error: 'Failed to fetch export' });
141
+ }
142
+ });
143
+
118
144
  app.all('/mcp', async (req, res) => {
119
145
  const normalizedBody = normalizeIncomingRpcBody(req.body);
120
146
  const requestId = randomUUID();