Skip to content

Commit 83f5718

Browse files
Merge pull request #19 from decibri/development
feat: upgrade decibri to 5.0.0, select devices by stable id
2 parents 8cfcc4c + 1b13be7 commit 83f5718

12 files changed

Lines changed: 763 additions & 57 deletions

File tree

.github/workflows/ci.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,13 @@ jobs:
6363
shell: bash
6464
run: |
6565
node -e '
66-
const Decibri = require("decibri");
66+
const { Microphone } = require("decibri");
6767
try {
68-
const devices = Decibri.devices();
69-
console.log("Decibri.devices() returned:");
68+
const devices = Microphone.devices();
69+
console.log("Microphone.devices() returned:");
7070
console.log(JSON.stringify(devices, null, 2));
7171
} catch (err) {
72-
console.log("Decibri.devices() threw:");
72+
console.log("Microphone.devices() threw:");
7373
console.log(err && err.stack ? err.stack : String(err));
7474
}
7575
'

.github/workflows/publish.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ jobs:
105105
echo "OK: npm ${NPM_VERSION} supports trusted publishing"
106106
107107
- name: Install ALSA runtime (Linux)
108-
# decibri's native addon links ALSA on Linux. Harmless today at decibri
109-
# 1.x; required once decibri 5.x lands. Mirrors the platform setup in the
110-
# decibri repo's own build matrix.
108+
# decibri's native addon links ALSA on Linux. Required since decibri
109+
# 5.x. Mirrors the platform setup in the decibri repo's own build
110+
# matrix.
111111
run: sudo apt-get update && sudo apt-get install -y libasound2-dev
112112

113113
- name: Install dependencies

