URSA-OSCAR 1.1.5
MCP spec compliance: RFC 7591 Dynamic Client Registration is now supported.
Fixed in 1.1.5
- MCP server now accepts non-claude.ai OAuth clients via RFC 7591 DCR (
mcp-server/src/ursa_oscar_mcp/auth.py). Prior versions had DCR disabled — the MCP server's only OAuth client was the pre-registered claude.ai one, so KAIROS or any other MCP client following the spec's standard discovery flow got400 Bad Requestat/authorize("Redirect URI not registered for client") when trying to use its own redirect_uri. The MCP spec requires DCR support for general-purpose servers; URSA now provides it.POST /registerper RFC 7591: the caller suppliesclient_name,redirect_uris,grant_types,response_types, and receives back a freshclient_id+client_secret. Registrations persist to/data/mcp_oauth_clients.json(mode 0600, atomic writes via tmpfile+rename) so they survive container restart. The pre-registered claude.ai client is reconstructed from env vars on every boot and is intentionally excluded from the persisted store (env vars remain the source of truth for it; persisting would risk a stale entry masking an env-var rotation). Startup banner now reportsdcr=ENABLEDinstead ofdcr=DISABLED. Five regression tests cover DCR registration with caller-specified redirect_uris, persistence across provider reconstruction, exclusion of the pre-registered client from disk, graceful handling of corrupt JSON stores, and skip-and-continue on individual corrupt entries.
Breaking compose change — MCP /data mount
The MCP container's /data mount must change from :ro to :rw so the DCR client store can be written. Both infra/docker-compose.yml and infra/docker-compose.production.yml have been updated. Operators on a Dockge-managed or hand-edited compose stack must mirror this change in their own compose file before redeploy, otherwise the MCP container will be unable to persist DCR registrations and they will be lost on container restart (the in-memory dict still works for the immediate caller; only persistence is lost).
The trust model is unchanged: the same operator who controls the API and watcher containers (both already :rw) also controls MCP. The /data directory is operator-owned on a private LAN volume.
No data migrations
No schema changes. No env-var changes. The DCR client store is created on first registration; missing file is normal on a fresh install.
Docker images
All four images are available at brain40/ursa-oscar-*:1.1.5 + :latest:
brain40/ursa-oscar-api:1.1.5brain40/ursa-oscar-mcp:1.1.5brain40/ursa-oscar-web:1.1.5brain40/ursa-oscar-watcher:1.1.5
Upgrade
-
Update your compose file: change
image:tags to 1.1.5 on all four services. Change the MCP container's/datamount from:roto:rw. -
docker compose pull && docker compose up -d --force-recreate. -
Verify by sending a DCR request. The MCP SDK requires the request to include both
authorization_codeandrefresh_tokeningrant_types(per the MCP connector spec's refresh-token requirement):curl -X POST https://your-mcp-host/register \ -H 'content-type: application/json' \ -d '{"client_name":"test","redirect_uris":["https://example.test/cb"],"grant_types":["authorization_code","refresh_token"],"response_types":["code"]}'
You should get a 201 response with a fresh
client_id(not the pre-registered claude.ai one) and aclient_secret.If you forget
refresh_tokeningrant_types, you'll seeerror: "invalid_client_metadata", error_description: "grant_types must be authorization_code and refresh_token". That comes from the upstream MCP SDK'sRegistrationHandler, not from URSA — it's the spec-mandated check. Send both grant types and it works.
Acknowledgments
Bug surfaced by the KAIROS Claude Code dev during a connector integration attempt. The diagnostic walkthrough (URSA's /.well-known advertised endpoints, the specific /authorize 400 error pattern, the recommended RFC 7591 implementation steps) made this fix straightforward to scope.
License
GNU GPL-3.0-or-later, preserving OSCAR's license terms.
Attribution
Built in the spirit and license terms of the OSCAR project. URSA-OSCAR is independent of OSCAR (different codebase, different deployment model) but downstream of OSCAR's file-format work.