模型上下文协议客户端库

MCPP是一个全面的Go库,实现了模型上下文协议(MCP)客户端系统,提供统一接口连接和管理多个MCP服务器,支持多种传输机制,内置会话管理、错误处理和工具集成功能。

  • by andrejsstepanovs
  • Go
  • 本地部署
  • 更新于
在 GitHub 查看 andrejsstepanovs/mcpp

使用说明

MCPP-模型上下文协议客户端库

MCPP是一个全面的Go库,它实现了模型上下文协议(MCP)客户端系统。它提供了一个统一的接口,用于通过不同的传输机制连接和管理多个MCP服务器,内置会话管理、错误处理和工具集成。

特性

  • 多服务器管理:同时连接和管理多个MCP服务器
  • 会话池:使用运行状况监视自动创建、重用和清理会话
  • 运输抽象:目前支持具有可扩展架构的stdio传输
  • 工具集成:与LiteLLM无缝集成,实现AI模型交互
  • 结构化错误处理:具有上下文和重试策略的全面错误类型
  • 可配置日志记录:具有多个级别和格式的结构化日志记录
  • 健康监测:内置健康检查和连接监控
  • 灵活的配置:支持基于文件和程序化配置

安装

go get github.com/andrejsstepanovs/mcpp

快速开始

基本客户端使用

package main

import (
    "context"
    "fmt"
    "log"
    
    "github.com/andrejsstepanovs/mcpp"
)

func main() {
    // Create client from configuration file
    client, err := mcpp.NewClientFromFile("config.json", nil)
    if err != nil {
        log.Fatal(err)
    }
    
    // Connect to all configured servers
    ctx := context.Background()
    if err := client.Connect(ctx); err != nil {
        log.Fatal(err)
    }
    defer client.Disconnect()
    
    // List available tools
    tools, err := client.ListTools(ctx)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Available tools: %d\n", len(tools))
    for _, tool := range tools {
        fmt.Printf("- %s: %s\n", tool.Name, tool.Description)
    }
    
    // Call a tool
    result, err := client.CallTool(ctx, "server1-echo", map[string]any{
        "message": "Hello, MCP!",
    })
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Tool result: %+v\n", result)
}

管理器使用(高级多服务器管理)

package main

import (
    "context"
    "fmt"
    "log"
    
    "github.com/andrejsstepanovs/mcpp"
)

func main() {
    // Create manager from configuration file
    manager, err := mcpp.NewManagerFromFile("config.json", nil)
    if err != nil {
        log.Fatal(err)
    }
    
    // Start all servers
    ctx := context.Background()
    if err := manager.Start(ctx); err != nil {
        log.Fatal(err)
    }
    defer manager.Stop()
    
    // Add a new server at runtime
    serverConfig := mcpp.ServerConfig{
        Transport: "stdio",
        Command:   "python",
        Args:      []string{"my_mcp_server.py"},
    }
    
    if err := manager.AddServer("dynamic_server", serverConfig); err != nil {
        log.Fatal(err)
    }
    
    // List all servers
    servers := manager.ListServers()
    fmt.Printf("Managed servers: %v\n", servers)
    
    // Call tool on specific server
    result, err := manager.CallTool(ctx, "dynamic_server", "my_tool", map[string]any{
        "param": "value",
    })
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Tool result: %+v\n", result)
    
    // Get server statistics
    stats := manager.GetServerStats()
    for serverName, stat := range stats {
        fmt.Printf("Server %s: %d tool calls, %d errors\n", 
            serverName, stat.ToolCallCount, stat.ErrorCount)
    }
}

程序化配置

package main

import (
    "context"
    "log"
    "time"
    
    "github.com/andrejsstepanovs/mcpp"
)

func main() {
    // Create configuration programmatically
    config := &mcpp.Config{
        Servers: map[string]mcpp.ServerConfig{
            "my_server": {
                Transport: "stdio",
                Command:   "python",
                Args:      []string{"server.py"},
                Env: map[string]string{
                    "DEBUG": "1",
                },
                Timeout: func() *time.Duration { 
                    d := 30 * time.Second
                    return &d 
                }(),
            },
        },
        Global: mcpp.GlobalConfig{
            DefaultTimeout: 30 * time.Second,
            MaxSessions:    5,
            HealthCheck:    true,
        },
        Logging: mcpp.LoggingConfig{
            Level:  "info",
            Format: "json",
            Output: "stdout",
        },
    }
    
    // Create client with programmatic config
    client := mcpp.NewClient(config, nil)
    
    ctx := context.Background()
    if err := client.Connect(ctx); err != nil {
        log.Fatal(err)
    }
    defer client.Disconnect()
    
    // Use the client...
}

配置

配置文件格式

创建JSON配置文件(例如。, config.json):

{
  "servers": {
    "my_server": {
      "transport": "stdio",
      "command": "python",
      "args": ["my_mcp_server.py"],
      "env": {
        "DEBUG": "1"
      },
      "timeout": "30s",
      "disabled": false
    },
    "another_server": {
      "transport": "stdio",
      "command": "node",
      "args": ["server.js"],
      "workingDir": "/path/to/server",
      "timeout": "45s"
    }
  },
  "global": {
    "defaultTimeout": "30s",
    "maxSessions": 10,
    "healthCheck": true,
    "healthCheckInterval": "30s",
    "sessionIdleTimeout": "5m"
  },
  "logging": {
    "level": "info",
    "format": "text",
    "output": "stderr",
    "maxSize": 100,
    "maxBackups": 3,
    "maxAge": 28
  }
}

