Skip to content

Commit 6029b37

Browse files
stephentoubCopilot
andauthored
Expose enableConfigDiscovery in all SDK languages (#1044)
* Expose enableConfigDiscovery in all SDK languages Add enableConfigDiscovery option to session config types in Node.js, Python, Go, and .NET SDKs. When set to true, the runtime automatically discovers MCP server configurations (.mcp.json, .vscode/mcp.json) and skill directories from the working directory, merging them with any explicitly provided values (explicit takes precedence on name collision). This surfaces a capability already implemented in copilot-agent-runtime's resolveDiscoveredConfig() for SDK consumers. Changes per SDK: - Node.js: SessionConfig + ResumeSessionConfig pick + client passthrough - Python: create_session/resume_session params + payload serialization - Go: config structs + wire request structs + client passthrough - .NET: config classes + clone constructors + wire records + client passthrough Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix gofmt alignment in wire request structs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent e0a9028 commit 6029b37

File tree

7 files changed

+147
-55
lines changed

7 files changed

+147
-55
lines changed

dotnet/src/Client.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,7 @@ public async Task<CopilotSession> CreateSessionAsync(SessionConfig config, Cance
502502
config.CustomAgents,
503503
config.Agent,
504504
config.ConfigDir,
505+
config.EnableConfigDiscovery,
505506
config.SkillDirectories,
506507
config.DisabledSkills,
507508
config.InfiniteSessions,
@@ -618,6 +619,7 @@ public async Task<CopilotSession> ResumeSessionAsync(string sessionId, ResumeSes
618619
hasHooks ? true : null,
619620
config.WorkingDirectory,
620621
config.ConfigDir,
622+
config.EnableConfigDiscovery,
621623
config.DisableResume is true ? true : null,
622624
config.Streaming is true ? true : null,
623625
config.McpServers,
@@ -1640,6 +1642,7 @@ internal record CreateSessionRequest(
16401642
List<CustomAgentConfig>? CustomAgents,
16411643
string? Agent,
16421644
string? ConfigDir,
1645+
bool? EnableConfigDiscovery,
16431646
List<string>? SkillDirectories,
16441647
List<string>? DisabledSkills,
16451648
InfiniteSessionConfig? InfiniteSessions,
@@ -1686,6 +1689,7 @@ internal record ResumeSessionRequest(
16861689
bool? Hooks,
16871690
string? WorkingDirectory,
16881691
string? ConfigDir,
1692+
bool? EnableConfigDiscovery,
16891693
bool? DisableResume,
16901694
bool? Streaming,
16911695
Dictionary<string, object>? McpServers,

dotnet/src/Types.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,6 +1603,7 @@ protected SessionConfig(SessionConfig? other)
16031603
CustomAgents = other.CustomAgents is not null ? [.. other.CustomAgents] : null;
16041604
Agent = other.Agent;
16051605
DisabledSkills = other.DisabledSkills is not null ? [.. other.DisabledSkills] : null;
1606+
EnableConfigDiscovery = other.EnableConfigDiscovery;
16061607
ExcludedTools = other.ExcludedTools is not null ? [.. other.ExcludedTools] : null;
16071608
Hooks = other.Hooks;
16081609
InfiniteSessions = other.InfiniteSessions;
@@ -1660,6 +1661,19 @@ protected SessionConfig(SessionConfig? other)
16601661
/// </summary>
16611662
public string? ConfigDir { get; set; }
16621663

1664+
/// <summary>
1665+
/// When <see langword="true"/>, automatically discovers MCP server configurations
1666+
/// (e.g. <c>.mcp.json</c>, <c>.vscode/mcp.json</c>) and skill directories from
1667+
/// the working directory and merges them with any explicitly provided
1668+
/// <see cref="McpServers"/> and <see cref="SkillDirectories"/>, with explicit
1669+
/// values taking precedence on name collision.
1670+
/// <para>
1671+
/// Custom instruction files (<c>.github/copilot-instructions.md</c>, <c>AGENTS.md</c>, etc.)
1672+
/// are always loaded from the working directory regardless of this setting.
1673+
/// </para>
1674+
/// </summary>
1675+
public bool? EnableConfigDiscovery { get; set; }
1676+
16631677
/// <summary>
16641678
/// Custom tool functions available to the language model during the session.
16651679
/// </summary>
@@ -1817,6 +1831,7 @@ protected ResumeSessionConfig(ResumeSessionConfig? other)
18171831
Agent = other.Agent;
18181832
DisabledSkills = other.DisabledSkills is not null ? [.. other.DisabledSkills] : null;
18191833
DisableResume = other.DisableResume;
1834+
EnableConfigDiscovery = other.EnableConfigDiscovery;
18201835
ExcludedTools = other.ExcludedTools is not null ? [.. other.ExcludedTools] : null;
18211836
Hooks = other.Hooks;
18221837
InfiniteSessions = other.InfiniteSessions;
@@ -1929,6 +1944,19 @@ protected ResumeSessionConfig(ResumeSessionConfig? other)
19291944
/// </summary>
19301945
public string? ConfigDir { get; set; }
19311946

1947+
/// <summary>
1948+
/// When <see langword="true"/>, automatically discovers MCP server configurations
1949+
/// (e.g. <c>.mcp.json</c>, <c>.vscode/mcp.json</c>) and skill directories from
1950+
/// the working directory and merges them with any explicitly provided
1951+
/// <see cref="McpServers"/> and <see cref="SkillDirectories"/>, with explicit
1952+
/// values taking precedence on name collision.
1953+
/// <para>
1954+
/// Custom instruction files (<c>.github/copilot-instructions.md</c>, <c>AGENTS.md</c>, etc.)
1955+
/// are always loaded from the working directory regardless of this setting.
1956+
/// </para>
1957+
/// </summary>
1958+
public bool? EnableConfigDiscovery { get; set; }
1959+
19321960
/// <summary>
19331961
/// When true, the session.resume event is not emitted.
19341962
/// Default: false (resume event is emitted).

go/client.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,9 @@ func (c *Client) CreateSession(ctx context.Context, config *SessionConfig) (*Ses
578578
req.ClientName = config.ClientName
579579
req.ReasoningEffort = config.ReasoningEffort
580580
req.ConfigDir = config.ConfigDir
581+
if config.EnableConfigDiscovery {
582+
req.EnableConfigDiscovery = Bool(true)
583+
}
581584
req.Tools = config.Tools
582585
wireSystemMessage, transformCallbacks := extractTransformCallbacks(config.SystemMessage)
583586
req.SystemMessage = wireSystemMessage
@@ -754,6 +757,9 @@ func (c *Client) ResumeSessionWithOptions(ctx context.Context, sessionID string,
754757
}
755758
req.WorkingDirectory = config.WorkingDirectory
756759
req.ConfigDir = config.ConfigDir
760+
if config.EnableConfigDiscovery {
761+
req.EnableConfigDiscovery = Bool(true)
762+
}
757763
if config.DisableResume {
758764
req.DisableResume = Bool(true)
759765
}

go/types.go

Lines changed: 71 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,13 @@ type SessionConfig struct {
465465
// ConfigDir overrides the default configuration directory location.
466466
// When specified, the session will use this directory for storing config and state.
467467
ConfigDir string
468+
// EnableConfigDiscovery, when true, automatically discovers MCP server configurations
469+
// (e.g. .mcp.json, .vscode/mcp.json) and skill directories from the working directory
470+
// and merges them with any explicitly provided MCPServers and SkillDirectories, with
471+
// explicit values taking precedence on name collision.
472+
// Custom instruction files (.github/copilot-instructions.md, AGENTS.md, etc.) are
473+
// always loaded from the working directory regardless of this setting.
474+
EnableConfigDiscovery bool
468475
// Tools exposes caller-implemented tools to the CLI
469476
Tools []Tool
470477
// SystemMessage configures system message customization
@@ -692,6 +699,13 @@ type ResumeSessionConfig struct {
692699
WorkingDirectory string
693700
// ConfigDir overrides the default configuration directory location.
694701
ConfigDir string
702+
// EnableConfigDiscovery, when true, automatically discovers MCP server configurations
703+
// (e.g. .mcp.json, .vscode/mcp.json) and skill directories from the working directory
704+
// and merges them with any explicitly provided MCPServers and SkillDirectories, with
705+
// explicit values taking precedence on name collision.
706+
// Custom instruction files (.github/copilot-instructions.md, AGENTS.md, etc.) are
707+
// always loaded from the working directory regardless of this setting.
708+
EnableConfigDiscovery bool
695709
// Streaming enables streaming of assistant message and reasoning chunks.
696710
// When true, assistant.message_delta and assistant.reasoning_delta events
697711
// with deltaContent are sent as the response is generated.
@@ -889,33 +903,34 @@ type SessionLifecycleHandler func(event SessionLifecycleEvent)
889903

890904
// createSessionRequest is the request for session.create
891905
type createSessionRequest struct {
892-
Model string `json:"model,omitempty"`
893-
SessionID string `json:"sessionId,omitempty"`
894-
ClientName string `json:"clientName,omitempty"`
895-
ReasoningEffort string `json:"reasoningEffort,omitempty"`
896-
Tools []Tool `json:"tools,omitempty"`
897-
SystemMessage *SystemMessageConfig `json:"systemMessage,omitempty"`
898-
AvailableTools []string `json:"availableTools"`
899-
ExcludedTools []string `json:"excludedTools,omitempty"`
900-
Provider *ProviderConfig `json:"provider,omitempty"`
901-
ModelCapabilities *rpc.ModelCapabilitiesOverride `json:"modelCapabilities,omitempty"`
902-
RequestPermission *bool `json:"requestPermission,omitempty"`
903-
RequestUserInput *bool `json:"requestUserInput,omitempty"`
904-
Hooks *bool `json:"hooks,omitempty"`
905-
WorkingDirectory string `json:"workingDirectory,omitempty"`
906-
Streaming *bool `json:"streaming,omitempty"`
907-
MCPServers map[string]MCPServerConfig `json:"mcpServers,omitempty"`
908-
EnvValueMode string `json:"envValueMode,omitempty"`
909-
CustomAgents []CustomAgentConfig `json:"customAgents,omitempty"`
910-
Agent string `json:"agent,omitempty"`
911-
ConfigDir string `json:"configDir,omitempty"`
912-
SkillDirectories []string `json:"skillDirectories,omitempty"`
913-
DisabledSkills []string `json:"disabledSkills,omitempty"`
914-
InfiniteSessions *InfiniteSessionConfig `json:"infiniteSessions,omitempty"`
915-
Commands []wireCommand `json:"commands,omitempty"`
916-
RequestElicitation *bool `json:"requestElicitation,omitempty"`
917-
Traceparent string `json:"traceparent,omitempty"`
918-
Tracestate string `json:"tracestate,omitempty"`
906+
Model string `json:"model,omitempty"`
907+
SessionID string `json:"sessionId,omitempty"`
908+
ClientName string `json:"clientName,omitempty"`
909+
ReasoningEffort string `json:"reasoningEffort,omitempty"`
910+
Tools []Tool `json:"tools,omitempty"`
911+
SystemMessage *SystemMessageConfig `json:"systemMessage,omitempty"`
912+
AvailableTools []string `json:"availableTools"`
913+
ExcludedTools []string `json:"excludedTools,omitempty"`
914+
Provider *ProviderConfig `json:"provider,omitempty"`
915+
ModelCapabilities *rpc.ModelCapabilitiesOverride `json:"modelCapabilities,omitempty"`
916+
RequestPermission *bool `json:"requestPermission,omitempty"`
917+
RequestUserInput *bool `json:"requestUserInput,omitempty"`
918+
Hooks *bool `json:"hooks,omitempty"`
919+
WorkingDirectory string `json:"workingDirectory,omitempty"`
920+
Streaming *bool `json:"streaming,omitempty"`
921+
MCPServers map[string]MCPServerConfig `json:"mcpServers,omitempty"`
922+
EnvValueMode string `json:"envValueMode,omitempty"`
923+
CustomAgents []CustomAgentConfig `json:"customAgents,omitempty"`
924+
Agent string `json:"agent,omitempty"`
925+
ConfigDir string `json:"configDir,omitempty"`
926+
EnableConfigDiscovery *bool `json:"enableConfigDiscovery,omitempty"`
927+
SkillDirectories []string `json:"skillDirectories,omitempty"`
928+
DisabledSkills []string `json:"disabledSkills,omitempty"`
929+
InfiniteSessions *InfiniteSessionConfig `json:"infiniteSessions,omitempty"`
930+
Commands []wireCommand `json:"commands,omitempty"`
931+
RequestElicitation *bool `json:"requestElicitation,omitempty"`
932+
Traceparent string `json:"traceparent,omitempty"`
933+
Tracestate string `json:"tracestate,omitempty"`
919934
}
920935

921936
// wireCommand is the wire representation of a command (name + description only, no handler).
@@ -933,34 +948,35 @@ type createSessionResponse struct {
933948

934949
// resumeSessionRequest is the request for session.resume
935950
type resumeSessionRequest struct {
936-
SessionID string `json:"sessionId"`
937-
ClientName string `json:"clientName,omitempty"`
938-
Model string `json:"model,omitempty"`
939-
ReasoningEffort string `json:"reasoningEffort,omitempty"`
940-
Tools []Tool `json:"tools,omitempty"`
941-
SystemMessage *SystemMessageConfig `json:"systemMessage,omitempty"`
942-
AvailableTools []string `json:"availableTools"`
943-
ExcludedTools []string `json:"excludedTools,omitempty"`
944-
Provider *ProviderConfig `json:"provider,omitempty"`
945-
ModelCapabilities *rpc.ModelCapabilitiesOverride `json:"modelCapabilities,omitempty"`
946-
RequestPermission *bool `json:"requestPermission,omitempty"`
947-
RequestUserInput *bool `json:"requestUserInput,omitempty"`
948-
Hooks *bool `json:"hooks,omitempty"`
949-
WorkingDirectory string `json:"workingDirectory,omitempty"`
950-
ConfigDir string `json:"configDir,omitempty"`
951-
DisableResume *bool `json:"disableResume,omitempty"`
952-
Streaming *bool `json:"streaming,omitempty"`
953-
MCPServers map[string]MCPServerConfig `json:"mcpServers,omitempty"`
954-
EnvValueMode string `json:"envValueMode,omitempty"`
955-
CustomAgents []CustomAgentConfig `json:"customAgents,omitempty"`
956-
Agent string `json:"agent,omitempty"`
957-
SkillDirectories []string `json:"skillDirectories,omitempty"`
958-
DisabledSkills []string `json:"disabledSkills,omitempty"`
959-
InfiniteSessions *InfiniteSessionConfig `json:"infiniteSessions,omitempty"`
960-
Commands []wireCommand `json:"commands,omitempty"`
961-
RequestElicitation *bool `json:"requestElicitation,omitempty"`
962-
Traceparent string `json:"traceparent,omitempty"`
963-
Tracestate string `json:"tracestate,omitempty"`
951+
SessionID string `json:"sessionId"`
952+
ClientName string `json:"clientName,omitempty"`
953+
Model string `json:"model,omitempty"`
954+
ReasoningEffort string `json:"reasoningEffort,omitempty"`
955+
Tools []Tool `json:"tools,omitempty"`
956+
SystemMessage *SystemMessageConfig `json:"systemMessage,omitempty"`
957+
AvailableTools []string `json:"availableTools"`
958+
ExcludedTools []string `json:"excludedTools,omitempty"`
959+
Provider *ProviderConfig `json:"provider,omitempty"`
960+
ModelCapabilities *rpc.ModelCapabilitiesOverride `json:"modelCapabilities,omitempty"`
961+
RequestPermission *bool `json:"requestPermission,omitempty"`
962+
RequestUserInput *bool `json:"requestUserInput,omitempty"`
963+
Hooks *bool `json:"hooks,omitempty"`
964+
WorkingDirectory string `json:"workingDirectory,omitempty"`
965+
ConfigDir string `json:"configDir,omitempty"`
966+
EnableConfigDiscovery *bool `json:"enableConfigDiscovery,omitempty"`
967+
DisableResume *bool `json:"disableResume,omitempty"`
968+
Streaming *bool `json:"streaming,omitempty"`
969+
MCPServers map[string]MCPServerConfig `json:"mcpServers,omitempty"`
970+
EnvValueMode string `json:"envValueMode,omitempty"`
971+
CustomAgents []CustomAgentConfig `json:"customAgents,omitempty"`
972+
Agent string `json:"agent,omitempty"`
973+
SkillDirectories []string `json:"skillDirectories,omitempty"`
974+
DisabledSkills []string `json:"disabledSkills,omitempty"`
975+
InfiniteSessions *InfiniteSessionConfig `json:"infiniteSessions,omitempty"`
976+
Commands []wireCommand `json:"commands,omitempty"`
977+
RequestElicitation *bool `json:"requestElicitation,omitempty"`
978+
Traceparent string `json:"traceparent,omitempty"`
979+
Tracestate string `json:"tracestate,omitempty"`
964980
}
965981

966982
// resumeSessionResponse is the response from session.resume

nodejs/src/client.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,7 @@ export class CopilotClient {
742742
customAgents: config.customAgents,
743743
agent: config.agent,
744744
configDir: config.configDir,
745+
enableConfigDiscovery: config.enableConfigDiscovery,
745746
skillDirectories: config.skillDirectories,
746747
disabledSkills: config.disabledSkills,
747748
infiniteSessions: config.infiniteSessions,
@@ -873,6 +874,7 @@ export class CopilotClient {
873874
hooks: !!(config.hooks && Object.values(config.hooks).some(Boolean)),
874875
workingDirectory: config.workingDirectory,
875876
configDir: config.configDir,
877+
enableConfigDiscovery: config.enableConfigDiscovery,
876878
streaming: config.streaming,
877879
mcpServers: config.mcpServers,
878880
envValueMode: "direct",

nodejs/src/types.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,19 @@ export interface SessionConfig {
10741074
*/
10751075
configDir?: string;
10761076

1077+
/**
1078+
* When true, automatically discovers MCP server configurations (e.g. `.mcp.json`,
1079+
* `.vscode/mcp.json`) and skill directories from the working directory and merges
1080+
* them with any explicitly provided `mcpServers` and `skillDirectories`, with
1081+
* explicit values taking precedence on name collision.
1082+
*
1083+
* Note: custom instruction files (`.github/copilot-instructions.md`, `AGENTS.md`, etc.)
1084+
* are always loaded from the working directory regardless of this setting.
1085+
*
1086+
* @default false
1087+
*/
1088+
enableConfigDiscovery?: boolean;
1089+
10771090
/**
10781091
* Tools exposed to the CLI server
10791092
*/
@@ -1226,6 +1239,7 @@ export type ResumeSessionConfig = Pick<
12261239
| "hooks"
12271240
| "workingDirectory"
12281241
| "configDir"
1242+
| "enableConfigDiscovery"
12291243
| "mcpServers"
12301244
| "customAgents"
12311245
| "agent"

0 commit comments

Comments
 (0)