所有文章 > 日积月累 > 使用 Goland 远程开发基于 MCP 的智能对话助手
使用 Goland 远程开发基于 MCP 的智能对话助手

使用 Goland 远程开发基于 MCP 的智能对话助手

不知道大家有没有听说过 MCP 协议?Model Context Protocol (MCP) 是 Anthropic 开发的、实现大模型工程通信的重要协议,可以大规模拓展大模型的功能。感兴趣的同学可以参考下我们之前的文章

但是当大家开始研究和使用 MCP 时,就会发现一个问题:他的可用客户端很少,几乎只有 Claude Desktop 可以用,但是这个客户端只能使用 Claude 自家的模型,而且还有其他紧张的限制,那么这个时候我们就震惊了:我们能不能借助 MCP 的思想开发一套我们自己的客户端呢?

说干就干,本期就是为大家带来使用 Jetbrains Goland 开发的基于 MCP 的智能对话助手。

架构设计

MCP的核心简单来总结就是:程序读取大模型的输出格式化,并自动的去执行某些操作。

而Goland的客户端原理就更简单了,就是在此基础上增加一个对话循环:

  1. 初始化:客户端访问服务端的接口,获取工具,提示,资源等资源。
  2. 开始对话,客户端接收用户输入,并把上述资源的上下文一起发送给大模型。
  3. 客户端判断通过大模型输出判断是否需要调用资源,如果需要就去调用,并将调用的结果返回给大模型。
  4. 大模型分析,整合结果后返回给客户端。

有了这些知识我们就可以开始架构项目了。

这次要实现的是一个使用Go语言开发的对话助手,现在因为官方并没有Go的我们的MCP SDK,而且他的客户端服务器不支持远程连接,所以这次不使用官方的架构进行开发,而是在MCP的基础上,基于它的理念,用更简单的定义实现。

创建 IDE

工欲善其事,必先利其器。一个好的IDE可以很大程度上提高我们的开发效率。对于Go语言来说,我最推荐使用Jetbrains的Goland,它拥有强大的功能和漂亮的UI,尤其适合开发这种有点复杂的项目。

这很多同学可能要说:这种大型的IDE太卡了,我的电脑顶不住啊!

坦白说是有这个问题,首先是mbp,另外在大型项目建立索引的时候卡了一段时间。但还没解开的,使用Sealos Devbox就可以解决的问题。他将Goland的服务端放在远程云端,利用云端的算力实现构建索引等CPU密集的功能,只要你本地的电脑是什么型号和情况,就可以丝滑流畅的开发。

创建开发环境

先访问Sealos Cloud:https://hzh.sealos.run

点击 Devbox 图标,然后点击“新建项目”按钮。在“运行环境”配置中,选择 Go 语言作为开发框架,并通过仔细调整项目所需的 CPU 核心数和内存大小。因为 Goland 需要一定的性能,建议采用 4c 8g 或者更高的配置。

滚动到配置页面的“网络配置”部分,配置容器端口:

  • 输入 8080 (Go 的默认开发端口)
  • 添加其他端口,可点击“添加端口”按钮

配置外部访问:

  • 打开公网访问开关,允许外部用户通过域名访问应用。

域名配置:

  • 系统会自动为应用分配一个子域名。
  • 使用自定义域名,可以点击“自定义域名”并按提示设置。

注意:请确保容器端口 (8080) 与 Go 应用的运行端口一致。如果在 Go 配置中了端口,这里也需要相应修改更新。

最后,点击“创建”按钮完成项目创建。

项目创建完成后,你可以在项目列表中看到新建的项目。每个项目的“操作”栏都提供了许多便捷的选项。

使用 Goland 连接

在项目列表中找到你的项目,在“操作”列中,点击 VSCode 图标旁边的下拉箭头,从下拉菜单中选择 Jetbrains,就会自动跳出一个弹窗。

根据弹窗里的提示,下载好JetBrains Gateway应用,配置好SSH连接信息,选择自己要使用的IDE(比如Go语言项目就选择Goland),点击弹窗底部的【开始连接】。

提示

首次连接时,DevBox 需要下载相关组件,可能需要 3-5 分钟,等待等待即可。

组件下载完成后,自动打开Jetbrains Gateway。确认连接信息没问题后,直接点击“Check Connection and Continue”即可。

如果没有自动打开Jetbrains Gateway,可能是您的浏览器自动阻止了弹窗,请自行开通网站的弹窗权限。

接下来Jetbrains还会跳出一个弹窗进行一系列准备工作:

准备完成后,将自动打开Goland IDE,并自动连接到Devbox开发环境。

搞定,现在你就可以在 Goland 中开始愉快的进行远程开发了!

核心预测

代码:https://github.com/bearslyricattack/mcpTerminal,下面我们挑一些关键的代码为大家介绍一下位于:

加载MCP 服务

