Repository navigation
fix(mcp): resolve a ${VAR} only mcp.yaml names as the member's own secret (Tencent#1011) - #8
hsuchifeng wants to merge 2 commits into
Conversation
…cret
A `${VAR}` an MCP server references that no secrets file declares and no
env.yaml sets is a personal token the team repo cannot hold. It is now
treated as a declared secret everywhere: `teamai env set VAR` stores the
member's value, a pull resolves it from their stores and environment, a
pull that cannot see the value keeps the entry an earlier pull wrote
instead of deleting the server, and the missing-secret line names it.
Code Erosion ReportInformational — never blocks the merge.
Scanned 304 files / 60655 SLOC · high-CC functions 421/4840 * On TypeScript, Rule hits (TS verbosity layer)Standalone
38 distinct lines flagged across |
|
CI note on the The Generated by Claude Code |
c3d004a to
b59a689
Compare
Summary
Implements Tencent#1011: a team
mcp/mcp.yamlserver that references a personal token (X-Tapd-Access-Token: ${TAPD_ACCESS_TOKEN}) with noenv/in the repo. A pull from a shell that exports the variable installed the server; the session-start pull, which runs without the member's shell exports, then deleted it from.cursor/mcp.json, and the member had no place to keep the value except their shell profile.mainalready has the Tencent#875 team-secrets design (teamai env set, per-team 0600 value stores, "a missing declared secret keeps the MCP entry"), but only for keys declared inenv/secrets.yaml. This PR extends it to the undeclared case, with no new command or file format:withMcpReferencedSecrets(src/resources/secrets.ts): a${VAR}the scope's MCP servers reference that no secrets file declares and noenv.yamlsets becomes an implicit secret declaration, attributed to the referencingmcp.yaml.resolveTeamEnvapplies it, so every consumer sees it:env setaccepts the key,buildVarTableresolves it from the member's team/machine store and then their environment,desiredMcpForTargetkeeps the installed entry when the value is missing, and the "tapd: TAPD_ACCESS_TOKEN is not set. Run \teamai env set TAPD_ACCESS_TOKEN``" advisory names it.env setuses the same resolution (one read of the team env instead of two), and its help text names the new case;commands.mdregenerated.docs/designs/team-secrets.md(+ zh-CN) gain "A variable only mcp.yaml names is a secret" and the "removed, as before" bullet is updated;docs/usage-guide.md(+ zh-CN) updated where they said unresolved variables skip the server.Design choice vs the issue text: the issue proposes
process.envbefore the personal store. The existing Tencent#875 resolution order is store first, then environment (so a value exported for another account does not silently win for this team); the implicit secret follows that same order rather than adding a second one. The issue's other asks are already met by the existing store (~/.teamai/secrets/teams/<hash>.json, mode 0600, hidden-inputenv set, never rewritten by pull, redacted from logs).Type of Change
Test Plan
npx tsc --noEmitpassesnpm run lintpassesnpx vitest runpasses (full unit suite; the twomcp-reconcilecases that pinned "still removes a server whose missing variable is not declared as a secret" now assert the entry is kept)Real-CLI e2e,
npm run build && npx vitest run --config vitest.e2e.config.ts src/__tests__/e2e/mcp-member-token-1011.test.ts→ 5/5 passed. It reproduces the issue with the real binary (user scope,provider: gitbare remote, Cursor, noenv/):TAPD_ACCESS_TOKEN=… teamai pull --forceinstallstapdinto~/.cursor/mcp.jsonteamai pullwithout the export keeps the entry and printstapd: TAPD_ACCESS_TOKEN is not set. Run \teamai env set TAPD_ACCESS_TOKEN`andtapd: the entry an earlier pull wrote stays in cursor …`teamai env listlists it underTeam secrets (1)asmissingprintf token | teamai env set TAPD_ACCESS_TOKEN --stdin→ stored in~/.teamai/secrets/teams/<hash>.json, mode0600, not inmcp.jsonteamai pull --forcewith no export resolves the header from the store; the store file's content and mtime are unchanged; the token appears in neither the output nor~/.teamai/debug.logThe same test run against the pre-change build fails steps 2–5 (step 2 removes the server), so it pins the fix.
Related Issues
Implements Tencent#1011
Notes for Reviewers
Codex/Claude and the
gitlab/githubproviders are not exercised here; the change is in scope resolution and applies to every tool and provider the same way, so that coverage is left to CI.Generated by Claude Code