Skip to main content
Glama

mcp-agent-forge

main.go19 kB
package main import ( "context" "encoding/json" "errors" "fmt" "os" "strings" "time" "agent-forge/internal/config" "agent-forge/internal/logger" "github.com/google/uuid" "github.com/mark3labs/mcp-go/mcp" "github.com/mark3labs/mcp-go/server" "github.com/sashabaranov/go-openai" "go.uber.org/zap" ) // OpenAI客户端 var openaiClient *openai.Client // Agent 结构体定义 type Agent struct { ID string `json:"id"` Name string `json:"name"` CoreTraits string `json:"core_traits"` Personality string `json:"personality"` CreatedAt string `json:"created_at"` } // 存储所有生成的智能体 var agents = make(map[string]*Agent) // 定义角色常量 const ( // RoleSystem denotes the system message role for prompts. // DeepSeek uses "assistant" for system-style instructions // when embedding them into prompts. RoleSystem = "assistant" // RoleUser denotes a user message role. RoleUser = "user" ) func init() { // 初始化配置 if _, err := config.LoadConfig(); err != nil { fmt.Fprintf(os.Stderr, "配置加载失败: %v\n", err) os.Exit(1) } // 初始化日志系统 cfg := config.GetConfig() if err := logger.InitLogger(cfg); err != nil { panic(fmt.Sprintf("初始化日志系统失败: %v", err)) } // 初始化DeepSeek客户端 if cfg.DeepSeek.APIKey == "" { logger.Error("DEEPSEEK_API_KEY 环境变量未设置") fmt.Fprintln(os.Stderr, "\n请设置 DEEPSEEK_API_KEY 环境变量后再运行程序。例如:") fmt.Fprintln(os.Stderr, "export DEEPSEEK_API_KEY=your_api_key_here") os.Exit(1) } openaiConfig := openai.DefaultConfig(cfg.DeepSeek.APIKey) openaiConfig.BaseURL = cfg.DeepSeek.BaseURL openaiClient = openai.NewClientWithConfig(openaiConfig) } // 调用DeepSeek API的公共方法 func callOpenAI(ctx context.Context, systemPrompt, userQuestion, contextContent string) (string, error) { messages := []openai.ChatCompletionMessage{ { Role: openai.ChatMessageRoleSystem, Content: systemPrompt, }, } // 如果有背景信息,添加到提示中 if contextContent != "" { messages = append(messages, openai.ChatCompletionMessage{ Role: openai.ChatMessageRoleUser, Content: contextContent, }) } // 添加用户问题 messages = append(messages, openai.ChatCompletionMessage{ Role: openai.ChatMessageRoleUser, Content: userQuestion, }) cfg := config.GetConfig() // 设置请求超时 clientCtx, cancel := context.WithTimeout(context.Background(), time.Duration(cfg.DeepSeek.Timeout)*time.Second) defer cancel() // 如果传入的上下文不是nil,使用传入的上下文 requestCtx := clientCtx if ctx != nil { requestCtx = ctx } resp, err := openaiClient.CreateChatCompletion( requestCtx, openai.ChatCompletionRequest{ Model: "deepseek-chat", // 使用DeepSeek的模型 Messages: messages, Temperature: float32(cfg.DeepSeek.Temperature), // 转换为float32类型 }, ) if err != nil { return "", fmt.Errorf("DeepSeek API调用失败: %v", err) } if len(resp.Choices) == 0 { return "", errors.New("DeepSeek返回结果为空") } // 去除返回内容中可能的前后空白字符 content := strings.TrimSpace(resp.Choices[0].Message.Content) // 如果返回的内容是JSON格式,尝试提取纯文本内容 var jsonResponse map[string]interface{} if err := json.Unmarshal([]byte(content), &jsonResponse); err == nil { // 如果是JSON格式,尝试获取content字段 if textContent, ok := jsonResponse["content"].(string); ok { content = textContent } } return content, nil } // generateExpertAgentHandler 处理生成专家提示词的请求 func generateExpertAgentHandler(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) { // 获取并验证 agent_name agentName, ok := request.Params.Arguments["agent_name"] if !ok { return nil, fmt.Errorf("missing agent_name") } // 获取并验证 core_traits coreTraits, ok := request.Params.Arguments["core_traits"] if !ok { return nil, fmt.Errorf("missing core_traits") } messages := []mcp.PromptMessage{ mcp.NewPromptMessage( RoleSystem, mcp.NewTextContent("你是一个专家人格生成工具,请根据智能体名称和核心特质生成一个专家人格的提示词。注意仅返回提示词,不要包含任何其他内容。"), ), mcp.NewPromptMessage( RoleUser, mcp.NewTextContent(fmt.Sprintf("请为名为[%s]的智能体生成一个人格描述,核心特质是:[%s]", agentName, coreTraits)), ), } return mcp.NewGetPromptResult( "专家生成", messages, ), nil } // roundTableDiscussionHandler 处理生成圆桌讨论提示词的请求 func roundTableDiscussionHandler(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) { // 获取并验证 topic topic, ok := request.Params.Arguments["topic"] if !ok { return nil, fmt.Errorf("missing topic") } messages := []mcp.PromptMessage{ mcp.NewPromptMessage( RoleSystem, mcp.NewTextContent(`你是探索流的主持人,请你收集资料,根据需要讨论的话题创建必要角色的智能体专家来进行一场称为**探索流**的讨论。讨论的过程中,你将作为主持人来控场。探索流的规则如下: 1、探索流是一种交互式学习和讨论方式,旨在通过动态的对话、试验和反思,发现新观点、解决问题或突破现有局限。它强调通过"表达"、"呼应"和"看见"的过程,激发潜意识和群体智慧,创造新的认知和行为模式。探索流注重个体的自由表达和安全场域,禁止评判、建议和反馈,以实现深度的自我探索和心灵连接。作为一种创新实践方法,探索流通过组织内外的协作与同步,推动创造力和创新能力的涌现,同时探索人与人之间的交互方式,促进认知和情感的双向流动。它还涉及对流的研究和实践,通过关键词反应、生成式AI的交互模式以及集群智慧的涌现,优化复杂系统中的动态过程,发现问题的本质并寻找解决方案。探索流不仅是一种团队协作和深度讨论的方式,也是一种精神探索的过程,通过倾听和观察自然现象达到内心的平静,并通过持续探索和追问重新定义业务和产品的主题或方向。 2、探索流分为"表达"、"呼应"、"看见"三个大的讨论阶段,表达阶段每人发言一次,呼应阶段可以自由发言,看见阶段每人发言总结一次; 3、"表达"是一种交流方式,指个体通过语言、行为、艺术或其他形式,将内心深处的思想、情感、观点或灵魂传递给他人的过程。它既是探索流网络中的输出过程,也是探索流的第一阶段,**参与者轮流分享对主题的想法和内容物**。表达可以分为"表"和"达"两个层次,涵盖从信息传递到情感流露的多种形式,体现了个体内心真实感受的外化与分享。 4、"呼应"是一种交流方式,强调当下的真实发生和自然反应,同时通过倾听和回应他人表达的内容来建立深层次的联系。它是一种内在反应或共鸣,通过关键词或符号触发个人内心的潜意识反应,并生成新的关联。呼应不仅是一种对他人观点或行为的回应或支持,还涉及通过动作与流建立联系,强调看见和表达的重要性。作为探索流的核心步骤和第二阶段,**呼应通过对触动自己的关键词进行反馈或回应**,唤醒个人内在的想法和潜意识,并在探索流网络的隐藏层中产生新的火花。这种交互行为在哲学和社群动态中具有重要意义,能够促进思想的流动和情感的共鸣。 5、"看见"是一种深刻的意识和理解过程,既指对问题或现象的认知与关注,也是一种通过观察他人而发现自我并真实表达的心理体验。它超越了表面观察,达到心灵的共鸣,能够引发自我和他人的内心转变。作为探索流中的一个核心概念,"看见"涉及通过关键词发现其背后的结构或意义,并通过身心感知他人的表达来觉察内心深处的真实状态。在探索流网络中,"看见"是第三步,**通过识别关键词之间的关系生成结构,从而深化理解与觉察**。这一过程不仅是认知的深化,更是心灵的连接与转化的关键环节。 6、最后你作为主持人进行最终的收敛总结,输出一篇探索流报告。 7、每个阶段结束时,你都要通知用户,等用户的指令再进行下一阶段`), ), mcp.NewPromptMessage( RoleUser, mcp.NewTextContent(fmt.Sprintf("现在请围绕主题[%s]组织一场探索流讨论", topic)), ), } return mcp.NewGetPromptResult( "探索流", messages, ), nil } func main() { log := logger.GetLogger() // 创建 MCP 服务器 s := server.NewMCPServer( "智能体锻造工具", "1.0.0", server.WithPromptCapabilities(true), // 启用 prompts 功能 ) // 添加创建专家提示词 generateExpertAgentPrompt := mcp.NewPrompt("generate_expert_agent", mcp.WithPromptDescription("系统提示词,用于生成智能体的人格"), mcp.WithArgument("agent_name", mcp.ArgumentDescription("智能体名称"), mcp.RequiredArgument(), ), mcp.WithArgument("core_traits", mcp.ArgumentDescription("核心特质"), mcp.RequiredArgument(), ), ) // 添加圆桌讨论提示词 roundTableDiscussionPrompt := mcp.NewPrompt("round_table_discussion", mcp.WithPromptDescription("用于组织探索流的提示词"), mcp.WithArgument("topic", mcp.ArgumentDescription("探索主题"), mcp.RequiredArgument(), ), ) // 添加提示词处理器 s.AddPrompt(generateExpertAgentPrompt, generateExpertAgentHandler) s.AddPrompt(roundTableDiscussionPrompt, roundTableDiscussionHandler) // 创建智能体工具 createTool := mcp.NewTool( "expert_personality_generation", mcp.WithDescription("创建新的智能体"), mcp.WithString("agent_name", mcp.Required(), mcp.Description("智能体名称"), ), mcp.WithString("core_traits", mcp.Required(), mcp.Description("核心特质"), ), ) // 模拟智能体回答工具 answerTool := mcp.NewTool( "agent_answer", mcp.WithDescription(`模拟智能体作答。 参数说明: - agent_id: 智能体ID,创建智能体时返回的唯一标识 - context: 当前对话的上下文内容,具体包括: * 用户的原始问题及补充说明 * 其他专家智能体的观点 * 我已经陈述的观点 * 外部搜索或知识输入 - planned_rounds: 预估需要进行的回答次数 - current_round: 已回答次数 - need_more_rounds: 是否需要新增回答次数,当主持人认为需要新增回答次数时,设置为true,否则设置为false`), mcp.WithString("agent_id", mcp.Required(), mcp.Description("智能体ID"), ), mcp.WithString("context", mcp.Description("对话上下文"), ), mcp.WithNumber("planned_rounds", mcp.Description("计划回答次数"), ), mcp.WithNumber("current_round", mcp.Description("已回答次数"), ), mcp.WithBoolean("need_more_rounds", mcp.Description("是否需要新增回答次数"), ), ) // 获取智能体信息工具 getTool := mcp.NewTool( "get_agent", mcp.WithDescription("获取指定智能体的信息"), mcp.WithString("agent_id", mcp.Required(), mcp.Description("智能体ID"), ), ) // 列出所有智能体工具 listTool := mcp.NewTool( "list_agents", mcp.WithDescription("列出所有智能体"), ) // 删除智能体工具 deleteTool := mcp.NewTool( "delete_agent", mcp.WithDescription("删除指定的智能体"), mcp.WithString("agent_id", mcp.Required(), mcp.Description("要删除的智能体ID"), ), ) // 更新智能体工具 updateTool := mcp.NewTool( "update_agent", mcp.WithDescription("更新智能体信息"), mcp.WithString("agent_id", mcp.Required(), mcp.Description("智能体ID"), ), mcp.WithString("name", mcp.Description("新的智能体名称"), ), mcp.WithString("core_traits", mcp.Description("新的核心特质"), ), ) // 添加工具处理器 s.AddTool(createTool, createToolHandler) s.AddTool(answerTool, answerToolHandler) s.AddTool(getTool, getAgentHandler) s.AddTool(listTool, listAgentsHandler) s.AddTool(deleteTool, deleteAgentHandler) s.AddTool(updateTool, updateAgentHandler) // 启动服务器 if err := server.ServeStdio(s); err != nil { log.Fatal("服务启动失败", zap.Error(err)) os.Exit(1) } } // 修改getHandlerForModel函数 func createToolHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { log := logger.GetLogger() // 提取参数 agentName, ok := request.Params.Arguments["agent_name"].(string) if !ok || agentName == "" { log.Error("无效的智能体名称") return nil, errors.New("无效的智能体名称") } coreTraits, ok := request.Params.Arguments["core_traits"].(string) if !ok || coreTraits == "" { log.Error("无效的核心特征") return nil, errors.New("无效的核心特征") } log.Info("创建智能体", zap.String("name", agentName), zap.String("traits", coreTraits)) systemPrompt := "你是一个专家人格生成工具,请根据智能体名称和核心特质生成一个专家人格的提示词。注意仅返回提示词,不要包含任何其他内容。" question := fmt.Sprintf("请为名为[%s]的智能体生成一个人格描述,核心特质是:[%s]", agentName, coreTraits) // 调用OpenAI response, err := callOpenAI(ctx, systemPrompt, question, "") if err != nil { return nil, err } // 创建新的智能体实例 agentID := uuid.New().String() newAgent := &Agent{ ID: agentID, Name: agentName, CoreTraits: coreTraits, Personality: response, CreatedAt: time.Now().Format(time.RFC3339), } // 存储智能体 agents[agentID] = newAgent // 返回处理结果,包含智能体ID result := map[string]interface{}{ "status": "success", "message": "智能体创建成功", "agent_id": agentID, } jsonResponse, err := json.Marshal(result) if err != nil { return nil, fmt.Errorf("marshal response failed: %v", err) } // 确保返回的是有效的JSON字符串 return mcp.NewToolResultText(string(jsonResponse)), nil } // 获取智能体处理函数 func getAgentHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { agentID, ok := request.Params.Arguments["agent_id"].(string) if !ok { return nil, errors.New("agent_id must be a string") } agent, exists := agents[agentID] if !exists { return nil, fmt.Errorf("agent with ID %s not found", agentID) } jsonResponse, err := json.Marshal(agent) if err != nil { return nil, fmt.Errorf("marshal response failed: %v", err) } return mcp.NewToolResultText(string(jsonResponse)), nil } // 列出所有智能体处理函数 func listAgentsHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { agentList := make([]*Agent, 0, len(agents)) for _, agent := range agents { agentList = append(agentList, agent) } jsonResponse, err := json.Marshal(agentList) if err != nil { return nil, fmt.Errorf("marshal response failed: %v", err) } return mcp.NewToolResultText(string(jsonResponse)), nil } // 删除智能体处理函数 func deleteAgentHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { agentID, ok := request.Params.Arguments["agent_id"].(string) if !ok { return nil, errors.New("agent_id must be a string") } if _, exists := agents[agentID]; !exists { return nil, fmt.Errorf("agent with ID %s not found", agentID) } delete(agents, agentID) result := map[string]string{ "status": "success", "message": fmt.Sprintf("智能体 %s 已成功删除", agentID), } jsonResponse, err := json.Marshal(result) if err != nil { return nil, fmt.Errorf("marshal response failed: %v", err) } return mcp.NewToolResultText(string(jsonResponse)), nil } // 更新智能体处理函数 func updateAgentHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { agentID, ok := request.Params.Arguments["agent_id"].(string) if !ok { return nil, errors.New("agent_id must be a string") } agent, exists := agents[agentID] if !exists { return nil, fmt.Errorf("agent with ID %s not found", agentID) } // 更新名称(如果提供) if newName, ok := request.Params.Arguments["name"].(string); ok && newName != "" { agent.Name = newName } // 更新核心特质(如果提供) if newTraits, ok := request.Params.Arguments["core_traits"].(string); ok && newTraits != "" { agent.CoreTraits = newTraits // 重新生成人格描述 systemPrompt := "你是一个专家人格生成工具,请根据智能体名称和核心特质生成一个专家人格。" question := fmt.Sprintf("请为名为[%s]的智能体生成一个人格描述,核心特质是:[%s]", agent.Name, newTraits) newPersonality, err := callOpenAI(ctx, systemPrompt, question, "") if err != nil { return nil, fmt.Errorf("generate new personality failed: %v", err) } agent.Personality = newPersonality } result := map[string]interface{}{ "status": "success", "message": "智能体更新成功", "agent": agent, } jsonResponse, err := json.Marshal(result) if err != nil { return nil, fmt.Errorf("marshal response failed: %v", err) } return mcp.NewToolResultText(string(jsonResponse)), nil } // 模拟智能体回答处理函数 func answerToolHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { // 获取参数 agentID, ok := request.Params.Arguments["agent_id"].(string) if !ok { return nil, errors.New("agent_id must be a string") } context, _ := request.Params.Arguments["context"].(string) plannedRounds, _ := request.Params.Arguments["planned_rounds"].(float64) currentRound, _ := request.Params.Arguments["current_round"].(float64) needMoreRounds, _ := request.Params.Arguments["need_more_rounds"].(bool) if currentRound > plannedRounds { plannedRounds = currentRound } // 获取智能体 agent, exists := agents[agentID] if !exists { return nil, fmt.Errorf("agent with ID %s not found", agentID) } // 构建系统提示词 systemPrompt := fmt.Sprintf("你现在扮演一个%s。%s", agent.Name, agent.Personality) // 调用OpenAI生成回答 response, err := callOpenAI(ctx, systemPrompt, context, "") if err != nil { return nil, err } // 创建包含所有信息的响应 result := map[string]interface{}{ "content": response, "planned_rounds": plannedRounds, "current_round": currentRound, "need_more_rounds": needMoreRounds, } jsonResponse, err := json.Marshal(result) if err != nil { return nil, fmt.Errorf("marshal response failed: %v", err) } return mcp.NewToolResultText(string(jsonResponse)), nil }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/HundunOnline/mcp-agent-forge'

If you have feedback or need assistance with the MCP directory API, please join our Discord server