Skip to content

Fix add/remove_authorized_clients to use REST resource shape#48

Merged
Subterrane merged 1 commit intomainfrom
fix/authorized-clients-rest-shape
Apr 15, 2026
Merged

Fix add/remove_authorized_clients to use REST resource shape#48
Subterrane merged 1 commit intomainfrom
fix/authorized-clients-rest-shape

Conversation

@Subterrane
Copy link
Copy Markdown
Contributor

Summary

Fixes #47.

The /api/2/api_authorizations/{id}/clients endpoint is a Rails REST resource (routes, controller):

  • POST /clients creates one association from {app_id, scopes} (both required by required_params)
  • DELETE /clients/{app_id} removes one (keyed by the OIDC app's app_id, matching what list_authorized_clients returns)

The MCP was POSTing {client_ids: [...]} to the collection and DELETEing the collection with a body — neither shape the controller accepts, so both returned 400 Missing required field: app_id.

Changes

  • add_authorized_clients now takes clients: [{app_id, scopes: number[]}] and POSTs each (scopes are numeric API scope IDs from list_authorization_scopes, not value strings)
  • remove_authorized_clients now takes app_ids: number[] and DELETEs each at /clients/{app_id}
  • Both return a per-item results array so partial failures surface cleanly
  • Tool descriptions updated to clarify app_id vs misleading client_id, and that scopes are numeric IDs

Test plan

Verified end-to-end against the shadow chicken tenant:

  • Old POST /clients with {client_ids: [N]}400 Missing required field: app_id (reproduces remove_authorized_clients & add_authorized_clients #47)
  • New POST /clients with {app_id, scopes: [id]}201 with {app_id, api_auth_id}
  • Old DELETE /clients with body → 400
  • New DELETE /clients/{app_id}204, association removed (verified via list_authorized_clients)

The /api/2/api_authorizations/{id}/clients endpoint is a Rails REST
resource: POST creates one association from {app_id, scopes} (both
required), and DELETE targets /clients/{app_id} for one removal at
a time. The MCP was POSTing {client_ids: [...]} and DELETEing the
collection with a body, neither of which the controller accepts —
both calls returned 400.

Reshape the tools to match: add_authorized_clients now takes a
clients array of {app_id, scopes} and posts each; remove_authorized_clients
takes app_ids and deletes each at /clients/{app_id}. Both return a
per-item results array so partial failures surface cleanly.

Verified against shadow (chicken tenant): old shape returned 400
'Missing required field: app_id'; new shape returned 201 and 204.

Fixes #47
@Subterrane Subterrane merged commit 3e361ca into main Apr 15, 2026
2 checks passed
Subterrane added a commit that referenced this pull request Apr 16, 2026
The /scopes endpoint on api_authorizations is a standard nested REST
resource (config/api2_routes.rb:65), not a bulk endpoint. POST creates
one scope from {value, description}; DELETE requires the numeric
scope_id in the URL path.

- add_authorization_scopes now takes scopes: [{value, description?}]
  and iterates, reporting per-item status
- remove_authorization_scopes now takes scope_ids: [number] (from
  list_authorization_scopes) and iterates DELETE .../scopes/{scope_id}
- Both inspect response.success from the API wrapper so per-item
  status reflects actual outcomes (the client returns wrapped errors
  rather than throwing)

Same shape fix as PR #48 applied to the sibling /clients route.

Fixes #49
@Subterrane Subterrane deleted the fix/authorized-clients-rest-shape branch April 16, 2026 12:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

remove_authorized_clients & add_authorized_clients

1 participant