Mint OAuth client_credentials tokens as an umbra value provider, so a hosted upstream needs no static secret #83
Labels
No labels
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/mcp-beaver#83
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The cheap half of the OAuth problem, split out of #82 so it can be built on its own merits. Neither issue blocks the other, and this one has no human in the loop.
What
A token-minting value provider, so
{oauth2:<name>}resolves the way{env:VAR}and{file:path}do today:Config carries the token endpoint, client id, client secret reference, and scopes. The provider posts
grant_type=client_credentials, caches the access token to its ownexpires_in, and renews ahead of expiry.Why this belongs in umbra rather than the proxy path
#82's first open question was whether an OAuth loop belongs in umbra's value layer instead of mcp-beaver's proxy path, since umbra already owns credential resolution for spec mode. For
client_credentialsthe answer is clearly umbra. It is a value that happens to be minted rather than read, it needs nothing from the MCP session, and putting it in the value registry means spec mode and upstream mode both get it from one implementation.Why it is cheap, unlike #82
Every cost that makes #82 expensive is absent here:
client_credentialsis machine to machine by definition, so nothing needs an attended seeding flow.clientIddance.What lands is a POST, a cache with an expiry, and serialized renewal so concurrent calls do not stampede the token endpoint.
Why it is worth building regardless of Moxn
The MCP specification pushed HTTP transports toward OAuth, so hosted third-party MCP servers keep arriving OAuth-shaped rather than API-key-shaped.
--upstream-headercovers a hosted upstream holding a durable static secret, which is the shape that is becoming less common, not more.Moxn cannot use this. Its authorization server offers
authorization_codeandrefresh_tokenonly, with noclient_credentialsgrant. That is exactly why this is filed separately: the generic capability should not wait on, or be shaped by, the one upstream that needs the harder version.Notes for whoever builds it
authand query pins already behave, so a rotated client secret takes effect without a restart./adminshould report the scheme and never the credential, matching what62474acdid for static headers.62474achad to:boundedTransportonly recognizes an*http.Transportand the other order drops the time-to-first-byte bound from #79.Refs #82, coilyco-bridge/deploy#647