使用 Common Lisp 构建 MCP 服务器
Source: Dev.to
前置条件
在开始之前,请确保已安装以下工具:
- SBCL – 高性能的 Common Lisp 编译器
- Roswell – Common Lisp 实现管理器和脚本运行器
- Quicklisp – 实际上的 Common Lisp 包管理器
- Ultralisp – 由社区驱动的 Common Lisp 库发行版
安装 Ultralisp
在使用 Quicklisp 的 SBCL 中,你可以通过以下方式启用 Ultralisp:
(ql-dist:install-dist "http://dist.ultralisp.org/" :prompt nil)(如何安装 SBCL 和 Quicklisp 已在附录中说明。)
注意事项:加载 40ants-mcp
当你尝试使用以下代码加载 40ants-mcp 时:
(ql:quickload :40ants-mcp)可能会遇到错误。解决办法很简单但并不显而易见——先加载 jsonrpc:
(ql:quickload :jsonrpc)
(ql:quickload :40ants-mcp)这个依赖不会被自动解析,这正是导致困扰的原因。
创建你的 MCP 服务器
下面是 mcp-exper 包中的一个最小示例:
(in-package :mcp-exper)
(openrpc-server:define-api (mi-tools :title "mi-tools"))
(40ants-mcp/tools:define-tool (mi-tools add) (a b)
(:summary "just add")
(:param a integer "a")
(:param b integer "b")
(:result text-content)
(make-instance 'text-content :text (format nil "~a" (+ a b))))
(defun start-server ()
(40ants-mcp/server/definition:start-server mi-tools))关键点
- 使用
openrpc-server:define-api定义 API。 - 使用
40ants-mcp/tools:define-tool定义工具。 - 文本结果返回
text-content实例(MCP 需要特定的内容类型)。
运行服务器
创建一个 Roswell 脚本(mi-mcp-server.ros):
#!/bin/sh
#|-*- mode:lisp -*-|#
exec ros -Q -- $0 "$@"
|#
(progn
(ros:ensure-asdf)
#+quicklisp (ql:quickload '(:mcp-exper) :silent t))
(defun main (&rest argv)
(declare (ignorable argv))
(mcp-exper:start-server))快速测试
直接使用 Roswell 运行脚本:
ros mi-mcp-server.ros生产环境安装
构建并安装可执行文件:
ros build mi-mcp-server.ros
install -m 0755 mi-mcp-server $HOME/.local/bin/确保 $HOME/.local/bin 已加入你的 PATH。
与 Opencode 集成
要在 Opencode 中启用你的 MCP 服务器,向 ~/.config/opencode/opencode.json 添加以下内容:
{
"mcp": {
"mi-tools": {
"type": "local",
"command": ["mi-mcp-server"],
"enabled": true
}
}
}结论
一旦掌握技巧,使用 Common Lisp 构建 MCP 服务器就非常直接。40ants-mcp 库设计良好,OpenRPC 集成也十分顺畅。
希望本指南能帮你避免我曾经历的那些挫折。祝编码愉快!
本示例的完整源代码可在 mcp-exper 获取。
附录:安装 SBCL
macOS
brew install sbclDebian/Ubuntu
apt install sbclArch Linux
pacman -S sbcl附录:安装 Quicklisp
下载并安装 Quicklisp:
wget https://beta.quicklisp.org/quicklisp.lisp
sbcl --load quicklisp.lisp \
--eval '(quicklisp-quickstart:install)' \
--eval '(ql-util:without-prompting (ql:add-to-init-file))' \
--quit