Merge branch 'main' of github.com:mark3labs/mcphost

This commit is contained in:
Ed Zynda
2025-02-23 12:16:30 +03:00
9 changed files with 141 additions and 22 deletions
+33
View File
@@ -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 }}
+6
View File
@@ -3,3 +3,9 @@
aidocs/
.mcp.json
*.log
mcphost
.idea
test/
build/
scripts/
dist/
+45
View File
@@ -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
+5 -1
View File
@@ -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:
@@ -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
+27 -12
View File
@@ -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
+2
View File
@@ -2,6 +2,8 @@ package main
import "github.com/mark3labs/mcphost/cmd"
var version = "dev"
func main() {
cmd.Execute()
}
+14 -6
View File
@@ -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)
}
+6 -3
View File
@@ -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,
}
}
+3
View File
@@ -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,