fix: stabilize direct runtime endpoint tests

This commit is contained in:
InternZzp
2026-06-10 21:07:03 +08:00
parent 2c1be7a8fb
commit 532fcb4874
2 changed files with 27 additions and 35 deletions
+21 -28
View File
@@ -223,12 +223,9 @@ func directRuntimeToolEndpoint(toolName string) (string, bool) {
return "", false
}
dynamicMu.RLock()
te := dynamicToolEndpoints
dynamicMu.RUnlock()
if te == nil {
return "", false
}
endpoint, ok := te[toolName]
defer dynamicMu.RUnlock()
endpoint, ok := dynamicToolEndpoints[toolName]
return endpoint, ok && strings.TrimSpace(endpoint) != ""
}
@@ -252,24 +249,19 @@ func directRuntimeEndpoint(productID, toolName string) (string, bool) {
}
}
dynamicMu.RLock()
de := dynamicEndpoints
te := dynamicToolEndpoints
dynamicMu.RUnlock()
// Priority 1: product-level endpoint.
// When the caller already knows the productID (e.g. "drive"), the product
// endpoint is authoritative. This prevents cross-product tool name
// collisions (e.g. both "drive" and "doc" register "create_folder") from
// routing the request to the wrong MCP server. See issue #219.
dynamicMu.RLock()
for _, candidate := range []string{strings.TrimSpace(productID), normalized} {
if candidate == "" {
continue
}
if de != nil {
if endpoint, ok := de[candidate]; ok {
return endpoint, true
}
if endpoint, ok := dynamicEndpoints[candidate]; ok {
dynamicMu.RUnlock()
return endpoint, true
}
}
@@ -277,11 +269,13 @@ func directRuntimeEndpoint(productID, toolName string) (string, bool) {
// This path is used when the caller does not know the productID but has a
// tool name, e.g. in helper invocations or plugin routes where only the
// tool name is available.
if tool := strings.TrimSpace(toolName); tool != "" && te != nil {
if endpoint, ok := te[tool]; ok {
if tool := strings.TrimSpace(toolName); tool != "" {
if endpoint, ok := dynamicToolEndpoints[tool]; ok {
dynamicMu.RUnlock()
return endpoint, true
}
}
dynamicMu.RUnlock()
// Priority 3: built-in PAT fallback for cold-start paths that run before
// discovery/plugin registration has populated the dynamic registry.
@@ -347,12 +341,12 @@ func endpointFromEditionServers(productID string, fn func() []edition.ServerInfo
// through DINGTALK_<PRODUCT>_MCP_URL instead of requiring discovery.
func DirectRuntimeProductIDs() map[string]bool {
dynamicMu.RLock()
dp := dynamicProducts
dynamicMu.RUnlock()
ids := make(map[string]bool, len(dp)+2)
defer dynamicMu.RUnlock()
ids := make(map[string]bool, len(dynamicProducts)+2)
ids[defaultPATProductID] = true
ids[devappProductID] = true
for key := range dp {
for key := range dynamicProducts {
ids[key] = true
}
return ids
@@ -427,15 +421,14 @@ func AppendDynamicServer(server market.ServerDescriptor) {
}
func normalizeDirectRuntimeProductID(productID string) string {
dynamicMu.RLock()
da := dynamicAliases
dynamicMu.RUnlock()
trimmed := strings.TrimSpace(productID)
if da != nil {
if normalizedID, ok := da[trimmed]; ok && normalizedID != "" {
return normalizedID
}
dynamicMu.RLock()
if normalizedID, ok := dynamicAliases[trimmed]; ok && normalizedID != "" {
dynamicMu.RUnlock()
return normalizedID
}
dynamicMu.RUnlock()
if normalizedID, ok := legacyDirectRuntimeAliases[trimmed]; ok {
return normalizedID
}
+6 -7
View File
@@ -62,7 +62,7 @@ func TestDirectRuntimeEndpoint_DevappEnvOverridePreservesQuery(t *testing.T) {
assertEndpoint(t, "devapp", "list_open_dev_apps_by_condition", "https://example.test/server/devapp?key=secret")
}
func TestDirectRuntimeEndpoint_DevappDynamicServerWithoutRegistry(t *testing.T) {
func TestDirectRuntimeEndpoint_DevappDynamicServerDoesNotOverrideHardcoded(t *testing.T) {
withCleanDynamicRegistry(t)
SetDynamicServers([]market.ServerDescriptor{
{
@@ -74,10 +74,10 @@ func TestDirectRuntimeEndpoint_DevappDynamicServerWithoutRegistry(t *testing.T)
},
})
assertEndpoint(t, "devapp", "list_open_dev_apps_by_condition", "https://example.test/server/devapp-supplement")
assertEndpoint(t, "devapp", "list_open_dev_apps_by_condition", devappEndpoint)
}
func TestDirectRuntimeEndpoint_DevappEditionSupplementWithoutRegistry(t *testing.T) {
func TestDirectRuntimeEndpoint_DevappEditionSupplementDoesNotOverrideHardcoded(t *testing.T) {
withCleanDynamicRegistry(t)
prev := edition.Get()
edition.Override(&edition.Hooks{
@@ -95,11 +95,10 @@ func TestDirectRuntimeEndpoint_DevappEditionSupplementWithoutRegistry(t *testing
})
t.Cleanup(func() { edition.Override(prev) })
assertEndpoint(t, "devapp", "list_open_dev_apps_by_condition", "https://example.test/server/devapp-edition-supplement?key=secret")
assertEndpoint(t, "app", "list_open_dev_apps_by_condition", "https://example.test/server/devapp-edition-supplement?key=secret")
assertEndpoint(t, "devapp", "list_open_dev_apps_by_condition", devappEndpoint)
}
func TestDirectRuntimeEndpoint_DevappEditionStaticWithoutRegistry(t *testing.T) {
func TestDirectRuntimeEndpoint_DevappEditionStaticDoesNotOverrideHardcoded(t *testing.T) {
withCleanDynamicRegistry(t)
prev := edition.Get()
edition.Override(&edition.Hooks{
@@ -117,7 +116,7 @@ func TestDirectRuntimeEndpoint_DevappEditionStaticWithoutRegistry(t *testing.T)
})
t.Cleanup(func() { edition.Override(prev) })
assertEndpoint(t, "devapp", "list_open_dev_apps_by_condition", "https://example.test/server/devapp-edition-static")
assertEndpoint(t, "devapp", "list_open_dev_apps_by_condition", devappEndpoint)
}
func TestDirectRuntimeEndpoint_DevappEnvOverrideWinsOverEditionSupplement(t *testing.T) {