Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions dotnet/src/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,7 @@ public async Task<CopilotSession> CreateSessionAsync(SessionConfig config, Cance
config.Streaming is true ? true : null,
config.IncludeSubAgentStreamingEvents,
config.McpServers,
config.AllowAllMcpServerInstructions,
config.McpOAuthTokenStorage,
config.AuthClientIdMetadataUrl,
"direct",
Expand Down Expand Up @@ -1503,6 +1504,7 @@ public async Task<CopilotSession> ResumeSessionAsync(string sessionId, ResumeSes
config.Streaming is true ? true : null,
config.IncludeSubAgentStreamingEvents,
config.McpServers,
config.AllowAllMcpServerInstructions,
config.McpOAuthTokenStorage,
config.AuthClientIdMetadataUrl,
"direct",
Expand Down Expand Up @@ -3034,6 +3036,7 @@ internal record CreateSessionRequest(
bool? Streaming,
bool? IncludeSubAgentStreamingEvents,
IDictionary<string, McpServerConfig>? McpServers,
bool? AllowAllMcpServerInstructions,
McpOAuthTokenStorageMode? McpOAuthTokenStorage,
string? AuthClientIdMetadataUrl,
string? EnvValueMode,
Expand Down Expand Up @@ -3164,6 +3167,7 @@ internal record ResumeSessionRequest(
bool? Streaming,
bool? IncludeSubAgentStreamingEvents,
IDictionary<string, McpServerConfig>? McpServers,
bool? AllowAllMcpServerInstructions,
McpOAuthTokenStorageMode? McpOAuthTokenStorage,
string? AuthClientIdMetadataUrl,
string? EnvValueMode,
Expand Down
8 changes: 8 additions & 0 deletions dotnet/src/Types.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3288,6 +3288,7 @@ protected SessionConfigBase(SessionConfigBase? other)
DisabledSkills = other.DisabledSkills is not null ? [.. other.DisabledSkills] : null;
IncludedBuiltinSkills = other.IncludedBuiltinSkills is not null ? [.. other.IncludedBuiltinSkills] : null;
DisabledMcpServers = other.DisabledMcpServers is not null ? [.. other.DisabledMcpServers] : null;
AllowAllMcpServerInstructions = other.AllowAllMcpServerInstructions;
EnableCitations = other.EnableCitations;
EnableFileChangeTracking = other.EnableFileChangeTracking;
EnableConfigDiscovery = other.EnableConfigDiscovery;
Expand Down Expand Up @@ -3716,6 +3717,13 @@ protected SessionConfigBase(SessionConfigBase? other)
/// </summary>
public IDictionary<string, McpServerConfig>? McpServers { get; set; }

/// <summary>
/// Whether instructions from every configured MCP server are included in the
/// system prompt. Enabling this broadens the default trust boundary; only use
/// it with trusted servers. When null, the runtime default applies.
/// </summary>
public bool? AllowAllMcpServerInstructions { get; set; }

/// <summary>
/// Controls how MCP OAuth tokens are stored for this session.
/// Default: <see cref="McpOAuthTokenStorageMode.InMemory"/> for safe multitenant behavior.
Expand Down
48 changes: 48 additions & 0 deletions dotnet/test/Unit/ClientSessionLifetimeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,54 @@ public async Task SessionRequests_Serialize_CapiAutoTier(AutoTier tier, string e
}
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task SessionRequests_Forward_McpServerInstructionPolicy(bool value)
{
await using var server = await FakeCopilotServer.StartAsync();
await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(server.Url) });

await using var created = await client.CreateSessionAsync(new SessionConfig
{
AllowAllMcpServerInstructions = value,
OnPermissionRequest = PermissionHandler.ApproveAll
});
await using var resumed = await client.ResumeSessionAsync("resume-with-mcp-instruction-policy", new ResumeSessionConfig
{
AllowAllMcpServerInstructions = value,
OnPermissionRequest = PermissionHandler.ApproveAll
});

foreach (var method in new[] { "session.create", "session.resume" })
{
var request = Assert.Single(server.Requests, request => request.Method == method);
Assert.Equal(value, request.Params.GetProperty("allowAllMcpServerInstructions").GetBoolean());
}
}

[Fact]
public async Task SessionRequests_Omit_McpServerInstructionPolicy_WhenUnset()
{
await using var server = await FakeCopilotServer.StartAsync();
await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(server.Url) });

await using var created = await client.CreateSessionAsync(new SessionConfig
{
OnPermissionRequest = PermissionHandler.ApproveAll
});
await using var resumed = await client.ResumeSessionAsync("resume-without-mcp-instruction-policy", new ResumeSessionConfig
{
OnPermissionRequest = PermissionHandler.ApproveAll
});

foreach (var method in new[] { "session.create", "session.resume" })
{
var request = Assert.Single(server.Requests, request => request.Method == method);
Assert.False(request.Params.TryGetProperty("allowAllMcpServerInstructions", out _));
}
}

[Theory]
[InlineData("efficiency")]
[InlineData("balance")]
Expand Down
2 changes: 2 additions & 0 deletions go/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,7 @@ func (c *Client) CreateSession(ctx context.Context, config *SessionConfig) (*Ses
req.WorkingDirectory = config.WorkingDirectory
req.AdditionalDirectories = config.AdditionalDirectories
req.MCPServers = config.MCPServers
req.AllowAllMCPServerInstructions = config.AllowAllMCPServerInstructions
req.MCPOAuthTokenStorage = config.MCPOAuthTokenStorage
req.AuthClientIDMetadataURL = config.AuthClientIDMetadataURL
req.EnvValueMode = "direct"
Expand Down Expand Up @@ -1322,6 +1323,7 @@ func (c *Client) ResumeSessionWithOptions(ctx context.Context, sessionID string,
}
req.ContinuePendingWork = config.ContinuePendingWork
req.MCPServers = config.MCPServers
req.AllowAllMCPServerInstructions = config.AllowAllMCPServerInstructions
req.MCPOAuthTokenStorage = config.MCPOAuthTokenStorage
req.AuthClientIDMetadataURL = config.AuthClientIDMetadataURL
req.EnvValueMode = "direct"
Expand Down
37 changes: 37 additions & 0 deletions go/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1970,6 +1970,43 @@ func TestSessionRequests_PluginDirectoriesAndLargeOutput(t *testing.T) {
})
}

func TestSessionRequests_AllowAllMCPServerInstructions(t *testing.T) {
for _, tc := range []struct {
name string
value *bool
want any
}{
{name: "true", value: Bool(true), want: true},
{name: "false", value: Bool(false), want: false},
{name: "omitted", value: nil, want: nil},
} {
t.Run(tc.name, func(t *testing.T) {
requests := []any{
createSessionRequest{AllowAllMCPServerInstructions: tc.value},
resumeSessionRequest{SessionID: "s1", AllowAllMCPServerInstructions: tc.value},
}
for _, request := range requests {
data, err := json.Marshal(request)
if err != nil {
t.Fatalf("Failed to marshal: %v", err)
}
var payload map[string]any
if err := json.Unmarshal(data, &payload); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
got, present := payload["allowAllMcpServerInstructions"]
if tc.value == nil {
if present {
t.Fatalf("Expected policy to be omitted, got %v", got)
}
} else if !present || got != tc.want {
t.Fatalf("Expected policy %v, got %v", tc.want, got)
}
}
})
}
}

