mcpField
N
no-crd

no-crd

本地服务
github.com/nogoo9云与基础设施211 周前更新

关于 no-crd

no-crd 是面向 AI Agent 和平台团队的 MCP 服务与 TypeScript SDK,可在 Kubernetes 上创建、路由和管理临时容器工作区,无需 CRD 或集群 Operator。它支持多种 JavaScript 运行时,并提供模板化 Pod 配置和实验性路由代理。

主要功能

  1. 01创建和管理 Kubernetes Pod
  2. 02使用模板配置工作区
  3. 03将流量路由到运行中的工作区
  4. 04支持 Node.js、Bun 和 Deno
  5. 05内置 Pod 管理网页界面

适用场景

  1. 01为 AI Agent 创建临时沙箱
  2. 02管理标准 Kubernetes 集群中的 Pod
  3. 03将用户流量路由至活动容器工作区

MCP 相关

向 MCP 客户端提供 Kubernetes Pod 和工作区管理能力,支持 HTTP/SSE 与 stdio 传输。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"nogoo9-no-crd": {
"command": "npx",
"args": [
"-y",
"@nogoo9/no-crd"
],
"env": {
"KUBECONFIG": "<KUBECONFIG>",
"BASE_URL": "<BASE_URL>",
"STATELESS": "<STATELESS>",
"TLS_CERT": "<TLS_CERT>",
"TLS_KEY": "<TLS_KEY>",
"TLS_CA": "<TLS_CA>",
"NODE_TLS_REJECT_UNAUTHORIZED": "<NODE_TLS_REJECT_UNAUTHORIZED>",
"REGISTRY_URL": "<REGISTRY_URL>",
"TEMPLATES_DIR": "<TEMPLATES_DIR>",
"BUILTIN_TEMPLATES": "<BUILTIN_TEMPLATES>",
"AUTH_ENABLED": "<AUTH_ENABLED>",
"JWT_VERIFICATION_REQUIRED": "<JWT_VERIFICATION_REQUIRED>",
"JWT_SECRET": "<JWT_SECRET>",
"JWT_PUBLIC_KEY": "<JWT_PUBLIC_KEY>",
"JWKS_URI": "<JWKS_URI>",
"INTROSPECTION_ENDPOINT": "<INTROSPECTION_ENDPOINT>",
"OAUTH_CLIENT_ID": "<OAUTH_CLIENT_ID>",
"OAUTH_CLIENT_SECRET": "<OAUTH_CLIENT_SECRET>",
"JWT_AUDIENCE": "<JWT_AUDIENCE>",
"AUTH_ISSUER": "<AUTH_ISSUER>",
"AUTH_SUB_JSONPATH": "<AUTH_SUB_JSONPATH>",
"AUTH_ADMIN_ROLE": "<AUTH_ADMIN_ROLE>",
"AUTH_ADMIN_USERS": "<AUTH_ADMIN_USERS>",
"PROXY_SESSION_TTL": "<PROXY_SESSION_TTL>",
"PROXY_SESSION_SECRET": "<PROXY_SESSION_SECRET>",
"UI_ENABLED": "<UI_ENABLED>",
"THEMES_DIR": "<THEMES_DIR>",
"THEMES_CONFIGMAP": "<THEMES_CONFIGMAP>",
"DOCS_DIR": "<DOCS_DIR>",
"OAUTH_DISCOVERY_URL": "<OAUTH_DISCOVERY_URL>",
"OAUTH_LOGIN_METHOD": "<OAUTH_LOGIN_METHOD>",
"UI_TITLE": "<UI_TITLE>",
"UI_SUBTITLE": "<UI_SUBTITLE>"
}
}
}
}
启动命令npx -y @nogoo9/no-crd
需要配置的环境变量
KUBECONFIGPath to the Kubernetes API credentials configuration file
BASE_URLHosting URL subpath prefix for gateways and reverse proxies
STATELESSDisable in-memory session tracking for stateless execution
TLS_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 Authority
NODE_TLS_REJECT_UNAUTHORIZED密钥Set to '0' to allow connection to unverified TLS endpoints
REGISTRY_URLDefault container registry for workspace image resolution
TEMPLATES_DIRLocal filesystem directory containing custom YAML/JSON templates
BUILTIN_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 checks
JWT_SECRET密钥HMAC-SHA symmetric secret key to sign/verify JWT tokens
JWT_PUBLIC_KEY密钥PEM public key to verify asymmetric OIDC signatures
JWKS_URIDiscovery URI to fetch keys from OIDC provider dynamically
INTROSPECTION_ENDPOINTRFC 7662 compliant token introspection validation endpoint
OAUTH_CLIENT_ID密钥Client identifier for OAuth2 authentication flows
OAUTH_CLIENT_SECRET密钥Client secret credentials used for token introspection
JWT_AUDIENCETarget audience check value for incoming OIDC tokens
AUTH_ISSUER密钥Expected token issuer authority check value (e.g. Keycloak)
AUTH_SUB_JSONPATH密钥JSONPath pattern to extract user identity subject from token
AUTH_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 claims
PROXY_SESSION_TTLActive lifetime in seconds for signed proxy session cookies
PROXY_SESSION_SECRET密钥Secret key for session cookie signing
UI_ENABLEDServe the built-in HTML dashboard (default: true)
THEMES_DIRFilesystem directory to scan for custom CSS themes
THEMES_CONFIGMAPConfigMap name storing dynamic CSS theme overrides
DOCS_DIRDirectory containing static documentation web files to serve
OAUTH_DISCOVERY_URL密钥Standard OIDC .well-known configuration discovery endpoint
OAUTH_LOGIN_METHOD密钥UI SSO flow login method: 'redirect' or silent 'iframe'
UI_TITLECustom dashboard header title for white-label branding
UI_SUBTITLECustom dashboard subtitle text below the header title

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@nogoo9/no-crd0.18.0

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

