From 88a8c7bf15cbc030320bac06f35a54b4c36c2208 Mon Sep 17 00:00:00 2001 From: GargantuaX Date: Fri, 27 Dec 2024 19:10:29 +0800 Subject: [PATCH 1/3] support anthropicBaseURL , openaiAPIKey, anthropicAPIKey cli params (#6) * * support anthropicBaseURL , openaiAPIKey, anthropicAPIKey cli params * * support anthropicBaseURL , openaiAPIKey, anthropicAPIKey cli params * opt * remove the non-English comments * add new Flags to document --- .gitignore | 5 +++++ README.md | 6 +++++- cmd/root.go | 39 ++++++++++++++++++++++++----------- pkg/llm/anthropic/client.go | 20 ++++++++++++------ pkg/llm/anthropic/provider.go | 9 +++++--- pkg/llm/openai/client.go | 3 +++ 6 files changed, 60 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index 94d0e6b5..79bed4da 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,8 @@ aidocs/ .mcp.json *.log +mcphost +.idea +test/ +build/ +scripts/ \ No newline at end of file diff --git a/README.md b/README.md index 189b2102..885cdcae 100644 --- a/README.md +++ b/README.md @@ -112,11 +112,15 @@ mcphost -m openai:gpt-4 ``` ### Flags +- `--anthropic-url string`: Base URL for Anthropic API (defaults to api.anthropic.com) +- `--anthropic-api-key string`: Anthropic API key (can also be set via ANTHROPIC_API_KEY environment variable) - `--config string`: Config file location (default is $HOME/mcp.json) - `--debug`: Enable debug logging - `--message-window int`: Number of messages to keep in context (default: 10) - `-m, --model string`: Model to use (format: provider:model) (default "anthropic:claude-3-5-sonnet-latest") - `--openai-url string`: Base URL for OpenAI API (defaults to api.openai.com) +- `--openai-api-key string`: OpenAI API key (can also be set via OPENAI_API_KEY environment variable) + ### Interactive Commands @@ -154,4 +158,4 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file - Thanks to the Anthropic team for Claude and the MCP specification - Thanks to the Ollama team for their local LLM runtime -- Thanks to all contributors who have helped improve this tool +- Thanks to all contributors who have helped improve this tool \ No newline at end of file diff --git a/cmd/root.go b/cmd/root.go index acdfb470..9baa5f1b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -26,11 +26,14 @@ import ( ) var ( - renderer *glamour.TermRenderer - configFile string - messageWindow int - modelFlag string // New flag for model selection - openaiBaseURL string // Base URL for OpenAI API + renderer *glamour.TermRenderer + configFile string + messageWindow int + modelFlag string // New flag for model selection + openaiBaseURL string // Base URL for OpenAI API + anthropicBaseURL string // Base URL for Anthropic API + openaiAPIKey string + anthropicAPIKey string ) const ( @@ -79,8 +82,12 @@ func init() { // Add debug flag rootCmd.PersistentFlags(). BoolVar(&debugMode, "debug", false, "enable debug logging") - rootCmd.PersistentFlags(). - StringVar(&openaiBaseURL, "openai-url", "", "base URL for OpenAI API (defaults to api.openai.com)") + + flags := rootCmd.PersistentFlags() + flags.StringVar(&openaiBaseURL, "openai-url", "", "base URL for OpenAI API (defaults to api.openai.com)") + flags.StringVar(&anthropicBaseURL, "anthropic-url", "", "base URL for Anthropic API (defaults to api.anthropic.com)") + flags.StringVar(&openaiAPIKey, "openai-api-key", "", "OpenAI API key") + flags.StringVar(&anthropicAPIKey, "anthropic-api-key", "", "Anthropic API key") } // Add new function to create provider @@ -98,22 +105,30 @@ func createProvider(modelString string) (llm.Provider, error) { switch provider { case "anthropic": - apiKey := os.Getenv("ANTHROPIC_API_KEY") + apiKey := anthropicAPIKey + if apiKey == "" { + apiKey = os.Getenv("ANTHROPIC_API_KEY") + } + if apiKey == "" { return nil, fmt.Errorf( - "ANTHROPIC_API_KEY environment variable not set", + "Anthropic API key not provided. Use --anthropic-api-key flag or ANTHROPIC_API_KEY environment variable", ) } - return anthropic.NewProvider(apiKey), nil + return anthropic.NewProvider(apiKey, anthropicBaseURL, model), nil case "ollama": return ollama.NewProvider(model) case "openai": - apiKey := os.Getenv("OPENAI_API_KEY") + apiKey := openaiAPIKey + if apiKey == "" { + apiKey = os.Getenv("OPENAI_API_KEY") + } + if apiKey == "" { return nil, fmt.Errorf( - "OPENAI_API_KEY environment variable not set", + "OpenAI API key not provided. Use --openai-api-key flag or OPENAI_API_KEY environment variable", ) } return openai.NewProvider(apiKey, openaiBaseURL, model), nil diff --git a/pkg/llm/anthropic/client.go b/pkg/llm/anthropic/client.go index 6e35200e..f9c260d3 100644 --- a/pkg/llm/anthropic/client.go +++ b/pkg/llm/anthropic/client.go @@ -6,17 +6,25 @@ import ( "encoding/json" "fmt" "net/http" + "strings" ) type Client struct { - apiKey string - client *http.Client + apiKey string + client *http.Client + baseURL string } -func NewClient(apiKey string) *Client { +func NewClient(apiKey string, baseURL string) *Client { + if baseURL == "" { + baseURL = "https://api.anthropic.com/v1" + } else if !strings.HasSuffix(baseURL, "/v1") { + baseURL = strings.TrimSuffix(baseURL, "/") + "/v1" + } return &Client{ - apiKey: apiKey, - client: &http.Client{}, + apiKey: apiKey, + baseURL: baseURL, + client: &http.Client{}, } } @@ -26,7 +34,7 @@ func (c *Client) CreateMessage(ctx context.Context, req CreateRequest) (*APIMess return nil, fmt.Errorf("error marshaling request: %w", err) } - httpReq, err := http.NewRequestWithContext(ctx, "POST", "https://api.anthropic.com/v1/messages", bytes.NewReader(body)) + httpReq, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/messages", c.baseURL), bytes.NewReader(body)) if err != nil { return nil, fmt.Errorf("error creating request: %w", err) } diff --git a/pkg/llm/anthropic/provider.go b/pkg/llm/anthropic/provider.go index 98976357..75b395eb 100644 --- a/pkg/llm/anthropic/provider.go +++ b/pkg/llm/anthropic/provider.go @@ -16,10 +16,13 @@ type Provider struct { model string } -func NewProvider(apiKey string) *Provider { +func NewProvider(apiKey string, baseURL string, model string) *Provider { + if model == "" { + model = "claude-3-5-sonnet-20240620" // 默认模型 + } return &Provider{ - client: NewClient(apiKey), - model: "claude-3-5-sonnet-20240620", + client: NewClient(apiKey, baseURL), + model: model, } } diff --git a/pkg/llm/openai/client.go b/pkg/llm/openai/client.go index 88c2d0de..f6790c36 100644 --- a/pkg/llm/openai/client.go +++ b/pkg/llm/openai/client.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "net/http" + "strings" ) type Client struct { @@ -17,6 +18,8 @@ type Client struct { func NewClient(apiKey string, baseURL string) *Client { if baseURL == "" { baseURL = "https://api.openai.com/v1" + } else if !strings.HasSuffix(baseURL, "/v1") { + baseURL = strings.TrimSuffix(baseURL, "/") + "/v1" } return &Client{ apiKey: apiKey, From c4ed189f48b48d1fe59cef882bebc40170b807c8 Mon Sep 17 00:00:00 2001 From: Ed Zynda Date: Fri, 3 Jan 2025 07:08:49 +0300 Subject: [PATCH 2/3] Setup goreleaser --- .github/workflows/release.yml | 33 +++++++++++++++++++++++++ .gitignore | 3 ++- .goreleaser.yaml | 45 +++++++++++++++++++++++++++++++++++ main.go | 2 ++ 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release.yml create mode 100644 .goreleaser.yaml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..b14847fc --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,33 @@ +name: Release + +on: + push: + tags: + - "v*" + +permissions: + contents: write + +jobs: + goreleaser: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: ">=1.21.0" + cache: true + + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v5 + with: + distribution: goreleaser + version: latest + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 79bed4da..3fa4cdb6 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ mcphost .idea test/ build/ -scripts/ \ No newline at end of file +scripts/ +dist/ diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 00000000..c56db21f --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,45 @@ +before: + hooks: + - go mod tidy + +builds: + - env: + - CGO_ENABLED=0 + goos: + - linux + - windows + - darwin + goarch: + - amd64 + - arm64 + ignore: + - goos: windows + goarch: arm64 + binary: mcphost + ldflags: + - -s -w -X main.version={{.Version}} + +archives: + - format: tar.gz + name_template: >- + {{ .ProjectName }}_ + {{- title .Os }}_ + {{- if eq .Arch "amd64" }}x86_64 + {{- else }}{{ .Arch }}{{ end }} + {{- if .Arm }}v{{ .Arm }}{{ end }} + format_overrides: + - goos: windows + format: zip + +checksum: + name_template: "checksums.txt" + +changelog: + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" + - "^ci:" + - Merge pull request + - Merge branch diff --git a/main.go b/main.go index ba868ad3..e6aec7c2 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,8 @@ package main import "github.com/mark3labs/mcphost/cmd" +var version = "dev" + func main() { cmd.Execute() } From 9681971ee9f2f54b38c0c8934860f0ff048a37e0 Mon Sep 17 00:00:00 2001 From: Ed Zynda Date: Fri, 3 Jan 2025 07:12:20 +0300 Subject: [PATCH 3/3] Update README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 885cdcae..2b01d3ca 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ Each MCP server entry requires: ## Usage 🚀 -MCPHost is a CLI tool that allows you to interact with various AI models through a unified interface. It supports various tools through MCP servers and provides streaming responses. +MCPHost is a CLI tool that allows you to interact with various AI models through a unified interface. It supports various tools through MCP servers. ### Available Models Models can be specified using the `--model` (`-m`) flag: @@ -158,4 +158,4 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file - Thanks to the Anthropic team for Claude and the MCP specification - Thanks to the Ollama team for their local LLM runtime -- Thanks to all contributors who have helped improve this tool \ No newline at end of file +- Thanks to all contributors who have helped improve this tool