mirror of
https://github.com/samanhappy/mcphub.git
synced 2025-12-24 02:39:19 -05:00
feat: implement keep-alive functionality for SSE connections (#166)
Co-authored-by: samanhappy@qq.com <my6051199>
This commit is contained in:
@@ -20,6 +20,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
"no-undef": "off",
|
"no-undef": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,6 +107,11 @@ export const createServer = async (req: Request, res: Response): Promise<void> =
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set default keep-alive interval for SSE servers if not specified
|
||||||
|
if ((config.type === 'sse' || (!config.type && config.url)) && !config.keepAliveInterval) {
|
||||||
|
config.keepAliveInterval = 60000; // Default 60 seconds for SSE servers
|
||||||
|
}
|
||||||
|
|
||||||
const result = await addServer(name, config);
|
const result = await addServer(name, config);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
notifyToolChanged();
|
notifyToolChanged();
|
||||||
@@ -224,6 +229,11 @@ export const updateServer = async (req: Request, res: Response): Promise<void> =
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set default keep-alive interval for SSE servers if not specified
|
||||||
|
if ((config.type === 'sse' || (!config.type && config.url)) && !config.keepAliveInterval) {
|
||||||
|
config.keepAliveInterval = 60000; // Default 60 seconds for SSE servers
|
||||||
|
}
|
||||||
|
|
||||||
const result = await updateMcpServer(name, config);
|
const result = await updateMcpServer(name, config);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
notifyToolChanged();
|
notifyToolChanged();
|
||||||
|
|||||||
@@ -13,6 +13,38 @@ import { saveToolsAsVectorEmbeddings, searchToolsByVector } from './vectorSearch
|
|||||||
|
|
||||||
const servers: { [sessionId: string]: Server } = {};
|
const servers: { [sessionId: string]: Server } = {};
|
||||||
|
|
||||||
|
// Helper function to set up keep-alive ping for SSE connections
|
||||||
|
const setupKeepAlive = (serverInfo: ServerInfo, serverConfig: ServerConfig): void => {
|
||||||
|
// Only set up keep-alive for SSE connections
|
||||||
|
if (!(serverInfo.transport instanceof SSEClientTransport)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear any existing interval first
|
||||||
|
if (serverInfo.keepAliveIntervalId) {
|
||||||
|
clearInterval(serverInfo.keepAliveIntervalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use configured interval or default to 60 seconds for SSE
|
||||||
|
const interval = serverConfig.keepAliveInterval || 60000;
|
||||||
|
|
||||||
|
serverInfo.keepAliveIntervalId = setInterval(async () => {
|
||||||
|
try {
|
||||||
|
if (serverInfo.client && serverInfo.status === 'connected') {
|
||||||
|
await serverInfo.client.ping();
|
||||||
|
console.log(`Keep-alive ping successful for server: ${serverInfo.name}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`Keep-alive ping failed for server ${serverInfo.name}:`, error);
|
||||||
|
// TODO Consider handling reconnection logic here if needed
|
||||||
|
}
|
||||||
|
}, interval);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Keep-alive ping set up for server ${serverInfo.name} with interval ${interval / 1000} seconds`,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const initUpstreamServers = async (): Promise<void> => {
|
export const initUpstreamServers = async (): Promise<void> => {
|
||||||
await registerAllTools(true);
|
await registerAllTools(true);
|
||||||
};
|
};
|
||||||
@@ -210,6 +242,9 @@ export const initializeClientsFromSettings = (isInit: boolean): ServerInfo[] =>
|
|||||||
serverInfo.status = 'connected';
|
serverInfo.status = 'connected';
|
||||||
serverInfo.error = null;
|
serverInfo.error = null;
|
||||||
|
|
||||||
|
// Set up keep-alive ping for SSE connections
|
||||||
|
setupKeepAlive(serverInfo, conf);
|
||||||
|
|
||||||
// Save tools as vector embeddings for search
|
// Save tools as vector embeddings for search
|
||||||
saveToolsAsVectorEmbeddings(name, serverInfo.tools);
|
saveToolsAsVectorEmbeddings(name, serverInfo.tools);
|
||||||
})
|
})
|
||||||
@@ -389,6 +424,13 @@ export const updateMcpServer = async (
|
|||||||
function closeServer(name: string) {
|
function closeServer(name: string) {
|
||||||
const serverInfo = serverInfos.find((serverInfo) => serverInfo.name === name);
|
const serverInfo = serverInfos.find((serverInfo) => serverInfo.name === name);
|
||||||
if (serverInfo && serverInfo.client && serverInfo.transport) {
|
if (serverInfo && serverInfo.client && serverInfo.transport) {
|
||||||
|
// Clear keep-alive interval if exists
|
||||||
|
if (serverInfo.keepAliveIntervalId) {
|
||||||
|
clearInterval(serverInfo.keepAliveIntervalId);
|
||||||
|
serverInfo.keepAliveIntervalId = undefined;
|
||||||
|
console.log(`Cleared keep-alive interval for server: ${serverInfo.name}`);
|
||||||
|
}
|
||||||
|
|
||||||
serverInfo.client.close();
|
serverInfo.client.close();
|
||||||
serverInfo.transport.close();
|
serverInfo.transport.close();
|
||||||
console.log(`Closed client and transport for server: ${serverInfo.name}`);
|
console.log(`Closed client and transport for server: ${serverInfo.name}`);
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ export interface ServerConfig {
|
|||||||
env?: Record<string, string>; // Environment variables
|
env?: Record<string, string>; // Environment variables
|
||||||
headers?: Record<string, string>; // HTTP headers for SSE/streamable-http servers
|
headers?: Record<string, string>; // HTTP headers for SSE/streamable-http servers
|
||||||
enabled?: boolean; // Flag to enable/disable the server
|
enabled?: boolean; // Flag to enable/disable the server
|
||||||
|
keepAliveInterval?: number; // Keep-alive ping interval in milliseconds (default: 60000ms for SSE servers)
|
||||||
tools?: Record<string, { enabled: boolean; description?: string }>; // Tool-specific configurations with enable/disable state and custom descriptions
|
tools?: Record<string, { enabled: boolean; description?: string }>; // Tool-specific configurations with enable/disable state and custom descriptions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,6 +119,7 @@ export interface ServerInfo {
|
|||||||
transport?: SSEClientTransport | StdioClientTransport | StreamableHTTPClientTransport; // Transport mechanism used
|
transport?: SSEClientTransport | StdioClientTransport | StreamableHTTPClientTransport; // Transport mechanism used
|
||||||
createTime: number; // Timestamp of when the server was created
|
createTime: number; // Timestamp of when the server was created
|
||||||
enabled?: boolean; // Flag to indicate if the server is enabled
|
enabled?: boolean; // Flag to indicate if the server is enabled
|
||||||
|
keepAliveIntervalId?: NodeJS.Timeout; // Timer ID for keep-alive ping interval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Details about a tool available on the server
|
// Details about a tool available on the server
|
||||||
|
|||||||
Reference in New Issue
Block a user