func NewTool() (*Tool, error) {
// Open the local server.json file
file, err := os.Open("server.json")
if err != nil {
return nil, fmt.Errorf("failed to open server.json file: %v", err)
}
defer file.Close()

// Create an instance of the Tool type
var tool Tool

// Decode the JSON file into the server struct
decoder := json.NewDecoder(file)
err = decoder.Decode(&tool)
if err != nil {
return nil, fmt.Errorf("failed to decode JSON: %v", err)
}

// Return the decoded Tool object
return &tool, nil
}

当前我们没有使用官方 MCP 的格式,而是在本地配置了一个 json 文件,用于表征各个服务的链接地址,参数等信息。

迅速的

// GetPrompts generates a prompt message suitable for the assistant
func GetPrompts(tools string) string {
// Use a multi-line string for better readability
prompt := fmt.Sprintf(`
您是一位有用的助手,可以使用这些工具:%s
根据用户的问题选择适当的工具。
如果不需要工具,请直接回复。
重要提示:当您需要使用工具时,您必须仅使用以下确切的 JSON 对象格式进行回复,不能使用其他任何内容:
{
"name": "name",
"arguments": {
"argument-name": "value"
}
}
收到工具的响应后:
1. 将原始数据转换为自然的对话响应
2. 保持响应简洁但信息丰富
3. 关注最相关的信息
4. 使用用户问题中的适当上下文
5. 避免简单重复原始数据
请仅使用上面明确定义的工具。`, tools)
return prompt
}

首先向大模型发起请求的时候,需要为其做一些介绍,并包含需要使用的所有工具。下面是一个提示词的示例,大家也可以持续优化提示词,以期达到更好的效果。

对话

// Start the conversation loop
scanner := bufio.NewScanner(os.Stdin)
for {
userInput := getUserInput(scanner)
response, err := chatClient.SendMessage(userInput)
if err != nil {
log.Fatalf("Error sending message: %v", err)
}
// Process the response to check if it contains a ToolRequest
if tool.HandleToolRequest(response, mcpServers, chatClient) {
continue // If a ToolRequest is handled, continue to the next iteration
}
fmt.Println("Assistant:", response)
}

读取模型的输出,由模型来判断是否需要调用。

工具调用

var request ToolRequest
// Try to unmarshal the response into a ToolRequest struct
err := json.Unmarshal([]byte(response), &request)
if err != nil {
return false // If it's not a ToolRequest, return false to continue normal processing
}

// Search for the corresponding mcpServer and send a request to it
for _, mcpServer := range mcpServers.Server {
if request.Name == mcpServer.Name {
request, _ := req.BuildRequest(mcpServer.Host, request.Arguments)
response, err := chatClient.SendMessage(request)
if err != nil {
log.Fatalf("Error sending message: %v", err)
}
fmt.Println("Assistant:", response)
return true
}
}

可能到大型模型修剪的 JSON 的输出之后,检索所有的 MCP Server 进行查找和工具调用。

效果

我们以平台上现有的“获取应用程序的日志”HTTP 接口为例子,只需要在文件配置中配置这个接口,就可以自动的成为一个可以被大模型调用的服务器,不需要做任何额外的操作:

{
"server": [
{
"name": "vlogs-server",
"version": "1.0.0",
"type": "remote",
"host": "http://ip:port/queryLogsByParams",
"description": "Get logs from the API by passing parameters.",
"args": [
{
"key": "time",
"value": "10h",
"description": "The time filter for logs (e.g., \"10h\")."
},
{
"key": "namespace",
"value": "gpu-operator",
"description": "The namespace of the application (e.g., \"gpu-operator\")."
},
{
"key": "app",
"value": "gpu-operator",
"description": "The name of the application (e.g., \"gpu-operator\")."
},
{
"key": "limit",
"value": "100",
"description": "The limit for the number of logs to retrieve. (e.g., \"20\"). if use this key, please use string type."
},
{
"key": "pod",
"value": "pod-123",
"description": "The list of pods to query."
},
{
"key": "container",
"value": "container-456",
"description": "The list of containers to query."
},
{
"key": "keyword",
"value": "error",
"description": "The keyword to filter logs by."
}
]
}
]
}

然后只需在我们的主要方法中配置大模型的uri apikey等信息我们就可以开始使用了,任何符合OpenAPI输出格式的模型都支持。可以像与任何大模型一样,与它以自然语言自由的对话,它会需要的时候调用我们提供的工具去执行并分析结果。

以下是几张效果图

可以看到效果还是非常优秀的,也有一定的稳定性,详细优化下提示词的话应该会有更好的效果。

总结

随着大模型能力的不断增强,其工程化是必然的趋势。而MCP的思想和设计,是其工程化的一条重要道路。虽然目前其各个社区的支持强度似乎相差甚远,但随着时间的发展,一定会越来越多的模型和工具都支持以MCP的格式进行调用。

使用Goland的开发体验非常的丝滑流畅的,而且连接稳定,甚至你一晚上不开发都不会断连接。大家也可以尝试一下,开发出属于自己的MCP对话助手。

文章转载自: 使用 Goland 远程开发基于 MCP 的智能对话助手

#你可能也喜欢这些API文章!