Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ start again on the next request
| apps-operator | Reconciles `App` resources into a Deployment, Service, ConfigMap and `NebariApp`, reports status, scales idle Apps to zero and serves the page they show while they start. | `operator` |
| apps-api | REST API for CRUD, status, logs, events, analytics and zip/`.html` upload; writes `App` resources (and each App's write-only Secret) for the UI and the MCP server. | `api` |
| apps-ui | The apps list as the home page (with a Needs attention banner, a Mine filter and Open links), app detail with logs and events, the launch form, and a Settings page (the UI and API versions, your groups, the cluster's settings, and how to connect an agent). | `ui` |
| apps-mcp | MCP server at `/mcp` that lets coding agents launch and manage apps (tools), attach an app's spec, status, logs and events as context (resources), and follow the triage, launch and access-review workflows (prompts), with Keycloak device-flow login. | `mcp` |
| apps-mcp | MCP server at `/mcp` that lets coding agents launch and manage apps (tools), attach an app's spec, status, logs and events as context (resources), and follow the triage, launch and access-review workflows (prompts), with standard MCP OAuth sign-in through Keycloak. | `mcp` |
| apps-authz | Sidecar in the pods of Apps that can idle (records when the app last served a request) and of image Apps (gives them the one front port). It checks no tokens: `access.groups` are enforced at the gateway. | `authz` |

Images are published to `ghcr.io/nebari-dev/apps-pack/<image>` and
Expand Down
4 changes: 2 additions & 2 deletions docs/src/content/docs/local-development.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ open http://docs-site.apps.nebari.test # the example app
install Envoy Gateway, cert-manager, Keycloak (realm `nebari`, login
`admin` / `nebari-admin`), and the nebari-operator itself. Pins the gateway Service to
fixed NodePorts and creates the `apps` namespace labeled `nebari.dev/managed=true`.
3. **`images`** — builds `apps-operator:dev`, `apps-api:dev`, `apps-ui:dev`, and
`apps-mcp:dev` and loads them into the kind cluster.
3. **`images`** — builds `apps-operator:dev`, `apps-api:dev`, `apps-ui:dev`,
`apps-mcp:dev` and `apps-authz:dev` and loads them into the kind cluster.
4. **`deploy`** — installs the chart with `clusterDomain=nebari.test` and
**`tls.enabled=false`** (plain HTTP — no certificate warnings locally).
5. Applies the inline example App and waits for `Running`.
Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ the CA is trusted through [`mcp.orgCABundle`](/configuration/#apps-mcp).
| Tool | Purpose |
|---|---|
| `describe_cluster` | Source types, launchable namespaces, apps domain, the cluster's default idle timeout and, when `image` is a source type, the `imageRegistries` images may come from — call first to pick valid options. |
| `launch_app` | Create + launch (static, Python/pixi via `pixi_task`, or a prebuilt container image with `source_type: image`, `image_reference` (tag or digest, from an allowed registry) and `image_port`, plus optional `image_command`, `image_args` and `image_run_as_user`; see [Container images](/launching-apps/#container-images)); optional `resources` (requests/limits, cluster defaults otherwise) and `groups`/`users` to restrict a private app (a member of any group or a listed user gets in; everyone else gets `403`); `idle_timeout_minutes` and `keep_alive` control [scale to zero](/app-crd-reference/#scale-to-zero); `manager_users`/`manager_groups` set who else may [manage](/launching-apps/#managers) it (omit to keep the current list); `secrets` (`{NAME: value}`) stores credentials in the app's own Secret instead of `env` (see [Secrets](#secrets)). **Idempotent on (namespace, name)** — re-launching an app you own or manage updates it instead of failing, so retries are safe; any other app is refused, never overwritten. Only the owner or an admin may change the managers. |
| `launch_app` | Create + launch (static, Python/pixi via `pixi_task`, or a prebuilt container image with `source_type: image`, `image_reference` (tag or digest, from an allowed registry) and `image_port`, plus optional `image_command`, `image_args` and `image_run_as_user`; see [Container images](/launching-apps/#container-images)); optional `resources` (requests/limits, cluster defaults otherwise) and `groups` to restrict a private app (full Keycloak paths matched exactly, `finance` is `/finance`; a member of any listed group gets in, every other signed-in user gets `403` at the gateway); `idle_timeout_minutes` and `keep_alive` control [scale to zero](/app-crd-reference/#scale-to-zero); `manager_users`/`manager_groups` set who else may [manage](/launching-apps/#managers) it (omit to keep the current list); `secrets` (`{NAME: value}`) stores credentials in the app's own Secret instead of `env` (see [Secrets](#secrets)). **Idempotent on (namespace, name)** — re-launching an app you own or manage updates it instead of failing, so retries are safe; any other app is refused, never overwritten. Only the owner or an admin may change the managers. |
| `list_apps` | Apps with phase, URL, owner; optional namespace filter. Inline sources list file `paths` only. |
| `get_app` | Full spec + status for one app; inline files come back fenced (see below). |
| `get_app_status` | Lightweight poll: phase, URL, replicas, conditions. |
Expand Down
19 changes: 19 additions & 0 deletions docs/src/content/docs/upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,25 @@ configures only apps-api and apps-mcp.
next to an older apps-operator, so a restricted App never runs open; upgrade the chart and
images together.

### Upgrading to MCP OAuth

**Breaking:** MCP clients sign in themselves with standard
[MCP authorization](/mcp/#authentication): apps-mcp is an OAuth 2.0 protected resource with
the Keycloak realm as its authorization server, and it verifies the bearer token on every
request. The `authenticate` tool, the per-session device-flow token cache and
`MCP_SESSION_TTL_SECONDS` are removed.

- **Create the sign-in client before you upgrade.** On a cluster with auth on, MCP clients
need a public Keycloak client with a loopback redirect URI, which the pack cannot
provision. A cluster admin creates it once ([The sign-in client](/mcp/#the-sign-in-client))
and sets `mcp.oauth.clientId` (and `mcp.oauth.callbackPort` if it is not `33418`). Until
then MCP clients cannot sign in on their own.
- **Users reconnect their agents.** Re-add the server with the command on the UI's
**Settings** page (`claude mcp add … --client-id <id> --callback-port <port>`), then run
`/mcp` in Claude Code, select it and choose **Authenticate**. Agents that called the
`authenticate` tool no longer find it.
- **Drop `MCP_SESSION_TTL_SECONDS`** from `mcp.extraEnv` if you set it; it is ignored.

### Upgrading to group-only access

**Breaking:** Apps restrict who may open them by Keycloak group only. `spec.access.users`
Expand Down
Loading