feat(functions): two-phase ZIP deploy via presigned COS upload - #1084
Conversation
What: - queryFunctions: new getFunctionUploadUrl action (phase A) that resolves the environment's own COS bucket (DescribeEnvs) and mints a presigned PUT URL with the caller's credentials - manageFunctions: new code input (cosBucketName/cosObjectName/ cosBucketRegion) for createFunction/updateFunctionCode (phase B), wired to deployMode=cos; strict schema, cloud-mode gate allows it - new pure module function-cos-upload.ts replicates the COS q-sign algorithm (no new dependency); tests include golden-value comparison against cos-nodejs-sdk-v5 getAuth for permanent keys and session tokens - i18n (zh/en) for the new action, schema fields, and follow-up guidance; regenerated scripts/tools.json and doc/mcp-tools.md Why: - hosted/cloud mode callers previously had no way to deploy function code without a local directory or the 20MB inline zipFile limit; a presigned upload to the environment bucket removes both limits without new CAM permissions or exposing the appId How to verify: - cd mcp && npx vitest run src/tools/function-cos-upload.test.ts src/tools/functions.test.ts (81 tests, incl. SDK golden values and cloud-mode gate cases) - npx tsc --noEmit && npm run build:webpack - live: getFunctionUploadUrl -> PUT zip -> manageFunctions code deploy verified against a scratch function (create + update, invoke OK)
|
Cloud-mode verification: ran the built server with
Both create and update paths deploy real code end-to-end in cloud mode with no local directory involved. Driver script: |
What: - resolveEnvFunctionCosStorage now falls back to the env-scoped DescribeEnvInfo (EnvInfo.EnvBaseInfo.Storages, same shape as DescribeEnvs Storages) when DescribeEnvs fails or returns nothing - test mock covers both actions Why: - DescribeEnvs is an account-level action; env-scoped credentials (e.g. STS exchanged from an API Key, as remote MCP uses) get rejected by the gateway. The fallback keeps the presigned-upload flow working under those credentials. How to verify: - cd mcp && npx vitest run src/tools/functions.test.ts (81 passed) - live: with CLOUDBASE_API_KEY credentials, full two-phase flow (getFunctionUploadUrl -> PUT -> createFunction/updateFunctionCode with code) verified end-to-end; Invoke returned the uploaded marker on both create and update
|
Remote-MCP-style verification (ephemeral API Key credentials): ran the built server with
So the two-phase flow works under API-Key credentials with zero local directory. |
|
OAuth 登录态路径 E2E 实测(两段式 ZIP 部署) 场景:hosted MCP 同款 OAuth 登录态(refreshToken → 临时密钥)。驱动进程注入面剥掉 结果(国内站环境,ap-shanghai,函数创建/更新/调用后已清理):
结论:OAuth 登录态与 API Key 登录态两条链路下,两段式部署均端到端可用。OAuth 临时密钥为账号级权限, |
|
生产远程 MCP 现状实测(OAuth 浏览器登录全链路) 用标准 OAuth 链路(discovery → 动态客户端注册 → PKCE 授权码 → 浏览器登录授权 → token 交换)连接生产远程 MCP,验证函数部署能力现状:
结论:生产远程 MCP 目前在 cloud mode 下无法用代码方式创建函数(只剩镜像部署一条路)。本 PR 合并发版后, |
|
CAPI 层预验证:生产远程 MCP OAuth 会话下,两段式依赖的底层云 API 实测 通过生产远程 MCP 暴露的 callCloudApi 工具(OAuth 浏览器登录会话),把两段式部署链路依赖的底层云 API 逐个实测:
结论:
即:PR 合并发版后,远程 MCP 的两段式部署在云端接口层面已全部就绪。 |
|
补充:PUT 上传段的实测(外部 OAuth 会话下的可行路径)\n\n之前外部探测打不了 COS PUT,根因已定位:环境自有桶的预签名需要调用者持有 STS,而远程 MCP 的 OAuth access_token 是 MCP 层 JWT, |
pkg.pr.new build (webpack) compiles *.test.ts and failed to resolve cos-nodejs-sdk-v5, which is not a direct dependency of the package. Freeze the SDK getAuth outputs as expected values so the golden-value comparison no longer needs the SDK at build time.
What
Two-phase ZIP deployment for cloud functions: the agent PUTs the code zip straight to the environment's own COS bucket with a presigned URL, then deploys by reference — no local code directory required.
getFunctionUploadUrl(phase A): resolves the environment's storage bucket (DescribeEnvs→Storages[0]) and mints a presigned PUT URL from the caller's own credentials. ReturnsuploadUrl,uploadHeaders(session-token header when the credential is temporary), and thecosBucketName / cosBucketRegion / cosObjectNametriplet. functionName is optional and only shapes the object key.code(phase B): new strict input forcreateFunction/updateFunctionCode, wired to the SDK'sdeployMode: "cos"path. The cloud-mode gate allows it (like image deploy, it touches no local directory).function-cos-upload.tsreplicates the COS q-sign algorithm withnode:cryptoonly (no new dependency). Session tokens are signed intox-cos-security-tokenand returned as a request header.scripts/tools.json+doc/mcp-tools.mdregenerated.Why
Hosted / cloud-mode callers previously had no way to deploy function code: local directory paths don't exist on the caller machine, and the inline
zipFilechannel is capped at 20MB base64. A presigned upload to the environment's own bucket removes both limits with zero new CAM permissions, works for permanent and temporary credentials, and never exposes the appId to the agent.How to verify
cos-nodejs-sdk-v5getAuthfor both permanent keys and session tokens.codepasses cloud mode), strict schema rejection, anddeployMode=cospassthrough for create/update.getFunctionUploadUrl→ PUT → create/update withcode→Invokereturns the expected payload.