fix(agent): match MCP server allowlists case-insensitively

This commit is contained in:
afjcjsbx
2026-05-07 18:17:37 +02:00
parent dd8e247550
commit 96fd887cad
4 changed files with 89 additions and 3 deletions
+9 -1
View File
@@ -317,8 +317,16 @@ func filterMCPConfigServers(
filtered := mcpCfg
filtered.Servers = make(map[string]config.MCPServerConfig)
normalizedAllowed := make(map[string]struct{}, len(allowed))
for serverName := range allowed {
name := normalizeMCPServerName(serverName)
if name == "" {
continue
}
normalizedAllowed[name] = struct{}{}
}
for serverName, serverCfg := range mcpCfg.Servers {
if _, ok := allowed[serverName]; ok {
if _, ok := normalizedAllowed[normalizeMCPServerName(serverName)]; ok {
filtered.Servers[serverName] = serverCfg
}
}
+32
View File
@@ -172,6 +172,38 @@ func TestToolRegistryIncludesReportsOnlyRegisteredTools(t *testing.T) {
}
}
func TestFilterMCPConfigServersCaseInsensitivePreservesOriginalKeys(t *testing.T) {
mcpCfg := config.MCPConfig{
Servers: map[string]config.MCPServerConfig{
"GitHub": {Enabled: true},
"filesystem": {Enabled: true},
"Slack": {Enabled: true},
},
}
allowed := map[string]struct{}{
"github": {},
"FILESYSTEM": {},
}
filtered := filterMCPConfigServers(mcpCfg, allowed)
if len(filtered.Servers) != 2 {
t.Fatalf("filtered.Servers = %v, want 2 entries", filtered.Servers)
}
if _, ok := filtered.Servers["GitHub"]; !ok {
t.Fatal("expected original GitHub config key to be preserved")
}
if _, ok := filtered.Servers["filesystem"]; !ok {
t.Fatal("expected filesystem config key to be preserved")
}
if _, ok := filtered.Servers["github"]; ok {
t.Fatal("did not expect normalized github key to replace original config key")
}
if _, ok := filtered.Servers["Slack"]; ok {
t.Fatal("did not expect unallowed Slack server")
}
}
func TestEnsureMCPInitialized_LoadFailureSetsInitErr(t *testing.T) {
al, cfg, _, _, cleanup := newTestAgentLoop(t)
defer cleanup()
+21 -2
View File
@@ -11,6 +11,24 @@ import (
const dynamicMCPToolPrefix = "mcp_"
func normalizeMCPServerName(name string) string {
return strings.ToLower(strings.TrimSpace(name))
}
func normalizedMCPServerNameSet(
servers map[string]config.MCPServerConfig,
) map[string]struct{} {
normalized := make(map[string]struct{}, len(servers))
for serverName := range servers {
name := normalizeMCPServerName(serverName)
if name == "" {
continue
}
normalized[name] = struct{}{}
}
return normalized
}
func warnOnUnknownAgentToolDeclarations(
agentID, workspace string,
definition AgentContextDefinition,
@@ -93,13 +111,14 @@ func unknownAgentMCPServerNames(cfg *config.Config, definition AgentContextDefin
return nil
}
knownServers := normalizedMCPServerNameSet(cfg.Tools.MCP.Servers)
unknown := make(map[string]struct{})
for _, raw := range definition.Agent.Frontmatter.MCPServers {
name := strings.ToLower(strings.TrimSpace(raw))
name := normalizeMCPServerName(raw)
if name == "" {
continue
}
if _, ok := cfg.Tools.MCP.Servers[name]; ok {
if _, ok := knownServers[name]; ok {
continue
}
unknown[name] = struct{}{}
+27
View File
@@ -93,3 +93,30 @@ mcpServers: [github, githb]
t.Fatalf("unknownAgentMCPServerNames() = %v, want [githb]", unknown)
}
}
func TestUnknownAgentMCPServerNamesMatchesConfigCaseInsensitively(t *testing.T) {
workspace := setupWorkspace(t, map[string]string{
"AGENT.md": `---
mcpServers: [github, FileSystem, slak]
---
# Agent
`,
})
defer cleanupWorkspace(t, workspace)
cfg := &config.Config{
Tools: config.ToolsConfig{
MCP: config.MCPConfig{
Servers: map[string]config.MCPServerConfig{
"GitHub": {Enabled: true},
"filesystem": {Enabled: true},
},
},
},
}
unknown := unknownAgentMCPServerNames(cfg, loadAgentDefinition(workspace))
if len(unknown) != 1 || unknown[0] != "slak" {
t.Fatalf("unknownAgentMCPServerNames() = %v, want [slak]", unknown)
}
}