laive-mcp 0.1.1 → 0.1.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/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## v0.1.2 - 2026-03-22
6
+
7
+ - Fixed an MCP transport crash when the Live bridge socket is unreachable by preventing the bridge client from raising an unhandled `error` event during lazy connection attempts. Tool calls now return structured MCP errors instead of closing the server process.
8
+
5
9
  ## v0.1.1 - 2026-03-22
6
10
 
7
11
  - Fixed MCP startup compatibility by implementing the `initialize` handshake, ignoring `notifications/initialized`, and deferring Live bridge connection until the first real tool call so the server can start before Ableton is reachable.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "laive-mcp",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Local MCP, install tooling, and helper assets for controlling Ableton Live.",
5
5
  "license": "GPL-3.0-only",
6
6
  "type": "module",
@@ -55,7 +55,11 @@ export class BridgeClient extends EventEmitter {
55
55
 
56
56
  this.socket.on("data", (chunk) => parser.push(Buffer.from(chunk)));
57
57
  this.socket.on("end", () => parser.end());
58
- this.socket.on("error", (error) => this.emit("error", error));
58
+ this.socket.on("error", (error) => {
59
+ if (this.listenerCount("error") > 0) {
60
+ this.emit("error", error);
61
+ }
62
+ });
59
63
  this.socket.on("close", () => {
60
64
  this.socket = null;
61
65
  this.emit("close");
@@ -55,7 +55,7 @@ async function main() {
55
55
  const session = await createSession(options);
56
56
  const server = new LaiveMcpServer({
57
57
  stateAdapter: createStateAdapter(session),
58
- bridgeAdapter: createBridgeAdapter(session.bridgeClient),
58
+ bridgeAdapter: createBridgeAdapter(session),
59
59
  policyAdapter: createAllowAllPolicyAdapter()
60
60
  });
61
61
  let lineReader = null;
@@ -158,18 +158,23 @@ export function createAllowAllPolicyAdapter() {
158
158
  };
159
159
  }
160
160
 
161
- export function createBridgeAdapter(bridgeClient) {
161
+ async function resolveBridgeClient(target) {
162
+ if (target && typeof target.ensureConnected === "function") {
163
+ await target.ensureConnected();
164
+ return target.bridgeClient;
165
+ }
166
+
167
+ return target;
168
+ }
169
+
170
+ export function createBridgeAdapter(target) {
162
171
  return {
163
172
  async getCapabilities() {
164
- if (typeof bridgeClient.ensureConnected === "function") {
165
- await bridgeClient.ensureConnected();
166
- }
173
+ const bridgeClient = await resolveBridgeClient(target);
167
174
  return (await bridgeClient.request("capabilities")).result;
168
175
  },
169
176
  async setTempo(tempo, options = {}) {
170
- if (typeof bridgeClient.ensureConnected === "function") {
171
- await bridgeClient.ensureConnected();
172
- }
177
+ const bridgeClient = await resolveBridgeClient(target);
173
178
  return (
174
179
  await bridgeClient.request(
175
180
  "set",
@@ -180,9 +185,7 @@ export function createBridgeAdapter(bridgeClient) {
180
185
  ).result;
181
186
  },
182
187
  async createTrack(kind, options = {}) {
183
- if (typeof bridgeClient.ensureConnected === "function") {
184
- await bridgeClient.ensureConnected();
185
- }
188
+ const bridgeClient = await resolveBridgeClient(target);
186
189
  const result = (
187
190
  await bridgeClient.request(
188
191
  "call",
@@ -198,9 +201,7 @@ export function createBridgeAdapter(bridgeClient) {
198
201
  };
199
202
  },
200
203
  async createClip(payload) {
201
- if (typeof bridgeClient.ensureConnected === "function") {
202
- await bridgeClient.ensureConnected();
203
- }
204
+ const bridgeClient = await resolveBridgeClient(target);
204
205
  const result = (
205
206
  await bridgeClient.request(
206
207
  "call",
@@ -221,9 +222,7 @@ export function createBridgeAdapter(bridgeClient) {
221
222
  };
222
223
  },
223
224
  async setParameter(payload, options = {}) {
224
- if (typeof bridgeClient.ensureConnected === "function") {
225
- await bridgeClient.ensureConnected();
226
- }
225
+ const bridgeClient = await resolveBridgeClient(target);
227
226
  const result = (
228
227
  await bridgeClient.request(
229
228
  "set",