feat(missions): install the skills door, with a credential it is safe to leave

The capability has been built and undeployed since `88eef99d4`:
`claude_cli` accepts `mcp_config` and passes `--mcp-config
--strict-mcp-config`, so Claude Code's own MCP client can reach our
skills server. What was missing was the config document and, underneath
it, a credential that could be left in a container an untrusted agent
reads.

Now both halves happen together — the document goes in, and the daemon is
told to pass it — because doing one without the other leaves a door
installed and unreachable, which looks exactly like a door nobody walked
through. That is the same shape as the hooks that shipped installed and
inert three bugs running.

The API origin defaults to our own `HOSTNAME` rather than a container
name. Mission containers share `clawmates_core` with the server, and the
server's name differs between deployments (`clawmates-server-1` locally,
`clawmates_server_1` on gw-04); docker's embedded DNS resolves a
container id on a user-defined network, so this is self-configuring.
Measured from a sibling container: both the id and the name return 200.

`--allowedTools` is deliberately NOT touched. The provider passes it only
when `tools` is set and the seed already sets it — without it `claude -p`
stops mid-turn asking for write permission. Whether MCP tools also need
naming there is undocumented in anything we control, and the daemon
exposes no config read to merge into the list safely; overwriting it
would take `Write` and `Bash` from every mission agent, and that failure
would look like agents that stopped working rather than a config that was
replaced. So the question gets answered by running a mission with the
door installed. Guessing is how the last three defects in this file got in.

Every failure degrades to "no door", never to a failed launch.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018i9Ten1LU4jUr5d7TAWda9
This commit is contained in:
Omar Sobh
2026-08-21 11:47:13 -07:00
co-authored by Claude Opus 5
parent 2668191e30
commit 73f5d71c55
4 changed files with 183 additions and 3 deletions
+15
View File
@@ -201,6 +201,21 @@ impl RuntimeProvisioner {
.await
}
/// Point `claude -p` at an MCP configuration.
///
/// The counterpart to [`set_claude_cli_settings`](Self::set_claude_cli_settings):
/// writing the document into the container and telling the daemon about it
/// are two halves of one thing, and doing one without the other leaves a
/// door that is installed and unreachable — which looks exactly like a door
/// nobody walked through.
pub async fn set_claude_cli_mcp_config(&self, path: &str) -> Result<(), String> {
self.set_prop(
"providers.models.claude_cli.default.mcp_config",
serde_json::json!(path),
)
.await
}
/// Rebind an existing claw's model without touching its risk_profile
/// or mcp_bundles. Used by the "change model" UI on the Agents page
/// so we don't accidentally demote a coding_readwrite claw back to