区块链 区块链技术 比特币公众号手机端

我们用Go在90分钟内构建了一个MCP服务器

我们花了 90 分钟,用 Go 构建了一个 MCP Server

每个教程都在讲 TypeScript。而我们想要的,是一个二进制文件,而不是 node_modules。

Model Context Protocol 已经成为将 AI 模型连接到真实系统的默认方式。到目前为止,几乎所有指南都假设你使用 TypeScript 来编写。

这个假设给团队带来的成本,比表面看起来更高。它意味着每台运行服务器的机器上都要有 Node 运行时;意味着你必须审计一整棵依赖树;也意味着部署方式与你后端其余部分不匹配。

我们的大部分基础设施都是用 Go 构建的。于是我们花了一个下午去搞清楚:用 Go 写 MCP Server,到底是一个真实可行的选项,还是一种新鲜玩物。结果我们花了九十分钟,就让一个能正常工作的服务器与客户端对上了话。以下就是我们的收获。

MCP Server 到底是什么

抛开术语,这个概念本身并不复杂。

MCP Server 是一个程序,它会公布一份清单,列出自己能做的事情。模型连接到它,读取这份清单,然后请求服务器执行其中一项。服务器执行后返回结果。

从概念层面看,这就是整个协议。

→ Tools 是模型可以调用的操作。查询数据库。调用内部 API。读取文件。

→ Resources 是模型可以拉取的上下文片段。文档、记录、日志。

→ Prompts 是服务器可以返回给模型的可复用指令模板。

模型永远不会直接接触你的系统。它发送一个结构化请求,由你的服务器决定如何处理。正是这个边界让 MCP 值得使用,也正是它,让编写服务器所用的语言变得重要。

为什么我们选择 Go

三个原因,都很实际。

→ 单一二进制文件。用 Go 编写的 MCP Server 编译成单一文件,没有任何运行时依赖。你把它复制到机器上就能运行。对于任何要交付到客户环境、或驻留在客户网络内部的东西来说,这直接消除了一整类支持工单。

→ 并发才是真正的工作负载。MCP Server 的一生都在处理重叠的请求,每个请求都在等待数据库、API 或文件系统。Goroutines 处理这种模式,不需要其他语言所要求的那一堆异步管道机制。

→ 它契合技术栈的其余部分。我们的后端服务本来就是用 Go 写的。共享同样的日志、同样的错误处理、同样的部署流水线,比任何按语言区分的基准测试都更有价值。

九十分钟,如实交代

整个构建分为四个阶段,各阶段的耗时并不均匀。

第一阶段,大约十五分钟。项目搭建和传输方式。MCP Server 在本机使用时通过标准输入输出通信,远程使用时通过 HTTP。我们从本机传输开始,因为这是通向可测试状态的最短路径。

第二阶段,大约二十分钟。定义第一个工具。大部分思考都发生在这里。一个工具就是一个名称、一段描述和一个描述其输入的 schema。描述不是文档。它是模型决定是否调用你的工具时唯一会读取的东西,所以它干的是实打实的活。

记住我,以便更快登录

工具定义在协议层面上看起来像这样:

{
  "name": "get_contract_status",
  "description": "Returns the current audit status for a
                  deployed contract address",
  "inputSchema": {
    "type": "object",
    "properties": {
      "address": { "type": "string" }
    },
    "required": ["address"]
  }
}

第三阶段,大约三十分钟。编写 handler。这就是普通的 Go 代码。解析参数,干活,返回结果。其中没有任何 AI 特有的东西,而这正是关键。

第四阶段,大约二十五分钟。连接客户端,修复没跑通的地方。下面会详述。

各个部分如何拼在一起

+----------------+
      |    AI Model    |
      +--------+-------+
               |
               |   1. asks: what can you do?
               |   2. calls: run this tool
               v
  +--------------------------------+
  |        MCP SERVER (Go)         |
  |                                |
  |   +------------------------+   |
  |   |     Tool registry      |   |   names, descriptions,
  |   +-----------+------------+   |   schemas
  |               |                |
  |               v                |
  |   +------------------------+   |
  |   |        Handler         |   |   validates input,
  |   +-----------+------------+   |   runs the work
  |               |                |
  +---------------+----------------+
                  |
                  v
  +--------------------------------+
  |       Your real systems        |
  |    DB / API / files / RPC      |
  +--------------------------------+

模型永远不会越过底部边界。进入你系统的每一条路径,都要经过你编写、且可以审计的 handler。这是值得保护的安全属性。

四件消耗我们时间的事

→ 模糊的工具描述会被忽略。我们的第一条描述写的是“获取合约数据”。模型从未调用过它。把它重写成准确说明输入什么、输出什么之后,问题立刻解决了。把描述当作指令,而不是标签。

→ 往 stdout 打日志会毁掉一切。当传输方式是标准输入输出时,每一行多余的 print 语句都会污染协议流。日志要写到 stderr 或文件。这是最常见的失败原因,而且它产生的错误非常令人困惑。

→ Schema 必须严格。宽松的 schema 会招致格式错误的参数。把必填字段标为必填。约束类型。模型会发送 schema 允许的任何内容。

→ 错误应该被返回,而不是被抛出。执行失败的工具应该返回一条清晰的错误消息,让模型可以读取并作出反应。服务器因为坏输入而崩溃,只会让会话直接结束。

什么时候 Go 是正确选择,什么时候不是

当服务器要交付到自有基础设施之外、要贴近现有 Go 服务部署、或者要针对内部系统处理高并发负载时,Go 是更好的选择。

对于原型开发、已经身处 Node 生态的团队,以及主要封装 Web API 的服务器来说,TypeScript 依然是更快的选择。它的生态更大,示例也更容易找到。

坦率的总结是:这是一个部署决策,而不是性能决策。选择让服务器在它需要运行的地方最容易运行的语言。

这改变了什么

MCP 有意思的地方不在于协议本身,而在于模型与生产系统之间的边界,如今已经变成你可以刻意设计的东西:一个 schema、一个 handler、一份清晰的允许操作清单。

这对任何构建过 API 的人来说,都是熟悉的样子。它也应该用同样的纪律来构建:经过验证的输入、最小权限、审计日志,以及没有任何一条进入系统的路径能绕过被审查过的代码。

九十分钟就能让你得到一个能工作的服务器。真正的工程,体现在此后的每一件事里。

正在构建必须对接生产系统的 Agent 基础设施?

Ancilar 构建并审查 AI Agent 与真实基础设施之间的集成层,包括 MCP Server、工具边界,以及保障它们安全的权限设计。如果你正在把 Agent 从演示推向生产环境,我们可以帮你第一次就把边界做对。

通过 ancilar.com 联系我们

  • 原文链接: medium.com/@ancilartech/...
  • 鸿途知科网 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
版权声明

本文仅代表作者观点,不代表区块链技术网立场。
本文系作者授权本站发表,未经许可,不得转载。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门