Skip to content

Commit 4a29eb5

Browse files
authored
Merge pull request #64 from k255/feature/proxy-optional-params
Support optional parameters in proxy mode
2 parents ca0de7e + e119a5f commit 4a29eb5

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,9 @@ mcp proxy tool add_operation "Adds a and b" "a:int,b:int" ./examples/add.sh
556556
# Register an inline command as an MCP tool
557557
mcp proxy tool add_operation "Adds a and b" "a:int,b:int" -e 'echo "total is $a + $b = $(($a+$b))"'
558558

559+
# Register an inline command as an MCP tool with optional parameter
560+
mcpt proxy tool add_operation "Adds a and b with optional result msg" "a:int,b:int,[msg:string]" -e 'echo "$msg$a + $b = $(($a+$b))"'
561+
559562
# Unregister a tool
560563
mcp proxy tool --unregister add_operation
561564

pkg/proxy/proxy.go

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ import (
1616

1717
// Parameter represents a tool parameter with a name and type.
1818
type Parameter struct {
19-
Name string
20-
Type string
19+
Name string
20+
Type string
21+
Required bool
2122
}
2223

2324
// Tool represents a proxy tool that executes a shell script or command.
@@ -157,6 +158,7 @@ func (s *Server) AddTool(name, description, paramStr, scriptPath string, command
157158
}
158159

159160
// parseParameters parses a comma-separated parameter string in the format "name:type,name:type".
161+
// If a parameter is wrapped in square brackets like [name:type], it's considered optional.
160162
func parseParameters(paramStr string) ([]Parameter, error) {
161163
if paramStr == "" {
162164
return []Parameter{}, nil
@@ -166,6 +168,17 @@ func parseParameters(paramStr string) ([]Parameter, error) {
166168
parameters := make([]Parameter, 0, len(params))
167169

168170
for _, param := range params {
171+
param = strings.TrimSpace(param)
172+
required := true
173+
174+
// Check if parameter is optional (wrapped in square brackets)
175+
if strings.HasPrefix(param, "[") && strings.HasSuffix(param, "]") {
176+
// Remove the brackets
177+
param = strings.TrimPrefix(param, "[")
178+
param = strings.TrimSuffix(param, "]")
179+
required = false
180+
}
181+
169182
parts := strings.Split(strings.TrimSpace(param), ":")
170183
if len(parts) != 2 {
171184
return nil, fmt.Errorf("invalid parameter format: %s, expected name:type", param)
@@ -189,8 +202,9 @@ func parseParameters(paramStr string) ([]Parameter, error) {
189202
}
190203

191204
parameters = append(parameters, Parameter{
192-
Name: name,
193-
Type: normalizedType,
205+
Name: name,
206+
Type: normalizedType,
207+
Required: required,
194208
})
195209
}
196210

@@ -286,7 +300,11 @@ func (s *Server) GetToolSchema(toolName string) (map[string]interface{}, error)
286300
}
287301

288302
properties[param.Name] = paramSchema
289-
required = append(required, param.Name)
303+
304+
// Only add the parameter to required list if it's marked as required
305+
if param.Required {
306+
required = append(required, param.Name)
307+
}
290308
}
291309

292310
schema := map[string]interface{}{
@@ -435,7 +453,11 @@ func (s *Server) handleToolsList() map[string]interface{} {
435453
}
436454

437455
properties[param.Name] = paramSchema
438-
required = append(required, param.Name)
456+
457+
// Only add to required list if the parameter is required
458+
if param.Required {
459+
required = append(required, param.Name)
460+
}
439461
}
440462

441463
schema := map[string]interface{}{
@@ -471,7 +493,7 @@ func (s *Server) handleToolCall(params map[string]interface{}) (map[string]inter
471493
return nil, fmt.Errorf("'name' parameter must be a string")
472494
}
473495

474-
_, exists := s.tools[name]
496+
tool, exists := s.tools[name]
475497
if !exists {
476498
return nil, fmt.Errorf("tool not found: %s", name)
477499
}
@@ -487,6 +509,15 @@ func (s *Server) handleToolCall(params map[string]interface{}) (map[string]inter
487509
return nil, fmt.Errorf("'arguments' parameter must be an object")
488510
}
489511

512+
// Check for required parameters
513+
for _, param := range tool.Parameters {
514+
if param.Required {
515+
if _, exists := arguments[param.Name]; !exists {
516+
return nil, fmt.Errorf("missing required parameter: %s", param.Name)
517+
}
518+
}
519+
}
520+
490521
// Log the input parameters
491522
s.logJSON("Tool input", arguments)
492523

@@ -605,7 +636,11 @@ func RunProxyServer(toolConfigs map[string]map[string]string) error {
605636
if i > 0 {
606637
paramStr += ", "
607638
}
608-
paramStr += param.Name + ":" + param.Type
639+
if param.Required {
640+
paramStr += param.Name + ":" + param.Type
641+
} else {
642+
paramStr += "[" + param.Name + ":" + param.Type + "]"
643+
}
609644
}
610645
if paramStr != "" {
611646
fmt.Fprintf(os.Stderr, " Parameters: %s\n", paramStr)

0 commit comments

Comments
 (0)