Skip to content

Commit b08b5d4

Browse files
Copilotbrunoborges
andauthored
Add MCP server events and session management methods
Co-authored-by: brunoborges <129743+brunoborges@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/copilot-sdk-java/sessions/4f9a9fb9-2883-4dd6-843d-2e4a25ddd7e0
1 parent 20c551c commit b08b5d4

File tree

9 files changed

+498
-1
lines changed

9 files changed

+498
-1
lines changed

src/main/java/com/github/copilot/sdk/CopilotSession.java

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.github.copilot.sdk.json.AgentInfo;
3636
import com.github.copilot.sdk.json.GetMessagesResponse;
3737
import com.github.copilot.sdk.json.HookInvocation;
38+
import com.github.copilot.sdk.json.McpServerInfo;
3839
import com.github.copilot.sdk.json.MessageOptions;
3940
import com.github.copilot.sdk.json.PermissionHandler;
4041
import com.github.copilot.sdk.json.PermissionInvocation;
@@ -1275,6 +1276,74 @@ public CompletableFuture<Void> compact() {
12751276
return rpc.invoke("session.compaction.compact", Map.of("sessionId", sessionId), Void.class);
12761277
}
12771278

1279+
/**
1280+
* Lists the MCP servers configured for this session, including their connection
1281+
* status.
1282+
*
1283+
* @return a future that resolves with the list of MCP server info objects
1284+
* @throws IllegalStateException
1285+
* if this session has been terminated
1286+
* @since 1.0.0
1287+
*/
1288+
public CompletableFuture<List<McpServerInfo>> listMcpServers() {
1289+
ensureNotTerminated();
1290+
return rpc.invoke("session.mcp.list", Map.of("sessionId", sessionId), McpListResponse.class)
1291+
.thenApply(response -> response.servers() != null
1292+
? Collections.unmodifiableList(response.servers())
1293+
: Collections.emptyList());
1294+
}
1295+
1296+
/**
1297+
* Enables a previously disabled MCP server in this session.
1298+
*
1299+
* @param serverName
1300+
* the name of the MCP server to enable (the key used in the
1301+
* {@link com.github.copilot.sdk.json.SessionConfig#setMcpServers(java.util.Map)}
1302+
* map)
1303+
* @return a future that completes when the server has been enabled
1304+
* @throws IllegalStateException
1305+
* if this session has been terminated
1306+
* @since 1.0.0
1307+
*/
1308+
public CompletableFuture<Void> enableMcpServer(String serverName) {
1309+
ensureNotTerminated();
1310+
return rpc.invoke("session.mcp.enable", Map.of("sessionId", sessionId, "serverName", serverName), Void.class);
1311+
}
1312+
1313+
/**
1314+
* Disables an MCP server in this session without removing its configuration.
1315+
* <p>
1316+
* A disabled server can be re-enabled later via
1317+
* {@link #enableMcpServer(String)}.
1318+
*
1319+
* @param serverName
1320+
* the name of the MCP server to disable
1321+
* @return a future that completes when the server has been disabled
1322+
* @throws IllegalStateException
1323+
* if this session has been terminated
1324+
* @since 1.0.0
1325+
*/
1326+
public CompletableFuture<Void> disableMcpServer(String serverName) {
1327+
ensureNotTerminated();
1328+
return rpc.invoke("session.mcp.disable", Map.of("sessionId", sessionId, "serverName", serverName), Void.class);
1329+
}
1330+
1331+
/**
1332+
* Reloads all MCP servers in this session.
1333+
* <p>
1334+
* This disconnects and reconnects all configured MCP servers, which can be
1335+
* useful to pick up configuration changes or recover from failed connections.
1336+
*
1337+
* @return a future that completes when the reload is initiated
1338+
* @throws IllegalStateException
1339+
* if this session has been terminated
1340+
* @since 1.0.0
1341+
*/
1342+
public CompletableFuture<Void> reloadMcpServers() {
1343+
ensureNotTerminated();
1344+
return rpc.invoke("session.mcp.reload", Map.of("sessionId", sessionId), Void.class);
1345+
}
1346+
12781347
/**
12791348
* Verifies that this session has not yet been terminated.
12801349
*
@@ -1330,4 +1399,10 @@ private record AgentGetCurrentResponse(@JsonProperty("agent") AgentInfo agent) {
13301399
private record AgentSelectResponse(@JsonProperty("agent") AgentInfo agent) {
13311400
}
13321401

1402+
// ===== Internal response types for MCP API =====
1403+
1404+
@JsonIgnoreProperties(ignoreUnknown = true)
1405+
private record McpListResponse(@JsonProperty("servers") List<McpServerInfo> servers) {
1406+
}
1407+
13331408
}

src/main/java/com/github/copilot/sdk/events/AbstractSessionEvent.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public abstract sealed class AbstractSessionEvent permits
5555
SessionModelChangeEvent, SessionModeChangedEvent, SessionPlanChangedEvent, SessionWorkspaceFileChangedEvent,
5656
SessionHandoffEvent, SessionTruncationEvent, SessionSnapshotRewindEvent, SessionUsageInfoEvent,
5757
SessionCompactionStartEvent, SessionCompactionCompleteEvent, SessionShutdownEvent, SessionContextChangedEvent,
58-
SessionTaskCompleteEvent,
58+
SessionTaskCompleteEvent, SessionMcpServersLoadedEvent, SessionMcpServerStatusChangedEvent,
5959
// Assistant events
6060
AssistantTurnStartEvent, AssistantIntentEvent, AssistantReasoningEvent, AssistantReasoningDeltaEvent,
6161
AssistantMessageEvent, AssistantMessageDeltaEvent, AssistantStreamingDeltaEvent, AssistantTurnEndEvent,

src/main/java/com/github/copilot/sdk/events/SessionEventParser.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ public class SessionEventParser {
6666
TYPE_MAP.put("session.compaction_complete", SessionCompactionCompleteEvent.class);
6767
TYPE_MAP.put("session.context_changed", SessionContextChangedEvent.class);
6868
TYPE_MAP.put("session.task_complete", SessionTaskCompleteEvent.class);
69+
TYPE_MAP.put("session.mcp_servers_loaded", SessionMcpServersLoadedEvent.class);
70+
TYPE_MAP.put("session.mcp_server_status_changed", SessionMcpServerStatusChangedEvent.class);
6971
TYPE_MAP.put("user.message", UserMessageEvent.class);
7072
TYPE_MAP.put("pending_messages.modified", PendingMessagesModifiedEvent.class);
7173
TYPE_MAP.put("assistant.turn_start", AssistantTurnStartEvent.class);
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
*--------------------------------------------------------------------------------------------*/
4+
5+
package com.github.copilot.sdk.events;
6+
7+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
8+
import com.fasterxml.jackson.annotation.JsonProperty;
9+
10+
/**
11+
* Event: session.mcp_server_status_changed
12+
* <p>
13+
* Fired when the connection status of an MCP server changes during the session
14+
* (e.g., from {@code pending} to {@code connected} or {@code failed}).
15+
*
16+
* @since 1.0.0
17+
*/
18+
@JsonIgnoreProperties(ignoreUnknown = true)
19+
public final class SessionMcpServerStatusChangedEvent extends AbstractSessionEvent {
20+
21+
@JsonProperty("data")
22+
private SessionMcpServerStatusChangedData data;
23+
24+
@Override
25+
public String getType() {
26+
return "session.mcp_server_status_changed";
27+
}
28+
29+
public SessionMcpServerStatusChangedData getData() {
30+
return data;
31+
}
32+
33+
public void setData(SessionMcpServerStatusChangedData data) {
34+
this.data = data;
35+
}
36+
37+
/**
38+
* Data payload for the {@code session.mcp_server_status_changed} event.
39+
*/
40+
@JsonIgnoreProperties(ignoreUnknown = true)
41+
public static class SessionMcpServerStatusChangedData {
42+
43+
@JsonProperty("serverName")
44+
private String serverName;
45+
46+
@JsonProperty("status")
47+
private String status;
48+
49+
/**
50+
* Gets the name of the MCP server whose status changed.
51+
*
52+
* @return the server name
53+
*/
54+
public String getServerName() {
55+
return serverName;
56+
}
57+
58+
/**
59+
* Sets the server name.
60+
*
61+
* @param serverName
62+
* the server name
63+
*/
64+
public void setServerName(String serverName) {
65+
this.serverName = serverName;
66+
}
67+
68+
/**
69+
* Gets the new connection status.
70+
* <p>
71+
* Possible values: {@code "connected"}, {@code "failed"}, {@code "pending"},
72+
* {@code "disabled"}, {@code "not_configured"}.
73+
*
74+
* @return the status string
75+
*/
76+
public String getStatus() {
77+
return status;
78+
}
79+
80+
/**
81+
* Sets the new connection status.
82+
*
83+
* @param status
84+
* the status string
85+
*/
86+
public void setStatus(String status) {
87+
this.status = status;
88+
}
89+
}
90+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
*--------------------------------------------------------------------------------------------*/
4+
5+
package com.github.copilot.sdk.events;
6+
7+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
8+
import com.fasterxml.jackson.annotation.JsonProperty;
9+
import com.github.copilot.sdk.json.McpServerInfo;
10+
11+
import java.util.List;
12+
13+
/**
14+
* Event: session.mcp_servers_loaded
15+
* <p>
16+
* Fired after all MCP servers have been initialized for the session. Contains a
17+
* summary of each server's connection status.
18+
*
19+
* @since 1.0.0
20+
*/
21+
@JsonIgnoreProperties(ignoreUnknown = true)
22+
public final class SessionMcpServersLoadedEvent extends AbstractSessionEvent {
23+
24+
@JsonProperty("data")
25+
private SessionMcpServersLoadedData data;
26+
27+
@Override
28+
public String getType() {
29+
return "session.mcp_servers_loaded";
30+
}
31+
32+
public SessionMcpServersLoadedData getData() {
33+
return data;
34+
}
35+
36+
public void setData(SessionMcpServersLoadedData data) {
37+
this.data = data;
38+
}
39+
40+
/**
41+
* Data payload for the {@code session.mcp_servers_loaded} event.
42+
*/
43+
@JsonIgnoreProperties(ignoreUnknown = true)
44+
public static class SessionMcpServersLoadedData {
45+
46+
@JsonProperty("servers")
47+
private List<McpServerInfo> servers;
48+
49+
/**
50+
* Gets the list of MCP server status summaries.
51+
*
52+
* @return the servers list
53+
*/
54+
public List<McpServerInfo> getServers() {
55+
return servers;
56+
}
57+
58+
/**
59+
* Sets the list of MCP server status summaries.
60+
*
61+
* @param servers
62+
* the servers list
63+
*/
64+
public void setServers(List<McpServerInfo> servers) {
65+
this.servers = servers;
66+
}
67+
}
68+
}

src/main/java/com/github/copilot/sdk/events/package-info.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@
5252
* execution progress update</li>
5353
* </ul>
5454
*
55+
* <h3>MCP Server Events</h3>
56+
* <ul>
57+
* <li>{@link com.github.copilot.sdk.events.SessionMcpServersLoadedEvent} - MCP
58+
* servers have been initialized</li>
59+
* <li>{@link com.github.copilot.sdk.events.SessionMcpServerStatusChangedEvent}
60+
* - An MCP server's connection status changed</li>
61+
* </ul>
62+
*
5563
* <h3>Subagent Events</h3>
5664
* <ul>
5765
* <li>{@link com.github.copilot.sdk.events.SubagentSelectedEvent} - Subagent

0 commit comments

Comments
 (0)