CHANGELOG.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Changelog
2+
3+
All notable changes to this project are documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
10+
## [0.2.0] - 2026-07-13
11+
12+
### Changed
13+
14+
- **Breaking: device indexes are renumbered.** Device enumeration comes from
15+
the new capture engine, so the indexes and names reported by
16+
`list_audio_devices` differ from 0.1.x: indexes are renumbered from a
17+
different base, Windows loopback endpoints are no longer listed, and
18+
device names use the shorter WASAPI form. A hardcoded `device` index
19+
recorded under 0.1.x will silently select a different microphone, or fail
20+
if it is now out of range. Re-run `list_audio_devices` after upgrading and
21+
switch to the stable `id`, which does not shift.
22+
- Upgraded decibri from 1.0.0 to 5.0.0. The capture engine is now Rust
23+
(cpal) rather than C++ (PortAudio), shipped as prebuilt per-platform
24+
binaries with no install script and no source-build fallback.
25+
- A microphone whose native rate differs from the requested 16 kHz is now
26+
resampled inside the capture engine, so recordings are delivered at the
27+
configured rate on every device.
28+
- npm publishing now uses trusted publishing (OIDC) with provenance and a
29+
manual approval gate. No npm token is involved.
30+
31+
### Added
32+
33+
- Each device returned by `list_audio_devices` now includes a stable `id`
34+
string alongside `index`, `name`, `maxInputChannels`, `defaultSampleRate`,
35+
and `isDefault`. The `id` survives reboots and device changes; `index` is
36+
positional and `name` is not unique. Rarely, a device the host cannot
37+
identify reports an empty `id` and remains selectable by index.
38+
- The `device` parameter of `capture_audio` and `voice_query` accepts the
39+
stable device `id` (string) as well as the numeric index. Existing callers
40+
passing a number are unchanged.
41+
- On platforms decibri publishes no binary for, mcp-listen now fails at
42+
startup with a message naming the platform and listing the supported set,
43+
instead of surfacing the module loader's generic error.
44+
- A capture on the default-device path now fails with an actionable error
45+
when the system has no usable default input device: if no enumerated
46+
device is flagged default and the capture fails, the error reports the
47+
device count and points at `list_audio_devices`, with the original error
48+
included; if the only input device is the ALSA null device (the state of
49+
headless Linux hosts), the default path refuses rather than recording
50+
silence. Selecting a device explicitly, including the null device, is
51+
unaffected.
52+
- Cross-platform CI: the smoke tests run on Linux, Windows, and macOS across
53+
Node.js 18, 20, and 22 on every push and pull request.
54+
55+
### Removed
56+
57+
- Intel Mac (darwin-x64) support. Apple has discontinued the platform and no
58+
decibri 5.x binary is published for it. decibri 1.x could fall back to
59+
compiling from source at install time; 5.x ships prebuilt binaries only,
60+
so the fallback that made Intel Mac work is gone.
61+
62+
### Fixed
63+
64+
- `capture_audio` delivers exactly the requested duration of audio. Capture
65+
now stops once the requested amount of PCM has arrived rather than on a
66+
wall-clock timer, so stream startup time is no longer silently deducted
67+
from the recording and the WAV payload is byte-exact.
68+
69+
## [0.1.3] - 2026-04-16
70+
71+
### Changed
72+
73+
- Updated project metadata after the repository transfer to the decibri
74+
organization: `mcpName` is now `io.github.decibri/mcp-listen`, and the
75+
author, repository, homepage, and README links point at decibri.
76+
77+
### Fixed
78+
79+
- LICENSE copyright holder corrected to Decibri.
80+
81+
## [0.1.2] - 2026-04-09
82+
83+
### Added
84+
85+
- `server.json` manifest for MCP Registry publication.
86+
87+
### Changed
88+
89+
- README description revised; decibri links updated from decibri.dev to
90+
decibri.com.
91+
92+
## [0.1.1] - 2026-04-06
93+
94+
### Added
95+
96+
- `mcpName` field in `package.json` for MCP Registry ownership verification.
97+
98+
## [0.1.0] - 2026-04-05
99+
100+
### Added
101+
102+
- Initial release: a stdio MCP server giving MCP-compatible agents access to
103+
the microphone.
104+
- `list_audio_devices` tool: enumerate available audio input devices.
105+
- `capture_audio` tool: record from the microphone for a requested duration
106+
(100 to 30000 ms) and save as WAV, with duration validation, concurrent
107+
capture protection, and safety timeouts.
108+
- `voice_query` tool: capture, transcribe with whisper.cpp, and query a local
109+
Ollama LLM. Whisper and Ollama are optional dependencies; the capture tools
110+
work without them.
111+
- Smoke test suite covering server initialization, tool advertising, device
112+
listing, WAV output validation, and error responses.
113+
- Tag-triggered npm publish workflow.
114+
115+
[Unreleased]: https://github.com/decibri/mcp-listen/compare/v0.2.0...HEAD
116+
[0.2.0]: https://github.com/decibri/mcp-listen/compare/v0.1.3...v0.2.0
117+
[0.1.3]: https://github.com/decibri/mcp-listen/compare/v0.1.2...v0.1.3
118+
[0.1.2]: https://github.com/decibri/mcp-listen/compare/v0.1.1...v0.1.2
119+
[0.1.1]: https://github.com/decibri/mcp-listen/compare/v0.1.0...v0.1.1
120+
[0.1.0]: https://github.com/decibri/mcp-listen/releases/tag/v0.1.0

README.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ npm install -g mcp-listen
7171

7272
## Requirements
7373

74+
**Supported platforms:**
75+
76+
- Windows x64
77+
- macOS Apple silicon (arm64)
78+
- Linux x64 and arm64 (glibc)
79+
80+
Intel Mac (darwin-x64) is not supported: Apple has discontinued the platform and no decibri binary is published for it.
81+
7482
**For `list_audio_devices` and `capture_audio`:**
7583

7684
- Node.js 18+
@@ -93,11 +101,13 @@ Returns a JSON array of available audio input devices.
93101

