diff --git a/crates/oab-mcp/src/lib.rs b/crates/oab-mcp/src/lib.rs index 82f9707..48300ea 100644 --- a/crates/oab-mcp/src/lib.rs +++ b/crates/oab-mcp/src/lib.rs @@ -146,7 +146,7 @@ pub fn tools() -> Vec { ), Tool::new( "deploy_provision", - "Provision an agent from the compose library: compose template ⊕ overlay into a file bundle, push it to the agent's S3 artifacts prefix, and redeploy the ECS service at the chosen image tag. Reuses the agent's stored manifest for networking/resources/secrets, so the agent must already have been created.", + "Provision an agent from the compose library: compose template ⊕ overlay into a file bundle and push it to the agent's S3 artifacts prefix (bundle carrier — shared regardless of provider). If the agent already has a stored manifest, patches its image/bundle and re-applies (networking/resources/secrets/runtime ride along unchanged). If not, builds a fresh manifest with sensible defaults and creates the agent — this now works for a genuinely brand-new agent, not just a redeploy of one already created via `oabctl create`. `provider` (default \"aws\") selects the target: \"aws\" applies via ECS (`fleet`/`cluster` select the credential); \"k8s\" applies via the given kubeconfig `context` instead, with `expected_principal` optionally naming a service account (`system:serviceaccount::` — the bare name becomes the pod's serviceAccountName; unset uses the namespace's default).", as_map(json!({ "type": "object", "properties": { @@ -156,8 +156,11 @@ pub fn tools() -> Vec { "name": { "type": "string", "description": "Agent / service name (service = oab-{namespace}-{name})." }, "namespace": { "type": "string", "description": "Namespace (default \"default\")." }, "image_tag": { "type": "string", "description": "Image tag override (defaults to the bundle's own image tag)." }, - "fleet": { "type": "string", "description": "Fleet name (see fleet_config): targets the fleet's cluster and managing credential; a write to a service outside the fleet's members is refused. Overrides the cluster arg." }, - "cluster": { "type": "string", "description": "ECS cluster (defaults to the server's configured cluster)." } + "provider": { "type": "string", "description": "\"aws\" (default) or \"k8s\" — which driver applies the result." }, + "fleet": { "type": "string", "description": "AWS only. Fleet name (see fleet_config): targets the fleet's cluster and managing credential; a write to a service outside the fleet's members is refused. Overrides the cluster arg." }, + "cluster": { "type": "string", "description": "AWS only. ECS cluster (defaults to the server's configured cluster)." }, + "context": { "type": "string", "description": "k8s only. Kubeconfig context to apply through. Omit to use the kubeconfig's current-context." }, + "expected_principal": { "type": "string", "description": "k8s only, optional. `system:serviceaccount::` to set the pod's service account; unset uses the namespace's default." } }, "required": ["library", "template", "name"] })), @@ -546,8 +549,6 @@ impl OabMcp { } async fn t_provision(&self, args: &Map) -> Result { - let t = self.target(args)?; - let cluster = t.cluster.clone(); let namespace = args .get("namespace") .and_then(Value::as_str) @@ -569,6 +570,44 @@ impl OabMcp { ) .map_err(|e| anyhow::anyhow!("invalid library: {e}"))?; + // studio#104: k8s dispatch. `context`/`expected_principal` come as + // direct args — the console's identity form already collects them + // (context/namespace/service-account