Symptom in movie-library
movie-library's servers are configured entirely through operator environment variables (IPT_SESSION, MAM_SESSION, RTORRENT_SSH_HOST, …) kept in a gitignored <plugin root>/.env. That file only reaches a server through agent-bundle mcp run, so every non-mcp run launch path either has no credentials or needs a wrapper:
Root cause in agent-bundle (main @ 284141958)
The .env layer exists only in the mcp run service, not in the emitted entries a host actually launches:
packages/agent-bundle/src/services/mcp-run.ts:164-217 — loadEnv composes manifest env < .env files < operator process.env for mcp run children. docs/entry-conventions.md:1001-1004: "so operator credentials configured for the plugin reach a bare mcp run without a wrapper script".
- Host manifests launch the bundle directly — e.g. the emitted cursor
mcp.json: {"command":"node","args":["${CURSOR_PLUGIN_ROOT}/mcp/mcp-movie-library-public-….mjs"],"env":{"AGENT_BUNDLE_PLUGIN_ROOT":"${CURSOR_PLUGIN_ROOT}"}}. packages/agent-bundle/src/build/entry-shell.ts emits no .env read at all (rg '\.env' packages/agent-bundle/src/build packages/agent-bundle/src/adapters packages/agent-bundle/src/install → only the AGENT_BUNDLE_PLUGIN_ROOT anchor and CODEX_HOME lookups).
- Manifest
env is the only framework-provided channel, and it is (correctly) compiled into a content-addressed, re-emitted manifest — the wrong place for secrets and not editable across reinstalls.
- The install root would be a safe home:
packages/agent-bundle/src/install/receipt.ts:648-650 — files the receipt does not own are never touched on a same-version replace, so an operator-placed <install>/.env survives install --replace; nothing reads it.
Workaround in movie-library
scripts/run-stdio.sh (wrapper over mcp run), the opencode/kimi installers pointing at it, and the hand-rolled .env re-read in scripts/ipt-search.ts / scripts/mam-search.ts.
Proposed fix
Give installed packs the same launch-time .env layer mcp run has, with the same precedence and the same "never compiled in" guarantee:
- The generated stdio shell (and the routed CLI bin / hook wrappers) loads
<AGENT_BUNDLE_PLUGIN_ROOT>/.env (+ .env.local) at startup via the same loadEnv conventions, filling gaps only — operator process.env still wins, manifest env still loses. Under mcp run the anchor already expands to the project root, so behaviour there is unchanged.
agent-bundle install documents the location (INSTALL.md per target: "operator configuration: <install>/.env, copied from your .env.template if the project ships one") and doctor reports whether one is present (never its contents).
- Optionally an
install --env-file <path> that copies the named file into the install root as an unowned file.
- Update
docs/entry-conventions.md (Launch environment) and the site so the sentence about wrappers applies to installed packs too.
Acceptance
- A pack installed into an isolated
HOME with <install>/.env containing FOO=bar and no FOO in the host env: a real MCP client spawning the server via the host's manifest observes process.env.FOO === 'bar' inside a tool route; with FOO=host exported, the route observes host.
agent-bundle build --json output contains no value from .env (existing guarantee, add a test).
install --replace of a newer build keeps the operator's <install>/.env.
- movie-library can delete
scripts/run-stdio.sh's role as the credential launcher and point install-opencode.mjs / install-kimi.mjs at the bundled entries.
Symptom in movie-library
movie-library's servers are configured entirely through operator environment variables (
IPT_SESSION,MAM_SESSION,RTORRENT_SSH_HOST, …) kept in a gitignored<plugin root>/.env. That file only reaches a server throughagent-bundle mcp run, so every non-mcp runlaunch path either has no credentials or needs a wrapper:README.md:142: "Servers are configured through environment variables;agent-bundle mcp run(used byscripts/run-stdio.sh) loads the gitignored.envat the plugin root". There is no documented way to configure an installed claude/codex/cursor pack — and the PR build(deps): bump @mantine/core from 9.5.1 to 9.5.2 #8 install proof shows it: the installed Cursor public server lists 7 tools withdownloadfailing closed and no tracker credential present.scripts/run-stdio.sh:14-16, 38-45— kept alive purely as the.env-loading launcher (PR build(deps): bump @mantine/core from 9.5.1 to 9.5.2 #8 framework-mode audit, finding 7: "hand-roll launcher … overlaps the framework's stdio entry").scripts/install-opencode.mjs:29,79andscripts/install-kimi.mjs:29register the servers throughrun-stdio.shrather than the built pack's bundled entries, for the same reason.scripts/ipt-search.ts:94-98/scripts/mam-search.ts:96-100: the session-refresh path re-reads<PLUGIN_ROOT>/.envby hand ("from a built bundle this module lives in artifact//mcp/ where neither the refresh script nor .env ships, which silently killed auto-refresh" — the Codex P2 on movie-library#2).Root cause in agent-bundle (
main@284141958)The
.envlayer exists only in themcp runservice, not in the emitted entries a host actually launches:packages/agent-bundle/src/services/mcp-run.ts:164-217—loadEnvcomposes manifest env <.envfiles < operatorprocess.envformcp runchildren.docs/entry-conventions.md:1001-1004: "so operator credentials configured for the plugin reach a baremcp runwithout a wrapper script".mcp.json:{"command":"node","args":["${CURSOR_PLUGIN_ROOT}/mcp/mcp-movie-library-public-….mjs"],"env":{"AGENT_BUNDLE_PLUGIN_ROOT":"${CURSOR_PLUGIN_ROOT}"}}.packages/agent-bundle/src/build/entry-shell.tsemits no.envread at all (rg '\.env' packages/agent-bundle/src/build packages/agent-bundle/src/adapters packages/agent-bundle/src/install→ only theAGENT_BUNDLE_PLUGIN_ROOTanchor andCODEX_HOMElookups).envis the only framework-provided channel, and it is (correctly) compiled into a content-addressed, re-emitted manifest — the wrong place for secrets and not editable across reinstalls.packages/agent-bundle/src/install/receipt.ts:648-650— files the receipt does not own are never touched on a same-version replace, so an operator-placed<install>/.envsurvivesinstall --replace; nothing reads it.Workaround in movie-library
scripts/run-stdio.sh(wrapper overmcp run), the opencode/kimi installers pointing at it, and the hand-rolled.envre-read inscripts/ipt-search.ts/scripts/mam-search.ts.Proposed fix
Give installed packs the same launch-time
.envlayermcp runhas, with the same precedence and the same "never compiled in" guarantee:<AGENT_BUNDLE_PLUGIN_ROOT>/.env(+.env.local) at startup via the sameloadEnvconventions, filling gaps only — operatorprocess.envstill wins, manifest env still loses. Undermcp runthe anchor already expands to the project root, so behaviour there is unchanged.agent-bundle installdocuments the location (INSTALL.mdper target: "operator configuration:<install>/.env, copied from your.env.templateif the project ships one") anddoctorreports whether one is present (never its contents).install --env-file <path>that copies the named file into the install root as an unowned file.docs/entry-conventions.md(Launch environment) and the site so the sentence about wrappers applies to installed packs too.Acceptance
HOMEwith<install>/.envcontainingFOO=barand noFOOin the host env: a real MCP client spawning the server via the host's manifest observesprocess.env.FOO === 'bar'inside a tool route; withFOO=hostexported, the route observeshost.agent-bundle build --jsonoutput contains no value from.env(existing guarantee, add a test).install --replaceof a newer build keeps the operator's<install>/.env.scripts/run-stdio.sh's role as the credential launcher and pointinstall-opencode.mjs/install-kimi.mjsat the bundled entries.