94102
```json
95103
[
96-
{ "index": 3, "name": "Microphone (Creative Live! Cam)", "isDefault": true, "maxInputChannels": 2, "defaultSampleRate": 48000 },
97-
{ "index": 4, "name": "Microphone Array (Intel)", "isDefault": false, "maxInputChannels": 2, "defaultSampleRate": 48000 }
104+
{ "index": 0, "name": "Microphone", "id": "wasapi:{0.0.1.00000000}.{6b187949-26ea-470b-907d-66bf87261530}", "maxInputChannels": 2, "defaultSampleRate": 48000, "isDefault": true },
105+
{ "index": 1, "name": "Microphone Array", "id": "wasapi:{0.0.1.00000000}.{b7a6e3e2-a62b-4e92-9320-947c4be98552}", "maxInputChannels": 2, "defaultSampleRate": 48000, "isDefault": false }
98106
]
99107
```
100108

109+
The `id` is stable across reboots and device changes. The `index` is positional and can shift when devices are added or removed, and names are not unique. Prefer `id` when selecting a device. In the rare case the host cannot produce a stable id for a device, its `id` is an empty string and it can only be selected by `index`.
110+
101111
### capture_audio
102112

103113
Records audio from the microphone and saves as a WAV file.
@@ -107,7 +117,7 @@ Records audio from the microphone and saves as a WAV file.
107117
| Parameter | Type | Default | Description |
108118
| ---------- | ------ | --------- | ------------- |
109119
| `duration_ms` | number | 5000 | Recording duration in milliseconds (100-30000) |
110-
| `device` | number | system default | Device index from `list_audio_devices` |
120+
| `device` | number or string | system default | Device index or stable device `id` from `list_audio_devices` |
111121

112122
**Example response:**
113123

@@ -130,7 +140,7 @@ Full voice pipeline: capture audio, transcribe with whisper.cpp, send to Ollama,
130140
| Parameter | Type | Default | Description |
131141
| ----------- | ------ | --------- | ------------- |
132142
| `duration_ms` | number | 5000 | Recording duration in milliseconds (100-30000) |
133-
| `device` | number | system default | Device index from `list_audio_devices` |
143+
| `device` | number or string | system default | Device index or stable device `id` from `list_audio_devices` |
134144
| `whisper_model` | string | ggml-base.en.bin | Path or filename of Whisper GGML model |
135145
| `language` | string | en | Language code for transcription |
136146
| `model` | string | llama3.2 | Ollama model name |

assets/.gitkeep

Lines changed: 0 additions & 1 deletion
This file was deleted.

index.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
2323
tools: [
2424
{
2525
name: 'list_audio_devices',
26-
description: 'List available audio input devices (microphones) on this machine.',
26+
description: 'List available audio input devices (microphones) on this machine. Each device has a numeric index, a human-readable name, and a stable id. Prefer the id when selecting a device: indexes can shift when devices are added or removed, and names are not unique.',
2727
inputSchema: { type: 'object', properties: {} }
2828
},
2929
{
@@ -37,8 +37,8 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
3737
description: 'Recording duration in milliseconds, 100-30000 (default: 5000)'
3838
},
3939
device: {
40-
type: 'number',
41-
description: 'Device index from list_audio_devices. Omit for system default microphone.'
40+
type: ['number', 'string'],
41+
description: 'Device to record from: the numeric index or the stable string id, both reported by list_audio_devices. Prefer the id; indexes can shift when devices are added or removed. Omit for system default microphone.'
4242
}
4343
}
4444
}
@@ -54,8 +54,8 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
5454
description: 'Recording duration in milliseconds, 100-30000 (default: 5000)'
5555
},
5656
device: {
57-
type: 'number',
58-
description: 'Device index from list_audio_devices. Omit for system default microphone.'
57+
type: ['number', 'string'],
58+
description: 'Device to record from: the numeric index or the stable string id, both reported by list_audio_devices. Prefer the id; indexes can shift when devices are added or removed. Omit for system default microphone.'
5959
},
6060
whisper_model: {
6161
type: 'string',

0 commit comments

Comments
 (0)