Skip to content

Commit cef10c2

Browse files
committed
review feedback: auto discover mcp tools
Signed-off-by: Huamin Chen <[email protected]>
1 parent 4482eb4 commit cef10c2

File tree

4 files changed

+74
-8
lines changed

4 files changed

+74
-8
lines changed

config/config-mcp-classifier-example.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ classifier:
3030
transport_type: "http" # HTTP transport
3131
url: "http://localhost:8090/mcp" # MCP server endpoint
3232

33-
tool_name: "classify_text" # MCP tool name to call
33+
# tool_name: Optional - auto-discovers classification tool if not specified
34+
# Will search for tools like: classify_text, classify, categorize, etc.
35+
# Uncomment to explicitly specify:
36+
# tool_name: "classify_text"
37+
3438
threshold: 0.6 # Confidence threshold
3539
timeout_seconds: 30 # Request timeout
3640

examples/mcp-classifier-server/README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,21 @@ classifier:
5252
enabled: true
5353
transport_type: "http"
5454
url: "http://localhost:8090/mcp"
55-
tool_name: "classify_text"
55+
# tool_name: optional - auto-discovers classification tool if not specified
5656
threshold: 0.6
5757
timeout_seconds: 30
5858

5959
categories: [] # Loaded dynamically from MCP
6060
default_model: openai/gpt-oss-20b
6161
```
6262
63+
**Tool Auto-Discovery:**
64+
The router automatically discovers classification tools from the MCP server by:
65+
1. Listing available tools on connection
66+
2. Looking for common names: `classify_text`, `classify`, `categorize`, `categorize_text`
67+
3. Pattern matching for tools containing "classif" in name/description
68+
4. Optionally specify `tool_name` to use a specific tool
69+
6370
## How It Works
6471

6572
**Intelligent Routing Rules:**

src/semantic-router/pkg/config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ type RouterConfig struct {
3535
Args []string `yaml:"args,omitempty"`
3636
Env map[string]string `yaml:"env,omitempty"`
3737
URL string `yaml:"url,omitempty"`
38-
ToolName string `yaml:"tool_name"`
38+
ToolName string `yaml:"tool_name,omitempty"` // Optional: will auto-discover if not specified
3939
Threshold float32 `yaml:"threshold"`
4040
TimeoutSeconds int `yaml:"timeout_seconds,omitempty"`
4141
} `yaml:"mcp_category_model,omitempty"`

src/semantic-router/pkg/utils/classification/mcp_classifier.go

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,9 @@ func (m *MCPCategoryClassifier) Init(cfg *config.RouterConfig) error {
6262
if !cfg.Classifier.MCPCategoryModel.Enabled {
6363
return fmt.Errorf("MCP category classifier is not enabled")
6464
}
65-
if cfg.Classifier.MCPCategoryModel.ToolName == "" {
66-
return fmt.Errorf("MCP tool name is not specified")
67-
}
6865

69-
// Store config and tool name
66+
// Store config
7067
m.config = cfg
71-
m.toolName = cfg.Classifier.MCPCategoryModel.ToolName
7268

7369
// Create MCP client configuration
7470
mcpConfig := mcpclient.ClientConfig{
@@ -99,10 +95,69 @@ func (m *MCPCategoryClassifier) Init(cfg *config.RouterConfig) error {
9995
}
10096

10197
m.client = client
98+
99+
// Discover classification tool
100+
if err := m.discoverClassificationTool(); err != nil {
101+
client.Close()
102+
return fmt.Errorf("failed to discover classification tool: %w", err)
103+
}
104+
102105
observability.Infof("Successfully initialized MCP category classifier with tool '%s'", m.toolName)
103106
return nil
104107
}
105108

109+
// discoverClassificationTool finds the appropriate classification tool from available MCP tools
110+
func (m *MCPCategoryClassifier) discoverClassificationTool() error {
111+
// If tool name is explicitly specified, use it
112+
if m.config.Classifier.MCPCategoryModel.ToolName != "" {
113+
m.toolName = m.config.Classifier.MCPCategoryModel.ToolName
114+
observability.Infof("Using explicitly configured tool: %s", m.toolName)
115+
return nil
116+
}
117+
118+
// Otherwise, auto-discover by listing available tools
119+
tools := m.client.GetTools()
120+
if len(tools) == 0 {
121+
return fmt.Errorf("no tools available from MCP server")
122+
}
123+
124+
// Look for classification-related tools by common names
125+
classificationToolNames := []string{
126+
"classify_text",
127+
"classify",
128+
"categorize",
129+
"categorize_text",
130+
}
131+
132+
for _, toolName := range classificationToolNames {
133+
for _, tool := range tools {
134+
if tool.Name == toolName {
135+
m.toolName = tool.Name
136+
observability.Infof("Auto-discovered classification tool: %s - %s", m.toolName, tool.Description)
137+
return nil
138+
}
139+
}
140+
}
141+
142+
// If no common name found, look for tools that mention "classif" in name or description
143+
for _, tool := range tools {
144+
lowerName := strings.ToLower(tool.Name)
145+
lowerDesc := strings.ToLower(tool.Description)
146+
if strings.Contains(lowerName, "classif") || strings.Contains(lowerDesc, "classif") {
147+
m.toolName = tool.Name
148+
observability.Infof("Auto-discovered classification tool by pattern match: %s - %s", m.toolName, tool.Description)
149+
return nil
150+
}
151+
}
152+
153+
// Log available tools for debugging
154+
var toolNames []string
155+
for _, tool := range tools {
156+
toolNames = append(toolNames, tool.Name)
157+
}
158+
return fmt.Errorf("no classification tool found among available tools: %v", toolNames)
159+
}
160+
106161
// Close closes the MCP client connection
107162
func (m *MCPCategoryClassifier) Close() error {
108163
if m.client != nil {

0 commit comments

Comments
 (0)