fix(agent): match MCP server allowlists case-insensitively
This commit is contained in:
parent
dd8e247550
commit
96fd887cad
4 changed files with 89 additions and 3 deletions
|
|
@ -317,8 +317,16 @@ func filterMCPConfigServers(
|
||||||
|
|
||||||
filtered := mcpCfg
|
filtered := mcpCfg
|
||||||
filtered.Servers = make(map[string]config.MCPServerConfig)
|
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 {
|
for serverName, serverCfg := range mcpCfg.Servers {
|
||||||
if _, ok := allowed[serverName]; ok {
|
if _, ok := normalizedAllowed[normalizeMCPServerName(serverName)]; ok {
|
||||||
filtered.Servers[serverName] = serverCfg
|
filtered.Servers[serverName] = serverCfg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
func TestEnsureMCPInitialized_LoadFailureSetsInitErr(t *testing.T) {
|
||||||
al, cfg, _, _, cleanup := newTestAgentLoop(t)
|
al, cfg, _, _, cleanup := newTestAgentLoop(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,24 @@ import (
|
||||||
|
|
||||||
const dynamicMCPToolPrefix = "mcp_"
|
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(
|
func warnOnUnknownAgentToolDeclarations(
|
||||||
agentID, workspace string,
|
agentID, workspace string,
|
||||||
definition AgentContextDefinition,
|
definition AgentContextDefinition,
|
||||||
|
|
@ -93,13 +111,14 @@ func unknownAgentMCPServerNames(cfg *config.Config, definition AgentContextDefin
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
knownServers := normalizedMCPServerNameSet(cfg.Tools.MCP.Servers)
|
||||||
unknown := make(map[string]struct{})
|
unknown := make(map[string]struct{})
|
||||||
for _, raw := range definition.Agent.Frontmatter.MCPServers {
|
for _, raw := range definition.Agent.Frontmatter.MCPServers {
|
||||||
name := strings.ToLower(strings.TrimSpace(raw))
|
name := normalizeMCPServerName(raw)
|
||||||
if name == "" {
|
if name == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, ok := cfg.Tools.MCP.Servers[name]; ok {
|
if _, ok := knownServers[name]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
unknown[name] = struct{}{}
|
unknown[name] = struct{}{}
|
||||||
|
|
|
||||||
|
|
@ -93,3 +93,30 @@ mcpServers: [github, githb]
|
||||||
t.Fatalf("unknownAgentMCPServerNames() = %v, want [githb]", unknown)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue