@audiolabtools/mcp-server 0.3.0 → 0.3.2
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 +91 -90
- package/hosted-server.mjs +15 -2
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -1,90 +1,91 @@
|
|
|
1
|
-
# @audiolabtools/mcp-server
|
|
2
|
-
|
|
3
|
-
MCP ([Model Context Protocol](https://modelcontextprotocol.io)) server that gives any
|
|
4
|
-
MCP-capable AI — Claude Desktop, Claude Code, Cursor, and others —
|
|
5
|
-
tools, backed by the hosted **AudioLab** API. It is a thin HTTP client: **no local audio
|
|
6
|
-
engine, no ffmpeg, nothing to compile.** It can analyse a **public URL** or a **local file**
|
|
7
|
-
on your machine.
|
|
8
|
-
|
|
9
|
-
## Install
|
|
10
|
-
|
|
11
|
-
Point your MCP client at the package via `npx` (nothing to install globally):
|
|
12
|
-
|
|
13
|
-
```json
|
|
14
|
-
{
|
|
15
|
-
"mcpServers": {
|
|
16
|
-
"audiolab": {
|
|
17
|
-
"command": "npx",
|
|
18
|
-
"args": ["-y", "@audiolabtools/mcp-server"],
|
|
19
|
-
"env": { "AUDIOLAB_API_KEY": "al_live_yourkey" }
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
Get a key: sign in at **https://audiolab.tools/account** and generate one (free tier available).
|
|
26
|
-
|
|
27
|
-
## Requirements
|
|
28
|
-
|
|
29
|
-
- **Node ≥ 18** — uses the built-in global `fetch` + `AbortSignal.timeout`.
|
|
30
|
-
- An `AUDIOLAB_API_KEY`. No ffmpeg, no native dependencies.
|
|
31
|
-
|
|
32
|
-
## Tools
|
|
33
|
-
|
|
34
|
-
Every tool takes **one audio source** — a public `url` **or** a local `path`:
|
|
35
|
-
|
|
36
|
-
- `{ url: "https://…" }` — a public https URL the API fetches server-side.
|
|
37
|
-
- `{ path: "./mix.wav" }` — a file on the machine running this server. Files up to **4 MB**
|
|
38
|
-
are sent inline; larger files (up to **50 MB**) upload over a one-shot signed URL, are
|
|
39
|
-
analysed, and are then deleted. *(Local `path` works only in this stdio server, not the
|
|
40
|
-
remote `/mcp` endpoint.)*
|
|
41
|
-
|
|
42
|
-
| Tool | Returns |
|
|
43
|
-
|---|---|
|
|
44
|
-
| `analyze_loudness` | Integrated LUFS (EBU R128 / BS.1770-4), true-peak (dBTP), LRA, crest factor, stereo correlation, mono compatibility, tonal balance |
|
|
45
|
-
| `check_target` | Pass/fail vs a delivery target (`spotify` / `apple-music` / `youtube` / `tidal` / `amazon-music` / `podcast` / `ebu-broadcast` / `atsc-broadcast`, or `target:"custom"` + `lufs`+`tp`), with per-metric deltas and an ffmpeg loudnorm fix command |
|
|
46
|
-
| `analyze_timeseries` | Short-term LUFS over time + downsampled waveform peaks (`waveformPoints?`) |
|
|
47
|
-
| `get_spectrum` | FFT magnitude data + 7-band energies + dominant band |
|
|
48
|
-
| `analyze_voice` | Voice QA: speech/silence ratio, speaking rate, SNR, noise floor, room echo, sibilance & clipping risk |
|
|
49
|
-
| `get_speech_segments` | Voiced regions with start/end + per-segment RMS (auto-trim, chapters) |
|
|
50
|
-
| `index_signal` | Content-type guess, tags, clipping/silence regions, brightness & dynamics buckets |
|
|
51
|
-
| `compare_loudness` | A/B on two sources (`urlA`/`pathA` + `urlB`/`pathB`), returns both results |
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
- *“
|
|
57
|
-
- *“
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
| `
|
|
65
|
-
| `
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
-
|
|
80
|
-
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
1
|
+
# @audiolabtools/mcp-server
|
|
2
|
+
|
|
3
|
+
MCP ([Model Context Protocol](https://modelcontextprotocol.io)) server that gives any
|
|
4
|
+
MCP-capable AI — Claude Desktop, Claude Code, Cursor, and others — nine audio-analysis
|
|
5
|
+
tools, backed by the hosted **AudioLab** API. It is a thin HTTP client: **no local audio
|
|
6
|
+
engine, no ffmpeg, nothing to compile.** It can analyse a **public URL** or a **local file**
|
|
7
|
+
on your machine.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
Point your MCP client at the package via `npx` (nothing to install globally):
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"mcpServers": {
|
|
16
|
+
"audiolab": {
|
|
17
|
+
"command": "npx",
|
|
18
|
+
"args": ["-y", "@audiolabtools/mcp-server"],
|
|
19
|
+
"env": { "AUDIOLAB_API_KEY": "al_live_yourkey" }
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Get a key: sign in at **https://audiolab.tools/account** and generate one (free tier available).
|
|
26
|
+
|
|
27
|
+
## Requirements
|
|
28
|
+
|
|
29
|
+
- **Node ≥ 18** — uses the built-in global `fetch` + `AbortSignal.timeout`.
|
|
30
|
+
- An `AUDIOLAB_API_KEY`. No ffmpeg, no native dependencies.
|
|
31
|
+
|
|
32
|
+
## Tools
|
|
33
|
+
|
|
34
|
+
Every tool takes **one audio source** — a public `url` **or** a local `path`:
|
|
35
|
+
|
|
36
|
+
- `{ url: "https://…" }` — a public https URL the API fetches server-side.
|
|
37
|
+
- `{ path: "./mix.wav" }` — a file on the machine running this server. Files up to **4 MB**
|
|
38
|
+
are sent inline; larger files (up to **50 MB**) upload over a one-shot signed URL, are
|
|
39
|
+
analysed, and are then deleted. *(Local `path` works only in this stdio server, not the
|
|
40
|
+
remote `/mcp` endpoint.)*
|
|
41
|
+
|
|
42
|
+
| Tool | Returns |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `analyze_loudness` | Integrated LUFS (EBU R128 / BS.1770-4), true-peak (dBTP), LRA, crest factor, stereo correlation, mono compatibility, tonal balance |
|
|
45
|
+
| `check_target` | Pass/fail vs a delivery target (`spotify` / `apple-music` / `youtube` / `tidal` / `amazon-music` / `podcast` / `ebu-broadcast` / `atsc-broadcast`, or `target:"custom"` + `lufs`+`tp`), with per-metric deltas and an ffmpeg loudnorm fix command |
|
|
46
|
+
| `analyze_timeseries` | Short-term LUFS over time + downsampled waveform peaks (`waveformPoints?`) |
|
|
47
|
+
| `get_spectrum` | FFT magnitude data + 7-band energies + dominant band |
|
|
48
|
+
| `analyze_voice` | Voice QA: speech/silence ratio, speaking rate, SNR, noise floor, room echo, sibilance & clipping risk |
|
|
49
|
+
| `get_speech_segments` | Voiced regions with start/end + per-segment RMS (auto-trim, chapters) |
|
|
50
|
+
| `index_signal` | Content-type guess, tags, clipping/silence regions, brightness & dynamics buckets |
|
|
51
|
+
| `compare_loudness` | A/B on two sources (`urlA`/`pathA` + `urlB`/`pathB`), returns both results |
|
|
52
|
+
| `analyze_batch` | One route over up to 20 sources in a single call (`urls` and/or `paths`), per-item ok/data/error. For folder QA, library indexing, or checking a whole release against a target. Each item meters as one call |
|
|
53
|
+
|
|
54
|
+
Example asks to your AI:
|
|
55
|
+
|
|
56
|
+
- *“Analyze the loudness of https://example.com/track.wav”* → `analyze_loudness` with `url`
|
|
57
|
+
- *“Run loudness on ./master.wav”* → `analyze_loudness` with `path`
|
|
58
|
+
- *“Does ./mix.mp3 pass Spotify?”* → `check_target` with `path` + `target:"spotify"`
|
|
59
|
+
|
|
60
|
+
## Configuration (env)
|
|
61
|
+
|
|
62
|
+
| Var | Default | Purpose |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| `AUDIOLAB_API_KEY` | — (required) | Your API key. |
|
|
65
|
+
| `AUDIOLAB_API_BASE` | `https://audiolab.tools/v1` | Override the API base (must be `https://`). |
|
|
66
|
+
| `AUDIOLAB_TIMEOUT_MS` | `60000` | Per-request timeout in milliseconds. |
|
|
67
|
+
|
|
68
|
+
## Privacy
|
|
69
|
+
|
|
70
|
+
Analysis happens on the AudioLab API, so the audio **does reach `audiolab.tools`** — a `url`
|
|
71
|
+
is fetched server-side, and a local `path` is sent to the API (small files inline; larger
|
|
72
|
+
files via a private one-shot signed upload that is deleted right after analysis). The API
|
|
73
|
+
returns **numbers only** and does not retain your audio (see https://audiolab.tools/privacy).
|
|
74
|
+
This package has no telemetry and writes nothing to disk. If audio must never leave the
|
|
75
|
+
machine, don't use a hosted analyser.
|
|
76
|
+
|
|
77
|
+
## Limits
|
|
78
|
+
|
|
79
|
+
- Local files: up to **50 MB** (host bigger ones at a public URL).
|
|
80
|
+
- One file per call (agents loop for many); one-shot (no streaming/realtime).
|
|
81
|
+
- Rate and monthly limits are enforced by the API, per key.
|
|
82
|
+
|
|
83
|
+
## Smoke test
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
node hosted-server.mjs --selftest # verifies the 9 tools + guards; no network
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## License
|
|
90
|
+
|
|
91
|
+
MIT © Nathan Renting
|
package/hosted-server.mjs
CHANGED
|
@@ -29,8 +29,15 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
29
29
|
import { readFile } from 'node:fs/promises';
|
|
30
30
|
import { basename } from 'node:path';
|
|
31
31
|
import { pathToFileURL } from 'node:url';
|
|
32
|
+
import { createRequire } from 'node:module';
|
|
32
33
|
import { z } from 'zod';
|
|
33
34
|
|
|
35
|
+
// The version reported over MCP used to be a literal with a "keep in sync with
|
|
36
|
+
// package.json" comment next to it. It drifted anyway: the package shipped 0.3.1
|
|
37
|
+
// while every initialize response still announced 0.3.0. Read it instead, so the
|
|
38
|
+
// comment cannot be ignored and the two cannot disagree.
|
|
39
|
+
const { version: PKG_VERSION } = createRequire(import.meta.url)('./package.json');
|
|
40
|
+
|
|
34
41
|
// Vercel serverless caps a raw request body at ~4.5 MB, so small files POST directly and
|
|
35
42
|
// larger ones go through the signed-URL storage flow. The bucket policy caps at 50 MB.
|
|
36
43
|
const RAW_MAX = 4 * 1024 * 1024;
|
|
@@ -194,7 +201,7 @@ const sourceShape = (local) => local
|
|
|
194
201
|
: { url: z.string().url().describe('Public https URL to the audio file.') };
|
|
195
202
|
|
|
196
203
|
export function buildServer({ apiKey, local = false } = {}) {
|
|
197
|
-
const server = new McpServer({ name: 'audiolab', version:
|
|
204
|
+
const server = new McpServer({ name: 'audiolab', version: PKG_VERSION });
|
|
198
205
|
const toolNames = [];
|
|
199
206
|
const tool = (name, def, handler) => { server.registerTool(name, def, handler); toolNames.push(name); };
|
|
200
207
|
const src = sourceShape(local);
|
|
@@ -313,7 +320,13 @@ if (isMain && process.argv.includes('--selftest')) {
|
|
|
313
320
|
await assert.rejects(() => batchSources({ urls: Array.from({ length: 21 }, (_, n) => `https://x/${n}.wav`) }, 'mixlab/analyze', {}, 'al_live_selftest', false), /max 20/, 'oversized batch rejected before network');
|
|
314
321
|
if (prev) process.env.AUDIOLAB_API_KEY = prev; else delete process.env.AUDIOLAB_API_KEY;
|
|
315
322
|
|
|
316
|
-
|
|
323
|
+
// The version announced over MCP drifted from the published package once already
|
|
324
|
+
// (server said 0.3.0, npm had 0.3.1). Now it is read from package.json, and this
|
|
325
|
+
// asserts the read actually resolved rather than silently yielding undefined.
|
|
326
|
+
assert.equal(typeof PKG_VERSION, 'string', 'version resolves from package.json');
|
|
327
|
+
assert.match(PKG_VERSION, /^\d+\.\d+\.\d+/, 'version looks like a semver');
|
|
328
|
+
|
|
329
|
+
console.log(`selftest ok · v${PKG_VERSION} · 9 tools (incl. analyze_batch) + missing-key guard + remote-path refusals + batch guards`);
|
|
317
330
|
process.exit(0);
|
|
318
331
|
}
|
|
319
332
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@audiolabtools/mcp-server",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
|
+
"mcpName": "tools.audiolab/audiolab",
|
|
4
5
|
"description": "MCP server for AudioLab \u2014 loudness (EBU R128 / BS.1770-4), true-peak, voice-quality, and signal analysis for AI agents (Claude, Cursor, any MCP client), via the AudioLab hosted API. No local audio engine required.",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"bin": {
|
|
@@ -26,7 +27,7 @@
|
|
|
26
27
|
],
|
|
27
28
|
"homepage": "https://audiolab.tools/api",
|
|
28
29
|
"bugs": {
|
|
29
|
-
"url": "https://
|
|
30
|
+
"url": "https://github.com/Audio-Launch/audiolab-mcp-server/issues"
|
|
30
31
|
},
|
|
31
32
|
"license": "MIT",
|
|
32
33
|
"author": "Nathan Renting",
|
|
@@ -39,5 +40,9 @@
|
|
|
39
40
|
"dependencies": {
|
|
40
41
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
41
42
|
"zod": "^4.4.3"
|
|
43
|
+
},
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "git+https://github.com/Audio-Launch/audiolab-mcp-server.git"
|
|
42
47
|
}
|
|
43
48
|
}
|