We're excited to announce the v0.22.0 release of the Obot Platform. This release introduces two major capabilities focused on deeper integrations with popular coding agents running on users' local devices. Admins can curate a catalog of skills in Obot, govern access with dedicated skill access policies that work similarly to the policies used for MCP servers, and let users install those skills into their local coding agents with obot skills. Separately, obot scan gives admins fleet-wide visibility into which AI clients, MCP servers, and skills are installed across users' machines. The release also adds image pull secret management, external secret integration for MCP servers, and an OAuth inspector for diagnosing remote MCP authentication.
Big Updates
obot scan: Fleet Inventory of Local AI Clients
The new obot scan CLI command walks a user's home directory and reports every installed AI client it knows about (Claude Code, Claude Desktop, Codex, Cursor, Goose, Hermes, Openclaw, Opencode, VS Code, Windsurf, Zed), the MCP servers each one is configured to talk to, and any skills and plugins present on disk. Each scan submits a single envelope to the Obot backend.
Admins get a new Device Management area in the admin UI. The Dashboard shows distinct device and user counts and ranked donut breakdowns of the top clients, MCP servers, and skills across the fleet over a configurable time window. From there, admins can drill into per-device scan history, per-MCP-server occurrence lists (grouped by a content hash so the same logical server collates across users), and per-skill occurrence lists. Auditors get read-only access to the same views.
This gives admins concrete answers to "what MCP servers are people actually running" and "where is this skill installed" without surveying users by hand.
Centrally Managed Skills for Local Agents
Admins can now curate a catalog of skills in Obot and govern who can use them with dedicated skill access policies. These are managed separately from MCP server access policies but follow the same model, so the workflow is familiar. The user UI surfaces a new Skills page that lists exactly the skills a given user is allowed to install.
Users discover and install those skills into their local coding agents with the new obot skills command in the Obot CLI. It can be used two ways: directly from the terminal to search the catalog and install a skill into the current agent, or from inside the agent itself once Obot's bootstrap skill set is installed.
The bootstrap path is handled by obot setup. It walks the user through an OAuth login against a specific Obot instance, detects the major coding agents that follow the ~/.agents skills convention (Cursor, VS Code, Codex, and others), plus Claude Code (which uses its own dir), and installs four skills: obot (visible to the agent, explains how to use the CLI to find more skills) and the obot-scan, obot-skills-install, and obot-skills-search slash commands. From then on, users can run /obot-skills-search and /obot-install-skill from inside their agent without touching the terminal.
No manual config file editing and no API key handling: authentication is OAuth per Obot instance, and CLI tokens are stored in the OS keychain.
Image Pull Secrets
Admins can now manage container registry image pull secrets for containerized MCP servers from the Obot UI. Two secret types are supported: Basic, for registries like Docker Hub and GHCR, and ECR, for AWS Elastic Container Registry.
For ECR secrets, Obot assumes a configured IAM role and refreshes the ECR token every six hours so the secret stays valid without manual rotation. The UI surfaces the Trust Policy and ECR IAM Policy required for Obot to assume the role, includes a Test button to verify the secret works against the configured registry, and gives auditors read-only access.
UI-managed image pull secrets and static Helm-configured pull secrets are mutually exclusive: if any pull secrets are configured through the Helm chart, the UI is locked out and shows a clear explanation.
External Secret Integration for MCP Servers
MCP catalog entry env vars can now bind to existing Kubernetes Secrets instead of requiring users to type credentials into Obot. A catalog entry declares a secretBinding (Secret name and key) on an env var, and at deploy time Obot wires the value into the MCP server pod with a secretKeyRef rather than resolving the secret itself.
This lets teams keep credentials managed by Vault, AWS Secrets Manager, External Secrets Operator, or any other tool that syncs into Kubernetes Secrets. The secret value flows from the external store to the Kubernetes Secret to the container; Obot never sees or stores it. The UI shows configs that are secret-bound as such, without exposing the underlying value.
In V1, secret bindings can only be defined in git-managed catalog sync sources, not through the UI, so they remain code-reviewed and version-controlled.
MCP OAuth Inspector
This release adds a set of tools for diagnosing OAuth-protected remote MCP servers. The MCP server details page now surfaces the OAuth metadata Obot discovered for the server (authorization endpoints, supported scopes, client info, and so on), and exposes a walk-through debugger that steps through the OAuth handshake so it is clear where a flow is failing.
Users can also re-trigger the OAuth flow for a server directly from the UI when a token has gone stale or the server's OAuth configuration has changed, instead of having to delete and re-add the server.
User-Defined Headers for Multi-User MCP Servers
Multi-user MCP servers can now accept per-user header values. Previously, the only way to require per-user configuration on an MCP server was to deploy it as a single-user server, which spins up a separate pod for every user and can waste capacity in large deployments.
With user-defined headers, admins deploy one shared multi-user server, and each user supplies their own credential (or other per-user value) as a header that Obot passes through on every request. This only works when the MCP server implementation reads the header itself, so it is intended for servers built with this pattern in mind.
Generic Model Provider Replaces Ollama
The dedicated Ollama model provider has been replaced with a generic OpenAI Responses-compatible model provider. The generic provider works with Ollama, LiteLLM, and any other gateway that exposes an OpenAI-compatible Responses endpoint.
If you were using the Ollama provider, reconfigure it under the new Generic provider with the same endpoint.
Improvements
- Per-server MCP startup timeout:
npx,uvx, andcontainerizedcatalog entries can now declare astartupTimeoutSecondsthat the Docker and Kubernetes backends honor, so slow-starting servers (especially ones building from source vianpx) no longer time out under the previous default. - Separate resource request defaults for agents, remote MCP servers, and other workload types, so the admin can tune capacity per workload class instead of with one global value.
- Dynamic OAuth client expiration is now configurable, instead of a fixed default.
- CLI auth tokens are stored in the OS keychain.
- Model providers support a per-provider log level for debugging.
- The Helm chart supports an
existingSecretfor the custom encryption configuration, so the encryption key can be sourced from a pre-created Secret instead of generated at install time.
Upgrade Notes
This release contains several breaking changes. Review carefully before upgrading.
Legacy chat functionality has been removed. The legacy chat UI is gone, nanobot agent support is now always on, and a number of legacy APIs, configuration parameters, and the old triggers/knowledge/workspace systems have been removed alongside it. See #6680 for the full list.
Helm chart extraEnv and extraEnvFrom values have been removed. If your values.yaml set either of these to inject environment variables into the Obot deployment, move those values into the existing config: block (or, for secret references, use config.existingSecret) before upgrading. See #6648 for details.
Ollama provider has been replaced. See the "Generic Model Provider Replaces Ollama" section above.
What's Changed
- feat: allow multi-user servers to have user-defined headers by @thedadams in #6469
- chore: update user-ui pnpm@v11.x+ by @ivyjeong13 in #6482
- fix: filter out coming soon model providers by @ivyjeong13 in #6517
- Add user-configurable MCP startup timeouts by @calvinmclean in #6399
- chore: add build step for helm chart by @thedadams in #6521
- chore: migration from nanobot-ai/nanobot to obot-platform/nanobot by @thedadams in #6527
- fix: ensure user has access to mcp-connect URL by @thedadams in #6528
- Add workflow to post user-reported security advisories to Slack by @cjellick in #6536
- Revert "Add workflow to post user-reported security advisories to Slack" by @cjellick in #6537
- fix: allow access to mcp-connect URLs with extra path by @thedadams in #6539
- fix: allow users to access system MCP servers by @thedadams in #6541
- fix: indicate when multi-user server needs configuration by @thedadams in #6538
- fix: only create multi-user MCP after user config by @thedadams in #6535
- chore: update dependabot alerted packages by @ivyjeong13 in #6540
- fix: move published artifacts authorization out of API layer by @thedadams in #6542
- feat: add
obot scanto inventory local AI client config by @njhale in #6530 - docs: overview: provide more information about authentication by @g-linville in #6546
- docs: add bootstrap token to overview by @g-linville in #6549
- fix: ensure passthrough headers are always set for multi-user servers by @thedadams in #6532
- feat: add OAuth debug information to the UI by @thedadams in #6526
- fix: correct backgrounds for scanned config files by @njhale in #6560
- feat: add ability to reauthenticate oauth flows in the UI by @thedadams in #6557
- fix: display a better error message for multi-user MCP servers by @thedadams in #6552
- fix: audit logs filters fix & server instances link fix by @ivyjeong13 in #6533
- fix: change login route to /mcp-servers & sidebar navigation layout adjustment by @ivyjeong13 in #6566
- enhance: make dynamic client expiration configurable by @thedadams in #6570
- fix: deep-link scan observations by row id instead of slice index by @njhale in #6574
- fix: prefer catalog token, try anonymous otherwise by @calvinmclean in #6573
- feat: Replace Ollama with generic provider by @calvinmclean in #6522
- feat: External Secret Integration for MCP Servers by @calvinmclean in #6484
- chore: dependabot updates for ui by @ivyjeong13 in #6581
- enhance: additional device management pages by @ivyjeong13 in #6562
- enhance: store CLI auth tokens in OS keychain by @g-linville in #6582
- chore: add OAuth client expiration configuration to docs and chart by @thedadams in #6585
- fix: remove configs from Connect To Server & reference doc links by @ivyjeong13 in #6597
- feat: add setup and skills commands to Obot CLI by @g-linville in #6599
- fix: move StartupTimeoutSeconds to compatible runtimes by @calvinmclean in #6576
- fix: default timeout for startupTimeoutSeconds by @calvinmclean in #6607
- chore: cleanup from nanobot ui to obot & branding page update by @ivyjeong13 in #6472
- feat: Add ServerUserType by @calvinmclean in #6587
- chore: drop gemini image generation by @njhale in #6613
- feat: add OAuth walk-through debugger by @thedadams in #6575
- enhance: add Cursor support to
obot setupby @g-linville in #6614 - enhance: separate resource requests for agents, remotes, and others by @thedadams in #6611
- fix: ensure oauth-protected-resource endpoints have correct content-type by @thedadams in #6617
- fix: branding page configuration labels by @ivyjeong13 in #6612
- feat: manage image pull secrets in Obot by @g-linville in #6567
- fix: issues with UI and behaviors for secret binding by @calvinmclean in #6605
- enhance: add nanobot agent resources to APIs by @thedadams in #6622
- enhance: add non-interactive mode to
obot setupby @g-linville in #6621 - chore: dependabot package bumps by @ivyjeong13 in #6619
- chore: add missing types to deployment encryption config by @thedadams in #6628
- feat: Run Obot local with local K8s backend by @calvinmclean in #6331
- fix: make image pull secrets UI not broken by @g-linville in #6636
- chore: remove legacy chat from ui by @ivyjeong13 in #6615
- chore: remove legacy APIs and types by @thedadams in #6642
- chore: simplify by removing extraEnv and extraEnvFrom settings by @drpebcak in #6648
- fix: support existingSecret for custom encryption init by @cloudnautique in #6626
- docs: add docs for resource requests/limits for catalog entries by @thedadams in #6646
- chore: ci: set up quill signing and notarizing by @g-linville in #6645
- fix: font-family consistency in Device Scan related pages by @ivyjeong13 in #6653
- chore: ci: remove quill test step by @g-linville in #6655
- chore: update nanobot image to v0.0.81 by @calvinmclean in #6656
- enhance: include cowork skills and plugins in claude desktop scan results by @njhale in #6654
- fix: ci: download quill in a temp dir by @g-linville in #6657
- fix: incorrect View Diff shown for up-to-date MCP servers by @calvinmclean in #6635
- chore: remove unused MCPSession object by @thedadams in #6651
- fix: detect external tools by @thedadams in #6662
- fix: include defaults when hashing Kubernetes settings by @thedadams in #6660
- enhance: use local IPs in docker backend by @thedadams in #6667
- fix: ui: disable test button for invalid image pull secrets by @g-linville in #6672
- fix: strip metadata from composite component manifests in View Diff by @calvinmclean in #6671
- feat: make obot scan preview results by default by @njhale in #6674
- chore: remove more legacy APIs by @thedadams in #6675
- fix: give auditors read-only access to image pull secrets by @g-linville in #6679
- fix: ui: image pull secrets: increase contrast in ECR JSON policies by @g-linville in #6676
- chore: restore encryption config key in docs by @thedadams in #6681
- fix: ui: improve text when static image pull secrets are configured by @g-linville in #6682
- fix: add sorting and filtering to device management tables by @njhale in #6673
- fix: ensure the www-authenticate header is returned on the MCP path by @thedadams in #6686
- feat: obot-cli page, skills page & obot-cli banner by @ivyjeong13 in #6678
- chore: hide obot scan --device-id flag by @njhale in #6690
- fix: ui: image pull secrets: condense buttons into menu by @g-linville in #6685
- fix: llm token usage by @njhale in #6699
- enhance: improve obot setup to support ~/.agents by @g-linville in #6687
- chore: log 500-level API errors by @thedadams in #6702
- chore: make MCP JWT audience validation strict by @thedadams in #6706
- chore: cli: raise max skill files to 200 by @g-linville in #6712
- fix: obot local skills: make /obot-install-skill instructions clearer by @g-linville in #6711
- enhance: add model provider log level by @calvinmclean in #6710
- fix: change install step for install obot cli by @ivyjeong13 in #6714
- chore: goreleaser: skip brew upload for pre-releases by @g-linville in #6715
- fix: error status code in errors page by @ivyjeong13 in #6713
- fix: obot local skills: make /obot-skills-search able to list by @g-linville in #6717
- fix: display
/.agents multi client as "/.agents" in device management by @njhale in #6723 - chore: hide the server command by @thedadams in #6725
- chore: dependabot - bump sveltejs/kit by @ivyjeong13 in #6684
- chore: update model-provider docs by @calvinmclean in #6730
- docs: document the obot setup command by @g-linville in #6728
- docs: update branding docs by @ivyjeong13 in #6733
- docs: device management and obot scan by @njhale in #6735
- fix: sort devices user column by displayed name by @njhale in #6737
Full Changelog: v0.21.1...v0.22.0