返回市场
MCP代理程序-go

MCP代理程序-go

作者:carlossantin2 星标更新:2025-07-07

项目介绍

技术文档摘要

mcp-agents-go

一个使用大型语言模型(LLMs)与多个模型上下文协议(MCP)服务器交互的智能代理构建Go库。

概述

mcp-agents-go 提供了一个框架,用于创建能够:

  • 连接到多个 MCP 服务器以访问各种工具和资源
  • 使用不同的 LLM 提供商(当前支持 Azure OpenAI)
  • 根据自然语言提示执行工具调用
  • 管理具有不同能力和工具访问权限的多个代理

该项目使用了:

特性

  • 多提供商 LLM 支持:目前支持 Azure OpenAI,并具有可扩展架构
  • 灵活的 MCP 服务器连接:支持 stdio 和 SSE 传输类型
  • 基于代理的架构:创建具有不同工具访问权限的多个代理
  • 配置驱动设置:基于 YAML 的配置文件便于部署
  • 工具访问控制:对每个代理可以使用的工具进行细粒度控制
  • 流式响应:通过 GenerateContentAsStreaming 实现实时响应流
  • 增强的对话流程:支持复杂的多轮次对话及工具交互

安装

go get github.com/carlossantin/mcp-agents-go

快速开始

1. 配置文件

创建一个包含提供商、服务器和代理的 config.yaml 文件:

providers:
  - name: my-azure-provider
    type: AZURE
    token: <YOUR_AZURE_TOKEN>
    baseUrl: <YOUR_AZURE_BASE_URL>
    model: gpt-4o-mini
    version: 2025-01-01-preview

servers:
  - name: my-mcp-server
    type: sse
    url: http://localhost:8080/mcp/events
    # 对于 stdio 服务器:
    # type: stdio
    # command: 
    #   - /path/to/your/mcp-server

agents:
  - name: my-agent
    servers:
      - name: my-mcp-server
        allowed_tools:
          - tool001
          - tool002
    provider: my--azure-provider

2. 基本用法

package main

import (
    "context"
    "fmt"
    "github.com/carlossantin/mcp-agents-go/config"
    "github.com/tmc/langchaingo/llms"
)

func main() {
    ctx := context.Background()
    
    // 从配置文件设置
    err := config.SetupFromFile(ctx, "config.yaml")
    if err != nil {
        panic(err)
    }
    
    // 获取代理并生成内容
    agent, ok := config.SysConfig.Agents["my-agent"]
    if !ok {
        panic("代理未找到")
    }
    
    // 创建消息内容
    msgs := []llms.MessageContent{
        {Role: llms.ChatMessageTypeHuman, Parts: []llms.ContentPart{llms.TextContent{Text: "有哪些可用的工具?"}}},
    }
    
    response, _ := agent.GenerateContent(ctx, msgs, false)
    fmt.Println(response)
}

2.1 流式用法

对于实时流式响应:

package main

import (
    "context"
    "fmt"
    "github.com/carlossantin/mcp-agents-go/config"
    "github.com/tmc/langchaingo/llms"
)

func main() {
    ctx := context.Background()
    
    // 从配置文件设置
    err := config.SetupFromFile(ctx, "config.yaml")
    if err != nil {
        panic(err)
    }
    
    // 获取代理
    agent, ok := config.SysConfig.Agents["my-agent"]
    if !ok {
        panic("代理未找到")
    }
    
    // 创建消息内容
    msgs := []llms.MessageContent{
        {Role: llms.ChatMessageTypeHuman, Parts: []llms.ContentPart{llms.TextContent{Text: "给我当前美元兑巴西雷亚尔的汇率。"}}},
    }
    
    // 流式响应
    var textResp <-chan string
    var msgsResp <-chan llms.MessageContent
    textResp, msgsResp = agent.GenerateContentAsStreaming(ctx, msgs, true)

    // 并发处理两个通道
    go func() {
        for resp := range msgsResp {
            msgs = append(msgs, resp)
        }
    }()

    for resp := range textResp {
        fmt.Print(resp)
    }
}

3. 程序化设置

不使用配置文件,而是程序化设置系统:

