@audiolabtools/mcp-server 0.3.2 → 0.4.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.
Files changed (3) hide show
  1. package/README.md +95 -91
  2. package/hosted-server.mjs +66 -15
  3. package/package.json +48 -48
package/README.md CHANGED
@@ -1,91 +1,95 @@
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
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) ten 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 |
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
+ | `analyze_profile` | One named question, `voice`, `master`, `provenance`, `dataset`, `environment`, `broadcast` or `loop`, answered with only the lenses it needs. These seven need a paid plan; the free tier gets the `basic` profile, keyed by stable lens id. Add `series:true` for the curves, per-block lanes and per-phrase values. Carries a `note` when the profile’s voice lenses land on non-speech material. Full catalogue: <https://audiolab.tools/lenses> |
52
+ | `compare_loudness` | A/B on two sources (`urlA`/`pathA` + `urlB`/`pathB`), returns both results |
53
+ | `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 |
54
+
55
+ Example asks to your AI:
56
+
57
+ - *“Analyze the loudness of https://example.com/track.wav”* → `analyze_loudness` with `url`
58
+ - *“Is this take usable?”* → `analyze_profile` with `profile:"voice"`
59
+ - *“Has this file been re-encoded, and is it all one source?”* → `analyze_profile` with `profile:"provenance"`
60
+ - *“Run loudness on ./master.wav”* → `analyze_loudness` with `path`
61
+ - *“Does ./mix.mp3 pass Spotify?”* → `check_target` with `path` + `target:"spotify"`
62
+
63
+ ## Configuration (env)
64
+
65
+ | Var | Default | Purpose |
66
+ |---|---|---|
67
+ | `AUDIOLAB_API_KEY` | – (required) | Your API key. |
68
+ | `AUDIOLAB_API_BASE` | `https://audiolab.tools/v1` | Override the API base (must be `https://`). |
69
+ | `AUDIOLAB_TIMEOUT_MS` | `330000` | Per-request timeout in milliseconds (long files and batches stream server-side and can legitimately take minutes). |
70
+
71
+ ## Privacy
72
+
73
+ Analysis happens on the AudioLab API, so the audio **does reach `audiolab.tools`**: a `url`
74
+ is fetched server-side, and a local `path` is sent to the API (small files inline; larger
75
+ files via a private one-shot signed upload that is deleted right after analysis). The API
76
+ returns **numbers only** and does not retain your audio (see https://audiolab.tools/privacy).
77
+ This package has no telemetry and writes nothing to disk. If audio must never leave the
78
+ machine, don't use a hosted analyser.
79
+
80
+ ## Limits
81
+
82
+ - Local files: up to **50 MB** (host bigger ones at a public URL).
83
+ - Duration: loudness routes (`analyze_loudness`, `check_target`, `analyze_timeseries`, `get_spectrum`) handle **long files** (podcast episodes, full sets, up to ~3 h) via server-side streaming; voice/signal routes are limited to ~7 minutes.
84
+ - One file per call (agents loop for many); one-shot (no streaming/realtime).
85
+ - Rate and monthly limits are enforced by the API, per key.
86
+
87
+ ## Smoke test
88
+
89
+ ```sh
90
+ node hosted-server.mjs --selftest # verifies the 10 tools + guards; no network
91
+ ```
92
+
93
+ ## License
94
+
95
+ MIT © Nathan Renting
package/hosted-server.mjs CHANGED
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
- // AudioLab HOSTED-mode MCP server. Exposes the 9 AudioLab tools to any MCP-capable
2
+ // AudioLab HOSTED-mode MCP server. Exposes the 10 AudioLab tools to any MCP-capable
3
3
  // AI (Claude Desktop / Claude Code, Cursor, etc.) by calling the hosted API at
4
4
  // audiolab.tools/v1/*. It contains NO engine code, just HTTP calls, so it is safe to
5
5
  // distribute publicly without exposing the proprietary engine.
6
6
  //
7
7
  // Two consumers share buildServer():
8
8
  // 1. This file run directly = a stdio server (the npm package @audiolabtools/mcp-server),
9
- // reading the key from AUDIOLAB_API_KEY. Started with { local: true } — so it can also
9
+ // reading the key from AUDIOLAB_API_KEY. Started with { local: true }, so it can also
10
10
  // analyse a LOCAL file via `{ path }` (small files POST raw; larger files are PUT to
11
11
  // storage via a signed URL and analysed by objectPath). Nothing is exposed publicly.
12
12
  // 2. api/mcp.mjs = the remote streamable-HTTP endpoint at /mcp, which passes the
13
- // per-request Bearer key via buildServer({ apiKey }). local defaults to FALSE there —
13
+ // per-request Bearer key via buildServer({ apiKey }). local defaults to FALSE there,
14
14
  // a remote server must NEVER read a path off its own filesystem, so `{ path }` is
15
15
  // rejected and only `{ url }` is accepted.
16
16
  //
@@ -21,7 +21,7 @@
21
21
  // "env": { "AUDIOLAB_API_KEY": "al_live_yourkey" } } } }
22
22
  //
23
23
  // Env: AUDIOLAB_API_KEY (required at call time for stdio mode), AUDIOLAB_API_BASE
24
- // (default https://audiolab.tools/v1, must be https), AUDIOLAB_TIMEOUT_MS (default 60000).
24
+ // (default https://audiolab.tools/v1, must be https), AUDIOLAB_TIMEOUT_MS (default 330000).
25
25
  // Smoke test (no network): node hosted-server.mjs --selftest
26
26
 
27
27
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
@@ -36,11 +36,21 @@ import { z } from 'zod';
36
36
  // package.json" comment next to it. It drifted anyway: the package shipped 0.3.1
37
37
  // while every initialize response still announced 0.3.0. Read it instead, so the
38
38
  // comment cannot be ignored and the two cannot disagree.
39
- const { version: PKG_VERSION } = createRequire(import.meta.url)('./package.json');
39
+ // ponytail: the npm package always ships package.json, the Vercel bundle of api/mcp.mjs
40
+ // never does (includeFiles skips it too). A throw here took the remote /mcp down at load
41
+ // time from 11 Aug to 14 Sep, so the hosted copy reports 'hosted' instead of crashing.
42
+ const PKG_VERSION = (() => {
43
+ try { return createRequire(import.meta.url)('./package.json').version; } catch { return 'hosted'; }
44
+ })();
40
45
 
41
46
  // Vercel serverless caps a raw request body at ~4.5 MB, so small files POST directly and
42
47
  // larger ones go through the signed-URL storage flow. The bucket policy caps at 50 MB.
43
48
  const RAW_MAX = 4 * 1024 * 1024;
49
+ // Dit bestand is het ENIGE dat npm meestuurt, dus het mag niets buiten zijn eigen map
50
+ // importeren. `MAX_STORAGE_BYTES` uit ../lib/limits.mjs stond hier even, en daarmee
51
+ // crashte het gepubliceerde pakket bij de eerste import: die map wordt niet meegeleverd.
52
+ // De waarde staat daarom weer hier, en de zelfcheck hieronder houdt hem tegen limits.mjs aan
53
+ // zolang die bereikbaar is, dus in de monorepo faalt drift alsnog.
44
54
  const STORAGE_MAX = 50 * 1024 * 1024;
45
55
 
46
56
  // Read env at CALL time (not module load) so the key can be injected by the MCP host
@@ -52,7 +62,10 @@ const apiBase = () => {
52
62
  return base;
53
63
  };
54
64
 
55
- const timeoutMs = () => Number(process.env.AUDIOLAB_TIMEOUT_MS) || 60_000;
65
+ // Just above the API's own 300 s ceiling: since long files stream server-side
66
+ // (a 25-min track ≈ 10-30 s, batches of them add up), a 60 s client default
67
+ // made the client give up while the server was still happily working.
68
+ const timeoutMs = () => Number(process.env.AUDIOLAB_TIMEOUT_MS) || 330_000;
56
69
 
57
70
  function requireKey(key) {
58
71
  const k = key || process.env.AUDIOLAB_API_KEY;
@@ -196,7 +209,7 @@ const wrap = (fn) => async (input) => {
196
209
  const sourceShape = (local) => local
197
210
  ? {
198
211
  url: z.string().url().optional().describe('Public https URL to the audio file. Provide exactly one of url or path.'),
199
- path: z.string().optional().describe('Path to a LOCAL audio file on this machine — analysed without hosting it publicly (files up to 4 MB are sent inline; larger ones up to 50 MB upload over a one-shot signed URL). Provide exactly one of url or path.'),
212
+ path: z.string().optional().describe('Path to a LOCAL audio file on this machine, analysed without hosting it publicly (files up to 4 MB are sent inline; larger ones up to 50 MB upload over a one-shot signed URL). Provide exactly one of url or path.'),
200
213
  }
201
214
  : { url: z.string().url().describe('Public https URL to the audio file.') };
202
215
 
@@ -227,7 +240,7 @@ export function buildServer({ apiKey, local = false } = {}) {
227
240
 
228
241
  tool('get_spectrum', {
229
242
  title: 'FFT spectrum data',
230
- description: 'Frequency-domain magnitude data (paired frequency/magnitude arrays) plus energies in 7 standard bands (sub/bass/lowMid/mid/highMid/presence/air) and the dominant band. For spectrum-analyzer UIs and tonal-balance analysis.' + srcDoc,
243
+ description: 'Frequency-domain magnitude data (paired frequency/magnitude arrays) plus energies in 7 standard bands (sub/bass/lowMid/mid/highMid/presence/air). There is no dominant-band field in the response. For spectrum-analyzer UIs and tonal-balance analysis.' + srcDoc,
231
244
  inputSchema: src,
232
245
  }, wrap((i) => analyzeSource('mixlab/spectrum', i, {}, apiKey, local)));
233
246
 
@@ -247,9 +260,37 @@ export function buildServer({ apiKey, local = false } = {}) {
247
260
  title: 'Index a signal (SignalLab)',
248
261
  description: 'A metadata index for any audio file: content-type guess (voice/music/mixed/noise/silence) with confidence, brightness & dynamics buckets, dominant band, clipping/silence regions, and tag suggestions. For triage or auto-tagging a library.' + srcDoc,
249
262
  inputSchema: src,
250
- }, wrap((i) => analyzeSource('signallab/index', i, {}, apiKey, local)));
263
+ }, wrap((i) => analyzeSource('signallab', i, {}, apiKey, local)));
264
+
265
+ // analyze_profile: the lens registry as one tool. A model that knows what it
266
+ // is looking for names the question, not forty field names; a model that does
267
+ // not can read the profiles here and pick one.
268
+ tool('analyze_profile', {
269
+ title: 'Analyse against a profile',
270
+ description:
271
+ 'Measure a file against a named working set of lenses and get back only what that question needs. '
272
+ + 'Profiles: voice (is this take usable, and which phrase is the problem), '
273
+ + 'master (will this translate to real platforms and speakers), '
274
+ + 'provenance (what has been done to this file, and is it all one source), '
275
+ + 'dataset (which of these files are good enough, and why not the rest), '
276
+ + 'environment (what is in this space, and what kind of noise is it), '
277
+ + 'broadcast (does this file meet the delivery spec), '
278
+ + 'loop (is this loop clean, on the grid, and safe to drop in a DAW). '
279
+ + 'basic is the free tier; the other seven need a paid plan. '
280
+ + 'Results are keyed by stable lens id. Only the analysis passes the profile needs are run. '
281
+ + 'Set series:true to also get the curves, the per-block lanes and the per-phrase values,'
282
+ + 'a much larger payload, so leave it off unless you are going to read them.'
283
+ + srcDoc,
284
+ inputSchema: {
285
+ ...src,
286
+ profile: z.enum(['basic', 'voice', 'master', 'provenance', 'dataset', 'environment', 'broadcast', 'loop'])
287
+ .describe('Which question to answer.'),
288
+ series: z.boolean().optional()
289
+ .describe('Include time series, per-block lanes and per-phrase arrays. Off by default.'),
290
+ },
291
+ }, wrap((i) => analyzeSource('analyze/profile', i, { profile: i.profile, series: i.series === true }, apiKey, local)));
251
292
 
252
- // compare_loudness — two independent sources, each a url or (local only) a path.
293
+ // compare_loudness: two independent sources, each a url or (local only) a path.
253
294
  const cmp = local
254
295
  ? {
255
296
  urlA: z.string().url().optional().describe('First source URL (e.g. master). Provide urlA or pathA.'),
@@ -273,7 +314,7 @@ export function buildServer({ apiKey, local = false } = {}) {
273
314
  return { a, b };
274
315
  }));
