MCP服务器
该项目使用C++20、Drogon、Boost实现了一个用于文件操作的有状态MCP服务器。进程间、Cpp任务流和Glaze。
特性
- 状态资源:作为MCP资源公开的预加载文件
- 内存映射文件I/O,实现高效操作
- 两种服务器实现:
- mcp_stdio:基于stdio的MCP协议(用于VS Code集成) - mcp_server:基于HTTP-带有SSE事件的API
- 文件处理程序的引用计数
- 跨平台文件映射
- 异步任务执行
- 结构化错误处理和安全
构建说明
- 使用vcpkg安装依赖项:
vcpkg install drogon boost-interprocess glaze taskflow openssl- 使用CMake进行配置和构建:
cmake -B build
cmake --build build- 运行stdio MCP服务器(用于VS代码):
./build/mcp_stdio或者运行HTTP服务器:
./build/mcp_serverVS代码集成
要将此MCP服务器与VS Code和GitHub Copilot一起使用:
- 构建stdio服务器:
cmake --build build - 添加到
~/Library/Application Support/Code/User/mcp.json:
{
"servers": {
"mcp-fileop": {
"type": "stdio",
"command": "/absolute/path/to/build/mcp_stdio"
}
}
}- 重新加载VS代码并在Copilot聊天中使用
看 .github/vscode-mcp-integration.md 获取详细的集成指南。
项目结构
src/-源文件和头文件tests/-单元和集成测试CMakeLists.txt-构建配置
API
- 工具:预加载、读取、读取倍数、关闭
- 结果格式:符合MCP的工具结果模式
- 每次读取操作都会返回 content[] 包含以下项的数组 type 和 text 字段 - 文本/行格式: {"type": "text", "text": "..."} - 十六进制格式: {"type": "text", "format": "hex", "text": "..."} - 二进制格式: {"type": "bytes", "format": "binary", "text": "..."} - 多个范围创建单独的内容项(无嵌套 parts[])
- 资源:将预加载的文件作为资源列出
- 协议:JSON-RPC 2.0通过标准输入
HTTP API(旧版)
POST /mcp-操作:预加载、读取、read_multiple、关闭GET /events-服务器发送的事件
看 mcp_server_design.md 了解完整的设计细节和 MCP_RESULT_FORMAT.md 用于格式规范。
Docker(构建和运行)
您可以构建并运行 mcp_stream 使用Docker或Docker Compose在容器化环境中提供服务。存储库包括 Dockerfile 和 docker-compose.yml 构建发布就绪 mcp_stream 用于测试文件的映像和映射主机目录。
使用Docker构建
使用标签构建Docker镜像(Dockerfile构建版本 mcp_stream 在中间阶段进行二进制处理,并将其复制到最终图像中):
docker build -t mcp-fileop:latest .这将创建一个名为的图像 mcp-fileop:latest 在repo中使用多级Dockerfile。
使用Docker运行(单容器)
您可以直接使用以下命令运行容器 docker run默认映像暴露端口8080并写入 config.json 使用 config.docker.json 包含在存储库中:
docker run --rm -it -p 8080:8080 --name=mcp-fileop-server \
-v /tmp:/mnt/tmp:ro -v $HOME/tmp:/mnt/home_tmp:ro \
mcp-fileop:latest使用 -v 如果您希望容器中的服务器对主机上的文件具有读取权限以进行测试,则可以装载卷(/tmp 和 $HOME/tmp 由合成文件使用)。
使用Docker Compose运行(推荐)
要使用Docker Compose构建和运行项目,您可以使用附带的 docker-compose.yml。这是使用开发中使用的相同配置运行服务的最简单方法:
# Build the image and run as a background service
docker-compose build
docker-compose up -d
# Tail logs
docker-compose logs -f
# Stop and remove the containers
docker-compose down默认情况下,组成映射端口 8080 集装箱到港口 8080 在主机上。compose文件还将主机路径映射到 /mnt/tmp 和 /mnt/home_tmp 在容器里,这样你就可以 preload 来自主机的文件。
通过HTTP访问MCP API
容器运行后,您可以使用HTTP端点:
# Health/Events
curl http://localhost:8080/events
# Make an MCP call (JSON-RPC) to preload or read — example (preload):
curl -s -X POST http://localhost:8080/mcp -H 'Content-Type: application/json' -d '{"op":"preload","params":{"path":"/mnt/home_tmp/myfile.bin"}}'
# Read hex (example) — format will reflect the repo's `mcp_stream` behavior
curl -s -X POST http://localhost:8080/mcp -H 'Content-Type: application/json' -d '{"op":"read","params":{"handler":"/mnt/home_tmp/myfile.bin","offset":0,"size":16,"format":"hex"}}'注意事项和提示
- Docker镜像使用
config.docker.json作为config.json在容器内。如果您需要不同的配置,请将您自己的配置文件挂载到/app/config.json运行容器时。 - 当前图像生成
mcp_stream(基于HTTP的服务)。如果你想运行基于stdio的服务器(mcp_stdio)在开发过程中,通常的方式是cmake --build build随后./build/mcp_stdio在一个壳。 - 编写文件集
restart: unless-stopped。要查看正在运行的容器中的日志,请运行docker-compose logs -f或docker logs -f mcp-fileop-server. - 如果更改代码,请使用以下命令重建映像
docker-compose build或使用docker build.
如果你愿意,我还可以添加一个简单的 docker-compose.override.yml 用于本地开发(例如,将本地源代码映射到容器中并运行调试构建)。如果你愿意,请告诉我。
将主机数据装载到容器中(以便mcp可以预加载和读取文件)
默认值 docker-compose.yml 为了方便起见,将两条主机路径装载到容器中:
/tmp→/mnt/tmp(只读)${HOME}/tmp→/mnt/home_tmp(只读)
这意味着您的主机上存在于这些路径下的文件将在容器中可见 /mnt/tmp 和 /mnt/home_tmp 分别。这 mcp_stream/mcp_stdio 服务器使用容器的规范路径作为 handler 通话时的价值 preload --您应该使用以下函数返回的处理程序 preload (或容器路径)进行后续操作时 read 或 read_multiple 电话。
将文件组合到容器中并通过HTTP API读取文件的示例工作流:
- 在您的主机上创建一个文件(该文件将显示为
/mnt/home_tmp容器内):
mkdir -p $HOME/tmp
echo "Hello, MCP from Docker" > $HOME/tmp/example.bin- 启动服务:
docker-compose up -d- 通过HTTP API预加载文件(使用容器的路径):
curl -s -X POST http://localhost:8080/mcp -H 'Content-Type: application/json' -d '{"op":"preload","params":{"path":"/mnt/home_tmp/example.bin"}}' | jq .预加载调用响应将包括规范 handler 在 result.content[0].text 字符串和a resourceListChanged 通知。在后续的读取调用中使用该处理程序。
- 直接使用返回的处理程序或容器路径读取文件:
curl -s -X POST http://localhost:8080/mcp -H 'Content-Type: application/json' -d '{"op":"read","params":{"handler":"/mnt/home_tmp/example.bin","offset":0,"size":16,"format":"hex"}}' | jq .注意事项和故障排除:
- 如果你看到
Invalid handler,确保您使用的是preload调用(规范路径),而不是容器看不到的主机路径。 - 撰写文件使用
:ro挂载以保护主机文件免受容器内的修改。如果需要从容器中写入已装载的目录(此服务器不常见),请删除:ro使用写访问权限挂载的后缀。 - 在macOS上,Docker使用可以更改某些路径的VM(例如
/tmp可能成为/private/tmp).使用容器/mnt/...执行操作时的路径避免了与这些规范路径差异的混淆。 - 您可以将任何主机路径映射到容器中(例如,
/path/to/myfiles->/mnt/home_tmp:ro)使文件可访问;更新您的docker-compose.yml或docker run -v根据需要选择。 - 如果要将单个特定文件装载到容器中,请绑定装载其目录并引用容器内的文件。例如:
# on host
mkdir -p $HOME/testdata
echo 'hello' > $HOME/testdata/onefile.bin
docker run --rm -it -p 8080:8080 -v $HOME/testdata:/mnt/home_tmp:ro mcp-fileop:latest有用的docker-composeoverride.yml示例
如果您是在本地开发,则覆盖可以用于装载工作目录中的测试数据:
docker-compose.override.yml:
services:
mcp-fileop:
volumes:
- ./testdata:/mnt/home_tmp:ro
# where ./testdata contains files you want to preload and read此覆盖保持图像构建不变,但映射本地 ./testdata 将文件夹放入服务器将从中读取的容器中 /mnt/home_tmp.