func TestSessionRequests_Memory(t *testing.T) {
t.Run("create includes memory in JSON when enabled", func(t *testing.T) {
req := createSessionRequest{Memory: &MemoryConfiguration{Enabled: true}}
Expand Down
12 changes: 12 additions & 0 deletions go/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1490,6 +1490,11 @@ type SessionConfig struct {
ModelCapabilities *rpc.ModelCapabilitiesOverride
// MCPServers configures MCP servers for the session
MCPServers map[string]MCPServerConfig
// AllowAllMCPServerInstructions controls whether instructions from every
// configured MCP server are included in the system prompt. Enabling this
// broadens the default trust boundary; only use it with trusted servers.
// Nil leaves the runtime default unchanged.
AllowAllMCPServerInstructions *bool
// MCPOAuthTokenStorage controls how MCP OAuth tokens are stored for this session.
// When empty, the runtime default ("in-memory") is used.
MCPOAuthTokenStorage string
Expand Down Expand Up @@ -2053,6 +2058,11 @@ type ResumeSessionConfig struct {
IncludeSubAgentStreamingEvents *bool
// MCPServers configures MCP servers for the session
MCPServers map[string]MCPServerConfig
// AllowAllMCPServerInstructions controls whether instructions from every
// configured MCP server are included in the system prompt. Enabling this
// broadens the default trust boundary; only use it with trusted servers.
// Nil leaves the runtime default unchanged.
AllowAllMCPServerInstructions *bool
// MCPOAuthTokenStorage controls how MCP OAuth tokens are stored for this session.
// When empty, the runtime default ("in-memory") is used.
MCPOAuthTokenStorage string
Expand Down Expand Up @@ -2650,6 +2660,7 @@ type createSessionRequest struct {
IncludeSubAgentStreamingEvents *bool `json:"includeSubAgentStreamingEvents,omitempty"`
EnableGitHubTelemetryForwarding *bool `json:"enableGitHubTelemetryForwarding,omitempty"`
MCPServers map[string]MCPServerConfig `json:"mcpServers,omitempty"`
AllowAllMCPServerInstructions *bool `json:"allowAllMcpServerInstructions,omitempty"`
MCPOAuthTokenStorage string `json:"mcpOAuthTokenStorage,omitempty"`
AuthClientIDMetadataURL string `json:"authClientIdMetadataUrl,omitempty"`
EnvValueMode string `json:"envValueMode,omitempty"`
Expand Down Expand Up @@ -2762,6 +2773,7 @@ type resumeSessionRequest struct {
IncludeSubAgentStreamingEvents *bool `json:"includeSubAgentStreamingEvents,omitempty"`
EnableGitHubTelemetryForwarding *bool `json:"enableGitHubTelemetryForwarding,omitempty"`
MCPServers map[string]MCPServerConfig `json:"mcpServers,omitempty"`
AllowAllMCPServerInstructions *bool `json:"allowAllMcpServerInstructions,omitempty"`
MCPOAuthTokenStorage string `json:"mcpOAuthTokenStorage,omitempty"`
AuthClientIDMetadataURL string `json:"authClientIdMetadataUrl,omitempty"`
EnvValueMode string `json:"envValueMode,omitempty"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ static CreateSessionRequest buildCreateRequest(SessionConfig config, String sess
}
config.getIncludeSubAgentStreamingEvents().ifPresent(request::setIncludeSubAgentStreamingEvents);
request.setMcpServers(config.getMcpServers());
request.setAllowAllMcpServerInstructions(config.getAllowAllMcpServerInstructions());
request.setMcpOAuthTokenStorage(config.getMcpOAuthTokenStorage());
request.setAuthClientIdMetadataUrl(config.getAuthClientIdMetadataUrl());
request.setCustomAgents(config.getCustomAgents());
Expand Down Expand Up @@ -304,6 +305,7 @@ static ResumeSessionRequest buildResumeRequest(String sessionId, ResumeSessionCo
}
config.getIncludeSubAgentStreamingEvents().ifPresent(request::setIncludeSubAgentStreamingEvents);
request.setMcpServers(config.getMcpServers());
request.setAllowAllMcpServerInstructions(config.getAllowAllMcpServerInstructions());
request.setMcpOAuthTokenStorage(config.getMcpOAuthTokenStorage());
request.setAuthClientIdMetadataUrl(config.getAuthClientIdMetadataUrl());
request.setCustomAgents(config.getCustomAgents());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ public final class CreateSessionRequest {
@JsonProperty("mcpServers")
private Map<String, McpServerConfig> mcpServers;

@JsonProperty("allowAllMcpServerInstructions")
private Boolean allowAllMcpServerInstructions;

@JsonProperty("mcpOAuthTokenStorage")
private String mcpOAuthTokenStorage;

Expand Down Expand Up @@ -594,6 +597,16 @@ public void setMcpServers(Map<String, McpServerConfig> mcpServers) {
this.mcpServers = mcpServers;
}

/** Gets the MCP server instruction policy. @return the policy value */
public Boolean getAllowAllMcpServerInstructions() {
return allowAllMcpServerInstructions;
}

/** Sets the MCP server instruction policy. @param value the policy value */
public void setAllowAllMcpServerInstructions(Boolean value) {
this.allowAllMcpServerInstructions = value;
}

/** Gets MCP OAuth token storage mode. @return the storage mode */
public String getMcpOAuthTokenStorage() {
return mcpOAuthTokenStorage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public class ResumeSessionConfig {
private boolean streaming;
private Boolean includeSubAgentStreamingEvents;
private Map<String, McpServerConfig> mcpServers;
private Boolean allowAllMcpServerInstructions;
private String mcpOAuthTokenStorage;
private String authClientIdMetadataUrl;
private List<CustomAgentConfig> customAgents;
Expand Down Expand Up @@ -1397,6 +1398,30 @@ public ResumeSessionConfig setMcpServers(Map<String, McpServerConfig> mcpServers
return this;
}

/**
* Gets whether instructions from every configured MCP server are included in
* the system prompt.
*
* @return the policy value, or {@code null} when the runtime default applies
*/
public Boolean getAllowAllMcpServerInstructions() {
return allowAllMcpServerInstructions;
}

/**
* Controls whether instructions from every configured MCP server are included
* in the system prompt. Enabling this broadens the default trust boundary; only
* use it with trusted servers.
*
* @param allowAllMcpServerInstructions
* the explicit policy value, or {@code null} for the runtime default
* @return this config instance for method chaining
*/
public ResumeSessionConfig setAllowAllMcpServerInstructions(Boolean allowAllMcpServerInstructions) {
this.allowAllMcpServerInstructions = allowAllMcpServerInstructions;
return this;
}

/**
* Gets the MCP OAuth token storage mode.
*
Expand Down Expand Up @@ -2143,6 +2168,7 @@ public ResumeSessionConfig clone() {
copy.streaming = this.streaming;
copy.includeSubAgentStreamingEvents = this.includeSubAgentStreamingEvents;
copy.mcpServers = this.mcpServers != null ? new java.util.HashMap<>(this.mcpServers) : null;
copy.allowAllMcpServerInstructions = this.allowAllMcpServerInstructions;
copy.mcpOAuthTokenStorage = this.mcpOAuthTokenStorage;
copy.authClientIdMetadataUrl = this.authClientIdMetadataUrl;
copy.customAgents = this.customAgents != null ? new ArrayList<>(this.customAgents) : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ public final class ResumeSessionRequest {
@JsonProperty("mcpServers")
private Map<String, McpServerConfig> mcpServers;

@JsonProperty("allowAllMcpServerInstructions")
private Boolean allowAllMcpServerInstructions;

@JsonProperty("mcpOAuthTokenStorage")
private String mcpOAuthTokenStorage;

Expand Down Expand Up @@ -820,6 +823,16 @@ public void setMcpServers(Map<String, McpServerConfig> mcpServers) {
this.mcpServers = mcpServers;
}

/** Gets the MCP server instruction policy. @return the policy value */
public Boolean getAllowAllMcpServerInstructions() {
return allowAllMcpServerInstructions;
}

/** Sets the MCP server instruction policy. @param value the policy value */
public void setAllowAllMcpServerInstructions(Boolean value) {
this.allowAllMcpServerInstructions = value;
}

/** Gets MCP OAuth token storage mode. @return the storage mode */
public String getMcpOAuthTokenStorage() {
return mcpOAuthTokenStorage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public class SessionConfig {
private boolean streaming;
private Boolean includeSubAgentStreamingEvents;
private Map<String, McpServerConfig> mcpServers;
private Boolean allowAllMcpServerInstructions;
private String mcpOAuthTokenStorage;
private String authClientIdMetadataUrl;
private List<CustomAgentConfig> customAgents;
Expand Down Expand Up @@ -1050,6 +1051,30 @@ public SessionConfig setMcpServers(Map<String, McpServerConfig> mcpServers) {
return this;
}

/**
* Gets whether instructions from every configured MCP server are included in
* the system prompt.
*
* @return the policy value, or {@code null} when the runtime default applies
*/
public Boolean getAllowAllMcpServerInstructions() {
return allowAllMcpServerInstructions;
}

/**
* Controls whether instructions from every configured MCP server are included
* in the system prompt. Enabling this broadens the default trust boundary; only
* use it with trusted servers.
*
* @param allowAllMcpServerInstructions
* the explicit policy value, or {@code null} for the runtime default
* @return this config instance for method chaining
*/
public SessionConfig setAllowAllMcpServerInstructions(Boolean allowAllMcpServerInstructions) {
this.allowAllMcpServerInstructions = allowAllMcpServerInstructions;
return this;
}

/**
* Gets the MCP OAuth token storage mode.
*
Expand Down Expand Up @@ -2272,6 +2297,7 @@ public SessionConfig clone() {
copy.streaming = this.streaming;
copy.includeSubAgentStreamingEvents = this.includeSubAgentStreamingEvents;
copy.mcpServers = this.mcpServers != null ? new java.util.HashMap<>(this.mcpServers) : null;
copy.allowAllMcpServerInstructions = this.allowAllMcpServerInstructions;
copy.mcpOAuthTokenStorage = this.mcpOAuthTokenStorage;
copy.authClientIdMetadataUrl = this.authClientIdMetadataUrl;
copy.customAgents = this.customAgents != null ? new ArrayList<>(this.customAgents) : null;
Expand Down
Loading