{"record":{"id":"3d87206a77075876","repo":"astrid-runtime/astrid","slug":"system-resident-capsule-id-cannot-host-princip","errorCode":null,"errorMessage":"system-resident capsule '{id}' cannot host principal-bearing stdio MCP servers","messagePattern":"system-resident capsule '(.+?)' cannot host principal-bearing stdio MCP servers","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-kernel/src/lib.rs","lineNumber":1736,"sourceCode":"                principal,\n                &manifest,\n                &bound.snapshot,\n            )?;\n        }\n        if *principal != PrincipalId::default()\n            && self.capabilities.is_principal_retiring(principal).await\n        {\n            anyhow::bail!(\"cannot load capsule '{id}' for retiring principal '{principal}'\");\n        }\n        let wasm_hash = capsule_instance_hash(&manifest, &runtime_dir);\n        // `capabilities.uplink` alone remains a principal-scoped daemon/host\n        // grant unless the operator explicitly promotes it. A manifest that\n        // actually provides an uplink must be operator-approved.\n        let system_allowed = self.system_capsules.read().await.contains(id.as_str());\n        let system_runtime =\n            classify_runtime_residency(&manifest, &id, system_allowed)?.is_system();\n        if system_runtime && !manifest.mcp_servers.is_empty() {\n            anyhow::bail!(\n                \"system-resident capsule '{id}' cannot host principal-bearing stdio MCP servers\"\n            );\n        }\n        self.verify_workspace_capsule_tree(&runtime_dir)?;\n\n        // Mutable runtimes are authority-scoped. A principal always receives a\n        // fresh runtime for its immutable UID; only an explicitly classified\n        // SystemResident service may attach another view to one runtime.\n        {\n            let mut registry = self.capsules.write().await;\n            if registry.get_for(principal, &id).is_some() {\n                return Ok(());\n            }\n            if system_runtime && registry.contains_system_runtime(&id, &wasm_hash) {\n                registry\n                    .register_existing(&id, &wasm_hash, principal)\n                    .map_err(|e| anyhow::anyhow!(\"Failed to add capsule view: {e}\"))?;\n                if let Some(capsule) = registry.get_for(principal, &id) {","sourceCodeStart":1718,"sourceCodeEnd":1754,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-kernel/src/lib.rs#L1718-L1754","documentation":"Capsules classified as system-resident (operator-approved, shared runtime) are forbidden from declaring stdio MCP servers, because those servers run with a principal's identity and would break the isolation of a shared system runtime. The kernel throws this during load when `classify_runtime_residency` returns system residency and `manifest.mcp_servers` is non-empty.","triggerScenarios":"Loading a capsule whose Capsule.toml declares `[mcp_servers]` entries while the capsule id is listed in `system_capsules` (or otherwise classified system-resident).","commonSituations":"An operator promotes a capsule with MCP servers to the system capsule list; a Capsule.toml is copied into a system-resident deployment without stripping MCP server entries; residency classification changed after the manifest was written.","solutions":["Remove the `mcp_servers` entries from the capsule's Capsule.toml.","Remove the capsule id from the operator's `system_capsules` admission set so it runs as a principal-scoped runtime.","Split the MCP servers into a separate principal-scoped capsule."],"exampleFix":"# before (Capsule.toml)\n[mcp_servers]\nstdio = { command = \"./mcp.sh\" }\n# after\n# [mcp_servers] section removed for system-resident capsule","handlingStrategy":"validation","validationCode":"let manifest = astrid_capsule::discovery::load_manifest(&dir.join(\"Capsule.toml\"))?;\nif is_system_capsule(&manifest.package.name) && !manifest.mcp_servers.is_empty() {\n    return Err(anyhow!(\"system-resident capsule cannot declare mcp_servers\"));\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = kernel.load_capsule(&dir, &principal).await {\n    if e.to_string().contains(\"cannot host principal-bearing stdio MCP servers\") {\n        strip_mcp_servers_from_manifest(&dir)?;\n        return kernel.load_capsule(&dir, &principal).await;\n    }\n    return Err(e);\n}","preventionTips":["Lint Capsule.toml for mcp_servers before adding a capsule to the system list.","Keep MCP servers in dedicated principal-scoped capsules.","Validate manifests in CI against residency classification."],"tags":["capsule-manifest","mcp-servers","system-resident","manifest-validation"],"backgroundTag":"invalid-config-value","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}