Pre-alpha documentation
Authorize one MCP resource without widening trust.
Configure StateKnot's challenge-driven MCP OAuth client, durable credential stores, exact callback boundary, bounded replay, and frozen official evidence.
Bind OAuth to one exact resource
Production MCP resources require HTTPS. The host supplies a trusted user agent plus encrypted, tenant-scoped credential and expiring PKCE-state stores. The in-memory constructor is for processes that deliberately do not promise restart recovery.
use std::sync::Arc;
use stateknot_integrations::{
McpClient, McpClientIdentity, McpClientOptions,
McpOAuthAuthorization, McpOAuthOptions, McpOAuthRegistration,
McpOAuthResource, ProviderEndpoint,
};
let endpoint = ProviderEndpoint::https("https://mcp.example.com/mcp/")?;
let resource = McpOAuthResource::from_endpoint(&endpoint)?;
let registration = McpOAuthRegistration::client_metadata_document(
"https://agent.example.com/oauth/client-metadata.json",
)?;
let policy = McpOAuthOptions::native(
"http://127.0.0.1:49152/callback",
"Inventory Agent",
registration,
)?;
let authorization = Arc::new(
McpOAuthAuthorization::new_with_stores(
resource,
policy,
user_agent,
encrypted_credential_store,
expiring_pkce_state_store,
)
.await?,
);
let client = McpClient::connect(
endpoint,
McpClientIdentity::new("inventory-agent", "1.0.0")?,
authorization,
McpClientOptions::default().with_maximum_authorization_retries(1)?,
)
.await?; Use pre-registration when credentials were provisioned out of band. Use CIMD for a published HTTPS client metadata document. Enable DCR fallback only when it is an accepted deployment policy.
Keep challenge recovery finite
- The client sends anonymously when no usable credential exists.
- A bounded 401/403 Bearer challenge drives protected-resource and authorization-server discovery.
- StateKnot restores issuer-bound credentials or starts a PKCE flow using pre-registration, CIMD, then DCR according to policy.
- The host opens the validated authorization URL and returns the complete callback URL from the exact registered origin and path.
- After token exchange, the MCP method is replayed once with a fresh JSON-RPC ID. Timeout and ambiguous dispatch are never replayed.
A 403 triggers step-up only for an explicit
insufficient_scope challenge carrying a scope. Scope upgrade and
transport replay have separate hard ceilings. An issuer change forces a new
issuer-bound registration flow.
Own the user-agent boundary
A native host reserves its loopback listener before opening the browser, accepts only the configured address, port, and path, returns one complete callback URL, and closes the listener. StateKnot enforces a five-minute default handoff timeout, exact callback binding, PKCE, state, RFC 8707 resource indicators, and RFC 9207 issuer checks. URLs, codes, verifier material, client identity, and tokens must never enter logs.
Treat stores as security infrastructure
- Encrypt access tokens, refresh tokens, client secrets, and PKCE state at rest with a rotation procedure.
- Isolate records by tenant, principal, MCP resource, and authorization server issuer.
- Make state one-time and expiring; make credential replacement atomic.
- Emit only redacted audit facts for discovery, registration, refresh, migration, scope upgrade, cancellation, and failure.
Reproduce the exact claim
cargo test -p stateknot-integrations --test mcp_client_contract --locked
bash conformance/mcp-client/run-2026-07-28.sh The frozen gate passes all 32 scored client scenarios, including all 25 OAuth scenarios: 371 scored assertions succeed and zero fail. Seven explicitly not-scored extensions are reported separately and remain outside the claim. Read the complete evidence boundary and the full operating contract.