Skip to content

Commit 8fdba3b

Browse files
committed
feat(ai): Implement ConnectionService Lifecycle Tools (#8181)
- Added startServer and stopServer methods to ConnectionService - Exposed start_ws_server and stop_ws_server tools in OpenAPI - Enables agents to manage the WebSocket bridge lifecycle
1 parent 0c25505 commit 8fdba3b

3 files changed

Lines changed: 100 additions & 1 deletion

File tree

ai/mcp/server/neural-link/openapi.yaml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,58 @@ paths:
241241
schema:
242242
$ref: '#/components/schemas/ErrorResponse'
243243

244+
/server/start:
245+
post:
246+
summary: Start WebSocket Server
247+
operationId: start_ws_server
248+
description: |
249+
Starts the WebSocket server to accept connections from the Neo.mjs app.
250+
251+
**When to Use:**
252+
Use this to recover the bridge if the server was previously stopped or crashed.
253+
tags: [Lifecycle]
254+
requestBody:
255+
content:
256+
application/json:
257+
schema:
258+
type: object
259+
properties: {}
260+
responses:
261+
'200':
262+
description: Server started successfully
263+
'500':
264+
description: Internal server error
265+
content:
266+
application/json:
267+
schema:
268+
$ref: '#/components/schemas/ErrorResponse'
269+
270+
/server/stop:
271+
post:
272+
summary: Stop WebSocket Server
273+
operationId: stop_ws_server
274+
description: |
275+
Stops the WebSocket server and closes all active connections.
276+
277+
**When to Use:**
278+
Use this to simulate a network disconnect or to perform a clean shutdown of the bridge.
279+
tags: [Lifecycle]
280+
requestBody:
281+
content:
282+
application/json:
283+
schema:
284+
type: object
285+
properties: {}
286+
responses:
287+
'200':
288+
description: Server stopped successfully
289+
'500':
290+
description: Internal server error
291+
content:
292+
application/json:
293+
schema:
294+
$ref: '#/components/schemas/ErrorResponse'
295+
244296
/worker/topology:
245297
post:
246298
summary: Get Worker Topology

ai/mcp/server/neural-link/services/ConnectionService.mjs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,19 @@ class ConnectionService extends Base {
7171
* @returns {Promise<void>}
7272
*/
7373
async initAsync() {
74+
await this.startServer();
75+
}
76+
77+
/**
78+
* Starts the WebSocket server.
79+
* @returns {Promise<void>}
80+
*/
81+
async startServer() {
82+
if (this.wss) {
83+
logger.warn('WebSocket Server is already running.');
84+
return;
85+
}
86+
7487
this.wss = new WebSocketServer({port: this.port});
7588

7689
this.wss.on('connection', (ws) => this.#handleConnection(ws));
@@ -79,6 +92,38 @@ class ConnectionService extends Base {
7992
logger.info(`WebSocket Server listening on port ${this.port}`);
8093
}
8194

95+
/**
96+
* Stops the WebSocket server and closes all active connections.
97+
* @returns {Promise<void>}
98+
*/
99+
async stopServer() {
100+
if (!this.wss) {
101+
logger.warn('WebSocket Server is not running.');
102+
return;
103+
}
104+
105+
logger.info('Stopping WebSocket Server...');
106+
107+
// Close all active sessions
108+
for (const [sessionId, ws] of this.sessions) {
109+
ws.close();
110+
this.#handleDisconnect(sessionId);
111+
}
112+
113+
return new Promise((resolve, reject) => {
114+
this.wss.close((err) => {
115+
if (err) {
116+
logger.error('Error closing WebSocket Server:', err);
117+
reject(err);
118+
} else {
119+
logger.info('WebSocket Server stopped.');
120+
this.wss = null;
121+
resolve();
122+
}
123+
});
124+
});
125+
}
126+
82127
/**
83128
* Handles a new WebSocket connection.
84129
* @param {WebSocket} ws

ai/mcp/server/neural-link/services/toolService.mjs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ const serviceMapping = {
2121
get_worker_topology : RuntimeService.getWorkerTopology.bind(RuntimeService),
2222
healthcheck : HealthService.healthcheck.bind(HealthService),
2323
reload_page : RuntimeService.reloadPage.bind(RuntimeService),
24-
set_component_property: ComponentService.setComponentProperty.bind(ComponentService)
24+
set_component_property: ComponentService.setComponentProperty.bind(ComponentService),
25+
start_ws_server : ConnectionService.startServer.bind(ConnectionService),
26+
stop_ws_server : ConnectionService.stopServer.bind(ConnectionService)
2527
};
2628

2729
const toolService = Neo.create(ToolService, {

0 commit comments

Comments
 (0)