275
316
 
276
- // analyze_batch — one route over many sources, a single metered-per-item call.
317
+ // analyze_batch: one route over many sources, a single metered-per-item call.
277
318
  const batchSrc = local
278
319
  ? {
279
320
  urls: z.array(z.string().url()).optional().describe('Public https URLs to audio files. Combined max 20 items with paths.'),
@@ -301,9 +342,9 @@ const isMain = process.argv[1] && import.meta.url === pathToFileURL(process.argv
301
342
 
302
343
  if (isMain && process.argv.includes('--selftest')) {
303
344
  const assert = (await import('node:assert/strict')).default;
304
- const expected = ['analyze_batch', 'analyze_loudness', 'analyze_timeseries', 'analyze_voice', 'check_target', 'compare_loudness', 'get_spectrum', 'get_speech_segments', 'index_signal'];
305
- assert.deepEqual(buildServer().toolNames.slice().sort(), expected, 'nine hosted tools (remote / url-only)');
306
- assert.deepEqual(buildServer({ local: true }).toolNames.slice().sort(), expected, 'nine hosted tools (local / url+path)');
345
+ const expected = ['analyze_batch', 'analyze_loudness', 'analyze_profile', 'analyze_timeseries', 'analyze_voice', 'check_target', 'compare_loudness', 'get_spectrum', 'get_speech_segments', 'index_signal'];
346
+ assert.deepEqual(buildServer().toolNames.slice().sort(), expected, 'ten hosted tools (remote / url-only)');
347
+ assert.deepEqual(buildServer({ local: true }).toolNames.slice().sort(), expected, 'ten hosted tools (local / url+path)');
307
348
 
308
349
  const prev = process.env.AUDIOLAB_API_KEY;
309
350
  delete process.env.AUDIOLAB_API_KEY;
@@ -326,7 +367,17 @@ if (isMain && process.argv.includes('--selftest')) {
326
367
  assert.equal(typeof PKG_VERSION, 'string', 'version resolves from package.json');
327
368
  assert.match(PKG_VERSION, /^\d+\.\d+\.\d+/, 'version looks like a semver');
328
369
 
329
- console.log(`selftest ok · v${PKG_VERSION} · 9 tools (incl. analyze_batch) + missing-key guard + remote-path refusals + batch guards`);
370
+ // De opslaggrens staat hier hardgecodeerd omdat het pakket zichzelf moet kunnen draaien.
371
+ // In de monorepo is limits.mjs er wel, en dan moet hij gelijk zijn; in het gepubliceerde
372
+ // pakket ontbreekt hij en slaan we over. Zo kan de waarde niet stil uit elkaar lopen.
373
+ try {
374
+ const { MAX_STORAGE_BYTES } = await import('../lib/limits.mjs');
375
+ assert.equal(STORAGE_MAX, MAX_STORAGE_BYTES, 'STORAGE_MAX loopt uit de pas met lib/limits.mjs');
376
+ } catch (e) {
377
+ if (e?.code !== 'ERR_MODULE_NOT_FOUND') throw e;
378
+ }
379
+
380
+ console.log(`selftest ok · v${PKG_VERSION} · ${expected.length} tools (incl. analyze_profile) + missing-key guard + remote-path refusals + batch guards`);
330
381
  process.exit(0);
331
382
  }
332
383
 
package/package.json CHANGED
@@ -1,48 +1,48 @@
1
- {
2
- "name": "@audiolabtools/mcp-server",
3
- "version": "0.3.2",
4
- "mcpName": "tools.audiolab/audiolab",
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.",
6
- "type": "module",
7
- "bin": {
8
- "audiolabtools-mcp-server": "hosted-server.mjs"
9
- },
10
- "files": [
11
- "hosted-server.mjs",
12
- "README.md"
13
- ],
14
- "keywords": [
15
- "mcp",
16
- "model-context-protocol",
17
- "claude",
18
- "audio",
19
- "audio-analysis",
20
- "loudness",
21
- "lufs",
22
- "ebu-r128",
23
- "bs-1770",
24
- "true-peak",
25
- "voice-quality",
26
- "audiolab"
27
- ],
28
- "homepage": "https://audiolab.tools/api",
29
- "bugs": {
30
- "url": "https://github.com/Audio-Launch/audiolab-mcp-server/issues"
31
- },
32
- "license": "MIT",
33
- "author": "Nathan Renting",
34
- "publishConfig": {
35
- "access": "public"
36
- },
37
- "engines": {
38
- "node": ">=18"
39
- },
40
- "dependencies": {
41
- "@modelcontextprotocol/sdk": "^1.29.0",
42
- "zod": "^4.4.3"
43
- },
44
- "repository": {
45
- "type": "git",
46
- "url": "git+https://github.com/Audio-Launch/audiolab-mcp-server.git"
47
- }
48
- }
1
+ {
2
+ "name": "@audiolabtools/mcp-server",
3
+ "version": "0.4.0",
4
+ "mcpName": "tools.audiolab/audiolab",
5
+ "description": "MCP server for AudioLab, 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.",
6
+ "type": "module",
7
+ "bin": {
8
+ "audiolabtools-mcp-server": "hosted-server.mjs"
9
+ },
10
+ "files": [
11
+ "hosted-server.mjs",
12
+ "README.md"
13
+ ],
14
+ "keywords": [
15
+ "mcp",
16
+ "model-context-protocol",
17
+ "claude",
18
+ "audio",
19
+ "audio-analysis",
20
+ "loudness",
21
+ "lufs",
22
+ "ebu-r128",
23
+ "bs-1770",
24
+ "true-peak",
25
+ "voice-quality",
26
+ "audiolab"
27
+ ],
28
+ "homepage": "https://audiolab.tools/api",
29
+ "bugs": {
30
+ "url": "https://github.com/Audio-Launch/audiolab-mcp-server/issues"
31
+ },
32
+ "license": "MIT",
33
+ "author": "Nathan Renting",
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "engines": {
38
+ "node": ">=18"
39
+ },
40
+ "dependencies": {
41
+ "@modelcontextprotocol/sdk": "^1.29.0",
42
+ "zod": "^4.4.3"
43
+ },
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "git+https://github.com/Audio-Launch/audiolab-mcp-server.git"
47
+ }
48
+ }