mirror of
https://github.com/mark3labs/kit.git
synced 2026-06-13 19:20:06 +00:00
feat: add Google Vertex AI support for Claude models (#146)
Add support for using Claude models via Google Cloud Vertex AI through the `google-vertex-anthropic` provider. This enables users who have Claude access through their Google Cloud account to use mcphost with Vertex AI authentication. Changes: - Add `google-vertex-anthropic` provider case and createVertexAnthropicProvider() - Support multiple env var names for project/region to match eino-claude: - Project: ANTHROPIC_VERTEX_PROJECT_ID, GOOGLE_CLOUD_PROJECT, GCLOUD_PROJECT - Region: CLOUD_ML_REGION (defaults to "global" if not set) - Upgrade eino from v0.5.11 to v0.7.11 (required by eino-claude v0.1.12) - Migrate schema API from OpenAPI v3 to JSON Schema (eino v0.7.11 change) Usage: # Authenticate with Google Cloud gcloud auth application-default login # Set required environment variables export ANTHROPIC_VERTEX_PROJECT_ID="your-project-id" export CLOUD_ML_REGION="us-east5" # or use default "global" # Run mcphost mcphost --model google-vertex-anthropic:claude-sonnet-4@20250514 Reference: https://docs.anthropic.com/en/docs/claude-code/google-vertex-ai 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -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.44.0-beta.2
|
||||
github.com/ollama/ollama v0.11.8
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -122,6 +123,7 @@ 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
|
||||
@@ -129,6 +131,9 @@ require (
|
||||
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
|
||||
|
||||
@@ -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=
|
||||
@@ -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=
|
||||
@@ -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=
|
||||
@@ -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=
|
||||
@@ -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=
|
||||
@@ -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=
|
||||
@@ -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=
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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 == "" {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
@@ -228,7 +228,7 @@ func (m *MCPToolManager) loadServerTools(ctx context.Context, serverName string,
|
||||
// Pre-process the schema to convert numeric exclusive bounds to boolean format.
|
||||
marshaledInputSchema = convertExclusiveBoundsToBoolean(marshaledInputSchema)
|
||||
|
||||
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)
|
||||
@@ -238,7 +238,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
|
||||
@@ -258,7 +258,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,
|
||||
}
|
||||
|
||||
@@ -7,7 +7,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"
|
||||
)
|
||||
|
||||
@@ -132,7 +132,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
|
||||
}
|
||||
@@ -144,7 +144,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
|
||||
@@ -154,7 +154,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")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user