Skip to content

Commit 46fd622

Browse files
author
Your Name
committed
Make load and remove MCP tools match their command counterparts
1 parent f40f182 commit 46fd622

2 files changed

Lines changed: 61 additions & 16 deletions

File tree

cecli/tools/load_mcp.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
from typing import List
22

3+
from cecli.commands.utils.helpers import (
4+
iter_all_coders,
5+
update_server_registration,
6+
)
37
from cecli.tools.utils.base_tool import BaseTool
48

59

@@ -35,7 +39,7 @@ async def execute(cls, coder, servers: List[str]):
3539

3640
if servers == ["*"]:
3741
for server in coder.mcp_manager.servers:
38-
if server.name in coder.mcp_manager.connected_servers:
42+
if server.name in {s.name for s in coder.mcp_manager.connected_servers}:
3943
results.append(f"Server already loaded: {server.name}")
4044
continue
4145
auto_connect = server.config.get("enabled", True)
@@ -54,10 +58,24 @@ async def execute(cls, coder, servers: List[str]):
5458
if not servers_to_load and results:
5559
return "\n".join(results)
5660

61+
# Before connecting any new server, convert coders with empty included sets
62+
# to explicit include lists of all currently connected MCP servers.
63+
# This moves them from "implicitly include all" to explicit state-machine
64+
# management, preventing the new server from being implicitly available
65+
# to all coders.
66+
connected_names = {s.name for s in coder.mcp_manager.connected_servers}
67+
if connected_names:
68+
for c in iter_all_coders(coder):
69+
if not c.registered_servers["included"]:
70+
included = set(connected_names) - c.registered_servers["excluded"]
71+
if c.edit_format in ("agent", "subagent"):
72+
included.add("Local") # "local" is always available
73+
c.registered_servers["included"] = included
74+
5775
# Process the loading
5876
for server in servers_to_load:
5977
server_name = server.name
60-
if server_name in coder.mcp_manager.connected_servers:
78+
if server_name in {s.name for s in coder.mcp_manager.connected_servers}:
6179
results.append(f"Server already loaded: {server_name}")
6280
continue
6381

@@ -71,6 +89,15 @@ async def execute(cls, coder, servers: List[str]):
7189
results.append(f"Interrupted: {server_name}")
7290
continue
7391
if did_connect:
92+
# Force-include on the primary (active) coder
93+
update_server_registration(coder, server_name, "include", force=True)
94+
95+
# Safe-exclude on all other coders (respects existing inclusions)
96+
for other_coder in iter_all_coders(coder):
97+
if other_coder is coder:
98+
continue
99+
update_server_registration(other_coder, server_name, "exclude", force=False)
100+
74101
results.append(f"Loaded server: {server_name}")
75102
else:
76103
results.append(f"Unable to load server: {server_name}")

cecli/tools/remove_mcp.py

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
from typing import List
22

3+
from cecli.commands.utils.helpers import (
4+
is_server_globally_excluded,
5+
update_server_registration,
6+
)
37
from cecli.tools.utils.base_tool import BaseTool
48

59

@@ -39,13 +43,13 @@ async def execute(cls, coder, servers: List[str]):
3943

4044
# Determine which servers to act on
4145
if servers == ["*"]:
42-
servers_to_action.extend(coder.mcp_manager.connected_servers.keys())
46+
servers_to_action.extend(s.name for s in coder.mcp_manager.connected_servers)
4347
else:
4448
for server_name in servers:
4549
server = coder.mcp_manager.get_server(server_name)
4650
if not server:
4751
results.append(f"MCP server {server_name} does not exist.")
48-
elif server.name not in coder.mcp_manager.connected_servers:
52+
elif server.name not in {s.name for s in coder.mcp_manager.connected_servers}:
4953
results.append(f"Server {server_name} is not currently connected.")
5054
else:
5155
servers_to_action.append(server.name)
@@ -58,20 +62,34 @@ async def execute(cls, coder, servers: List[str]):
5862
if not servers_to_action:
5963
return "No servers to remove."
6064

61-
# Process the removal
65+
# Process the removal with server registration awareness
6266
for server_name in servers_to_action:
63-
coder.interrupt_event.clear()
64-
did_disconnect, interrupted = await coder.coroutines.interruptible(
65-
coder.mcp_manager.disconnect_server(server_name),
66-
coder.interrupt_event,
67-
)
68-
69-
if interrupted:
70-
results.append(f"Interrupted: {server_name}")
67+
# Never remove the "local" server
68+
if server_name == "Local":
69+
results.append("Cannot remove 'Local' server")
7170
continue
72-
if did_disconnect:
73-
results.append(f"Removed server: {server_name}")
71+
72+
# Force-exclude on the primary (active) coder
73+
update_server_registration(coder, server_name, "exclude", force=True)
74+
75+
# Check if all coders in the hierarchy have this server excluded
76+
all_excluded = is_server_globally_excluded(coder, server_name)
77+
78+
if all_excluded:
79+
coder.interrupt_event.clear()
80+
did_disconnect, interrupted = await coder.coroutines.interruptible(
81+
coder.mcp_manager.disconnect_server(server_name),
82+
coder.interrupt_event,
83+
)
84+
85+
if interrupted:
86+
results.append(f"Interrupted: {server_name}")
87+
continue
88+
if did_disconnect:
89+
results.append(f"Removed server: {server_name}")
90+
else:
91+
results.append(f"Unable to remove server: {server_name}")
7492
else:
75-
results.append(f"Unable to remove server: {server_name}")
93+
results.append(f"Removed from active coder, still active for others: {server_name}")
7694

7795
return "\n".join(results)

0 commit comments

Comments
 (0)