Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion mcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,21 @@ type mcpTool struct {
}

func (t *mcpTool) Tool() openai.Tool {
// A tool without arguments has no properties, and the unmarshal leaves
// the map nil. jsonschema.Definition encoded that as {}, but this
// struct would send null, which vLLM and others reject.
props := t.props
if props == nil {
props = map[string]jsonschema.Definition{}
}
return openai.Tool{
Type: openai.ToolTypeFunction,
Function: &openai.FunctionDefinition{
Name: t.name,
Description: t.description,
Parameters: mcpToolParameters{
Type: jsonschema.Object,
Properties: t.props,
Properties: props,
Required: t.inputSchema.Required,
AdditionalProperties: t.inputSchema.AdditionalProperties,
},
Expand Down
34 changes: 34 additions & 0 deletions mcp_params_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cogito

import (
"encoding/json"
"testing"
)

// An MCP tool that takes no arguments has no "properties" in its input
// schema, so the unmarshal leaves props nil. OpenAI-compatible servers
// such as vLLM validate the schema and reject "properties": null, which
// fails the whole request, not only this tool.
func TestMCPToolWithoutArgumentsSendsEmptyProperties(t *testing.T) {
tool := &mcpTool{
name: "list_things",
inputSchema: toolInputSchema{Type: "object"},
}

dat, err := json.Marshal(tool.Tool().Function.Parameters)
if err != nil {
t.Fatalf("marshal parameters: %v", err)
}

var params map[string]any
if err := json.Unmarshal(dat, &params); err != nil {
t.Fatalf("unmarshal parameters: %v", err)
}
props, ok := params["properties"].(map[string]any)
if !ok {
t.Fatalf("properties must be an object, got %s", dat)
}
if len(props) != 0 {
t.Fatalf("properties must be empty, got %s", dat)
}
}
Loading