feat: mcp proxy keep alive (ping) mechanism

This commit is contained in:
justin 2025-05-10 12:32:55 -04:00
parent 7eecc9ca3f
commit cc84c2ce10
3 changed files with 85 additions and 5 deletions

View file

@ -18,11 +18,12 @@ import {
parseCommandLineArgs,
setupSignalHandlers,
getServerUrlHash,
MCP_REMOTE_VERSION,
TransportStrategy,
setupPing,
} from './lib/utils'
import { NodeOAuthClientProvider } from './lib/node-oauth-client-provider'
import { createLazyAuthCoordinator } from './lib/coordination'
import { PingConfig } from './lib/types'
/**
* Main function to run the proxy
@ -32,6 +33,7 @@ async function runProxy(
callbackPort: number,
headers: Record<string, string>,
transportStrategy: TransportStrategy = 'http-first',
pingConfig: PingConfig,
) {
// Set up event emitter for auth flow
const events = new EventEmitter()
@ -80,6 +82,9 @@ async function runProxy(
// Connect to remote server with lazy authentication
const remoteTransport = await connectToRemoteServer(null, serverUrl, authProvider, headers, authInitializer, transportStrategy)
// Set up ping mechanism for remote transport
const stopPing = setupPing(remoteTransport, pingConfig)
// Set up bidirectional proxy between local and remote transports
mcpProxy({
transportToClient: localTransport,
@ -89,11 +94,15 @@ async function runProxy(
// Start the local STDIO server
await localTransport.start()
log('Local STDIO server running')
if (pingConfig.enabled) {
log(`Automatic ping enabled with ${pingConfig.interval} second interval`)
}
log(`Proxy established successfully between local STDIO and remote ${remoteTransport.constructor.name}`)
log('Press Ctrl+C to exit')
// Setup cleanup handler
const cleanup = async () => {
stopPing()
await remoteTransport.close()
await localTransport.close()
// Only close the server if it was initialized
@ -136,8 +145,8 @@ to the CA certificate file. If using claude_desktop_config.json, this might look
// Parse command-line arguments and run the proxy
parseCommandLineArgs(process.argv.slice(2), 'Usage: npx tsx proxy.ts <https://server-url> [callback-port]')
.then(({ serverUrl, callbackPort, headers, transportStrategy }) => {
return runProxy(serverUrl, callbackPort, headers, transportStrategy)
.then(({ serverUrl, callbackPort, headers, transportStrategy, pingConfig }) => {
return runProxy(serverUrl, callbackPort, headers, transportStrategy, pingConfig)
})
.catch((error) => {
log('Fatal error:', error)