@agentrq/acp-gateway 0.1.8 → 0.1.9
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 +1 -1
- package/dist/__tests__/mcpClient.test.js +106 -148
- package/dist/__tests__/mcpClient.test.js.map +1 -1
- package/dist/mcpClient.js +50 -24
- package/dist/mcpClient.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,30 +2,34 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
|
2
2
|
import { MCPBridge } from "../mcpClient.js";
|
|
3
3
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
4
4
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
5
|
-
const
|
|
5
|
+
const createMockClient = () => ({
|
|
6
6
|
connect: vi.fn().mockResolvedValue(undefined),
|
|
7
7
|
close: vi.fn().mockResolvedValue(undefined),
|
|
8
8
|
callTool: vi.fn().mockResolvedValue({ result: "ok" }),
|
|
9
9
|
notification: vi.fn().mockResolvedValue(undefined),
|
|
10
10
|
setNotificationHandler: vi.fn(),
|
|
11
|
-
};
|
|
12
|
-
const
|
|
11
|
+
});
|
|
12
|
+
const createMockTransport = () => ({
|
|
13
13
|
close: vi.fn().mockResolvedValue(undefined),
|
|
14
|
-
onclose:
|
|
15
|
-
onerror:
|
|
14
|
+
onclose: undefined,
|
|
15
|
+
onerror: undefined,
|
|
16
16
|
_sessionId: "mock-session-id",
|
|
17
|
-
};
|
|
17
|
+
});
|
|
18
|
+
let lastMockClient;
|
|
19
|
+
let lastMockTransport;
|
|
18
20
|
vi.mock("@modelcontextprotocol/sdk/client/index.js", () => {
|
|
19
21
|
return {
|
|
20
22
|
Client: vi.fn().mockImplementation(function () {
|
|
21
|
-
|
|
23
|
+
lastMockClient = createMockClient();
|
|
24
|
+
return lastMockClient;
|
|
22
25
|
}),
|
|
23
26
|
};
|
|
24
27
|
});
|
|
25
28
|
vi.mock("@modelcontextprotocol/sdk/client/streamableHttp.js", () => {
|
|
26
29
|
return {
|
|
27
30
|
StreamableHTTPClientTransport: vi.fn().mockImplementation(function () {
|
|
28
|
-
|
|
31
|
+
lastMockTransport = createMockTransport();
|
|
32
|
+
return lastMockTransport;
|
|
29
33
|
}),
|
|
30
34
|
};
|
|
31
35
|
});
|
|
@@ -38,19 +42,17 @@ describe("MCPBridge", () => {
|
|
|
38
42
|
beforeEach(() => {
|
|
39
43
|
vi.clearAllMocks();
|
|
40
44
|
vi.useFakeTimers();
|
|
45
|
+
lastMockClient = undefined;
|
|
46
|
+
lastMockTransport = undefined;
|
|
41
47
|
});
|
|
42
48
|
afterEach(() => {
|
|
43
49
|
vi.useRealTimers();
|
|
44
50
|
});
|
|
45
|
-
it("should initialize
|
|
51
|
+
it("should initialize without connecting", () => {
|
|
46
52
|
const bridge = new MCPBridge(config);
|
|
47
53
|
expect(bridge).toBeDefined();
|
|
48
|
-
expect(StreamableHTTPClientTransport).toHaveBeenCalled();
|
|
49
|
-
expect(Client).toHaveBeenCalled();
|
|
50
|
-
});
|
|
51
|
-
it("should get session ID from transport", () => {
|
|
52
|
-
const bridge = new MCPBridge(config);
|
|
53
|
-
expect(bridge.getSessionId()).toBe("mock-session-id");
|
|
54
|
+
expect(StreamableHTTPClientTransport).not.toHaveBeenCalled();
|
|
55
|
+
expect(Client).not.toHaveBeenCalled();
|
|
54
56
|
});
|
|
55
57
|
it("should throw error if config has no URL", () => {
|
|
56
58
|
expect(() => new MCPBridge({ name: "fail", type: "http" })).toThrow("has no URL");
|
|
@@ -58,176 +60,132 @@ describe("MCPBridge", () => {
|
|
|
58
60
|
describe("connect", () => {
|
|
59
61
|
it("should connect successfully and set up handlers", async () => {
|
|
60
62
|
const bridge = new MCPBridge(config);
|
|
61
|
-
const mClient = bridge.client;
|
|
62
63
|
await bridge.connect();
|
|
63
|
-
expect(
|
|
64
|
-
expect(
|
|
64
|
+
expect(Client).toHaveBeenCalled();
|
|
65
|
+
expect(StreamableHTTPClientTransport).toHaveBeenCalled();
|
|
66
|
+
expect(lastMockClient.connect).toHaveBeenCalled();
|
|
67
|
+
expect(lastMockClient.setNotificationHandler).toHaveBeenCalledTimes(2);
|
|
65
68
|
expect(bridge.isConnected).toBe(true);
|
|
66
69
|
});
|
|
67
|
-
it("should retry on connection failure", async () => {
|
|
70
|
+
it("should retry on connection failure with exponential backoff", async () => {
|
|
68
71
|
const bridge = new MCPBridge(config);
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
.
|
|
72
|
+
// We need to mock Client.connect to fail
|
|
73
|
+
Client.mockImplementationOnce(function () {
|
|
74
|
+
lastMockClient = createMockClient();
|
|
75
|
+
lastMockClient.connect.mockRejectedValue(new Error("fail 1"));
|
|
76
|
+
return lastMockClient;
|
|
77
|
+
}).mockImplementationOnce(function () {
|
|
78
|
+
lastMockClient = createMockClient();
|
|
79
|
+
lastMockClient.connect.mockRejectedValue(new Error("fail 2"));
|
|
80
|
+
return lastMockClient;
|
|
81
|
+
}).mockImplementationOnce(function () {
|
|
82
|
+
lastMockClient = createMockClient();
|
|
83
|
+
lastMockClient.connect.mockResolvedValue(undefined);
|
|
84
|
+
return lastMockClient;
|
|
85
|
+
});
|
|
73
86
|
const connectPromise = bridge.connect();
|
|
74
|
-
|
|
87
|
+
// First attempt (immediate)
|
|
88
|
+
await vi.advanceTimersByTimeAsync(0);
|
|
89
|
+
expect(Client).toHaveBeenCalledTimes(1);
|
|
90
|
+
// Second attempt (after 1s)
|
|
91
|
+
await vi.advanceTimersByTimeAsync(1000);
|
|
92
|
+
expect(Client).toHaveBeenCalledTimes(2);
|
|
93
|
+
// Third attempt (after 2s)
|
|
94
|
+
await vi.advanceTimersByTimeAsync(2000);
|
|
95
|
+
expect(Client).toHaveBeenCalledTimes(3);
|
|
75
96
|
await connectPromise;
|
|
76
|
-
expect(mClient.connect).toHaveBeenCalledTimes(2);
|
|
77
97
|
expect(bridge.isConnected).toBe(true);
|
|
78
98
|
});
|
|
79
|
-
it("should
|
|
99
|
+
it("should cap exponential backoff at 15 minutes", async () => {
|
|
80
100
|
const bridge = new MCPBridge(config);
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
expect(bridge.isConnected).toBe(false);
|
|
88
|
-
expect(connectSpy).toHaveBeenCalled();
|
|
89
|
-
});
|
|
90
|
-
it("should start connection in ensureConnected if not already connecting", async () => {
|
|
91
|
-
const bridge = new MCPBridge(config);
|
|
92
|
-
const connectSpy = vi.spyOn(bridge, "connect");
|
|
93
|
-
// Mock connect to immediately set isConnected = true to avoid long wait
|
|
94
|
-
connectSpy.mockImplementation(async () => {
|
|
95
|
-
bridge.isConnected = true;
|
|
101
|
+
// Override default mock behavior for this test only
|
|
102
|
+
const clientMock = Client;
|
|
103
|
+
clientMock.mockImplementation(function () {
|
|
104
|
+
lastMockClient = createMockClient();
|
|
105
|
+
lastMockClient.connect.mockRejectedValue(new Error("fail"));
|
|
106
|
+
return lastMockClient;
|
|
96
107
|
});
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
// Initial connect
|
|
103
|
-
await bridge.connect();
|
|
104
|
-
expect(bridge.isConnected).toBe(true);
|
|
105
|
-
// Now replace the method on the instance
|
|
106
|
-
let resolveReconnect;
|
|
107
|
-
const reconnectPromise = new Promise((resolve) => { resolveReconnect = resolve; });
|
|
108
|
-
bridge._connectOnce = vi.fn().mockReturnValue(reconnectPromise);
|
|
109
|
-
// Manually trigger onclose
|
|
110
|
-
if (mockTransport.onclose) {
|
|
111
|
-
mockTransport.onclose();
|
|
112
|
-
}
|
|
113
|
-
// Ticking to allow onclose to call connect()
|
|
114
|
-
await vi.advanceTimersByTimeAsync(0);
|
|
115
|
-
// Reconnection should have been triggered
|
|
116
|
-
expect(bridge.isConnecting).toBe(true);
|
|
117
|
-
expect(bridge.isConnected).toBe(false);
|
|
118
|
-
// Clean up
|
|
119
|
-
resolveReconnect();
|
|
120
|
-
await vi.runAllTimersAsync();
|
|
121
|
-
});
|
|
122
|
-
it("should do nothing on transport close if not previously connected", async () => {
|
|
123
|
-
const bridge = new MCPBridge(config);
|
|
124
|
-
bridge.isConnected = false;
|
|
125
|
-
const connectSpy = vi.spyOn(bridge, "connect");
|
|
126
|
-
if (mockTransport.onclose) {
|
|
127
|
-
mockTransport.onclose();
|
|
128
|
-
}
|
|
129
|
-
expect(connectSpy).not.toHaveBeenCalled();
|
|
130
|
-
});
|
|
131
|
-
it("should log transport errors", async () => {
|
|
132
|
-
const consoleSpy = vi
|
|
133
|
-
.spyOn(console, "error")
|
|
134
|
-
.mockImplementation(() => { });
|
|
135
|
-
const bridge = new MCPBridge(config);
|
|
136
|
-
await bridge.connect();
|
|
137
|
-
const transport = bridge.transport;
|
|
138
|
-
if (transport.onerror) {
|
|
139
|
-
transport.onerror(new Error("transport error"));
|
|
108
|
+
const connectPromise = bridge.connect();
|
|
109
|
+
// Skip several attempts to reach near 900s
|
|
110
|
+
// 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024(cap to 900)
|
|
111
|
+
for (let i = 0; i < 11; i++) {
|
|
112
|
+
await vi.advanceTimersByTimeAsync(1000 * Math.pow(2, i));
|
|
140
113
|
}
|
|
141
|
-
|
|
114
|
+
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
115
|
+
// Advance by 900s (maxDelay)
|
|
116
|
+
await vi.advanceTimersByTimeAsync(900000);
|
|
117
|
+
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Retrying in 900s..."));
|
|
142
118
|
consoleSpy.mockRestore();
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
const mClient = bridge.client;
|
|
149
|
-
let taskHandler;
|
|
150
|
-
mClient.setNotificationHandler.mockImplementation((schema, handler) => {
|
|
151
|
-
if (mClient.setNotificationHandler.mock.calls.length === 1) {
|
|
152
|
-
taskHandler = handler;
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
await bridge.connect();
|
|
156
|
-
const emitSpy = vi.spyOn(bridge, "emit");
|
|
157
|
-
if (taskHandler) {
|
|
158
|
-
taskHandler({ params: { content: "test task", meta: { foo: 1 } } });
|
|
159
|
-
}
|
|
160
|
-
expect(emitSpy).toHaveBeenCalledWith("task", {
|
|
161
|
-
content: "test task",
|
|
162
|
-
meta: { foo: 1 },
|
|
119
|
+
await bridge.close();
|
|
120
|
+
// Restore default mock behavior for other tests
|
|
121
|
+
clientMock.mockImplementation(function () {
|
|
122
|
+
lastMockClient = createMockClient();
|
|
123
|
+
return lastMockClient;
|
|
163
124
|
});
|
|
164
125
|
});
|
|
165
|
-
it("should
|
|
126
|
+
it("should handle transport close by reconnecting with a fresh client", async () => {
|
|
166
127
|
const bridge = new MCPBridge(config);
|
|
167
|
-
const mClient = bridge.client;
|
|
168
|
-
let verdictHandler;
|
|
169
|
-
mClient.setNotificationHandler.mockImplementation((schema, handler) => {
|
|
170
|
-
if (mClient.setNotificationHandler.mock.calls.length === 2) {
|
|
171
|
-
verdictHandler = handler;
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
128
|
await bridge.connect();
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
129
|
+
const firstClient = lastMockClient;
|
|
130
|
+
const firstTransport = lastMockTransport;
|
|
131
|
+
expect(bridge.isConnected).toBe(true);
|
|
132
|
+
// Simulate disconnection
|
|
133
|
+
if (firstTransport.onclose) {
|
|
134
|
+
firstTransport.onclose();
|
|
178
135
|
}
|
|
179
|
-
expect(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
136
|
+
expect(bridge.isConnected).toBe(false);
|
|
137
|
+
expect(bridge.isConnecting).toBe(true);
|
|
138
|
+
// Reconnection attempt (after 1s)
|
|
139
|
+
await vi.advanceTimersByTimeAsync(1000);
|
|
140
|
+
expect(Client).toHaveBeenCalledTimes(2);
|
|
141
|
+
expect(lastMockClient).not.toBe(firstClient);
|
|
142
|
+
expect(bridge.isConnected).toBe(true);
|
|
183
143
|
});
|
|
184
144
|
});
|
|
185
145
|
describe("ensureConnected", () => {
|
|
186
146
|
it("should wait for connection if currently connecting", async () => {
|
|
187
147
|
const bridge = new MCPBridge(config);
|
|
188
148
|
bridge.isConnecting = true;
|
|
189
|
-
|
|
149
|
+
// Mock isConnected to true after 2s
|
|
190
150
|
setTimeout(() => {
|
|
191
151
|
bridge.isConnected = true;
|
|
192
|
-
},
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
152
|
+
}, 2000);
|
|
153
|
+
const ensurePromise = bridge.ensureConnected();
|
|
154
|
+
await vi.advanceTimersByTimeAsync(2500);
|
|
155
|
+
await ensurePromise;
|
|
156
|
+
expect(bridge.isConnected).toBe(true);
|
|
196
157
|
});
|
|
197
158
|
it("should throw if connection times out", async () => {
|
|
198
159
|
const bridge = new MCPBridge(config);
|
|
199
160
|
bridge.isConnecting = true;
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
// Advance time enough to trigger the timeout
|
|
203
|
-
await vi.runAllTimersAsync();
|
|
161
|
+
const expectPromise = expect(bridge.ensureConnected()).rejects.toThrow("MCP not connected after 10s timeout");
|
|
162
|
+
await vi.advanceTimersByTimeAsync(11000);
|
|
204
163
|
await expectPromise;
|
|
205
164
|
});
|
|
206
165
|
});
|
|
207
166
|
describe("tool calls and notifications", () => {
|
|
208
|
-
it("should call tools correctly", async () => {
|
|
167
|
+
it("should call tools correctly after ensuring connection", async () => {
|
|
209
168
|
const bridge = new MCPBridge(config);
|
|
210
|
-
|
|
211
|
-
const
|
|
169
|
+
// Start connect but don't finish yet
|
|
170
|
+
const callPromise = bridge.callTool("test-tool", { arg: 1 });
|
|
171
|
+
// Advance to trigger _connectOnce and ensureConnected loop
|
|
172
|
+
await vi.advanceTimersByTimeAsync(1000);
|
|
173
|
+
const result = await callPromise;
|
|
212
174
|
expect(result).toEqual({ result: "ok" });
|
|
175
|
+
expect(lastMockClient.callTool).toHaveBeenCalledWith({
|
|
176
|
+
name: "test-tool",
|
|
177
|
+
arguments: { arg: 1 },
|
|
178
|
+
});
|
|
213
179
|
});
|
|
214
|
-
it("should send notifications correctly", async () => {
|
|
215
|
-
const bridge = new MCPBridge(config);
|
|
216
|
-
bridge.isConnected = true;
|
|
217
|
-
await bridge.sendNotification("test-method", { foo: "bar" });
|
|
218
|
-
expect(bridge.client.notification).toHaveBeenCalled();
|
|
219
|
-
});
|
|
220
|
-
it("should handle transport close rejection in _connectOnce", async () => {
|
|
221
|
-
const bridge = new MCPBridge(config);
|
|
222
|
-
mockTransport.close.mockRejectedValue(new Error("close failed"));
|
|
223
|
-
await bridge._connectOnce();
|
|
224
|
-
expect(mockTransport.close).toHaveBeenCalled();
|
|
225
|
-
expect(bridge.isConnected).toBe(false);
|
|
226
|
-
});
|
|
227
|
-
it("should close the client", async () => {
|
|
180
|
+
it("should send notifications correctly after ensuring connection", async () => {
|
|
228
181
|
const bridge = new MCPBridge(config);
|
|
229
|
-
|
|
230
|
-
|
|
182
|
+
const notifyPromise = bridge.sendNotification("test-method", { foo: "bar" });
|
|
183
|
+
await vi.advanceTimersByTimeAsync(1000);
|
|
184
|
+
await notifyPromise;
|
|
185
|
+
expect(lastMockClient.notification).toHaveBeenCalledWith({
|
|
186
|
+
method: "test-method",
|
|
187
|
+
params: { foo: "bar" },
|
|
188
|
+
});
|
|
231
189
|
});
|
|
232
190
|
});
|
|
233
191
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcpClient.test.js","sourceRoot":"","sources":["../../src/__tests__/mcpClient.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAEnG,MAAM,
|
|
1
|
+
{"version":3,"file":"mcpClient.test.js","sourceRoot":"","sources":["../../src/__tests__/mcpClient.test.ts"],"names":[],"mappings":"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"}
|
package/dist/mcpClient.js
CHANGED
|
@@ -10,10 +10,13 @@ import { EventEmitter } from "node:events";
|
|
|
10
10
|
import { z } from "zod";
|
|
11
11
|
export class MCPBridge extends EventEmitter {
|
|
12
12
|
config;
|
|
13
|
-
client;
|
|
14
|
-
transport;
|
|
13
|
+
client = null;
|
|
14
|
+
transport = null;
|
|
15
|
+
isConnected = false;
|
|
16
|
+
isConnecting = false;
|
|
17
|
+
isClosed = false;
|
|
15
18
|
getSessionId() {
|
|
16
|
-
return this.transport
|
|
19
|
+
return this.transport?._sessionId;
|
|
17
20
|
}
|
|
18
21
|
constructor(config) {
|
|
19
22
|
super();
|
|
@@ -21,55 +24,60 @@ export class MCPBridge extends EventEmitter {
|
|
|
21
24
|
if (!config.url) {
|
|
22
25
|
throw new Error(`MCP server ${config.name} has no URL`);
|
|
23
26
|
}
|
|
24
|
-
const url = new URL(config.url);
|
|
25
|
-
this.transport = new StreamableHTTPClientTransport(url);
|
|
26
|
-
this.client = new Client({
|
|
27
|
-
name: "acp-gateway",
|
|
28
|
-
version: "0.1.0",
|
|
29
|
-
}, {
|
|
30
|
-
capabilities: {},
|
|
31
|
-
});
|
|
32
27
|
}
|
|
33
|
-
isConnected = false;
|
|
34
|
-
isConnecting = false;
|
|
35
28
|
async connect() {
|
|
36
29
|
if (this.isConnecting || this.isConnected)
|
|
37
30
|
return;
|
|
38
31
|
this.isConnecting = true;
|
|
32
|
+
this.isClosed = false;
|
|
39
33
|
let attempt = 0;
|
|
40
34
|
const initialDelay = 1000;
|
|
41
|
-
const maxDelay =
|
|
42
|
-
while (!this.isConnected) {
|
|
35
|
+
const maxDelay = 900000; // 15 minutes
|
|
36
|
+
while (!this.isConnected && !this.isClosed) {
|
|
43
37
|
try {
|
|
44
38
|
await this._connectOnce();
|
|
45
39
|
this.isConnected = true;
|
|
46
|
-
this.isConnecting = false;
|
|
47
40
|
console.error(`[mcp] Connected to ${this.config.name}`);
|
|
48
41
|
}
|
|
49
42
|
catch (error) {
|
|
43
|
+
if (this.isClosed)
|
|
44
|
+
break;
|
|
50
45
|
const delay = Math.min(initialDelay * Math.pow(2, attempt), maxDelay);
|
|
51
|
-
console.error(`[mcp] Connection failed to ${this.config.name}. Retrying in ${delay / 1000}s...`);
|
|
46
|
+
console.error(`[mcp] Connection failed to ${this.config.name} (attempt ${attempt + 1}): ${error.message || error}. Retrying in ${delay / 1000}s...`);
|
|
52
47
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
53
48
|
attempt++;
|
|
54
49
|
}
|
|
55
50
|
}
|
|
51
|
+
this.isConnecting = false;
|
|
56
52
|
}
|
|
57
53
|
async _connectOnce() {
|
|
54
|
+
// Clean up existing transport and client
|
|
58
55
|
if (this.transport) {
|
|
56
|
+
this.transport.onclose = undefined;
|
|
57
|
+
this.transport.onerror = undefined;
|
|
59
58
|
await this.transport.close().catch(() => { });
|
|
59
|
+
this.transport = null;
|
|
60
|
+
}
|
|
61
|
+
if (this.client) {
|
|
62
|
+
await this.client.close().catch(() => { });
|
|
63
|
+
this.client = null;
|
|
60
64
|
}
|
|
61
65
|
if (!this.config.url) {
|
|
62
66
|
throw new Error("MCP server URL is not configured");
|
|
63
67
|
}
|
|
64
68
|
const url = new URL(this.config.url);
|
|
65
69
|
this.transport = new StreamableHTTPClientTransport(url);
|
|
70
|
+
this.client = new Client({
|
|
71
|
+
name: "acp-gateway",
|
|
72
|
+
version: "0.1.0",
|
|
73
|
+
}, {
|
|
74
|
+
capabilities: {},
|
|
75
|
+
});
|
|
66
76
|
// Set up transport hooks for disconnection
|
|
67
77
|
this.transport.onclose = () => {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
this.connect(); // Start reconnection loop
|
|
72
|
-
}
|
|
78
|
+
console.error(`[mcp] Connection to ${this.config.name} lost.`);
|
|
79
|
+
this.isConnected = false;
|
|
80
|
+
this.connect(); // Start reconnection loop
|
|
73
81
|
};
|
|
74
82
|
this.transport.onerror = (error) => {
|
|
75
83
|
console.error(`[mcp] Transport error:`, error.message || error);
|
|
@@ -104,7 +112,10 @@ export class MCPBridge extends EventEmitter {
|
|
|
104
112
|
if (this.isConnected)
|
|
105
113
|
return;
|
|
106
114
|
if (!this.isConnecting) {
|
|
107
|
-
|
|
115
|
+
// Fire and forget connect loop if not already running
|
|
116
|
+
this.connect().catch((err) => {
|
|
117
|
+
console.error(`[mcp] Unexpected error in connect loop:`, err);
|
|
118
|
+
});
|
|
108
119
|
}
|
|
109
120
|
// Wait up to 10 seconds for connection
|
|
110
121
|
let waited = 0;
|
|
@@ -118,6 +129,8 @@ export class MCPBridge extends EventEmitter {
|
|
|
118
129
|
}
|
|
119
130
|
async callTool(name, args = {}) {
|
|
120
131
|
await this.ensureConnected();
|
|
132
|
+
if (!this.client)
|
|
133
|
+
throw new Error("MCP client not initialized");
|
|
121
134
|
return await this.client.callTool({
|
|
122
135
|
name,
|
|
123
136
|
arguments: args,
|
|
@@ -125,13 +138,26 @@ export class MCPBridge extends EventEmitter {
|
|
|
125
138
|
}
|
|
126
139
|
async sendNotification(method, params) {
|
|
127
140
|
await this.ensureConnected();
|
|
141
|
+
if (!this.client)
|
|
142
|
+
throw new Error("MCP client not initialized");
|
|
128
143
|
await this.client.notification({
|
|
129
144
|
method,
|
|
130
145
|
params,
|
|
131
146
|
});
|
|
132
147
|
}
|
|
133
148
|
async close() {
|
|
134
|
-
|
|
149
|
+
this.isClosed = true;
|
|
150
|
+
this.isConnected = false;
|
|
151
|
+
if (this.transport) {
|
|
152
|
+
this.transport.onclose = undefined;
|
|
153
|
+
this.transport.onerror = undefined;
|
|
154
|
+
await this.transport.close().catch(() => { });
|
|
155
|
+
this.transport = null;
|
|
156
|
+
}
|
|
157
|
+
if (this.client) {
|
|
158
|
+
await this.client.close().catch(() => { });
|
|
159
|
+
this.client = null;
|
|
160
|
+
}
|
|
135
161
|
}
|
|
136
162
|
}
|
|
137
163
|
//# sourceMappingURL=mcpClient.js.map
|
package/dist/mcpClient.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcpClient.js","sourceRoot":"","sources":["../src/mcpClient.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,OAAO,SAAU,SAAQ,YAAY;
|
|
1
|
+
{"version":3,"file":"mcpClient.js","sourceRoot":"","sources":["../src/mcpClient.ts"],"names":[],"mappings":"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"}
|