@nogoo9/no-crd

nogoo9 徽标

no-crd 仪表板

由 Agent 驱动,在 Kubernetes 中按需编排 Pod——无需自定义资源定义。

npm 版本 npm 下载量 文档 许可证 覆盖率状态 OpenSSF 评分卡 Semgrep

模型上下文协议 使用 Antigravity 构建 由 Gemini 提供支持

Bun Deno Node.js

@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, --transportTRANSPORThttphttp, stdio, both服务传输模式。both 会同时启动两种传输方式。
-p, --portPORT3000NumberSSE 传输的 HTTP 服务端口。
-H, --hostHOST0.0.0.0StringHTTP/SSE 服务绑定的主机接口。
--base-urlBASE_URL""Path string用于在反向代理后托管的基础 URL 路径前缀(例如 /gateway/no-crd)。
-STATELESSfalsetrue, false启用无状态请求处理(无会话亲和性)。
-l, --log-levelLOG_LEVELinfodebug, info, warning, error, fatal日志详细程度筛选级别。
-LOG_FILEnogoo9-mcp.logString文件日志的输出文件路径。
-RATE_LIMIT_MAX100Number限流路由在每个时间窗口内允许的最大请求数。
-RATE_LIMIT_WINDOW60000Number限流路由的时间窗口(毫秒)。
--proxy-timeoutPROXY_TIMEOUT120000Number路由代理上游请求的超时时间(毫秒)。
--proxy-keep-alivePROXY_KEEP_ALIVEtruetrue, false为路由代理上游请求启用 TCP keep-alive。
🔒 TLS 配置
CLI 选项环境变量默认值允许的值描述
--tls-certTLS_CERT-Path string启用 HTTPS 的 TLS 证书文件路径。
--tls-keyTLS_KEY-Path string启用 HTTPS 的 TLS 私钥文件路径。
--tls-caTLS_CA-Path string用于 HTTPS 客户端验证的 TLS CA 证书文件路径。
-NODE_TLS_REJECT_UNAUTHORIZEDtrue0 (false), 1 (true)设置为 0 可绕过 TLS 验证(仅用于开发/测试)。
🌐 CORS 配置
CLI 选项环境变量默认值允许的值描述
--cors-originCORS_ALLOWED_ORIGIN, CORS_ORIGIN*StringCORS 允许的来源标头。
--cors-methodsCORS_ALLOWED_METHODS, CORS_METHODSGET, POST, OPTIONSStringCORS 允许的方法标头。
--cors-headersCORS_ALLOWED_HEADERS, CORS_HEADERSContent-Type, Authorization, mcp-protocol-version, mcp-session-idStringCORS 允许的标头。
--cors-allow-credentialsCORS_ALLOW_CREDENTIALS, CORS_CREDENTIALSfalsetrue, false启用 CORS Access-Control-Allow-Credentials 标头。
--cors-expose-headersCORS_EXPOSED_HEADERS, CORS_EXPOSEDmcp-session-id, x-refreshed-tokenString自定义 CORS Access-Control-Expose-Headers 标头。
--cors-max-ageCORS_MAX_AGE-Number自定义 CORS Access-Control-Max-Age 标头的秒数。
☸️ Kubernetes 配置
CLI 选项环境变量默认值允许的值描述
-m, --modeMODEclustercluster、namespacedKubernetes 访问范围。namespaced 会将操作限制在单个命名空间内。
-n, --namespaceNAMESPACE, DEFAULT_NAMESPACEnogoo9字符串操作的默认 Kubernetes 命名空间。
--disable-permission-checksDISABLE_PERMISSION_CHECKSfalsetrue、false禁用 Kubernetes RBAC 权限检查,并假定所有工具均已启用。
--managed-onlyMANAGED_ONLYtruetrue、false为 true 时,Pod 工具仅操作由此服务管理的 Pod(带有 nogoo9/managed-by 标签)。任何人都无法绕过此限制,包括管理员。参见 ADR-008。
--default-workspace-portDEFAULT_WORKSPACE_PORT-数字工作区 Pod 内部用于代理流量的默认目标端口。
-REGISTRY_URL-URL 字符串要查询镜像的目标容器注册表 URL(例如 http://localhost:5001)。
-TEMPLATES_DIR-路径字符串包含 Pod 模板文件(YAML/JSON)的本地目录路径。参见 ADR-001。
-BUILTIN_TEMPLATEStruetrue、false设为 false 可禁用软件包附带的内置模板。
🔑 身份验证配置
CLI 选项环境变量默认值允许的值说明
--auth-enabledAUTH_ENABLEDfalsetrue、false在 MCP 工具和路由代理上启用 JWT 令牌身份验证。
-JWT_VERIFICATION_REQUIREDtruetrue、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$.subJSONPath从 JWT 载荷中提取唯一用户身份的载荷路径。
--auth-scope-jsonpathAUTH_SCOPE_JSONPATH$.scopeJSONPath从 JWT 载荷中提取 scope 声明的载荷路径。
--auth-roles-jsonpathAUTH_ROLES_JSONPATH、AUTH_ADMIN_JSONPATH$.realm_access.rolesJSONPath从 JWT 载荷中提取用户角色的载荷路径。
-AUTH_ADMIN_ROLEadmin字符串表示管理员访问权限的角色名称。
--auth-required-read-scopeAUTH_REQUIRED_READ_SCOPEnogoo9:read字符串读取操作所需的 OAuth scope。未设置时,将跳过读取 scope 检查。
--auth-required-write-scopeAUTH_REQUIRED_WRITE_SCOPEnogoo9:write字符串写入/变更操作所需的 OAuth scope。未设置时,将跳过写入 scope 检查。
--auth-required-admin-scopeAUTH_REQUIRED_ADMIN_SCOPEnogoo9:admin字符串管理员操作所需的 OAuth scope。未设置时,将跳过管理员 scope 检查。
-AUTH_ADMIN_USERS``以逗号分隔的用户主体 ID(sub)列表以逗号分隔的用户主体 ID(sub)列表,这些用户无需 OIDC scope/角色声明即可获得管理员权限(备用回退方案)。
--auth-required-read-roleAUTH_REQUIRED_READ_ROLEviewer字符串读取操作所需的用户角色。未设置时,将跳过读取角色检查。
--auth-required-write-roleAUTH_REQUIRED_WRITE_ROLEuser字符串写入/变更操作所需的用户角色。未设置时,将跳过写入角色检查。
-PROXY_SESSION_TTL1800数字会话 Cookie 的过期时间(秒)(滑动窗口时长)。
-PROXY_REFRESH_COOKIE_TTL604800数字加密刷新令牌 Cookie(nocr_refresh)的默认 Max-Age。若 IdP 提供 refresh_expires_in,则以其为准。
-PROXY_TOKEN_COOKIE_TTL86400数字访问令牌 Cookie(nocr_token)的默认 Max-Age。若 JWT 提供 exp 声明,则以其为准。
-PROXY_SESSION_SECRET""字符串用于签署无状态会话 Cookie 的 HMAC 密钥。未配置时回退到 JWT_SECRET。
-OAUTH_SCOPESopenid 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-jwtAUTH_INJECT_WORKSPACE_JWTtruetrue、false确定是否在代理请求中注入包含原始令牌的自定义 'x-workspace-jwt' 标头。
-AUTH_DEFAULT_ROLEviewer字符串令牌未提供 scope/角色时使用的回退角色。
--max-workspaces-per-userMAX_WORKSPACES_PER_USER0数字非管理员用户可拥有的最大并发活跃工作区数量(0 表示不限制)。
🖥️ UI 与主题配置
CLI 选项环境变量默认值允许的值描述
-UI_ENABLEDtruetrue, false启用嵌入式 HTML Pod Manager UI 资源。
-THEMES_DIRthemes路径字符串包含自定义 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_METHODredirectredirect, popupUI OAuth 客户端的登录交互模式。
-UI_TITLEnogoo9 Pod Manager字符串仪表板标题栏中显示的自定义标题。
-UI_SUBTITLEOn-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 工具描述 / 用途
createcreate_template将新的 Pod 模板定义保存为 ConfigMap。
deletedelete_template删除已存储的 Pod 模板 ConfigMap。
getcreate_pod_from_template读取存储在 ConfigMap 中的模板 Pod 规格。
updateupdate_template修改现有模板的元数据、注解或规格。
资源:events
所需操作动词关联的 MCP 工具描述 / 用途
listget_workspace_events
资源:namespaces
所需操作动词关联的 MCP 工具描述 / 用途
listlist_namespaces发现集群中的命名空间(仅在集群访问模式下需要)。
资源:pods
所需操作动词关联的 MCP 工具描述 / 用途
createcreate_pod, create_pod_from_template, spawn_workspace, upgrade_all_workspaces, upgrade_workspace创建并部署新的 Pod 或工作区沙箱。
deletedelete_pod, stop_workspace, upgrade_all_workspaces, upgrade_workspace终止并清理 Pod 或工作区沙箱。
getget_pod, get_workspace, upgrade_workspace获取特定 Pod 的详细 JSON 规格。
listlist_pods, list_workspaces, upgrade_all_workspaces获取 Pod 或 Agent 工作区 Pod 列表。
patchpatch_pod对标签、注解或资源请求/限制应用战略合并补丁。
资源:pods/log
所需操作动词关联的 MCP 工具描述 / 用途
getget_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 中的模板可从三个来源加载(按优先级从高到低):

  1. Kubernetes ConfigMaps — 使用 nogoo9/pod-template: "true" 标签(原始机制)
  2. 自定义本地目录 — 通过 TEMPLATES_DIR 环境变量设置(YAML 或 JSON 文件)
  3. 内置模板 — 随 npm 包一同提供(使用 BUILTIN_TEMPLATES=false 禁用)

格式详情请参阅 ADR-001。

1. 如何定义模板

要向生成器注册模板,请创建一个满足以下要求的 ConfigMap:

  1. 发现标签:必须带有 nogoo9/pod-template: "true" 标签。
  2. Spec 键:data 块必须包含名为 spec 的键,其值为符合 PodSpecSchema 的 JSON 字符串(例如 containers、volumes、restartPolicy)。
  3. 行为自定义:在 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 样式表:
    1. Kubernetes ConfigMap(THEMES_CONFIGMAP 环境变量)。
    2. 自定义本地目录(THEMES_DIR 环境变量,默认为 themes/)。
    3. 内置目录(预置样式:Dracula、Nord、Stripe、Slack、Vercel、Apple、Superhuman、Notion 和 Antigravity)。

重复的主题 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。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。