package main

import (
    "context"
    "github.com/carlossantin/mcp-agents-go/config"
    "github.com/carlossantin/mcp-agents-go/agent"
    "github.com/tmc/langchaingo/llms"
)

func main() {
    ctx := context.Background()
    
    providers := []config.LLMProvider{
        {
            Name:    "my-provider",
            Type:    "AZURE",
            Token:   "your-token",
            BaseURL: "your-base-url",
            Model:   "gpt-4o-mini",
            Version: "2025-01-01-preview",
        },
    }
    
    servers := []config.MCPServer{
        {
            Name: "my-server",
            Type: "sse",
            URL:  "http://localhost:8080/mcp/events",
        },
    }
    
    agents := []config.MCPAgent{
        {
            Name: "my-agent",
            MCPAgentServers: []agent.MCPAgentServer{
                {
                    Name:         "my-server",
                    AllowedTools: []string{"tool1", "tool2"},
                },
            },
            Provider: "my-provider",
        },
    }
    
    err := config.Setup(ctx, providers, servers, agents)
    if err != nil {
        panic(err)
    }
}

配置参考

LLM 提供商

providers:
  - name: string          # 提供商的唯一标识符
    type: string          # 目前支持 "AZURE"
    token: string         # API 令牌/密钥
    baseUrl: string       # API 的基础 URL
    model: string         # 模型名称(例如 "gpt-4o-mini")
    version: string       # API 版本(针对 Azure)

MCP 服务器

servers:
  - name: string          # 服务器的唯一标识符
    type: string          # "stdio" 或 "sse"
    # 对于 stdio 服务器:
    command: []string     # 启动服务器的命令
    # 对于 SSE 服务器:
    url: string           # 服务器 URL
    headers: []string     # 可选的 HTTP 头

代理

agents:
  - name: string          # 代理的唯一标识符
    servers:              # 该代理可以使用的 MCP 服务器列表
      - name: string      # 服务器名称(必须匹配某个服务器定义)
        allowed_tools:    # 可选:限制哪些工具可以使用
          - string
    provider: string      # 提供商名称(必须匹配某个提供商定义)

架构

该库由几个主要组件组成:

  • Config:管理系统配置和初始化
  • Server:处理 MCP 服务器连接(stdio 和 SSE)
  • Agent:实现带有 LLM 集成的代理逻辑
  • Examples:演示使用模式

代理工作流程

  1. 代理接收一个作为 MessageContent 的自然语言提示
  2. LLM 分析提示并确定是否需要工具
  3. 如果需要工具,代理通过 MCP 服务器执行它们
  4. 工具响应被反馈给 LLM 以生成最终响应
  5. 在流式模式下,响应在生成时实时传递

API 参考

代理方法

GenerateContent(ctx context.Context, msgs []llms.MessageContent, addNotFinalResponses bool) (string, []llms.MessageContent)

同步生成内容。

参数:

  • ctx:请求的上下文
  • msgs:表示对话的消息内容数组
  • addNotFinalResponses:是否在响应中包括中间工具执行细节

返回值:

  • string:生成的响应文本
  • []llms.MessageContent:完整的对话上下文,包括新响应

GenerateContentAsStreaming(ctx context.Context, msgs []llms.MessageContent, addNotFinalResponses bool) (chan string, chan llms.MessageContent)

生成内容并实现实时流式响应。

参数:

  • ctx:请求的上下文
  • msgs:表示对话的消息内容数组
  • addNotFinalResponses:是否在流中包括中间工具执行细节

返回值:

  • chan string:流式响应片段的通道
  • chan llms.MessageContent:完整消息上下文的通道

消息内容结构

消息使用 llms.MessageContent 结构:

type MessageContent struct {
    Role  ChatMessageType  // Human, AI, Tool 等
    Parts []ContentPart    // Text, 图像, 工具调用等
}

示例用法:

msgs := []llms.MessageContent{
    {
        Role: llms.ChatMessageTypeHuman, 
        Parts: []llms.ContentPart{
            llms.TextContent{Text: "你的问题在这里"}
        }
    },
}

环境变量