配置选项

服务器配置

  • transport:传输机制(目前支持“stdio”)
  • command:要为MCP服务器执行的命令
  • args:命令行参数(可选)
  • env:环境变量(可选)
  • timeout:连接超时(可选,从全局继承)
  • disabled:是否跳过此服务器(可选,默认值:false)
  • workingDir:命令执行的工作目录(可选)
  • maxRetries:最大重试次数(可选)

全局配置

  • defaultTimeout:所有操作的默认超时
  • maxSessions:并发会话的最大数量
  • healthCheck:启用健康检查(默认值:true)
  • healthCheckInterval:多久进行一次健康检查
  • sessionIdleTimeout:何时关闭空闲会话

日志记录配置

  • level:日志级别(“调试”、“信息”、“警告”、“错误”)
  • format:日志格式(“文本”或“json”)
  • output:输出目标(“stdout”、“stderr”或文件路径)
  • maxSize:最大日志文件大小(MB)
  • maxBackups:备份文件的最大数量
  • maxAge:日志文件的最长期限(天)

错误处理

MCPP提供具有详细上下文的结构化错误处理:

// Handle specific error types
if err != nil {
    if mcpErr, ok := err.(*mcpp.MCPError); ok {
        switch mcpErr.Type {
        case mcpp.ErrorTypeConnection:
            fmt.Printf("Connection error: %s\n", mcpErr.Message)
        case mcpp.ErrorTypeTimeout:
            fmt.Printf("Timeout error: %s\n", mcpErr.Message)
        case mcpp.ErrorTypeValidation:
            fmt.Printf("Validation error: %s\n", mcpErr.Message)
        default:
            fmt.Printf("Other error: %s\n", mcpErr.Message)
        }
        
        // Access error context
        if context := mcpErr.Context; context != nil {
            fmt.Printf("Error context: %+v\n", context)
        }
    }
}

错误类型

  • ErrorTypeConnection:网络或连接相关错误
  • ErrorTypeProtocol:MCP协议违规或通信错误
  • ErrorTypeConfiguration:配置验证或加载错误
  • ErrorTypeTimeout:操作超时错误
  • ErrorTypeValidation:输入验证错误

健康监测

监控MCP连接的健康状况:

// Check overall client health
if err := client.Health(ctx); err != nil {
    fmt.Printf("Health check failed: %v\n", err)
}

// Get detailed statistics
if statsClient, ok := client.(*mcpp.DefaultClient); ok {
    stats := statsClient.GetStats()
    for serverName, stat := range stats {
        fmt.Printf("Server %s: Connected=%v, Calls=%d, Errors=%d\n",
            serverName, stat.Connected, stat.ToolCallCount, stat.ErrorCount)
    }
}

// Manager health checks
healthErrors := manager.HealthCheck(ctx)
for serverName, err := range healthErrors {
    fmt.Printf("Server %s health issue: %v\n", serverName, err)
}

工具名称格式

工具会自动与其服务器名称进行命名空间分隔:

  • 原始工具: echo
  • 命名空间工具: my_server-echo

使用Manager界面时,您可以直接按服务器和工具名称调用工具:

// Client interface (namespaced)
result, err := client.CallTool(ctx, "my_server-echo", args)

// Manager interface (explicit server)
result, err := manager.CallTool(ctx, "my_server", "echo", args)

日志记录

配置结构化日志记录以监控您的MCP操作:

// Create custom logger
logger := mcpp.NewDefaultLogger()

// Use with client
client := mcpp.NewClient(config, logger)

// Logger will output structured information about:
// - Connection establishment and teardown
// - Tool calls and their duration
// - Error conditions and retries
// - Health check results

最佳实践

1.配置管理

// Load configuration with validation
config, err := mcpp.LoadConfigFromFileEnhanced("config.json")
if err != nil {
    log.Fatal("Configuration error:", err)
}

// Apply defaults before use
config.ApplyDefaults()

2.资源管理

// Always clean up resources
defer func() {
    if err := client.Disconnect(); err != nil {
        log.Printf("Cleanup error: %v", err)
    }
}()

// Use context for timeouts
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

3.错误处理

// Handle errors gracefully with retries
for attempts := 0; attempts < 3; attempts++ {
    if err := client.Connect(ctx); err == nil {
        break
    }
    time.Sleep(time.Duration(attempts+1) * time.Second)
}

4.健康监测

// Regular health checks
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()

go func() {
    for range ticker.C {
        if err := client.Health(ctx); err != nil {
            log.Printf("Health check failed: %v", err)
        }
    }
}()

测试

该库包括一个用于集成测试的综合测试服务器:

# Build and run the test server
cd tools
go build -tags testserver -o test-server .
./test-server

测试服务器提供各种工具来测试不同的场景,包括错误条件、超时和边缘情况。

贡献

  1. 分叉存储库
  2. 创建要素分支
  3. 添加新功能的测试
  4. 确保所有测试通过: go test ./...
  5. 提交拉取请求

许可证

此项目根据MIT许可证获得许可-有关详细信息,请参阅许可证文件。

支持

如有疑问、问题或意见,请访问 GitHub存储库.