关于 Kubernetes Ephemeral Job
Kubernetes Ephemeral Job 是面向 Agent 和自动化流程的 MCP 服务,可在 Kubernetes 中创建临时 Job 执行命令,并返回状态、输出和文件产物。它支持同步与后台任务,执行后删除 Pod,并通过服务端生成清单而非接受调用方提供的 YAML。
主要功能
- 01在临时 Kubernetes Pod 中运行命令
- 02同步运行或提交后台任务
- 03返回退出码、输出和文件产物
- 04支持仓库克隆与可控资源限制
- 05执行后删除 Pod
适用场景
- 01在指定镜像中运行构建或测试
- 02启动长时间任务并稍后收取结果
- 03克隆仓库后执行代码检查
- 04从运行结果中收集生成文件
MCP 相关
作为 MCP 服务,它向客户端提供 run_job、submit_job 和 fetch_job 工具,可通过 stdio、HTTP 或 SSE 使用。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
docker run -i --rm -e MCP_K8S_ALLOWED_IMAGES -e MCP_K8S_KUBECONFIG -e MCP_K8S_NAMESPACE -e MCP_K8S_TRANSPORT -e MCP_K8S_DEFAULT_TIMEOUT_S -e MCP_K8S_MAX_TIMEOUT_S -e MCP_K8S_MAX_OUTPUT_BYTES -e MCP_K8S_MAX_ARTIFACT_BYTES -e MCP_K8S_MAX_CONCURRENT -e MCP_K8S_DEFAULT_CPU -e MCP_K8S_DEFAULT_MEMORY -e MCP_K8S_SIDECAR_IMAGE -e MCP_K8S_CLONE_IMAGE -e MCP_K8S_CLONE_SECRET -e MCP_K8S_CACHE_PVC -e MCP_K8S_CACHE_MOUNT_PATH -e MCP_K8S_JOB_EXTRA_ENV -e MCP_K8S_AUTH_TOKEN docker.io/idconstruct/mcp-k8s-ephemeral-job:v0.7.1MCP_K8S_ALLOWED_IMAGESStrict image allowlist (CSV). Empty means every call is rejected, so this must be set.MCP_K8S_KUBECONFIGPath to the kubeconfig inside the container. Empty = use in-cluster credentials.MCP_K8S_NAMESPACENamespace the ephemeral pods are created in. Needs a Role/RoleBinding for jobs and pods.MCP_K8S_TRANSPORTMCP transport: stdio | http | sse. Must be 'stdio' for direct docker/stdio use.MCP_K8S_DEFAULT_TIMEOUT_SDefault wall-clock timeout per job, seconds.MCP_K8S_MAX_TIMEOUT_SMaximum wall-clock timeout a caller may request, seconds.MCP_K8S_MAX_OUTPUT_BYTESCap on combined stdout/stderr before truncation.MCP_K8S_MAX_ARTIFACT_BYTESCap on the total size of returned artifacts.MCP_K8S_MAX_CONCURRENTMaximum ephemeral pods running at the same time.MCP_K8S_DEFAULT_CPUPod CPU request; limits come from the caller or the namespace LimitRange.MCP_K8S_DEFAULT_MEMORYPod memory request; limits come from the caller or the namespace LimitRange.MCP_K8S_SIDECAR_IMAGEHelper image used to inject input files and collect artifacts.MCP_K8S_CLONE_IMAGEImage carrying git for the clone init container. Empty disables the clone field.MCP_K8S_CLONE_SECRET密钥Secret with git tokens, mounted only on the cloner. Empty disables the clone field.MCP_K8S_CACHE_PVCExisting PVC mounted into every job pod as a shared cache. Empty = no cache.MCP_K8S_CACHE_MOUNT_PATHWhere the cache PVC is mounted, e.g. /go/pkg/mod. Empty = no cache.MCP_K8S_JOB_EXTRA_ENVJSON object of env vars added to every job pod; caller keys win on collision.MCP_K8S_AUTH_TOKEN密钥Optional X-MCP-AUTH token required on every request (http/sse transports only).本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
mcp-k8s-ephemeral-job
English | Русский
面向公众的开源 MCP 服务(Go,MIT),可使用调用方选择的镜像启动一个临时 Kubernetes Job/Pod,在其中运行命令,返回 exit_code / stdout / 制品,并删除 Pod。服务会直接在代码中构建 Pod 清单——调用方只需传递参数,无需提供原始 YAML。
它是 mcp-exec(“手术刀”)的“手术室”搭档:mcp-exec 能在毫秒内于受限且无网络的沙箱中运行单个 Python 文件;而这个服务会启动一个完整 Pod,使用你选择的工具链/镜像,支持受控网络(克隆仓库、拉取依赖)、长时间任务和导出文件制品。两者互为补充。
支持三种传输方式——stdio / HTTP / SSE——无论使用哪种方式,工具集都完全相同(官方 modelcontextprotocol/go-sdk)。
工具
run_job — 运行并等待
输入:{ image (required), command (required), files?, env?, limits?, timeout_s?, workdir?, clone? }
输出:{ exit_code, stdout, stderr, duration_ms, status, artifacts, truncated }
status的取值为succeeded/failed/timeout/error。非零exit_code或timeout属于正常结果,不会被视为工具错误。只有输入无效(镜像/命令为空、镜像不在允许列表中、文件路径无效)才会导致工具调用错误。stdout包含容器的合并后 stdout+stderr——Kubernetes 会在 Pod 日志中合并这两个流。stderr为保留字段,始终为空,因此将来添加流分离功能仍能保持向后兼容。- 制品(工作目录中的文件)会以 base64 格式内联返回,并受大小上限限制。超过上限时不会静默丢失数据:相应的
truncated标志会被设为 true。 - 服务以确定性方式构建清单——调用方无需提供原始 YAML。
submit_job / fetch_job — 在后台运行
submit_job 接受与 run_job 相同的参数,但会立即返回一个 job_token;
fetch_job 稍后收集结果。这样,Agent 就可以启动长时间运行的任务(完整的测试套件、
构建),同时继续工作,而不必在一次同步调用中空等整个运行时间。
- 任务运行期间,
fetch_job会返回status=running;传入wait_s(≤120)即可进行 长轮询,无需频繁轮询。任务完成后,它会立即返回,而不会等满整个等待时间。 - 结果会保留 60 分钟,且可以多次获取。
- 参数会在提交时验证,因此镜像有问题时,提交操作会失败,调用方仍可先修正问题。
- 任务句柄保存在内存中(该服务按设计采用单副本):重启会丢弃待处理的令牌,调用方只需重新提交。
克隆仓库
使用 clone: { repo_url, ref, subdir? } 时,init 容器会在命令运行前将仓库检出到工作目录。
调用方无需处理凭据:服务会持有一个密钥,其中每个 Git 主机对应一个令牌;该密钥
仅挂载到克隆容器,之后会在 .git/config 中屏蔽令牌,主容器永远无法看到它。只有在
操作员配置了 MCP_K8S_CLONE_IMAGE + MCP_K8S_CLONE_SECRET 时,才接受 clone 字段。
安全模型(不变量)
每次运行都会创建一个全新的临时 Pod,之后将其删除(无论成功、失败还是超时)。服务的
RBAC 限定在命名空间范围内(使用 Role/RoleBinding,绝不使用 ClusterRole)——在
单个命名空间中授予 create/delete jobs,pods 以及 pods/log、pods/exec 权限。生成的 Pod
以 cap-drop=ALL、no-privilege-escalation 和 seccomp RuntimeDefault 运行。影响范围仅限于
该命名空间:LimitRange(每个 Pod 的默认值和上限)+ ResourceQuota(命名空间上限)+
墙钟超时(→终止)+ TTL/所有者引用垃圾回收 + 并发上限。镜像必须通过严格的允许列表
(MCP_K8S_ALLOWED_IMAGES;为空表示不运行任何内容)。调用方数据(command / files /
输出 / 构件)绝不会持久化,也不会完整记录日志——只记录元数据。
run_job是最强大的功能(它会创建 Pod)。将其嵌入 Agent 时,应通过该 Agent 的工具策略 限制访问(仅限受信任的角色)。
网络说明:Pod 的网络不会禁用(克隆仓库/拉取依赖项需要网络)。
出口流量由命名空间 NetworkPolicy(允许列表)控制,这是部署配置的一部分,并非代码内置
的限制。安全不变量是临时性 + 删除,而不是禁用网络。
资源:服务的 MCP_K8S_DEFAULT_CPU/MEMORY 是 Pod 的请求值(调度器的预留值)。
仅当调用方传入 limits 时才会设置限制;否则,上限由命名空间的 LimitRange 决定。
传入 limits.memory 也会相应提高内存请求,使其与限制相同,因为内存不可压缩,Pod 必须
调度到实际有足够内存的节点上。
运行
已在 MCP Registry 中发布,名称为
io.github.inhuman/mcp-k8s-ephemeral-job;镜像托管在 Docker Hub,名称为
idconstruct/mcp-k8s-ephemeral-job。
docker run --rm -i \
-v "$HOME/.kube:/kube:ro" \
-e MCP_K8S_KUBECONFIG=/kube/config \
-e MCP_K8S_NAMESPACE=ephemeral-dev \
-e MCP_K8S_ALLOWED_IMAGES=busybox:1.36,python:3.12-slim \
idconstruct/mcp-k8s-ephemeral-job:latest
从源代码运行,连接开发集群,使用 stdio:
go build -o mcp-k8s-ephemeral-job ./cmd/mcp-k8s-ephemeral-job
export MCP_K8S_KUBECONFIG=$HOME/.kube/config
export MCP_K8S_NAMESPACE=ephemeral-dev
export MCP_K8S_ALLOWED_IMAGES=busybox:1.36,python:3.12-slim
./mcp-k8s-ephemeral-job
在生产环境中,服务以 Deployment 的形式在集群内运行,并配有自己的 ServiceAccount,以及
临时命名空间中的 Role/RoleBinding、ResourceQuota/LimitRange(可选的出口流量
NetworkPolicy),通常使用 http 传输方式。
调用示例(run_job)
{
"image": "python:3.12-slim",
"command": ["python", "gen.py"],
"files": [{ "path": "gen.py", "content_b64": "<base64 of a script writing out.png>" }],
"limits": { "cpu": "500m", "memory": "256Mi" },
"timeout_s": 30
}
返回 exit_code、捕获的输出,以及内嵌在 artifacts 中的 out.png。之后 Pod
即被删除(kubectl get jobs,pods -n $NS 返回空)。
可选身份验证(HTTP/SSE)
设置 MCP_K8S_AUTH_TOKEN,要求每个 HTTP/SSE 请求都携带匹配的 X-MCP-AUTH 标头
(以恒定时间进行比较;否则返回 401)。令牌为空时会禁用身份验证。不适用于 stdio。
配置
| 环境变量 | 用途 | 默认值 |
|---|---|---|
MCP_K8S_TRANSPORT | stdio | http | sse | stdio |
MCP_K8S_ADDR | http/sse 的监听地址 | :8080 |
MCP_K8S_NAMESPACE | 临时 Pod 的创建命名空间 | mcp-ephemeral |
MCP_K8S_DEFAULT_TIMEOUT_S | 默认墙钟超时时间(秒) | 60 |
MCP_K8S_MAX_TIMEOUT_S | 超时时间上限(秒) | 600 |
MCP_K8S_MAX_OUTPUT_BYTES | stdout 和 stderr 的合计上限 | 1048576 |
MCP_K8S_MAX_ARTIFACT_BYTES | 工件总大小上限 | 10485760 |
MCP_K8S_DEFAULT_CPU | Pod CPU 请求量(调度预留;限制取自调用方的 limits 或命名空间的 LimitRange) | 1 |
MCP_K8S_DEFAULT_MEMORY | Pod 内存请求量(见上文) | 512Mi |
MCP_K8S_MAX_CONCURRENT | 临时 Pod 的最大并发数(超出时排队或报错) | 10 |
MCP_K8S_ALLOWED_IMAGES | 严格的镜像允许列表(CSV);为空 = 全部拒绝 | `` |
MCP_K8S_SIDECAR_IMAGE | 用于收集工件的辅助 sidecar 镜像(固定版本) | busybox:1.36 |
MCP_K8S_CLONE_IMAGE | 含 git 的镜像,用于 clone init 容器;为空 = clone 不可用 | `` |
MCP_K8S_CLONE_SECRET | 存放每个 git 主机一个令牌的 secret(键 = 主机);仅挂载到克隆容器 | `` |
MCP_K8S_CACHE_PVC | 挂载到每个作业 Pod 的现有 PVC,作为共享缓存;为空 = 不使用缓存 | `` |
MCP_K8S_CACHE_MOUNT_PATH | 缓存 PVC 的挂载位置,例如 /go/pkg/mod | `` |
MCP_K8S_JOB_EXTRA_ENV | 添加到每个作业 Pod 的 JSON 对象 {"KEY":"value"};调用方的键优先 | `` |
MCP_K8S_KUBECONFIG | kubeconfig 的路径;为空 = 集群内配置 | `` |
MCP_K8S_AUTH_TOKEN | 若设置,http/sse 需要 X-MCP-AUTH 标头(恒定时间比较);为空 = 关闭 | `` |
必须同时设置两个缓存变量才能挂载缓存。PVC 本身需在带外配置(helm/manifest);服务仅通过名称引用它,如果启动时发现它不存在,就会立即失败。
尚未实现
用于传递过大而无法内嵌的工件的 PVC / 对象存储、多集群支持,以及将其他 MCP 服务代理到 Pod 中。
许可证
MIT。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。