您可以在配置文件中使用环境变量:

servers:
  - name: my-server
    type: sse
    url: ${MY_SERVER_URL|http://localhost:8080/mcp/events}

高级特性

工具执行跟踪

addNotFinalResponses 设置为 true 时,代理提供关于工具执行的详细信息:

  • [tool_usage] tool_name:指示正在执行哪个工具
  • [tool_response] tool_name: response:显示工具的响应(如果超过 1000 字符则截断)

这对于调试和理解代理的决策过程特别有用。

对话上下文管理

GenerateContentGenerateContentAsStreaming 方法都返回完整的对话上下文,允许您:

  • 跨多个交互维护对话历史
  • 实现对话持久性
  • 构建复杂的多轮对话

示例:

// 初始对话
msgs := []llms.MessageContent{
    {Role: llms.ChatMessageTypeHuman, Parts: []llms.ContentPart{llms.TextContent{Text: "你好!"}}},
}

response, conversationContext := agent.GenerateContent(ctx, msgs, false)

// 使用上下文继续对话
conversationContext = append(conversationContext, llms.MessageContent{
    Role: llms.ChatMessageTypeHuman, 
    Parts: []llms.ContentPart{llms.TextContent{Text: "我上一个问题是什么?"}},
})

response2, updatedContext := agent.GenerateContent(ctx, conversationContext, false)

实时流式

流式特征允许实时响应交付:

var textResp <-chan string
var msgsResp <-chan llms.MessageContent
textResp, msgsResp = agent.GenerateContentAsStreaming(ctx, msgs, true)

// 并发处理两个通道
go func() {
    for msg := range msgsResp {
        // 处理对话上下文更新
        msgs = append(msgs, msg)
    }
}()

for chunk := range textResp {
    fmt.Print(chunk) // 打印每个到达的片段
}

错误处理

该库包括全面的错误处理:

  • 初始化期间报告服务器连接失败
  • 工具执行错误传递给 LLM 进行适当处理
  • 配置验证确保所有必需字段存在
  • 流式操作通过通道传播错误

最佳实践

  1. 始终检查代理是否存在 在使用之前:

    agent, ok := config.SysConfig.Agents["my-agent"]
    if !ok {
        return fmt.Errorf("代理未找到")
    }
    
  2. 正确处理流式通道

    var textResp <-chan string
    var msgsResp <-chan llms.MessageContent
    textResp, msgsResp = agent.GenerateContentAsStreaming(ctx, msgs, true)
    
    // 并发处理两个通道
    go func() {
        for msg := range msgsResp {
            // 处理对话上下文
        }
    }()
    
    for chunk := range textResp {
        fmt.Print(chunk)
    }
    
  3. 使用上下文进行取消

    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()
    
    response, _ := agent.GenerateContent(ctx, msgs, false)
    
  4. 管理对话上下文 用于多轮对话:

    var conversationHistory []llms.MessageContent
    
    // 添加用户消息
    conversationHistory = append(conversationHistory, llms.MessageContent{
        Role: llms.ChatMessageTypeHuman,
        Parts: []llms.ContentPart{llms.TextContent{Text: userInput}},
    })
    
    // 获取响应并更新上下文
    response, updatedContext := agent.GenerateContent(ctx, conversationHistory, false)
    conversationHistory = updatedContext
    

依赖项

此项目使用了几个关键依赖项:

贡献

欢迎贡献!请随时提交 Pull Request。

在贡献时,请确保:

  • 您的代码遵循 Go 最佳实践
  • 包括新功能的测试
  • 更新 API 更改的文档
  • 适当地处理错误
  • 考虑向后兼容性

许可证

此项目根据 Apache License 2.0 许可 - 详情见 LICENSE 文件。

支持

如有疑问和支持需求,请在 GitHub 上 创建问题

常见问题

  1. 代理未找到:确保您的 config.yaml 文件格式正确且代理名称匹配
  2. 工具执行失败:检查您的 MCP 服务器是否运行并可访问
  3. 流式问题:确保您正确处理了 GenerateContentAsStreaming 返回的两个通道
  4. 配置错误:验证所有必需字段存在且环境变量已设置