Skip to main content

systemprompt_models/oauth/
protected_resource.rs

1//! RFC 9728 protected-resource metadata.
2//!
3//! One shape for both directions of the handshake: our routes serialise it to
4//! answer `/.well-known/oauth-protected-resource`, and our MCP client
5//! deserialises whatever a server points its `WWW-Authenticate` challenge at.
6//! Keeping a single declaration is what stops the advertised document and the
7//! parsed one drifting apart.
8//!
9//! Copyright (c) systemprompt.io — Business Source License 1.1.
10//! See <https://systemprompt.io> for licensing details.
11
12use serde::{Deserialize, Serialize};
13
14use crate::mcp::McpExtensionId;
15
16#[derive(Debug, Clone, Default, Serialize, Deserialize)]
17pub struct ProtectedResourceMetadata {
18    pub resource: String,
19    #[serde(default)]
20    pub authorization_servers: Vec<String>,
21    #[serde(default)]
22    pub scopes_supported: Vec<String>,
23    #[serde(default)]
24    pub bearer_methods_supported: Vec<String>,
25    #[serde(default, skip_serializing_if = "Option::is_none")]
26    pub resource_documentation: Option<String>,
27    #[serde(default, skip_serializing_if = "Vec::is_empty")]
28    pub mcp_extensions_supported: Vec<McpExtensionId>,
29}
30
31impl ProtectedResourceMetadata {
32    #[must_use]
33    pub fn requires_enterprise_managed_auth(&self) -> bool {
34        self.mcp_extensions_supported
35            .contains(&McpExtensionId::EnterpriseManagedAuth)
36    }
37}