Skip to content

Commit bc083d0

Browse files
committed
#906 Refactor file watcher management in McpHub
add support multiple watchers per server. modified the setupFileWatcher method to properly handle asynchronous operations and prevent unhandled promise rejections. error handling now includes specific error messages that identify exactly where the error occurred.
1 parent c5202d4 commit bc083d0

File tree

1 file changed

+36
-13
lines changed

1 file changed

+36
-13
lines changed

src/services/mcp/McpHub.ts

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export class McpHub {
103103
private disposables: vscode.Disposable[] = []
104104
private settingsWatcher?: vscode.FileSystemWatcher
105105
private projectMcpWatcher?: vscode.FileSystemWatcher
106-
private fileWatchers: Map<string, FSWatcher> = new Map()
106+
private fileWatchers: Map<string, FSWatcher[]> = new Map()
107107
private isDisposed: boolean = false
108108
connections: McpConnection[] = []
109109
isConnecting: boolean = false
@@ -682,45 +682,68 @@ export class McpHub {
682682
}
683683

684684
private setupFileWatcher(name: string, config: z.infer<typeof ServerConfigSchema>) {
685+
// Initialize an empty array for this server if it doesn't exist
686+
if (!this.fileWatchers.has(name)) {
687+
this.fileWatchers.set(name, [])
688+
}
689+
690+
const watchers = this.fileWatchers.get(name) || []
691+
685692
// Only stdio type has args
686693
if (config.type === "stdio") {
694+
// Setup watchers for custom watchPaths if defined
687695
if (config.watchPaths && config.watchPaths.length > 0) {
688-
console.log(`Setting up file watchers for ${name} MCP server...`)
689-
const watcher = chokidar.watch(config.watchPaths, {
696+
console.log(`Setting up custom path watchers for ${name} MCP server...`)
697+
const watchPathsWatcher = chokidar.watch(config.watchPaths, {
690698
// persistent: true,
691699
// ignoreInitial: true,
692700
// awaitWriteFinish: true,
693701
})
694702

695-
watcher.on("change", (changedPath) => {
696-
console.log(`Detected change in ${changedPath}. Restarting server ${name}...`)
697-
this.restartConnection(name)
703+
watchPathsWatcher.on("change", async (changedPath) => {
704+
console.log(`Detected change in custom path ${changedPath}. Restarting server ${name}...`)
705+
try {
706+
await this.restartConnection(name)
707+
} catch (error) {
708+
console.error(`Failed to restart server ${name} after change in ${changedPath}:`, error)
709+
}
698710
})
699711

700-
this.fileWatchers.set(name, watcher)
712+
watchers.push(watchPathsWatcher)
701713
}
702714

715+
// Also setup the fallback build/index.js watcher if applicable
703716
const filePath = config.args?.find((arg: string) => arg.includes("build/index.js"))
704717
if (filePath) {
705-
// we use chokidar instead of onDidSaveTextDocument because it doesn't require the file to be open in the editor. The settings config is better suited for onDidSave since that will be manually updated by the user or Cline (and we want to detect save events, not every file change)
706-
const watcher = chokidar.watch(filePath, {
718+
console.log(`Setting up build/index.js watcher for ${name} MCP server...`)
719+
// we use chokidar instead of onDidSaveTextDocument because it doesn't require the file to be open in the editor
720+
const indexJsWatcher = chokidar.watch(filePath, {
707721
// persistent: true,
708722
// ignoreInitial: true,
709723
// awaitWriteFinish: true, // This helps with atomic writes
710724
})
711725

712-
watcher.on("change", () => {
726+
indexJsWatcher.on("change", async () => {
713727
console.log(`Detected change in ${filePath}. Restarting server ${name}...`)
714-
this.restartConnection(name)
728+
try {
729+
await this.restartConnection(name)
730+
} catch (error) {
731+
console.error(`Failed to restart server ${name} after change in ${filePath}:`, error)
732+
}
715733
})
716734

717-
this.fileWatchers.set(name, watcher)
735+
watchers.push(indexJsWatcher)
736+
}
737+
738+
// Update the fileWatchers map with all watchers for this server
739+
if (watchers.length > 0) {
740+
this.fileWatchers.set(name, watchers)
718741
}
719742
}
720743
}
721744

722745
private removeAllFileWatchers() {
723-
this.fileWatchers.forEach((watcher) => watcher.close())
746+
this.fileWatchers.forEach((watchers) => watchers.forEach((watcher) => watcher.close()))
724747
this.fileWatchers.clear()
725748
}
726749

0 commit comments

Comments
 (0)