We're excited to announce the v0.24.0 release of the Obot Platform. This release expands Device Management with AI client audit logging and MDM support, brings full audit logging to the LLM Gateway, and adds AWS Bedrock and Azure support to the LLM Gateway. It also reworks Obot's MCP proxy to substantially reduce its resource footprint.
Big Updates
Enhanced Device Management: AI Client Audit Logging and MDM Support
Obot's Device Management feature expands this release, built around a new companion tool called Obot Sentry. Administrators can define an MDM configuration, issue enrollment keys, and generate per-platform install packages so devices enroll themselves. Enrolled devices authenticate with device-bound keys and submit scans over short-lived signed tokens.
Once installed, either manually or pushed through an MDM, Obot Sentry does two things: it submits periodic device scans, and it installs managed hooks for supported local AI coding tools, currently Claude Code, Codex, Visual Studio Code, and Cursor. Every tool call those tools make is submitted back to Obot and recorded in the MCP Audit Logs, normalized into the same event schema as MCP tool calls so the two appear side by side. See the Upgrade Notes below if you export audit logs today, as the exported format has changed.
We are initially shipping with first-class support for Microsoft Intune, and plan to add other MDM providers such as Jamf in future releases.
Device Management, including MDM enrollment, remains in Beta, and the
obot scanCLI command has been removed in favor of Obot Sentry-based scanning. See #7249 for details.
See the docs for details.
LLM Audit Logs
Obot now keeps a full audit trail of LLM Gateway activity. Every request that flows through the gateway is logged with its model, provider, user-agent, token usage, and outcome, and users with the Auditor role can view full request and response bodies. A new Audit Logs page under LLM Gateway supports filtering by provider, model, request path, status, user-agent, and session, along with one-time and scheduled export to S3, GCS, or Azure.
See the docs for details.
New LLM Gateway Model Providers: AWS Bedrock, Azure, and Generic Responses
The LLM Gateway adds three new provider options this release. AWS Bedrock can be configured with either static IAM credentials or a Bedrock API key, and routes Anthropic, OpenAI, and Google model families hosted on Bedrock through AWS inference profiles. Azure can be configured with an API key or an Entra ID service principal, covering both Azure OpenAI and Microsoft Foundry deployments. The Generic Responses provider, now out of experimental, lets Obot call any OpenAI Responses API compatible endpoint such as Ollama or LiteLLM.
If you were already using the previous Bedrock provider, you may need to update your API keys and reselect models, since credentials are scoped differently under the new provider. See the docs for setup details.
Composite MCP Servers: GitOps Support
Composite MCP catalog entries can now be defined through the Git-backed MCP catalog like any other server type. Component servers are referenced by a stable entry key instead of an internal catalog-entry ID, so a composite entry can reference components from its own catalog source or from a different one entirely.
MCP Proxy Rework: A Smaller Footprint
Obot's MCP proxy has been rewritten this release. Previously, remote and composite MCP servers were fronted by a distributed proxy, meaning every remote or composite server required its own Kubernetes pod or Docker container just to proxy traffic to it, consuming significant additional resources across a deployment. That proxy has now been moved entirely into the main Obot server process.
The result is a substantially smaller footprint: Obot now only deploys a pod or container when you choose to actually host an MCP server yourself (via the npx, uvx, or containerized runtimes), rather than for every remote or composite server it fronts.
See the Upgrade Notes below if you run Obot with the Docker backend.
Built-in Local Authentication
Obot now includes a built-in local authentication provider backed by its own database, so users can get up and running quickly when trying out Obot instead of spending time to integrate with an OAuth provider. It's aimed at development and testing and is not suited for production deployments.
Administrators enable the Local provider from Admin > Auth Providers, restrict it to specific email domains (or allow any), and create user accounts from a "Manage Users" dialog, which also handles password resets. Local users cannot change their own password; an admin must reset it, which signs the user out of all existing sessions. Passwords are hashed with Argon2id and are never stored or returned in plaintext.
Local authentication is intended for development and testing, not for production use.
See the docs for setup details.
Getting Started Guides
Obot now includes an in-app guided tour that highlights real interface elements and steps users through common tasks, replacing an older static tour. Separate guide tracks are available for end users, covering connecting to an MCP server and installing skills or the CLI, and for administrators, covering catalog entry creation and MCP access policies.
Guides can be hidden or re-enabled from the profile menu under My Account.
Improvements
- Shared, admin-managed Git credentials can now be reused across Skill Repository and MCP Catalog sources instead of pasting a personal access token into each one.
- SkillRepository sources can now sync from any Git host using a Personal Access Token, not just GitHub.
- MCP config secret bindings can be managed directly from the UI when creating or configuring multi-user MCP servers.
- Client ID Metadata Documents (CIMD) are now supported, letting OAuth clients present a URL-hosted metadata document instead of performing dynamic client registration.
- Administrators can cap CPU and memory maximums for MCP servers with new environment variables, blocking catalog entries and defaults from requesting more.
- Database connection settings (max open and idle connections, connection lifetime) can now be configured separately for the primary database, kinm, and the auth provider.
- Users connecting to an MCP server for the first time from an external client can now supply required configuration inline instead of the connection failing outright.
- Deprecated catalog entries now show a notice in the catalog, connect, and server-management views.
- Administrators can configure an app-wide notification banner, grouped with Branding and License under a new App Management section.
- LLM Gateway usage is now tracked with estimated USD cost per model, based on a new pricing pipeline.
- SSRF protections against loopback, private, and link-local addresses now also apply to Client ID Metadata Document fetching and general OAuth URL fetching.
Upgrade Notes
This release contains several behavior changes and known issues. Review carefully before upgrading.
Known issue with Obot Sentry: macOS manual installs create multiple device identities. When Obot Sentry is installed using the macOS standalone binary instructions, audit hooks can use a different device identity from device scans. As a result, hook audit logs and inventory scans appear under different device IDs. See #7298 (#7298) for status and updates.
Helm chart configuration overhaul. Kubernetes installations now separate sensitive settings into a Secret and non-sensitive settings into a ConfigMap. Update your custom values before upgrading:
- Rename
config.existingSecrettosecret.existingSecret. - Move credentials and other sensitive values from
config.*tosecret.*, including database DSNs, API keys, encryption keys, bootstrap tokens, license keys, and artifact-storage credentials. Known sensitive values left underconfignow cause chart rendering to fail. - External Secrets must provide all required sensitive values; bootstrap tokens are generated and preserved only for chart-managed Secrets.
- When combining
secret.existingSecretwithmcpImagePullSecrets, provideOBOT_SERVER_MCPIMAGE_PULL_SECRETSin the external Secret. OBOT_SERVER_MCPBASE_IMAGEno longer receives an automatic chart-version tag, so configure an explicit image tag if you relied on that behavior.
Additional Helm changes in this release:
- A startup probe now gives Obot up to 20 minutes to become healthy.
- Ingress configurations require at least one host when enabled.
- MCP namespaces can be configured with a Kubernetes ResourceQuota.
- Setting
persistence.storageClassto"-"explicitly disables dynamic storage-class selection. - Configuration changes now automatically trigger pod rollouts.
See #7252 for details.
obot scan CLI command removed. Device scanning now happens through Obot Sentry, installed manually or via MDM, instead of the CLI. If you have scripts or automation calling obot scan, they will need to move to Obot Sentry instead. See #7249 for details.
Audit log export format has changed. The JSON shape of exported audit logs (S3, GCS, or Azure) has changed completely, replacing the old flat per-log-type shape with a single normalized event envelope shared by MCP and local-agent tool-call events. Anything consuming exported logs downstream will need to be updated to the new shape. See #7174 for details.
Old Slack MCP server deprecated. The original Slack MCP server in Obot's default catalog is now marked deprecated in favor of a new official Slack MCP server. There is no automatic migration; existing users should switch manually. The legacy Slack server will be removed completely by the end of August 2026. See #7173 for details.
Docker-mode users should clean up old shim containers. As part of the MCP proxy rework above, Kubernetes deployments clean up old shim containers automatically, but Docker-mode deployments will not remove them on their own. Remove them with:
docker ps -aq --filter "label=mcp.deployment.id" | xargs docker rm -f
See #7100 for details.
What's Changed
- chore: clean up image builds by @njhale in #6992
- feat: add support for CIMD by @thedadams in #6964
- feat: admin ability to add app notification banner by @ivyjeong13 in #6999
- chore: dependabot, dompurify, & lucide-svelte deprecation by @ivyjeong13 in #7003
- fix: only check for a valid license once per day by @thedadams in #7011
- fix: sort devices initally by scannedAt descending by @ivyjeong13 in #7008
- fix: save sidebar scroll state on navigation for sidebar in Layout by @ivyjeong13 in #7013
- enhance: how to connect ai client updates by @ivyjeong13 in #7000
- chore: migrate mcp audit logs to support local agent audit logs by @g-linville in #6928
- Revert "chore: migrate mcp audit logs to support local agent audit logs by @g-linville in #7030
- feat: add ability to configure MCP server on first connect by @thedadams in #7007
- enhance: make redirect countdown dynamic by @thedadams in #7036
- enhance: more logging around successful license validation by @thedadams in #7037
- docs: fix private IP MCP env var by @thedadams in #7035
- chore: bump images for nanobot stdio fix by @thedadams in #7027
- fix: show partial pat in edit of mcp catalog source url by @ivyjeong13 in #7019
- chore: remove redunant check by @thedadams in #7040
- enhance: disallow loopback, private IP and link-local in more places by @thedadams in #7039
- fix: populate tool preview action should not be visible for basic users by @ivyjeong13 in #7038
- chore: bump nanobot to pick up extra logging by @thedadams in #7048
- enhance: track token burn in usd by @njhale in #7020
- fix: store OAuthMetadata raw-JSON fields as runtime.RawExtension by @zmiievskyi in #7053
- chore: change language when user configuration is required by @thedadams in #7051
- fix: allow users to provide optional configuration by @thedadams in #7054
- fix: displayName for magic link, id for command & no prompt for vscode magic link by @ivyjeong13 in #7043
- fix: stop refreshing invalid MCP tokens by @thedadams in #7057
- chore: add resource requirements to nanobot shims by @g-linville in #7044
- fix: stop showing "close this window" message when redirecting by @thedadams in #7061
- fix: allow composite MCP servers to use private IPs by @thedadams in #7064
- fix: stop blocking private IPs in the shim by @thedadams in #7067
- fix: stop block nanobot private IPs in Kubernetes by @thedadams in #7068
- feat: Manage MCP config secret bindings from the UI by @calvinmclean in #6754
- feat: GitOps for composite MCP servers by @calvinmclean in #7055
- fix: reduce the chance of conflict when configuring MCP server by @thedadams in #7074
- enhance: add OBOT_SERVER_HIDE_K8S_DETAILS toggle for server scheduling UI by @ivyjeong13 in #7069
- fix: do not allow multi-user remote catalog entries by @calvinmclean in #7073
- fix: secret bound config styling inconsistency by @ivyjeong13 in #7071
- chore: revamp chart configuration by @drpebcak in #6693
- chore: migrate MCPAuditLog type to support local tool calls by @g-linville in #7062
- chore: update/remove tag workflows by @drpebcak in #7084
- fix: show env var name in MultiUser launch UI by @calvinmclean in #7079
- fix: launch catalog entry / troubleshooting for debuggability by @ivyjeong13 in #7082
- feat: add env vars for k8s resource maximums by @g-linville in #7012
- feat: add API for local agent audit log submission by @g-linville in #7086
- fix: check access to MCP ID during OAuth by @thedadams in #7104
- chore: drop device scan from cli by @njhale in #7102
- fix: mcp catalog administrative tools & debugging, filter configured servers by owner id by @ivyjeong13 in #7103
- docs: add Slack MCP tutorial by @g-linville in #7091
- fix: hydrate composite multi-user components by @calvinmclean in #7106
- feat: add llm gateway audit log by @calvinmclean in #7089
- fix: short description catalog entry support and populate tool load fix by @ivyjeong13 in #7096
- enhance: show notices for deprecated catalog entries by @g-linville in #7093
- fix: block missing mcp secret bindings by @calvinmclean in #7107
- fix: support MCP servers with empty ToolOverrides and improve docs by @calvinmclean in #7098
- enhance: add device enrollment and device-authenticated scan submission by @njhale in #7087
- chore: allow configuring topologySpreadConstraints in chart by @drpebcak in #7117
- chore: bump dependencies by @thedadams in #7120
- fix: hydrate composite catalog entry refs by @calvinmclean in #7119
- fix: hide entryKey diff by @calvinmclean in #7133
- fix: resolve composite server details components by @calvinmclean in #7134
- chore: add PDB to chart by @g-linville in #7138
- feat: collapse shims into Obot by @thedadams in #7124
- feat: LLM Audit Log API and UI by @calvinmclean in #7105
- chore: bump kinm by @thedadams in #7151
- enhance: update initial configure process when agents disabled and device dashboard layout change by @ivyjeong13 in #7123
- fix: add leader election to local k8s router by @thedadams in #7150
- Docs: drop pgvector requirement by @cjellick in #7153
- fix: start Obot with a SQLite database by @calvinmclean in #7145
- chore: update docusaurus dependencies by @ivyjeong13 in #7152
- fix: enforce max char limit for catalog entry short description (160 chars) by @ivyjeong13 in #7144
- enhance: remove composite MCP containers by @thedadams in #7140
- fix: correctly display, filter, and rename message policy activity in audit logs by @calvinmclean in #7148
- chore: bump nanobot for oauth protected metadata fixes by @thedadams in #7162
- fix: filter out /models requests by default in LLM audit logs by @calvinmclean in #7158
- feat: AWS Bedrock LLM Gateway by @calvinmclean in #7126
- feat: add export feature for LLM Audit Logs by @calvinmclean in #7141
- fix: enforce buttons in form don't trigger submit by @ivyjeong13 in #7167
- feat: first time user tour/getting started guides by @ivyjeong13 in #7159
- fix: update LLM filter options from draft by @calvinmclean in #7164
- feat: add Generic Responses Model Provider to LLM Gateway by @calvinmclean in #7166
- feat: add local agent tool call audit logs by @g-linville in #7136
- fix: AWS Bedrock API Gateway setup and errors by @calvinmclean in #7183
- fix: show model discovery filter status by @calvinmclean in #7179
- fix: correct LLM audit log export filters by @calvinmclean in #7177
- fix(composite): stop using proxy for tool previews by @thedadams in #7180
- fix: address catalog-entry form validation bugs by @ivyjeong13 in #7185
- feat(db): add more fine-grained db connection config by @thedadams in #7189
- feat: Azure compatibility for LLM Gateway by @calvinmclean in #7165
- fix(composite): ensure components are deployed and contactable by @thedadams in #7202
- fix: capture LLM audit session IDs by dialect by @calvinmclean in #7193
- fix: improve auth provider path by @thedadams in #7206
- feat: mdm configuration management and device-config downloads by @njhale in #7139
- fix: remove redundant audit log model column by @calvinmclean in #7194
- fix: identify Claude Code from session header by @calvinmclean in #7205
- fix: improve LLM audit error details by @calvinmclean in #7204
- chore: audit logs: remove target.resolved field by @g-linville in #7208
- fix: fail sooner when command fails by @thedadams in #7211
- fix: alway prompt configuration for composite & composite/remote server details route fix by @ivyjeong13 in #7195
- fix(k8s): restart deployment watch every 5 seconds by @thedadams in #7214
- fix: use 24-hour audit log timestamps by @calvinmclean in #7215
- feat: support SkillRepository from any Git source with PAT by @calvinmclean in #6571
- fix: refresh LLM gateway models on navigation by @calvinmclean in #7199
- enhance: iterate getting started guides & related ux by @ivyjeong13 in #7210
- fix: store raw LLM audit user agent by @calvinmclean in #7218
- fix: ensure composite and remote servers report available by @thedadams in #7229
- chore: rework audit logs UX by @g-linville in #7216
- Chore: Drop experimental from generic responses by @cjellick in #7224
- Fix: Use correct email for license by @cjellick in #7225
- enhance: improve audit details layout by @ivyjeong13 in #7235
- enhance: add quick start guides for custom catalog entries & mcp access policy by @ivyjeong13 in #7231
- fix: audit logs: show proper tool name in identifier column for local agent tool calls by @g-linville in #7234
- fix: choose first install skill button in the "install skills" guide by @ivyjeong13 in #7242
- fix: invert model request audit filter by @calvinmclean in #7212
- fix: support beta tag in sidebar navigations for collapsible sections & subroutes by @ivyjeong13 in #7247
- fix: include static env vars in drift detection by @thedadams in #7243
- feat: shared credentials for git auth by @calvinmclean in #7217
- fix: remove obot banner, beta for device managmeent, and update install-cli page by @ivyjeong13 in #7250
- fix: install cli text fix by @ivyjeong13 in #7254
- fix: stop including server type and entry key in drift by @thedadams in #7257
- enhance: improve repository credential selection by @calvinmclean in #7256
- enhance: update text on admin guides & simplify composite entry guide by @ivyjeong13 in #7258
- feat: add built-in local authentication by @ibuildthecloud in #7182
- fix: indicate existing skill source tokens by @calvinmclean in #7262
- enhance: rework device management configuration and download flow by @njhale in #7251
- chore: set default mdm asset source by @njhale in #7266
- chore: one text line change for access policy guide step by @ivyjeong13 in #7263
- fix: only call shutdown if server is not idle by @thedadams in #7268
- docs: update device management by @njhale in #7276
- fix: store MDM asset fields as runtime.RawExtension by @njhale in #7275
- fix: pat/shared credential UI adjustments by @ivyjeong13 in #7273
- fix: cleanup Obot user on local auth user delete by @thedadams in #7278
- fix: stop immediate failed skill repository retries by @calvinmclean in #7280
- chore: bump default mdm assets to v0.1.0 by @njhale in #7287
- fix: fix code blocks font color in sentry install instructions & copy snippet option by @ivyjeong13 in #7281
- fix: use SensitiveInput for local auth password by @ivyjeong13 in #7285
- fix: "getting started" guides text changes updates by @ivyjeong13 in #7291
- Docs: Update readme and overview by @cjellick in #7294
- Docs: v0.24 docs by @cjellick in #7296
- chore: bump obot-sentry default version to v0.1.1 by @njhale in #7297
New Contributors
- @zmiievskyi made their first contribution in #7053
Full Changelog: v0.23.1...v0.24.0