Skip to content
Open
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
13 changes: 9 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ require (
github.com/bytedance/sonic v1.14.1
github.com/charmbracelet/fang v0.4.0
github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834
github.com/cloudwego/eino v0.5.11
github.com/cloudwego/eino-ext/components/model/claude v0.1.0
github.com/cloudwego/eino v0.7.11
github.com/cloudwego/eino-ext/components/model/claude v0.1.12
github.com/cloudwego/eino-ext/components/model/ollama v0.1.2
github.com/cloudwego/eino-ext/components/model/openai v0.0.0-20250903035842-96774a3ec845
github.com/getkin/kin-openapi v0.120.0
github.com/eino-contrib/jsonschema v1.0.3
github.com/mark3labs/mcp-filesystem-server v0.11.1
github.com/mark3labs/mcp-go v0.43.0
github.com/ollama/ollama v0.11.8
Expand All @@ -29,6 +29,7 @@ require (
require (
cloud.google.com/go v0.121.6 // indirect
cloud.google.com/go/auth v0.16.5 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.8.0 // indirect
github.com/alecthomas/chroma/v2 v2.20.0 // indirect
github.com/andybalholm/cascadia v1.3.3 // indirect
Expand Down Expand Up @@ -65,11 +66,11 @@ require (
github.com/djherbis/times v1.6.0 // indirect
github.com/dlclark/regexp2 v1.11.5 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/eino-contrib/jsonschema v1.0.2 // indirect
github.com/evanphx/json-patch v0.5.2 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.10 // indirect
github.com/getkin/kin-openapi v0.120.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.22.0 // indirect
Expand Down Expand Up @@ -122,13 +123,17 @@ require (
github.com/yuin/goldmark v1.7.13 // indirect
github.com/yuin/goldmark-emoji v1.0.6 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect
go.opentelemetry.io/otel v1.38.0 // indirect
go.opentelemetry.io/otel/metric v1.38.0 // indirect
go.opentelemetry.io/otel/trace v1.38.0 // indirect
golang.org/x/arch v0.20.0 // indirect
golang.org/x/crypto v0.41.0 // indirect
golang.org/x/net v0.43.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/time v0.12.0 // indirect
google.golang.org/api v0.246.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 // indirect
google.golang.org/grpc v1.75.0 // indirect
google.golang.org/protobuf v1.36.8 // indirect
Expand Down
22 changes: 16 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ cloud.google.com/go v0.121.6 h1:waZiuajrI28iAf40cWgycWNgaXPO06dupuS+sgibK6c=
cloud.google.com/go v0.121.6/go.mod h1:coChdst4Ea5vUpiALcYKXEpR1S9ZgXbhEzzMcMR66vI=
cloud.google.com/go/auth v0.16.5 h1:mFWNQ2FEVWAliEQWpAdH80omXFokmrnbDhUS9cBywsI=
cloud.google.com/go/auth v0.16.5/go.mod h1:utzRfHMP+Vv0mpOkTRQoWD2q3BatTOoWbA7gCc2dUhQ=
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA=
cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw=
github.com/JohannesKaufmann/html-to-markdown v1.6.0 h1:04VXMiE50YYfCfLboJCLcgqF5x+rHJnb1ssNmqpLH/k=
Expand Down Expand Up @@ -108,10 +110,10 @@ github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQ
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
github.com/cloudwego/eino v0.5.11 h1:R/BPZJPiMrGm1kA4ql2T0P8SlqLC16Pbxev+v6a6AGY=
github.com/cloudwego/eino v0.5.11/go.mod h1:N6E+toMzWw/3ql0IVM5n5lbYFCeblCYx7ebH16kt1JQ=
github.com/cloudwego/eino-ext/components/model/claude v0.1.0 h1:UZVwYzV7gOBCBKHGdAT2fZzm/+2TBEfDDYn713EvLF0=
github.com/cloudwego/eino-ext/components/model/claude v0.1.0/go.mod h1:lacy0WE3yKuOSxrhJQKqWAxn3LiUy/CJ91jU7nLDNNQ=
github.com/cloudwego/eino v0.7.11 h1:QQ3Ik4/nW1462CuvFsmH3gWAqNI/70BXRDmsYyvXyds=
github.com/cloudwego/eino v0.7.11/go.mod h1:nA8Vacmuqv3pqKBQbTWENBLQ8MmGmPt/WqiyLeB8ohQ=
github.com/cloudwego/eino-ext/components/model/claude v0.1.12 h1:c66gFH9J5Ku2/v1f7jPwI9R4CYw5TiAlIVzsfzjsF1g=
github.com/cloudwego/eino-ext/components/model/claude v0.1.12/go.mod h1:a9oQkf4Ib+/VqjsLRdRETytt2m/C4fbcvfjPNu6nVAg=
github.com/cloudwego/eino-ext/components/model/ollama v0.1.2 h1:WxJ+7oXnr3AhM6u4VbFF3L2ionxCrPfmLetx7V+zthw=
github.com/cloudwego/eino-ext/components/model/ollama v0.1.2/go.mod h1:OgGMCiR/G/RnOWaJvdK8pVSxAzoz2SlCqim43oFTuwo=
github.com/cloudwego/eino-ext/components/model/openai v0.0.0-20250903035842-96774a3ec845 h1:nxflfiBwWNPoKS9X4SMhmT+si7rtYv+lQzIyPJik4DM=
Expand All @@ -128,8 +130,8 @@ github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZ
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/eino-contrib/jsonschema v1.0.2 h1:HaxruBMUdnXa7Lg/lX8g0Hk71ZIfdTZXmBQz0e3esr8=
github.com/eino-contrib/jsonschema v1.0.2/go.mod h1:cpnX4SyKjWjGC7iN2EbhxaTdLqGjCi0e9DxpLYxddD4=
github.com/eino-contrib/jsonschema v1.0.3 h1:2Kfsm1xlMV0ssY2nuxshS4AwbLFuqmPmzIjLVJ1Fsp0=
github.com/eino-contrib/jsonschema v1.0.3/go.mod h1:cpnX4SyKjWjGC7iN2EbhxaTdLqGjCi0e9DxpLYxddD4=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/evanphx/json-patch v0.5.2 h1:xVCHIVMUu1wtM/VkR9jVZ45N3FhZfYMMYGorLCR8P3k=
Expand Down Expand Up @@ -361,6 +363,8 @@ github.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9
github.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg=
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
Expand Down Expand Up @@ -408,6 +412,8 @@ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand Down Expand Up @@ -463,6 +469,8 @@ golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
Expand All @@ -472,6 +480,8 @@ golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxb
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/api v0.246.0 h1:H0ODDs5PnMZVZAEtdLMn2Ul2eQi7QNjqM2DIFp8TlTM=
google.golang.org/api v0.246.0/go.mod h1:dMVhVcylamkirHdzEBAIQWUCgqY885ivNeZYd7VAVr8=
google.golang.org/genai v1.22.0 h1:5hrEhXXWJQZa3tdPocl4vQ/0w6myEAxdNns2Kmx0f4Y=
google.golang.org/genai v1.22.0/go.mod h1:QPj5NGJw+3wEOHg+PrsWwJKvG6UC84ex5FR7qAYsN/M=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 h1:pmJpJEvT846VzausCQ5d7KreSROcDqmO388w5YbnltA=
Expand Down
28 changes: 13 additions & 15 deletions internal/models/gemini/gemini.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/cloudwego/eino/components"
"github.com/cloudwego/eino/components/model"
"github.com/cloudwego/eino/schema"
"github.com/eino-contrib/jsonschema"
"github.com/getkin/kin-openapi/openapi3"
"google.golang.org/genai"
)
Expand Down Expand Up @@ -83,7 +84,7 @@ type Config struct {

// ResponseSchema defines the structure for JSON responses
// Optional. Used when you want structured output in JSON format
ResponseSchema *openapi3.Schema
ResponseSchema *jsonschema.Schema

// EnableCodeExecution allows the model to execute code
// Warning: Be cautious with code execution in production
Expand All @@ -103,7 +104,7 @@ type options struct {
// TopK limits the number of tokens to sample from
TopK *int32
// ResponseSchema defines the expected JSON structure for responses
ResponseSchema *openapi3.Schema
ResponseSchema *jsonschema.Schema
}

// ChatModel implements the Gemini chat model for the eino framework.
Expand All @@ -124,7 +125,7 @@ type ChatModel struct {
// topK limits token sampling
topK *int32
// responseSchema for structured JSON output
responseSchema *openapi3.Schema
responseSchema *jsonschema.Schema
// tools converted to Gemini format
tools []*genai.Tool
// origTools stores the original tool definitions
Expand Down Expand Up @@ -448,7 +449,7 @@ func (cm *ChatModel) buildGenerateConfig(opts ...model.Option) (*genai.GenerateC

// Set response schema for JSON mode
if geminiOptions.ResponseSchema != nil {
gSchema, err := cm.convertOpenAPISchema(geminiOptions.ResponseSchema)
gSchema, err := cm.convertJSONSchema(geminiOptions.ResponseSchema)
if err != nil {
return nil, nil, fmt.Errorf("convert response schema failed: %w", err)
}
Expand All @@ -466,12 +467,12 @@ func (cm *ChatModel) convertToGeminiTools(tools []*schema.ToolInfo) ([]*genai.To

var functionDeclarations []*genai.FunctionDeclaration
for _, tool := range tools {
openSchema, err := tool.ToOpenAPIV3()
openSchema, err := tool.ToJSONSchema()
if err != nil {
return nil, fmt.Errorf("get open schema failed: %w", err)
}

gSchema, err := cm.convertOpenAPISchema(openSchema)
gSchema, err := cm.convertJSONSchema(openSchema)
if err != nil {
return nil, fmt.Errorf("convert open schema failed: %w", err)
}
Expand All @@ -487,7 +488,7 @@ func (cm *ChatModel) convertToGeminiTools(tools []*schema.ToolInfo) ([]*genai.To
return []*genai.Tool{{FunctionDeclarations: functionDeclarations}}, nil
}

func (cm *ChatModel) convertOpenAPISchema(schema *openapi3.Schema) (*genai.Schema, error) {
func (cm *ChatModel) convertJSONSchema(schema *jsonschema.Schema) (*genai.Schema, error) {
if schema == nil {
return nil, nil
}
Expand All @@ -501,15 +502,12 @@ func (cm *ChatModel) convertOpenAPISchema(schema *openapi3.Schema) (*genai.Schem
result.Type = genai.TypeObject
if schema.Properties != nil {
properties := make(map[string]*genai.Schema)
for name, prop := range schema.Properties {
if prop == nil || prop.Value == nil {
continue
}
propSchema, err := cm.convertOpenAPISchema(prop.Value)
for pair := schema.Properties.Oldest(); pair != nil; pair = pair.Next() {
propSchema, err := cm.convertJSONSchema(pair.Value)
if err != nil {
return nil, err
}
properties[name] = propSchema
properties[pair.Key] = propSchema
}
result.Properties = properties
}
Expand All @@ -518,8 +516,8 @@ func (cm *ChatModel) convertOpenAPISchema(schema *openapi3.Schema) (*genai.Schem
}
case openapi3.TypeArray:
result.Type = genai.TypeArray
if schema.Items != nil && schema.Items.Value != nil {
itemSchema, err := cm.convertOpenAPISchema(schema.Items.Value)
if schema.Items != nil {
itemSchema, err := cm.convertJSONSchema(schema.Items)
if err != nil {
return nil, err
}
Expand Down
67 changes: 67 additions & 0 deletions internal/models/providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,12 @@ func CreateProvider(ctx context.Context, config *ProviderConfig) (*ProviderResul
return nil, err
}
return &ProviderResult{Model: model, Message: ""}, nil
case "google-vertex-anthropic":
model, err := createVertexAnthropicProvider(ctx, config, modelName)
if err != nil {
return nil, err
}
return &ProviderResult{Model: model, Message: ""}, nil
default:
return nil, fmt.Errorf("unsupported provider: %s", provider)
}
Expand Down Expand Up @@ -350,6 +356,67 @@ func createAnthropicProvider(ctx context.Context, config *ProviderConfig, modelN
return anthropic.NewCustomChatModel(ctx, claudeConfig)
}

func createVertexAnthropicProvider(ctx context.Context, config *ProviderConfig, modelName string) (model.ToolCallingChatModel, error) {
projectID := os.Getenv("GOOGLE_VERTEX_PROJECT")
if projectID == "" {
projectID = os.Getenv("ANTHROPIC_VERTEX_PROJECT_ID")
}
if projectID == "" {
projectID = os.Getenv("GOOGLE_CLOUD_PROJECT")
}
if projectID == "" {
projectID = os.Getenv("GCLOUD_PROJECT")
}
if projectID == "" {
projectID = os.Getenv("CLOUDSDK_CORE_PROJECT")
}
if projectID == "" {
return nil, fmt.Errorf("Google Vertex project ID not provided. Set ANTHROPIC_VERTEX_PROJECT_ID, GOOGLE_CLOUD_PROJECT, or GCLOUD_PROJECT environment variable")
}

region := os.Getenv("GOOGLE_VERTEX_LOCATION")
if region == "" {
region = os.Getenv("ANTHROPIC_VERTEX_REGION")
}
if region == "" {
region = os.Getenv("CLOUD_ML_REGION")
}
if region == "" {
region = "global"
}

maxTokens := config.MaxTokens
if maxTokens == 0 {
maxTokens = 4096 // Default value
}

claudeConfig := &einoclaude.Config{
ByVertex: true,
VertexProjectID: projectID,
VertexRegion: region,
Model: modelName,
MaxTokens: maxTokens,
}

if config.Temperature != nil {
claudeConfig.Temperature = config.Temperature
}

if config.TopP != nil {
claudeConfig.TopP = config.TopP
}

if config.TopK != nil {
claudeConfig.TopK = config.TopK
}

if len(config.StopSequences) > 0 {
claudeConfig.StopSequences = config.StopSequences
}

return anthropic.NewCustomChatModel(ctx, claudeConfig)
}

func createOpenAIProvider(ctx context.Context, config *ProviderConfig, modelName string) (model.ToolCallingChatModel, error) {
apiKey := config.ProviderAPIKey
if apiKey == "" {
Expand Down
13 changes: 13 additions & 0 deletions internal/models/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,19 @@ func (r *ModelsRegistry) ValidateEnvironment(provider string, apiKey string) err
return nil
}

// Add alternative environment variable names for google-vertex-anthropic
// These match the env vars checked by eino-claude and other tools
if provider == "google-vertex-anthropic" {
envVars = append(envVars,
"ANTHROPIC_VERTEX_PROJECT_ID",
"GOOGLE_CLOUD_PROJECT",
"GCLOUD_PROJECT",
"CLOUDSDK_CORE_PROJECT",
"ANTHROPIC_VERTEX_REGION",
"CLOUD_ML_REGION",
)
}

// Check if at least one environment variable is set
var foundVar bool
for _, envVar := range envVars {
Expand Down
8 changes: 4 additions & 4 deletions internal/tools/mcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/cloudwego/eino/components/model"
"github.com/cloudwego/eino/components/tool"
"github.com/cloudwego/eino/schema"
"github.com/getkin/kin-openapi/openapi3"
"github.com/eino-contrib/jsonschema"
"github.com/mark3labs/mcp-go/client"
"github.com/mark3labs/mcp-go/client/transport"
"github.com/mark3labs/mcp-go/mcp"
Expand Down Expand Up @@ -221,7 +221,7 @@ func (m *MCPToolManager) loadServerTools(ctx context.Context, serverName string,
if err != nil {
return fmt.Errorf("conv mcp tool input schema fail(marshal): %w, tool name: %s", err, mcpTool.Name)
}
inputSchema := &openapi3.Schema{}
inputSchema := &jsonschema.Schema{}
err = sonic.Unmarshal(marshaledInputSchema, inputSchema)
if err != nil {
return fmt.Errorf("conv mcp tool input schema fail(unmarshal): %w, tool name: %s", err, mcpTool.Name)
Expand All @@ -231,7 +231,7 @@ func (m *MCPToolManager) loadServerTools(ctx context.Context, serverName string,
// OpenAI function calling requires object schemas to have a "properties" field
// even if it's empty, otherwise it throws "object schema missing properties" error
if inputSchema.Type == "object" && inputSchema.Properties == nil {
inputSchema.Properties = make(openapi3.Schemas)
inputSchema.Properties = jsonschema.NewProperties()
}

// Create prefixed tool name
Expand All @@ -251,7 +251,7 @@ func (m *MCPToolManager) loadServerTools(ctx context.Context, serverName string,
info: &schema.ToolInfo{
Name: prefixedName,
Desc: mcpTool.Description,
ParamsOneOf: schema.NewParamsOneOfByOpenAPIV3(inputSchema),
ParamsOneOf: schema.NewParamsOneOfByJSONSchema(inputSchema),
},
mapping: mapping,
}
Expand Down
8 changes: 4 additions & 4 deletions internal/tools/mcp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"time"

"github.com/cloudwego/eino/schema"
"github.com/getkin/kin-openapi/openapi3"
"github.com/eino-contrib/jsonschema"
"github.com/mark3labs/mcphost/internal/config"
)

Expand Down Expand Up @@ -131,7 +131,7 @@ func TestMCPToolManager_ToolWithoutProperties(t *testing.T) {
func TestIssue89_ObjectSchemaMissingProperties(t *testing.T) {
// Create a schema that would cause the OpenAI validation error
// This simulates what might happen with tools that have no input properties
brokenSchema := &openapi3.Schema{
brokenSchema := &jsonschema.Schema{
Type: "object",
// Properties is nil - this causes "object schema missing properties" error in OpenAI
}
Expand All @@ -143,7 +143,7 @@ func TestIssue89_ObjectSchemaMissingProperties(t *testing.T) {

// Apply the fix from issue #89
if brokenSchema.Type == "object" && brokenSchema.Properties == nil {
brokenSchema.Properties = make(openapi3.Schemas)
brokenSchema.Properties = jsonschema.NewProperties()
}

// Verify the fix worked
Expand All @@ -153,7 +153,7 @@ func TestIssue89_ObjectSchemaMissingProperties(t *testing.T) {

// Test that we can create a ParamsOneOf from the fixed schema
// This is what would fail before the fix
paramsOneOf := schema.NewParamsOneOfByOpenAPIV3(brokenSchema)
paramsOneOf := schema.NewParamsOneOfByJSONSchema(brokenSchema)
if paramsOneOf == nil {
t.Error("Failed to create ParamsOneOf from fixed schema - OpenAI function calling would fail")
}
Expand Down