Closes#9880
## Summary
- Clarified `/add-mcp` so the slash-command menu says it adds a server
via the MCP settings page.
- Renamed the bundled file-config MCP skill display name to
`agent-add-mcp` while keeping its existing description.
- Added regression tests for both updated labels.
## Validation
- `cargo fmt`
- `git --no-pager diff --check`
- `cargo test -p ai test_parse_with_front_matter`
- Lightweight direct metadata check for `/add-mcp` and bundled
`agent-add-mcp` strings
Validation limitations:
- `cargo test -p warp add_mcp --lib` was attempted twice, including with
`CARGO_BUILD_JOBS=1`, but the sandbox killed the app crate compile with
SIGKILL.
- `CARGO_BUILD_JOBS=1 cargo clippy --workspace --all-targets
--all-features --tests -- -D warnings` was attempted. After installing
missing `libclang`, it remained blocked because the sandbox cannot
access the private `warp-channel-config` repository needed to generate
release-bundle channel config files for all-features clippy.
## Notes
- The implementation is intentionally scoped to the requested minimal
UI/text disambiguation.
---------
Co-authored-by: Oz <oz-agent@warp.dev>
Co-authored-by: Varoon Kodithala <116049637+vkodithala@users.noreply.github.com>
Co-authored-by: vkodithala <varoon@warp.dev>
### Description
The channel-gated skills README and the runtime error message in
\`script/copy_conditional_skills\` both pointed contributors at
\`resources/skills/\` for stable-ready skills, but that directory
doesn't exist in the repo — \`script/prepare_bundled_resources\` copies
the always-bundled skills from \`resources/bundled/\`, so the right
destination is \`resources/bundled/skills/\`.
The result: if anyone bumped into the existing \`stable/\` guard
(\`copy_conditional_skills\` line 39), the printed remediation pointed
them at a path that doesn't exist.
Three updates:
- \`resources/channel-gated-skills/README.md\` — \"place them in the
always-bundled \`resources/skills/\`\" → \`resources/bundled/skills/\`
(in the prose blockquote and in the gating table).
- \`script/copy_conditional_skills\` — header comment + the user-facing
error \`echo\`.
No behavior change in the script itself; only the comment and the error
string contents.
### Testing
Doc/script-comment only — nothing to run. The actual copy logic is
unchanged.
### Server API
No server changes.
### Agent Mode
Not applicable.
### Changelog Entries
None.
Co-authored-by: anshul-garg27 <anshul-garg27@users.noreply.github.com>
## Description
### Motivation
File-based stdio MCP servers spawned from a project's `.mcp.json` (e.g. `pnpm run mcp:foo`, or anything using `./tooling_scripts/...`) fail with:
```
Transport creation error: No such file or directory (os error 2)
```
Root cause: when the user's `.mcp.json` doesn't include a `working_directory`, Warp's spawner inherits whatever cwd Warp was launched from rather than the directory the config was discovered in. Two failure modes share this same root cause:
- **Repo-relative commands/args** (e.g. `./tooling_scripts/foo`, `node ./src/server.js`) can't be resolved from outside the repo, so `execvp` returns `ENOENT`.
- **Workspace-aware launchers** like `pnpm`/`npm`/`yarn` walk up from cwd looking for `package.json` (and workspace manifests). When cwd isn't inside the repo, they bail out before launching the requested script — surfacing as `ENOENT` from the spawner's perspective.
`working_directory` is a Warp/VS-Code-style extension; the canonical Anthropic/Cursor MCP schemas don't include it, so most `.mcp.json` files in the wild don't set it.
### Implementation
- New helper `FileBasedMCPManager::spawn_root_for_installation(uuid)` returning the discovery root for any file-based install: the repo root for project-scoped configs, the home directory for global configs (Warp and third-party). Returns `None` for non-file-based installs (e.g. cloud-templated ones), leaving them unaffected. Global Warp installs are remapped from `~/.warp/` (Warp internal state) to `~` so all global installs share a consistent cwd.
- In `TemplatableMCPServerManager::spawn_server_impl`, default `cli_server.cwd_parameter` from this helper when unset. Single funnel — covers both auto-spawn and the manual UI opt-in path. User-supplied `working_directory` always wins.
- ENOENT-aware logging at the spawn site: when `TokioChildProcess::spawn()` fails with `NotFound`, the MCP log file now spells out the server name, the missing executable, the cwd we used, and a hint pointing the user at `working_directory`. The user-surfaced error string is unchanged.
- Documented the new defaulting behavior and `working_directory` override in `resources/bundled/skills/add-mcp-server/SKILL.md`.
## Testing
Verified spawn-site behavior manually. Demo [here](https://www.loom.com/share/ec01d98ae9114433b8ae87f5f17adfd4)!
- Added `test_parse_cli_server_preserves_explicit_working_directory` in `mod_test.rs` to lock in that an explicitly-set `working_directory` round-trips through parsing and won't be clobbered by the new defaulting logic.
- Skipped a unit test for the new helper itself — it's a thin lookup over `file_based_servers_by_root` and the sorted-pick policy is straightforward enough to validate manually.
- Spawn-site behavior (cwd actually applied, ENOENT log emission) verified manually against a `pnpm`\-based repro.
## Agent Mode
- [x] Warp Agent Mode - This PR was created via Warp's AI Agent Mode
## Changelog Entries for Stable
CHANGELOG-BUG-FIX: Project-scoped file-based MCP servers now spawn from the repo root by default (and global ones from `~`), so configs with relative commands/args (and workspace launchers like `pnpm`/`npm`) work without an explicit `working_directory`.