关于 no-crd
no-crd 是面向 AI Agent 和平台团队的 MCP 服务与 TypeScript SDK,可在 Kubernetes 上创建、路由和管理临时容器工作区,无需 CRD 或集群 Operator。它支持多种 JavaScript 运行时,并提供模板化 Pod 配置和实验性路由代理。
主要功能
- 01创建和管理 Kubernetes Pod
- 02使用模板配置工作区
- 03将流量路由到运行中的工作区
- 04支持 Node.js、Bun 和 Deno
- 05内置 Pod 管理网页界面
适用场景
- 01为 AI Agent 创建临时沙箱
- 02管理标准 Kubernetes 集群中的 Pod
- 03将用户流量路由至活动容器工作区
MCP 相关
向 MCP 客户端提供 Kubernetes Pod 和工作区管理能力,支持 HTTP/SSE 与 stdio 传输。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @nogoo9/no-crdKUBECONFIGPath to the Kubernetes API credentials configuration fileBASE_URLHosting URL subpath prefix for gateways and reverse proxiesSTATELESSDisable in-memory session tracking for stateless executionTLS_CERTLocal file path containing TLS public certificate (HTTPS)TLS_KEY密钥Local file path containing TLS private key (HTTPS)TLS_CALocal file path containing trusted client Certificate AuthorityNODE_TLS_REJECT_UNAUTHORIZED密钥Set to '0' to allow connection to unverified TLS endpointsREGISTRY_URLDefault container registry for workspace image resolutionTEMPLATES_DIRLocal filesystem directory containing custom YAML/JSON templatesBUILTIN_TEMPLATESEnable loading of standard pre-configured templates (default: true)AUTH_ENABLED密钥Enforce JWT verification and user tenant isolation (default: false)JWT_VERIFICATION_REQUIREDSet to 'false' to skip OIDC cryptographic signature checksJWT_SECRET密钥HMAC-SHA symmetric secret key to sign/verify JWT tokensJWT_PUBLIC_KEY密钥PEM public key to verify asymmetric OIDC signaturesJWKS_URIDiscovery URI to fetch keys from OIDC provider dynamicallyINTROSPECTION_ENDPOINTRFC 7662 compliant token introspection validation endpointOAUTH_CLIENT_ID密钥Client identifier for OAuth2 authentication flowsOAUTH_CLIENT_SECRET密钥Client secret credentials used for token introspectionJWT_AUDIENCETarget audience check value for incoming OIDC tokensAUTH_ISSUER密钥Expected token issuer authority check value (e.g. Keycloak)AUTH_SUB_JSONPATH密钥JSONPath pattern to extract user identity subject from tokenAUTH_ADMIN_ROLE密钥Bypass role name that grants admin access (default: nogoo9-admin)AUTH_ADMIN_USERS密钥Comma-separated list of user subject IDs (sub) granted admin privileges without OIDC scope/role claimsPROXY_SESSION_TTLActive lifetime in seconds for signed proxy session cookiesPROXY_SESSION_SECRET密钥Secret key for session cookie signingUI_ENABLEDServe the built-in HTML dashboard (default: true)THEMES_DIRFilesystem directory to scan for custom CSS themesTHEMES_CONFIGMAPConfigMap name storing dynamic CSS theme overridesDOCS_DIRDirectory containing static documentation web files to serveOAUTH_DISCOVERY_URL密钥Standard OIDC .well-known configuration discovery endpointOAUTH_LOGIN_METHOD密钥UI SSO flow login method: 'redirect' or silent 'iframe'UI_TITLECustom dashboard header title for white-label brandingUI_SUBTITLECustom dashboard subtitle text below the header title本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
@nogoo9/no-crd
由 Agent 驱动,在 Kubernetes 中按需编排 Pod——无需自定义资源定义。
@nogoo9/no-crd 是一款轻量、跨运行时的模型上下文协议(MCP)服务,可让 AI Agent 和 API 在标准 Kubernetes(k8s/k3s)集群上动态创建、路由至并管理临时容器化沙盒——无需自定义资源定义(CRD)、集群级运算符或提升的 RBAC 权限。
它提供类似 JupyterHub 的动态 Pod 生命周期管理,但完全不依赖具体工作负载,并支持在 Bun、Deno 和 Node.js 下跨运行时执行。
📚 如需详细指南、API 参考和配置选项,请访问公开的文档网站,或在运行服务时访问直接提供的内置文档 /docs/(例如 http://localhost:3000/docs/)。
🗺️ 选择你的路径
开始使用 @nogoo9/no-crd,请选择符合你目标的路线:
- 路线 A:AI Agent 与 MCP 用户 $\rightarrow$ MCP 客户端设置指南
- 最适合: 将
no-crd连接到 Cursor、Claude Desktop、Cline 或 Roo Code,让你的 Agent 管理 Pod。
- 最适合: 将
- 路线 B:平台与服务部署者 $\rightarrow$ SSO 与路由部署指南
- 最适合: 在 Kubernetes 集群中部署多租户沙箱服务,使用 Keycloak OIDC、无状态 Cookie 和 反向代理路由。
- 路线 C:SDK 与代码贡献者 $\rightarrow$ SDK 与贡献者指南
- 最适合: 通过 TypeScript SDK 以编程方式控制 Pod,或为核心运行时代码库做贡献。
🚀 主要功能
- 无需 CRD: 直接对接 Kubernetes 核心资源(Pod、ConfigMap、ServiceAccount)。具有高度可移植性和安全性,并兼容受限/托管环境(EKS、GKE、K3s)。
- Agent 沙箱启动器: 专用启动器工具可自动配置工作区,支持上下文验证、初始化容器、IAM 角色、停止前钩子和生命周期同步。
- 基于 ConfigMap 的模板: 将可复用的 Pod 模板作为标准 Kubernetes ConfigMap 存储、版本化和加载。
- 本地文件系统模板: 将 YAML/JSON Pod 模板打包到 Docker 镜像中,或从主机路径挂载;软件包内还附带内置默认模板。
- 同构多运行时 SDK: 可无缝作为可组合的编程 SDK 导入,也可作为 MCP 服务在 Node.js、Bun 或 Deno 下运行。
- 工作区路由代理(实验性): 内置反向代理路由,可动态将流量转发到运行中的容器 IP,并通过安全的用户令牌所有权验证、路径范围会话 Cookie(
nocr_token和nocr_sess),以及自动 HMAC 签名会话管理,确保短期令牌的稳定性。 - 实验性 JWT 身份验证: 内置 OAuth 令牌验证引擎,支持 HS256、RS256、ES256、JWKS 端点和 OAuth 2.0 令牌内省(RFC 7662)。
- 内嵌式 Web UI 应用: 提供交互式 Web Pod 管理器界面,包含浅色/深色主题切换、客户端 PKCE OIDC 登录与主动静默令牌刷新,以及工作区文件预览渲染(支持 HTML 沙箱 iframe 和自定义 Markdown 渲染)。
⚡ 快速开始
通过 NPX 独立运行(无需安装)
# Option 1: Start HTTP/SSE server on port 3000
npx @nogoo9/no-crd --transport http --port 3000
# Option 2: Run over standard input/output (stdio) for local IDE agents
npx @nogoo9/no-crd --transport stdio --mode cluster
全局安装
npm install -g @nogoo9/no-crd
nocrd9 --transport stdio --mode cluster
通过 Docker 运行
docker run -d -p 3000:3000 \
-v "$HOME/.kube/config:/app/.kube/config:ro" \
-e KUBECONFIG=/app/.kube/config \
ghcr.io/nogoo9/no-crd:latest
⚙️ 配置与环境变量
可通过 CLI 选项或环境变量配置服务和命令行工具。以下是所有设置的快速参考表:
🔌 服务配置
| CLI 选项 | 环境变量 | 默认值 | 允许的值 | 描述 |
|---|---|---|---|---|
-t, --transport | TRANSPORT | http | http, stdio, both | 服务传输模式。both 会同时启动两种传输方式。 |
-p, --port | PORT | 3000 | Number | SSE 传输的 HTTP 服务端口。 |
-H, --host | HOST | 0.0.0.0 | String | HTTP/SSE 服务绑定的主机接口。 |
--base-url | BASE_URL | "" | Path string | 用于在反向代理后托管的基础 URL 路径前缀(例如 /gateway/no-crd)。 |
| - | STATELESS | false | true, false | 启用无状态请求处理(无会话亲和性)。 |
-l, --log-level | LOG_LEVEL | info | debug, info, warning, error, fatal | 日志详细程度筛选级别。 |
| - | LOG_FILE | nogoo9-mcp.log | String | 文件日志的输出文件路径。 |
| - | RATE_LIMIT_MAX | 100 | Number | 限流路由在每个时间窗口内允许的最大请求数。 |
| - | RATE_LIMIT_WINDOW | 60000 | Number | 限流路由的时间窗口(毫秒)。 |
--proxy-timeout | PROXY_TIMEOUT | 120000 | Number | 路由代理上游请求的超时时间(毫秒)。 |
--proxy-keep-alive | PROXY_KEEP_ALIVE | true | true, false | 为路由代理上游请求启用 TCP keep-alive。 |
🔒 TLS 配置
| CLI 选项 | 环境变量 | 默认值 | 允许的值 | 描述 |
|---|---|---|---|---|
--tls-cert | TLS_CERT | - | Path string | 启用 HTTPS 的 TLS 证书文件路径。 |
--tls-key | TLS_KEY | - | Path string | 启用 HTTPS 的 TLS 私钥文件路径。 |
--tls-ca | TLS_CA | - | Path string | 用于 HTTPS 客户端验证的 TLS CA 证书文件路径。 |
| - | NODE_TLS_REJECT_UNAUTHORIZED | true | 0 (false), 1 (true) | 设置为 0 可绕过 TLS 验证(仅用于开发/测试)。 |
🌐 CORS 配置
| CLI 选项 | 环境变量 | 默认值 | 允许的值 | 描述 |
|---|---|---|---|---|
--cors-origin | CORS_ALLOWED_ORIGIN, CORS_ORIGIN | * | String | CORS 允许的来源标头。 |
--cors-methods | CORS_ALLOWED_METHODS, CORS_METHODS | GET, POST, OPTIONS | String | CORS 允许的方法标头。 |
--cors-headers | CORS_ALLOWED_HEADERS, CORS_HEADERS | Content-Type, Authorization, mcp-protocol-version, mcp-session-id | String | CORS 允许的标头。 |
--cors-allow-credentials | CORS_ALLOW_CREDENTIALS, CORS_CREDENTIALS | false | true, false | 启用 CORS Access-Control-Allow-Credentials 标头。 |
--cors-expose-headers | CORS_EXPOSED_HEADERS, CORS_EXPOSED | mcp-session-id, x-refreshed-token | String | 自定义 CORS Access-Control-Expose-Headers 标头。 |
--cors-max-age | CORS_MAX_AGE | - | Number | 自定义 CORS Access-Control-Max-Age 标头的秒数。 |
☸️ Kubernetes 配置
| CLI 选项 | 环境变量 | 默认值 | 允许的值 | 描述 |
|---|---|---|---|---|
-m, --mode | MODE | cluster | cluster、namespaced | Kubernetes 访问范围。namespaced 会将操作限制在单个命名空间内。 |
-n, --namespace | NAMESPACE, DEFAULT_NAMESPACE | nogoo9 | 字符串 | 操作的默认 Kubernetes 命名空间。 |
--disable-permission-checks | DISABLE_PERMISSION_CHECKS | false | true、false | 禁用 Kubernetes RBAC 权限检查,并假定所有工具均已启用。 |
--managed-only | MANAGED_ONLY | true | true、false | 为 true 时,Pod 工具仅操作由此服务管理的 Pod(带有 nogoo9/managed-by 标签)。任何人都无法绕过此限制,包括管理员。参见 ADR-008。 |
--default-workspace-port | DEFAULT_WORKSPACE_PORT | - | 数字 | 工作区 Pod 内部用于代理流量的默认目标端口。 |
| - | REGISTRY_URL | - | URL 字符串 | 要查询镜像的目标容器注册表 URL(例如 http://localhost:5001)。 |
| - | TEMPLATES_DIR | - | 路径字符串 | 包含 Pod 模板文件(YAML/JSON)的本地目录路径。参见 ADR-001。 |
| - | BUILTIN_TEMPLATES | true | true、false | 设为 false 可禁用软件包附带的内置模板。 |
🔑 身份验证配置
| CLI 选项 | 环境变量 | 默认值 | 允许的值 | 说明 |
|---|---|---|---|---|
--auth-enabled | AUTH_ENABLED | false | true、false | 在 MCP 工具和路由代理上启用 JWT 令牌身份验证。 |
| - | JWT_VERIFICATION_REQUIRED | true | true、false | 启用/禁用 JWT 签名验证(签名检查)。 |
| - | JWT_SECRET | - | 字符串 | 用于验证令牌的对称 HMAC-SHA256 密钥。 |
| - | JWT_PUBLIC_KEY | - | 字符串 | 用于非对称令牌验证的 PEM 编码 RSA/ECDSA 公钥。 |
| - | JWKS_URI | - | URL 字符串 | 用于动态获取验证密钥的远程 JWKS 端点 URL。 |
| - | INTROSPECTION_ENDPOINT、JWT_INTROSPECTION_ENDPOINT | - | URL 字符串 | 用于令牌内省/验证的端点。 |
| - | OAUTH_CLIENT_ID | - | 字符串 | 身份验证配置中的 OAuth 客户端 ID。 |
| - | OAUTH_CLIENT_SECRET | - | 字符串 | 身份验证配置中的 OAuth 客户端密钥。 |
| - | JWT_AUDIENCE | - | 字符串 | 预期的令牌受众。如果已设置,则回退到 OAUTH_CLIENT_ID。 |
| - | AUTH_ISSUER、JWT_ISSUER | "" | URL 字符串 | 元数据发现中公布的授权服务器标识符 URL。 |
| - | AUTH_SUB_JSONPATH | $.sub | JSONPath | 从 JWT 载荷中提取唯一用户身份的载荷路径。 |
--auth-scope-jsonpath | AUTH_SCOPE_JSONPATH | $.scope | JSONPath | 从 JWT 载荷中提取 scope 声明的载荷路径。 |
--auth-roles-jsonpath | AUTH_ROLES_JSONPATH、AUTH_ADMIN_JSONPATH | $.realm_access.roles | JSONPath | 从 JWT 载荷中提取用户角色的载荷路径。 |
| - | AUTH_ADMIN_ROLE | admin | 字符串 | 表示管理员访问权限的角色名称。 |
--auth-required-read-scope | AUTH_REQUIRED_READ_SCOPE | nogoo9:read | 字符串 | 读取操作所需的 OAuth scope。未设置时,将跳过读取 scope 检查。 |
--auth-required-write-scope | AUTH_REQUIRED_WRITE_SCOPE | nogoo9:write | 字符串 | 写入/变更操作所需的 OAuth scope。未设置时,将跳过写入 scope 检查。 |
--auth-required-admin-scope | AUTH_REQUIRED_ADMIN_SCOPE | nogoo9:admin | 字符串 | 管理员操作所需的 OAuth scope。未设置时,将跳过管理员 scope 检查。 |
| - | AUTH_ADMIN_USERS | `` | 以逗号分隔的用户主体 ID(sub)列表 | 以逗号分隔的用户主体 ID(sub)列表,这些用户无需 OIDC scope/角色声明即可获得管理员权限(备用回退方案)。 |
--auth-required-read-role | AUTH_REQUIRED_READ_ROLE | viewer | 字符串 | 读取操作所需的用户角色。未设置时,将跳过读取角色检查。 |
--auth-required-write-role | AUTH_REQUIRED_WRITE_ROLE | user | 字符串 | 写入/变更操作所需的用户角色。未设置时,将跳过写入角色检查。 |
| - | PROXY_SESSION_TTL | 1800 | 数字 | 会话 Cookie 的过期时间(秒)(滑动窗口时长)。 |
| - | PROXY_REFRESH_COOKIE_TTL | 604800 | 数字 | 加密刷新令牌 Cookie(nocr_refresh)的默认 Max-Age。若 IdP 提供 refresh_expires_in,则以其为准。 |
| - | PROXY_TOKEN_COOKIE_TTL | 86400 | 数字 | 访问令牌 Cookie(nocr_token)的默认 Max-Age。若 JWT 提供 exp 声明,则以其为准。 |
| - | PROXY_SESSION_SECRET | "" | 字符串 | 用于签署无状态会话 Cookie 的 HMAC 密钥。未配置时回退到 JWT_SECRET。 |
| - | OAUTH_SCOPES | openid profile email offline_access | 以空格分隔的 scope 字符串 | 授权期间要请求的 OAuth scope。要获取刷新令牌,请包含 'offline_access'。 |
| - | OAUTH_AUTHORIZATION_URL | - | URL 字符串 | 直接 OAuth 授权 URL。 |
| - | OAUTH_SERVER_DISCOVERY_URL、OAUTH_DISCOVERY_URL | - | URL 字符串 | 后端网关使用的 OAuth 服务发现 URL。未设置时回退到 OAUTH_DISCOVERY_URL。 |
| - | OAUTH_TOKEN_URL、OAUTH_SERVER_TOKEN_URL | - | URL 字符串 | 后端服务器的直接 OAuth 令牌交换端点。 |
| - | OAUTH_END_SESSION_URL | - | URL 字符串 | 直接 OAuth 注销端点。 |
--auth-inject-workspace-jwt | AUTH_INJECT_WORKSPACE_JWT | true | true、false | 确定是否在代理请求中注入包含原始令牌的自定义 'x-workspace-jwt' 标头。 |
| - | AUTH_DEFAULT_ROLE | viewer | 字符串 | 令牌未提供 scope/角色时使用的回退角色。 |
--max-workspaces-per-user | MAX_WORKSPACES_PER_USER | 0 | 数字 | 非管理员用户可拥有的最大并发活跃工作区数量(0 表示不限制)。 |
🖥️ UI 与主题配置
| CLI 选项 | 环境变量 | 默认值 | 允许的值 | 描述 |
|---|---|---|---|---|
| - | UI_ENABLED | true | true, false | 启用嵌入式 HTML Pod Manager UI 资源。 |
| - | THEMES_DIR | themes | 路径字符串 | 包含自定义 CSS UI 主题的本地目录路径。 |
| - | THEMES_CONFIGMAP | - | 字符串 | 包含自定义 UI 主题配置的 Kubernetes ConfigMap 名称。 |
| - | DOCS_DIR | /app/docs (Docker) or docs/.vitepress/dist (Local) | 路径字符串 | 提供静态文档文件的根目录。 |
| - | OAUTH_DISCOVERY_URL | "" | URL 字符串 | UI 客户端使用的 OAuth 授权服务器发现 URL。 |
| - | OAUTH_CLIENT_ID | "" | 字符串 | 用于 UI 授权的 OAuth 客户端 ID。 |
| - | OAUTH_LOGIN_METHOD | redirect | redirect, popup | UI OAuth 客户端的登录交互模式。 |
| - | UI_TITLE | nogoo9 Pod Manager | 字符串 | 仪表板标题栏中显示的自定义标题。 |
| - | UI_SUBTITLE | On-demand Kubernetes pod orchestration and agent-sandbox management without CRDs. | 字符串 | 仪表板标题下方显示的自定义副标题。 |
☸️ Kubernetes 配置与 RBAC 权限
要让 @nogoo9/no-crd MCP 服务与 Kubernetes 交互,必须为其授予适当的 RBAC 权限。根据配置,可以通过**集群范围(ClusterRole)访问或命名空间范围(Role)**访问来部署。
工具与权限映射
以下映射展示了每个 MCP 工具所需的 Kubernetes API 资源和操作动词。服务会在启动时动态检查这些权限(通过 SelfSubjectAccessReview),并且只注册当前身份有权使用的工具。
资源:configmaps
| 所需操作动词 | 关联的 MCP 工具 | 描述 / 用途 |
|---|---|---|
create | create_template | 将新的 Pod 模板定义保存为 ConfigMap。 |
delete | delete_template | 删除已存储的 Pod 模板 ConfigMap。 |
get | create_pod_from_template | 读取存储在 ConfigMap 中的模板 Pod 规格。 |
update | update_template | 修改现有模板的元数据、注解或规格。 |
资源:events
| 所需操作动词 | 关联的 MCP 工具 | 描述 / 用途 |
|---|---|---|
list | get_workspace_events |
资源:namespaces
| 所需操作动词 | 关联的 MCP 工具 | 描述 / 用途 |
|---|---|---|
list | list_namespaces | 发现集群中的命名空间(仅在集群访问模式下需要)。 |
资源:pods
| 所需操作动词 | 关联的 MCP 工具 | 描述 / 用途 |
|---|---|---|
create | create_pod, create_pod_from_template, spawn_workspace, upgrade_all_workspaces, upgrade_workspace | 创建并部署新的 Pod 或工作区沙箱。 |
delete | delete_pod, stop_workspace, upgrade_all_workspaces, upgrade_workspace | 终止并清理 Pod 或工作区沙箱。 |
get | get_pod, get_workspace, upgrade_workspace | 获取特定 Pod 的详细 JSON 规格。 |
list | list_pods, list_workspaces, upgrade_all_workspaces | 获取 Pod 或 Agent 工作区 Pod 列表。 |
patch | patch_pod | 对标签、注解或资源请求/限制应用战略合并补丁。 |
资源:pods/log
| 所需操作动词 | 关联的 MCP 工具 | 描述 / 用途 |
|---|---|---|
get | get_pod_logs | 获取 Pod 容器的标准输出/错误日志。 |
1. 集群范围模式(MODE=cluster)
如果要让 MCP 服务管理集群中任意命名空间的沙箱,请使用此模式。
创建 ClusterRole 和 ClusterRoleBinding:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nogoo-mcp
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch", "create", "delete", "patch", "update"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["serviceaccounts"]
verbs: ["get", "list", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: nogoo-mcp
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nogoo-mcp
subjects:
- kind: ServiceAccount
name: nogoo-mcp
namespace: nogoo9 # Change to the namespace where your MCP server runs
2. 命名空间范围模式(MODE=namespaced)
如果 MCP 服务应限制在单个命名空间(例如 nogoo9),请使用此模式。在此模式下,无需集群级或管理权限。
在目标命名空间中创建 Role 和 RoleBinding:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: nogoo-mcp
namespace: nogoo9
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch", "create", "delete", "patch", "update"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["serviceaccounts"]
verbs: ["get", "list", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: nogoo-mcp
namespace: nogoo9
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: nogoo-mcp
subjects:
- kind: ServiceAccount
name: nogoo-mcp
namespace: nogoo9
(注意:在命名空间范围模式下,list_namespaces 工具只会返回目标命名空间,并且所有工具的命名空间参数输入都将默认使用目标命名空间。)
📑 工作区模板与生成器注解
@nogoo9/no-crd 中的模板可从三个来源加载(按优先级从高到低):
- Kubernetes ConfigMaps — 使用
nogoo9/pod-template: "true"标签(原始机制) - 自定义本地目录 — 通过
TEMPLATES_DIR环境变量设置(YAML 或 JSON 文件) - 内置模板 — 随 npm 包一同提供(使用
BUILTIN_TEMPLATES=false禁用)
格式详情请参阅 ADR-001。
1. 如何定义模板
要向生成器注册模板,请创建一个满足以下要求的 ConfigMap:
- 发现标签:必须带有
nogoo9/pod-template: "true"标签。 - Spec 键:
data块必须包含名为spec的键,其值为符合PodSpecSchema的 JSON 字符串(例如containers、volumes、restartPolicy)。 - 行为自定义:在
ConfigMap元数据上设置annotations,以配置高级生成器集成(例如 IAM 角色绑定、init 容器和 pre-stop 生命周期钩子)。
模板定义示例:
apiVersion: v1
kind: ConfigMap
metadata:
name: node-workspace-template
namespace: nogoo9
labels:
nogoo9/pod-template: "true"
annotations:
nogoo9/description: "A standard Node.js development sandbox with S3 storage sync"
nogoo9/tag: "node-20"
nogoo9/required-context: "PROJECT_NAME,REPO_URL"
nogoo9/iam-role-arn: "arn:aws:iam::123456789012:role/workspace-s3-access"
nogoo9/init-image: "alpine/git"
nogoo9/init-command: "git clone $REPO_URL /workspace/$PROJECT_NAME"
nogoo9/pre-stop-command: "aws s3 sync /workspace s3://my-workspace-backups/$PROJECT_NAME"
nogoo9/default-grace-period: "120"
data:
spec: |
{
"containers": [
{
"name": "workspace",
"image": "node:20-alpine",
"command": ["sleep", "infinity"],
"volumeMounts": [
{
"name": "workspace-storage",
"mountPath": "/workspace"
}
]
}
],
"volumes": [
{
"name": "workspace-storage",
"emptyDir": {}
}
]
}
2. 支持的生成器注解
生成器会检查 ConfigMap 元数据注解(以及在 spawn_workspace 期间传入的自定义内联注解),以自定义工作区生命周期:
| 注解 / 标签键 | 类型 | 描述 |
|---|---|---|
nogoo9/workspace-auth-mode | 注解(逗号分隔) | 配置工作区代理的授权模式。逗号分隔的列表,包含:token-api(在 _auth/token 和 _auth/authorize 暴露令牌获取端点,供 SPA 使用)、inject-headers(重写标头,将 x-user-sub 等用户身份信息和 JWT 转发到容器;当 AUTH_ENABLED=true 时默认启用)、no-auth(跳过公共工作区的所有身份验证 / 所有者检查)。(自 v0.6.0 起可用,no-auth 自 v0.8.0 起可用) |
nogoo9/auth-require-token | 注解("true" | "false") |
nogoo9/template-version | 注解(字符串) | 指定 Pod 模板的版本。用于跟踪工作区是否已过时。(自 v0.8.0 起可用) |
nogoo9/workspace-name | 注解(字符串) | 存储用户定义的工作区显示名称。(自 v0.4.0 起可用) |
nogoo9/template-ref | 注解(字符串) | 用于启动工作区的 Pod 模板引用(例如 default/workspace-terminal)。(自 v0.4.0 起可用) |
nogoo9/managed-by | 标签(字符串) | 用于标记由此 MCP 服务创建的工作区 Pod,以限制操作范围。(自 v0.5.0 起可用) |
nogoo9/pod-template | 标签("true") | 将 Kubernetes ConfigMap 标识为可复用的 Pod 模板。 |
nogoo9/type | 标签("workspace") | 由启动器自动添加,用于标识正在运行的 Agent 工作区 Pod。 |
nogoo9/workspace-id | 标签 | 标识与正在运行的 Pod 关联的唯一 Agent 会话 / 工作区 ID。 |
nogoo9/user-sub | 标签 / 注解 | 表示工作区 Pod 的经过身份验证的用户主体(所有者),用于访问控制验证和 ServiceAccount 标记。 |
nogoo9/description | 注解(字符串) | 对模板用途和内容的简明易读说明。 |
nogoo9/tag | 注解(字符串) | 与模板环境关联的版本或标签(例如 node-20)。 |
nogoo9/required-context | 注解(逗号分隔) | 验证工具调用的 context 参数中是否提供了目标环境变量(例如 GITHUB_TOKEN,DATABASE_URL)。 |
nogoo9/iam-role-arn | 注解(AWS Role ARN) | 指示启动器创建专用 Kubernetes ServiceAccount,并为其添加 EKS IAM Role 映射注解(IRSA)。 |
nogoo9/init-image | 注解(镜像字符串) | 在动态 spawner-init init-container 中运行的容器镜像。 |
nogoo9/init-command | 注解(Shell 命令) | 在 init-container 中运行的 Shell 命令。它会自动共享主容器的卷挂载。 |
nogoo9/init-share-volumes | 注解("true" | "false") |
nogoo9/pre-stop-command | 注解(Shell 命令) | 工作区终止时,在 Kubernetes preStop 生命周期 exec 钩子中执行的 Shell 命令(例如保存 / 推送状态)。 |
nogoo9/pre-stop-sidecar-image | 注解(镜像字符串) | 如果与 pre-stop-command 一起指定,则在专用 sidecar 容器中而不是主容器中运行 pre-stop 命令。 |
nogoo9/default-grace-period | 注解(秒数) | 覆盖 Pod 的 terminationGracePeriodSeconds(如果定义了 pre-stop 命令,默认值为 60),以留出足够时间完成清理命令。 |
nogoo9/workspace-port | 注解(数字) | 容器内供代理转发流量的端口。默认为 DEFAULT_WORKSPACE_PORT 或 3000。 |
nogoo9/workspace-path | 注解(字符串) | 工作区 Web 界面的默认 URL 子路径映射(默认为 /)。 |
nogoo9/workspace-type | 注解(字符串) | 主入口点的格式规范(例如 iframe、novnc)。 |
nogoo9/preview-path | 注解(字符串) | 在 UI 文件预览标签页中呈现的默认文件夹或文件子路径。 |
nogoo9/preview-type | 注解(字符串) | 预览标签页的备用预览渲染模式(例如 markdown、html)。 |
nogoo9/api.<api-name>.port | 注解(数字) | 定义工作区额外暴露的 HTTP 服务端口。 |
nogoo9/api.<api-name>.visibility | 注解(字符串) | 指定自定义 API 端点的访问可见性。支持的值:private(仅工作区所有者可访问)、internal(任何已登录用户均可访问)、admin(所有者或具有管理员作用域和角色的用户可访问)、scope:<scope_name>(具有指定 OIDC 作用域的用户可访问)、role:<role_name>(具有指定用户角色的用户可访问),或以逗号分隔的允许访问的用户主体列表。 |
nogoo9/api.<api-name>.path | 注解(字符串) | 定义此 API 的子路径路由前缀(例如 /terminal)。 |
nogoo9/api.<api-name>.desc | 注解(字符串) | 对此额外 API 的简短说明,会显示在 UI 界面中。 |
nogoo9/api.<api-name>.method | 注解(字符串) | 支持的 HTTP 方法的逗号分隔列表(例如 GET,POST、*;默认为任意方法)。 |
nogoo9/api.<api-name>.refresh | 注解(时长) | 设置仪表板卡片中自定义统计数据 / 活动信息或其他迷你 API 视图的刷新频率(例如 10s、1m,或设为 init 以仅在启动时查询一次)。 |
nogoo9/api.stats.refresh | 注解(时长) | 明确配置工作区仪表板卡片中保留的 stats API 指标的重新加载频率(例如 10s、30s、init)。 |
nogoo9/api.last_activity.refresh | 注解(时长) | 明确配置工作区仪表板卡片中保留的 last_activity Epoch 时间戳 API 的重新加载频率(例如 30s、1m、init)。 |
nogoo9/allowed-roles | 注解(逗号分隔) | 允许从此模板启动工作区的用户角色的逗号分隔列表(例如 developer,lead-dev)。管理员始终不受角色限制。 |
nogoo9/allowed-scopes | 注解(逗号分隔) | 允许从此模板启动工作区的 OAuth 作用域的逗号分隔列表(例如 nogoo9:write)。管理员始终不受作用域限制。 |
📦 编程 SDK 与 API 代理服务
@nogoo9/no-crd 提供完整的编程 SDK 和动态集群路由代理,让开发者能够构建自定义 Pod 编排器,并原生路由工作区流量。
1. 可组合的编程 SDK
你可以在 Bun、Deno 或 Node.js 代码库中导入 @nogoo9/no-crd,以编程方式控制 Pod 沙箱和模板,无需经过 MCP HTTP 服务。
import { KubeConfig } from "@kubernetes/client-node";
import {
initK8sContext,
spawnWorkspace,
stopWorkspace,
listWorkspaces
} from "@nogoo9/no-crd";
// 1. Initialize Kubernetes API Context (optionally pass custom configuration)
const kc = new KubeConfig();
kc.loadFromDefault();
const ctx = initK8sContext(kc);
// 2. Spawn a workspace sandbox from a template
const spawnResult = await spawnWorkspace(ctx, {
id: "agent-session-42",
templateRef: "nogoo9/default-agent-workspace",
context: {
"S3_BUCKET": "my-bucket",
"S3_FOLDER": "session-42"
}
});
console.log(`Spawned pod: ${spawnResult.podName}`);
// 3. List active workspaces running in the namespace
const list = await listWorkspaces(ctx, {
namespace: "nogoo9"
});
console.log(`Active workspaces count: ${list.workspaces.length}`);
// 4. Terminate the workspace sandbox
await stopWorkspace(ctx, {
id: "agent-session-42"
});
2. 工作区路由代理(实验性)
警告
工作区路由代理和 JWT 身份验证引擎均为实验性功能,可能会在下一个版本中发生变化。
服务内置了反向代理路由服务。目标地址为
http://<mcp-server-host>/route/<workspace-id>/<subpath>
的 HTTP 请求会被动态直接代理到集群内运行中的工作区 Pod 的 IP 地址。
如果 AUTH_ENABLED 为 true:
- 令牌引导与路径范围 Cookie:由于标准浏览器导航(链接、iframe)无法传输自定义 HTTP 标头,客户端会在初始重定向时通过
?token=查询参数传递有效的 JWT。代理会验证该令牌并签发安全的路径范围 Cookie(nocr_token),使后续资源请求(JS、CSS、图片、WebSocket)无需 URL 参数即可顺利完成身份验证。 - 直接访问重定向(SSO):在没有有效凭据的情况下直接访问工作区 URL,会将你重定向到主控制面板的登录界面。登录后,控制面板会自动将你路由回目标工作区 URL,并附上新的引导令牌。
- 资源所有权验证:工作区 Pod 的
nogoo9/user-sub标签必须与 JWT 的 subject 声明匹配,以防止未经授权访问其他用户的工作区。 - 代理目标端口:工作区 Pod 内的默认端口为
3000,也可通过 Pod 注解nogoo9/workspace-port或环境变量DEFAULT_WORKSPACE_PORT覆盖。 - 多端口/自定义 API 路由:你可以通过在模板中定义自定义注解(例如
nogoo9/api.terminal.port: "7681"、nogoo9/api.terminal.path: "/terminal"),在 Pod 中公开并路由其他 API(例如 Web 终端或辅助服务)。代理会动态处理子路径路由和方法检查。 - 首次成功验证 JWT 后会创建一个无状态签名会话 Cookie(
nocr_sess),使工作区流量能够在短期令牌过期后继续使用。(v0.4.0 起提供) 有关设计详情,请参阅 ADR-002 和 ADR-003。
有关重定向生命周期、Keycloak 配置和 JWT 声明的详细说明,请参阅 SSO 与 OIDC 集成指南。
3. OAuth 资源发现(RFC 9728)
公开标准化元数据端点 GET /.well-known/oauth-protected-resource,返回:
- 支持的授权服务器。
- 令牌格式规范。
- 必需的作用域。
这使客户端界面(以及 MCP 客户端)能够自动发现安全要求并处理动态 OAuth 身份验证流程。
4. 内嵌 Web UI 与仪表板主题
服务器以 HTTP/SSE 传输模式运行时,视觉化的 React Pod Manager UI 仪表板会直接在根路径 / 提供服务(例如 http://localhost:3000/)。
- 仪表板主题:UI 包含系统/浅色/深色切换功能,并支持自定义视觉主题。
- 三源主题合并引擎:动态扫描并合并以下来源的 CSS 样式表:
- Kubernetes ConfigMap(
THEMES_CONFIGMAP环境变量)。 - 自定义本地目录(
THEMES_DIR环境变量,默认为themes/)。 - 内置目录(预置样式:Dracula、Nord、Stripe、Slack、Vercel、Apple、Superhuman、Notion 和 Antigravity)。
- Kubernetes ConfigMap(
重复的主题 ID 按以下优先级处理:ConfigMap > 本地目录 > 内置目录。有关详细的自定义指南和 CSS 模板,请参阅 仪表板主题与品牌指南。
🔌 API 参考(MCP 工具与资源)
Pod 工具
list_pods:获取命名空间中的 Pod 摘要。支持按labelSelector、fieldSelector和limit筛选。get_pod:获取目标 Pod 名称对应的完整 Kubernetes API JSON 负载。create_pod:直接指定容器/卷配置,创建自定义 Pod。patch_pod:应用 Strategic Merge Patch,动态修改标签、注释或容器资源限制。delete_pod:终止 Pod,可选设置gracePeriodSeconds。get_pod_logs:获取容器日志,支持tailLines、sinceSeconds、timestamps、limitBytes和previous等选项。list_namespaces:列出当前凭据可访问的所有命名空间。list_registry_images:列出已配置的REGISTRY_URL中的目录镜像。
Pod 模板工具
管理以标准 Kubernetes ConfigMap 形式存储的预配置 Pod 规格(带有 nogoo9/pod-template=true 标签)。
list_templates:显示可用模板。get_template:获取原始 Pod 模板规格。create_template:存储新的 Pod 模板规格。update_template:更新现有模板的标签、注释或规格。delete_template:删除模板。create_pod_from_template:使用模板创建 Pod,并应用容器覆盖项(环境变量、命令、资源)和顶层覆盖项。
Agent 工作区(Spawner)工具
专为 AI Agent 设计,可安全地创建和清理自己的工作区沙箱。
list_workspaces:列出活动的 Agent 工作区(支持 JWT/所有者映射)。spawn_workspace:创建工作区沙箱 Pod。功能包括:- 上下文验证(
nogoo9/required-context):要求调用方在创建前提供关键环境变量(例如 API 密钥)。 - 初始化容器(
nogoo9/init-image/nogoo9/init-command):在主容器启动前初始化工作区目录/文件。 - 停止前钩子(
nogoo9/pre-stop-command):终止时运行自定义清理命令(例如将代码提交/同步到 git 或 S3)。 - IAM 角色映射(
nogoo9/iam-role-arn):动态配置 AWS EKS IAM 角色服务账户。
- 上下文验证(
stop_workspace:清理并终止工作区 Pod。
实用工具
current_namespace:返回当前命名空间和访问模式。
MCP 资源
pod-template://{namespace}/{name}:将存储的 Pod 模板作为只读 MCP 资源直接公开。ui://nogoo9/app:公开内嵌的 React/Web UI 应用(需设置UI_ENABLED=true且已构建)。服务器以 HTTP/SSE 传输模式运行时,UI 也会直接在/或/ui提供服务(例如http://localhost:3000/);当 UI 在不兼容 postMessage 的 MCP 宿主之外加载时(例如在标准浏览器标签页或 MCP Inspector 中),会自动回退到标准 HTTP JSON-RPC 调用。
🏗️ 架构
┌───────────────────────┐
│ AI Agent / Client │
└───────────┬───────────┘
│ (Stdio or SSE Transport)
▼
┌───────────────────────┐
│ MCP Server │ <── (Queries ConfigMaps for specs)
└───────────┬───────────┘
│ (Kubernetes API - CoreV1)
▼
┌──────────────────────────────────────────┐
│ Kubernetes Cluster │
│ ┌────────────────────────────────────┐ │
│ │ Target Namespace │ │
│ │ ┌──────────┐ ┌──────────┐ ┌────┐ │ │
│ │ │ Agent │ │ Custom │ │ │ │ │
│ │ │ Sandbox │ │ Workload │ │... │ │ │
│ │ │ Pod │ │ Pod │ │ │ │ │
│ │ └──────────┘ └──────────┘ └────┘ │ │
│ └────────────────────────────────────┘ │
└──────────────────────────────────────────┘
服务使用 @kubernetes/client-node 直接与 Kubernetes API 交互。通过使用标准的 Pod 和 ConfigMap 资源,该方案具有很强的可扩展性,无需安装集群运算符,并且能够轻松遵循严格的企业级命名空间安全策略。
🛠️ 开发
我们使用 Moon 管理工具链和运行任务,并使用 Biome 进行格式化和代码检查。
先决条件
- Bun
1.3.11+ - Node.js
22.14.0+ - Moon
2.1.3+ - k3d(用于本地 Kubernetes 集群)
设置环境
# Install dependencies
bun install
# Auto-fix code formatting and linting via Biome
bun run format
# Run TypeScript compilation checks
bun run typecheck
运行测试
# Run unit tests
moon run mcp:test
# Run full spawner workspace lifecycle tests (requires local k3d)
bun run test:lifecycle
本地集群测试(k3d)
启动本地 k3d Kubernetes 集群,其中包含本地注册表、内置的 S3 模拟服务和 Traefik:
# Spin up development cluster
moon run k3d:bootstrap
# Rebuild, push, and deploy MCP server to the cluster
moon run mcp:deploy
# Tear down the cluster
moon run k3d:teardown
📄 许可证
本项目采用 Apache License 2.0 许可。详情请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。