Testcontainers Java 的 Docker MCP Gateway 模块:在测试中启动 MCP 网关容器
Testcontainers Java 的 Docker MCP Gateway 模块在测试中启动 MCP 网关容器【免费下载链接】testcontainers-javaTestcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.项目地址: https://gitcode.com/GitHub_Trending/te/testcontainers-java导读本文讲解 Testcontainers for Java 提供的DockerMcpGatewayContainer模块它允许你在 JUnit 测试中以真实 Docker 容器的方式启动 Docker MCP Gateway将各种 MCPModel Context Protocol服务器聚合到一个统一的 SSE 端点下供测试代码通过 HTTP 调用。读完本文你将掌握如何引入依赖、如何在任意 Java 应用中启动网关容器、如何注册 MCP 服务器并选择暴露的工具、如何注入密钥secrets、如何获取网关端点地址以及容器底层是如何完成启动与就绪检测的。模块概览DockerMcpGatewayContainer是 Testcontainers 核心库org.testcontainers:testcontainers内置的一个专用容器类其实现位于 core/src/main/java/org/testcontainers/containers/DockerMcpGatewayContainer.java。它继承自GenericContainerDockerMcpGatewayContainer因此具备 Testcontainers 通用的生命周期管理能力start()、stop()、try-with-resources 自动关闭等。从源码看该模块有几个关键默认值默认镜像docker/mcp-gateway见 DockerMcpGatewayContainer.java默认暴露端口8811见 DockerMcpGatewayContainer.java默认以 SSE 传输模式启动--transportsse见 DockerMcpGatewayContainer.java自动将宿主机 Docker 套接字挂载到容器内的/var/run/docker.sock使网关能够通过 Docker 发现本地 MCP 服务器见 DockerMcpGatewayContainer.java启动就绪条件等待容器日志中出现.*Start sse server on port.*见 DockerMcpGatewayContainer.java。注意由于该模块会挂载宿主机 Docker 套接字请仅在受信任的测试/开发环境中使用并留意镜像docker/mcp-gateway的版本行为测试中通常使用docker/mcp-gateway:latest生产化测试建议固定具体版本号。使用示例你可以从任意 Java 应用中通过如下方式启动一个 Docker MCP Gateway 容器实例DockerMcpGatewayContainer gateway new DockerMcpGatewayContainer(docker/mcp-gateway:latest); gateway.start();上面的示例取自 core/src/test/java/org/testcontainers/containers/DockerMcpGatewayContainerTest.java测试通过gateway.isRunning()验证容器确实成功启动。更完整的典型用法是创建容器后链式调用withServer(...)注册 MCP 服务器并通过withSecret(...)/withSecrets(...)注入各服务器所需的 API Key 等机密信息然后启动容器try ( DockerMcpGatewayContainer gateway new DockerMcpGatewayContainer(docker/mcp-gateway:latest) .withServer(curl, curl) .withServer(brave, brave_local_search, brave_web_search) .withServer(github-official, Collections.singletonList(add_issue_comment)) .withSecret(brave.api_key, test_key) .withSecrets(Collections.singletonMap(github.personal_access_token, test_token)) ) { gateway.start(); assertThat(gateway.getLogs()).contains(4 tools listed); }该示例同样来自 DockerMcpGatewayContainerTest.java通过 try-with-resources 确保测试结束后容器自动停止注册了curl、brave、github-official三个服务器共 4 个工具curl、brave_local_search、brave_web_search、add_issue_comment并在启动后断言网关日志输出了4 tools listed从而验证服务器与工具的注册过程真实生效。添加模块依赖Docker MCP Gateway 支持包含在 Testcontainers 核心库中无需额外添加独立模块依赖。只需将org.testcontainers:testcontainers加入测试依赖即可将{{latest_version}}替换为实际使用的版本号 Gradlegroovy testImplementation org.testcontainers:testcontainers:{{latest_version}} Mavenxml dependency groupIdorg.testcontainers/groupId artifactIdtestcontainers/artifactId version{{latest_version}}/version scopetest/scope /dependency此外还需要确保测试环境具备可用的 Docker 运行时Docker daemon 或兼容的容器运行时因为 Testcontainers 的一切容器操作都依赖 Docker 客户端。配置 MCP 服务器与工具网关本身是一个聚合层它把多个 MCP 服务器的工具暴露在一个统一的入口后面。DockerMcpGatewayContainer提供两个重载的withServer方法见 DockerMcpGatewayContainer.javapublic DockerMcpGatewayContainer withServer(String server, ListString tools) public DockerMcpGatewayContainer withServer(String server, String... tools)第一个参数server是要注册的 MCP 服务器标识如curl、brave、github-official第二个参数是希望从该服务器暴露给网关的工具名列表如brave_local_search、add_issue_comment。两个重载方法内部都将服务器名加入servers列表、把工具名加入tools列表因此可以连续多次调用withServer注册多个服务器。在容器真正启动时configure()阶段这些值会被拼装为命令行参数--serversserver与--toolstool传给网关进程见 DockerMcpGatewayContainer.java并配合固定的--transportsse参数一起以单条 command 方式启动。注入密钥Secrets许多 MCP 服务器如 Brave Search、GitHub需要 API Key 或访问令牌。容器类提供了两种注入方式见 DockerMcpGatewayContainer.javapublic DockerMcpGatewayContainer withSecrets(MapString, String secrets) public DockerMcpGatewayContainer withSecret(String secretKey, String secretValue)withSecret(brave.api_key, test_key)逐条注入单个密钥withSecrets(Collections.singletonMap(github.personal_access_token, test_token))一次注入多个密钥。底层实现上所有密钥被汇总到内部的secrets映射中当存在任何密钥时启动命令会追加--secrets/testcontainers/app/secrets见 DockerMcpGatewayContainer.java。而在容器创建完成后containerIsCreated回调见 DockerMcpGatewayContainer.java容器类会把密钥按keyvalue格式逐行写入一个文本文件并通过copyFileToContainer复制到容器内的/testcontainers/app/secrets路径供网关读取。这种先启动、后注入文件的顺序确保了密钥文件在网关读取配置时已经就位。获取网关端点网关容器启动后测试代码通常需要连接它的 SSE 端点来调用工具。容器类提供getEndpoint()方法见 DockerMcpGatewayContainer.javapublic String getEndpoint() { return http:// getHost() : getMappedPort(DEFAULT_PORT); }它基于GenericContainer#getHost()与getMappedPort(8811)返回宿主机可访问的地址格式为http://host:mappedPort。因为 Testcontainers 会在运行时将容器内端口8811映射到宿主机随机可用端口测试代码应始终使用getEndpoint()或getMappedPort(8811)而非硬编码端口以保证测试在不同机器与 CI 环境下的可移植性。SSE 端点即getEndpoint() /sse对应容器启动时输出的Start sse server on port日志。工作原理与就绪检测从源码可以梳理出该容器完整的启动链路构造时解析并校验镜像名与docker/mcp-gateway兼容暴露端口8811挂载 Docker 套接字并注册日志等待策略Wait.forLogMessage(.*Start sse server on port.*, 1)见 DockerMcpGatewayContainer.javaconfigure()把传输模式、服务器列表、工具列表、密钥路径拼成启动命令containerIsCreated()容器创建后立即写入密钥文件等待策略Testcontainers 持续读取容器日志直到匹配到 SSE 服务启动日志start()才会返回保证测试在网关真正可服务之后才继续执行。因此测试中在start()之后立即getEndpoint()、发起 MCP 调用是安全可靠的。小结Docker MCP Gateway 支持内置于 Testcontainers 核心库通过org.testcontainers:testcontainers即可使用DockerMcpGatewayContainer默认使用docker/mcp-gateway镜像、暴露端口8811、以 SSE 模式启动并自动挂载 Docker 套接字通过withServer(server, tools...)注册 MCP 服务器与工具通过withSecret/withSecrets注入密钥使用getEndpoint()获取可访问的网关地址结合日志等待策略确保启动完成后才进行业务调用相关源码与测试可分别在 DockerMcpGatewayContainer.java 与 DockerMcpGatewayContainerTest.java 中查看作为自定义扩展与进一步研究的起点。【免费下载链接】testcontainers-javaTestcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.项目地址: https://gitcode.com/GitHub_Trending/te/testcontainers-java创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考