Skip to content

Commit 9db94d3

Browse files
committed
fix: prevent MCP server restart when toggling tool permissions
Add isProgrammaticUpdate flag to distinguish between programmatic config updates and user-initiated file changes. Skip file watcher processing during programmatic updates to prevent unnecessary server restarts.
1 parent 507a600 commit 9db94d3

File tree

1 file changed

+27
-2
lines changed

1 file changed

+27
-2
lines changed

src/services/mcp/McpHub.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ export class McpHub {
151151
isConnecting: boolean = false
152152
private refCount: number = 0 // Reference counter for active clients
153153
private configChangeDebounceTimers: Map<string, NodeJS.Timeout> = new Map()
154+
private isProgrammaticUpdate: boolean = false
154155

155156
constructor(provider: ClineProvider) {
156157
this.providerRef = new WeakRef(provider)
@@ -278,6 +279,11 @@ export class McpHub {
278279
* Debounced wrapper for handling config file changes
279280
*/
280281
private debounceConfigChange(filePath: string, source: "global" | "project"): void {
282+
// Skip processing if this is a programmatic update to prevent unnecessary server restarts
283+
if (this.isProgrammaticUpdate) {
284+
return
285+
}
286+
281287
const key = `${source}-${filePath}`
282288

283289
// Clear existing timer if any
@@ -1463,7 +1469,15 @@ export class McpHub {
14631469
mcpServers: config.mcpServers,
14641470
}
14651471

1466-
await fs.writeFile(configPath, JSON.stringify(updatedConfig, null, 2))
1472+
// Set flag to prevent file watcher from triggering server restart
1473+
this.isProgrammaticUpdate = true
1474+
try {
1475+
await fs.writeFile(configPath, JSON.stringify(updatedConfig, null, 2))
1476+
// Delay longer than debounce timer (500ms) to ensure watcher event is processed while flag is set
1477+
await delay(600)
1478+
} finally {
1479+
this.isProgrammaticUpdate = false
1480+
}
14671481
}
14681482

14691483
public async updateServerTimeout(
@@ -1686,7 +1700,15 @@ export class McpHub {
16861700
targetList.splice(toolIndex, 1)
16871701
}
16881702

1689-
await fs.writeFile(normalizedPath, JSON.stringify(config, null, 2))
1703+
// Set flag to prevent file watcher from triggering server restart
1704+
this.isProgrammaticUpdate = true
1705+
try {
1706+
await fs.writeFile(normalizedPath, JSON.stringify(config, null, 2))
1707+
// Delay longer than debounce timer (500ms) to ensure watcher event is processed while flag is set
1708+
await delay(600)
1709+
} finally {
1710+
this.isProgrammaticUpdate = false
1711+
}
16901712

16911713
if (connection) {
16921714
connection.server.tools = await this.fetchToolsList(serverName, source)
@@ -1796,6 +1818,9 @@ export class McpHub {
17961818
}
17971819
this.configChangeDebounceTimers.clear()
17981820

1821+
// Reset programmatic update flag
1822+
this.isProgrammaticUpdate = false
1823+
17991824
this.removeAllFileWatchers()
18001825
for (const connection of this.connections) {
18011826
try {

0 commit comments

Comments
 (0)