fastmcp 2.14.4__py3-none-any.whl → 3.0.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. fastmcp/_vendor/__init__.py +1 -0
  2. fastmcp/_vendor/docket_di/README.md +7 -0
  3. fastmcp/_vendor/docket_di/__init__.py +163 -0
  4. fastmcp/cli/cli.py +112 -28
  5. fastmcp/cli/install/claude_code.py +1 -5
  6. fastmcp/cli/install/claude_desktop.py +1 -5
  7. fastmcp/cli/install/cursor.py +1 -5
  8. fastmcp/cli/install/gemini_cli.py +1 -5
  9. fastmcp/cli/install/mcp_json.py +1 -6
  10. fastmcp/cli/run.py +146 -5
  11. fastmcp/client/__init__.py +7 -9
  12. fastmcp/client/auth/oauth.py +18 -17
  13. fastmcp/client/client.py +100 -870
  14. fastmcp/client/elicitation.py +1 -1
  15. fastmcp/client/mixins/__init__.py +13 -0
  16. fastmcp/client/mixins/prompts.py +295 -0
  17. fastmcp/client/mixins/resources.py +325 -0
  18. fastmcp/client/mixins/task_management.py +157 -0
  19. fastmcp/client/mixins/tools.py +397 -0
  20. fastmcp/client/sampling/handlers/anthropic.py +2 -2
  21. fastmcp/client/sampling/handlers/openai.py +1 -1
  22. fastmcp/client/tasks.py +3 -3
  23. fastmcp/client/telemetry.py +47 -0
  24. fastmcp/client/transports/__init__.py +38 -0
  25. fastmcp/client/transports/base.py +82 -0
  26. fastmcp/client/transports/config.py +170 -0
  27. fastmcp/client/transports/http.py +145 -0
  28. fastmcp/client/transports/inference.py +154 -0
  29. fastmcp/client/transports/memory.py +90 -0
  30. fastmcp/client/transports/sse.py +89 -0
  31. fastmcp/client/transports/stdio.py +543 -0
  32. fastmcp/contrib/component_manager/README.md +4 -10
  33. fastmcp/contrib/component_manager/__init__.py +1 -2
  34. fastmcp/contrib/component_manager/component_manager.py +95 -160
  35. fastmcp/contrib/component_manager/example.py +1 -1
  36. fastmcp/contrib/mcp_mixin/example.py +4 -4
  37. fastmcp/contrib/mcp_mixin/mcp_mixin.py +11 -4
  38. fastmcp/decorators.py +41 -0
  39. fastmcp/dependencies.py +12 -1
  40. fastmcp/exceptions.py +4 -0
  41. fastmcp/experimental/server/openapi/__init__.py +18 -15
  42. fastmcp/mcp_config.py +13 -4
  43. fastmcp/prompts/__init__.py +6 -3
  44. fastmcp/prompts/function_prompt.py +465 -0
  45. fastmcp/prompts/prompt.py +321 -271
  46. fastmcp/resources/__init__.py +5 -3
  47. fastmcp/resources/function_resource.py +335 -0
  48. fastmcp/resources/resource.py +325 -115
  49. fastmcp/resources/template.py +215 -43
  50. fastmcp/resources/types.py +27 -12
  51. fastmcp/server/__init__.py +2 -2
  52. fastmcp/server/auth/__init__.py +14 -0
  53. fastmcp/server/auth/auth.py +30 -10
  54. fastmcp/server/auth/authorization.py +190 -0
  55. fastmcp/server/auth/oauth_proxy/__init__.py +14 -0
  56. fastmcp/server/auth/oauth_proxy/consent.py +361 -0
  57. fastmcp/server/auth/oauth_proxy/models.py +178 -0
  58. fastmcp/server/auth/{oauth_proxy.py → oauth_proxy/proxy.py} +24 -778
  59. fastmcp/server/auth/oauth_proxy/ui.py +277 -0
  60. fastmcp/server/auth/oidc_proxy.py +2 -2
  61. fastmcp/server/auth/providers/auth0.py +24 -94
  62. fastmcp/server/auth/providers/aws.py +26 -95
  63. fastmcp/server/auth/providers/azure.py +41 -129
  64. fastmcp/server/auth/providers/descope.py +18 -49
  65. fastmcp/server/auth/providers/discord.py +25 -86
  66. fastmcp/server/auth/providers/github.py +23 -87
  67. fastmcp/server/auth/providers/google.py +24 -87
  68. fastmcp/server/auth/providers/introspection.py +60 -79
  69. fastmcp/server/auth/providers/jwt.py +30 -67
  70. fastmcp/server/auth/providers/oci.py +47 -110
  71. fastmcp/server/auth/providers/scalekit.py +23 -61
  72. fastmcp/server/auth/providers/supabase.py +18 -47
  73. fastmcp/server/auth/providers/workos.py +34 -127
  74. fastmcp/server/context.py +372 -419
  75. fastmcp/server/dependencies.py +541 -251
  76. fastmcp/server/elicitation.py +20 -18
  77. fastmcp/server/event_store.py +3 -3
  78. fastmcp/server/http.py +16 -6
  79. fastmcp/server/lifespan.py +198 -0
  80. fastmcp/server/low_level.py +92 -2
  81. fastmcp/server/middleware/__init__.py +5 -1
  82. fastmcp/server/middleware/authorization.py +312 -0
  83. fastmcp/server/middleware/caching.py +101 -54
  84. fastmcp/server/middleware/middleware.py +6 -9
  85. fastmcp/server/middleware/ping.py +70 -0
  86. fastmcp/server/middleware/tool_injection.py +2 -2
  87. fastmcp/server/mixins/__init__.py +7 -0
  88. fastmcp/server/mixins/lifespan.py +217 -0
  89. fastmcp/server/mixins/mcp_operations.py +392 -0
  90. fastmcp/server/mixins/transport.py +342 -0
  91. fastmcp/server/openapi/__init__.py +41 -21
  92. fastmcp/server/openapi/components.py +16 -339
  93. fastmcp/server/openapi/routing.py +34 -118
  94. fastmcp/server/openapi/server.py +67 -392
  95. fastmcp/server/providers/__init__.py +71 -0
  96. fastmcp/server/providers/aggregate.py +261 -0
  97. fastmcp/server/providers/base.py +578 -0
  98. fastmcp/server/providers/fastmcp_provider.py +674 -0
  99. fastmcp/server/providers/filesystem.py +226 -0
  100. fastmcp/server/providers/filesystem_discovery.py +327 -0
  101. fastmcp/server/providers/local_provider/__init__.py +11 -0
  102. fastmcp/server/providers/local_provider/decorators/__init__.py +15 -0
  103. fastmcp/server/providers/local_provider/decorators/prompts.py +256 -0
  104. fastmcp/server/providers/local_provider/decorators/resources.py +240 -0
  105. fastmcp/server/providers/local_provider/decorators/tools.py +315 -0
  106. fastmcp/server/providers/local_provider/local_provider.py +465 -0
  107. fastmcp/server/providers/openapi/__init__.py +39 -0
  108. fastmcp/server/providers/openapi/components.py +332 -0
  109. fastmcp/server/providers/openapi/provider.py +405 -0
  110. fastmcp/server/providers/openapi/routing.py +109 -0
  111. fastmcp/server/providers/proxy.py +867 -0
  112. fastmcp/server/providers/skills/__init__.py +59 -0
  113. fastmcp/server/providers/skills/_common.py +101 -0
  114. fastmcp/server/providers/skills/claude_provider.py +44 -0
  115. fastmcp/server/providers/skills/directory_provider.py +153 -0
  116. fastmcp/server/providers/skills/skill_provider.py +432 -0
  117. fastmcp/server/providers/skills/vendor_providers.py +142 -0
  118. fastmcp/server/providers/wrapped_provider.py +140 -0
  119. fastmcp/server/proxy.py +34 -700
  120. fastmcp/server/sampling/run.py +341 -2
  121. fastmcp/server/sampling/sampling_tool.py +4 -3
  122. fastmcp/server/server.py +1214 -2171
  123. fastmcp/server/tasks/__init__.py +2 -1
  124. fastmcp/server/tasks/capabilities.py +13 -1
  125. fastmcp/server/tasks/config.py +66 -3
  126. fastmcp/server/tasks/handlers.py +65 -273
  127. fastmcp/server/tasks/keys.py +4 -6
  128. fastmcp/server/tasks/requests.py +474 -0
  129. fastmcp/server/tasks/routing.py +76 -0
  130. fastmcp/server/tasks/subscriptions.py +20 -11
  131. fastmcp/server/telemetry.py +131 -0
  132. fastmcp/server/transforms/__init__.py +244 -0
  133. fastmcp/server/transforms/namespace.py +193 -0
  134. fastmcp/server/transforms/prompts_as_tools.py +175 -0
  135. fastmcp/server/transforms/resources_as_tools.py +190 -0
  136. fastmcp/server/transforms/tool_transform.py +96 -0
  137. fastmcp/server/transforms/version_filter.py +124 -0
  138. fastmcp/server/transforms/visibility.py +526 -0
  139. fastmcp/settings.py +34 -96
  140. fastmcp/telemetry.py +122 -0
  141. fastmcp/tools/__init__.py +10 -3
  142. fastmcp/tools/function_parsing.py +201 -0
  143. fastmcp/tools/function_tool.py +467 -0
  144. fastmcp/tools/tool.py +215 -362
  145. fastmcp/tools/tool_transform.py +38 -21
  146. fastmcp/utilities/async_utils.py +69 -0
  147. fastmcp/utilities/components.py +152 -91
  148. fastmcp/utilities/inspect.py +8 -20
  149. fastmcp/utilities/json_schema.py +12 -5
  150. fastmcp/utilities/json_schema_type.py +17 -15
  151. fastmcp/utilities/lifespan.py +56 -0
  152. fastmcp/utilities/logging.py +12 -4
  153. fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py +3 -3
  154. fastmcp/utilities/openapi/parser.py +3 -3
  155. fastmcp/utilities/pagination.py +80 -0
  156. fastmcp/utilities/skills.py +253 -0
  157. fastmcp/utilities/tests.py +0 -16
  158. fastmcp/utilities/timeout.py +47 -0
  159. fastmcp/utilities/types.py +1 -1
  160. fastmcp/utilities/versions.py +285 -0
  161. {fastmcp-2.14.4.dist-info → fastmcp-3.0.0b1.dist-info}/METADATA +8 -5
  162. fastmcp-3.0.0b1.dist-info/RECORD +228 -0
  163. fastmcp/client/transports.py +0 -1170
  164. fastmcp/contrib/component_manager/component_service.py +0 -209
  165. fastmcp/prompts/prompt_manager.py +0 -117
  166. fastmcp/resources/resource_manager.py +0 -338
  167. fastmcp/server/tasks/converters.py +0 -206
  168. fastmcp/server/tasks/protocol.py +0 -359
  169. fastmcp/tools/tool_manager.py +0 -170
  170. fastmcp/utilities/mcp_config.py +0 -56
  171. fastmcp-2.14.4.dist-info/RECORD +0 -161
  172. /fastmcp/server/{openapi → providers/openapi}/README.md +0 -0
  173. {fastmcp-2.14.4.dist-info → fastmcp-3.0.0b1.dist-info}/WHEEL +0 -0
  174. {fastmcp-2.14.4.dist-info → fastmcp-3.0.0b1.dist-info}/entry_points.txt +0 -0
  175. {fastmcp-2.14.4.dist-info → fastmcp-3.0.0b1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,178 @@
1
+ """OAuth Proxy Models and Constants.
2
+
3
+ This module contains all Pydantic models and constants used by the OAuth proxy.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import hashlib
9
+ from typing import Any, Final
10
+
11
+ from mcp.shared.auth import OAuthClientInformationFull
12
+ from pydantic import AnyUrl, BaseModel, Field
13
+
14
+ from fastmcp.server.auth.redirect_validation import validate_redirect_uri
15
+
16
+ # -------------------------------------------------------------------------
17
+ # Constants
18
+ # -------------------------------------------------------------------------
19
+
20
+ # Default token expiration times
21
+ DEFAULT_ACCESS_TOKEN_EXPIRY_SECONDS: Final[int] = 60 * 60 # 1 hour
22
+ DEFAULT_ACCESS_TOKEN_EXPIRY_NO_REFRESH_SECONDS: Final[int] = (
23
+ 60 * 60 * 24 * 365
24
+ ) # 1 year
25
+ DEFAULT_AUTH_CODE_EXPIRY_SECONDS: Final[int] = 5 * 60 # 5 minutes
26
+
27
+ # HTTP client timeout
28
+ HTTP_TIMEOUT_SECONDS: Final[int] = 30
29
+
30
+
31
+ # -------------------------------------------------------------------------
32
+ # Pydantic Models
33
+ # -------------------------------------------------------------------------
34
+
35
+
36
+ class OAuthTransaction(BaseModel):
37
+ """OAuth transaction state for consent flow.
38
+
39
+ Stored server-side to track active authorization flows with client context.
40
+ Includes CSRF tokens for consent protection per MCP security best practices.
41
+ """
42
+
43
+ txn_id: str
44
+ client_id: str
45
+ client_redirect_uri: str
46
+ client_state: str
47
+ code_challenge: str | None
48
+ code_challenge_method: str
49
+ scopes: list[str]
50
+ created_at: float
51
+ resource: str | None = None
52
+ proxy_code_verifier: str | None = None
53
+ csrf_token: str | None = None
54
+ csrf_expires_at: float | None = None
55
+
56
+
57
+ class ClientCode(BaseModel):
58
+ """Client authorization code with PKCE and upstream tokens.
59
+
60
+ Stored server-side after upstream IdP callback. Contains the upstream
61
+ tokens bound to the client's PKCE challenge for secure token exchange.
62
+ """
63
+
64
+ code: str
65
+ client_id: str
66
+ redirect_uri: str
67
+ code_challenge: str | None
68
+ code_challenge_method: str
69
+ scopes: list[str]
70
+ idp_tokens: dict[str, Any]
71
+ expires_at: float
72
+ created_at: float
73
+
74
+
75
+ class UpstreamTokenSet(BaseModel):
76
+ """Stored upstream OAuth tokens from identity provider.
77
+
78
+ These tokens are obtained from the upstream provider (Google, GitHub, etc.)
79
+ and stored in plaintext within this model. Encryption is handled transparently
80
+ at the storage layer via FernetEncryptionWrapper. Tokens are never exposed to MCP clients.
81
+ """
82
+
83
+ upstream_token_id: str # Unique ID for this token set
84
+ access_token: str # Upstream access token
85
+ refresh_token: str | None # Upstream refresh token
86
+ refresh_token_expires_at: (
87
+ float | None
88
+ ) # Unix timestamp when refresh token expires (if known)
89
+ expires_at: float # Unix timestamp when access token expires
90
+ token_type: str # Usually "Bearer"
91
+ scope: str # Space-separated scopes
92
+ client_id: str # MCP client this is bound to
93
+ created_at: float # Unix timestamp
94
+ raw_token_data: dict[str, Any] = Field(default_factory=dict) # Full token response
95
+
96
+
97
+ class JTIMapping(BaseModel):
98
+ """Maps FastMCP token JTI to upstream token ID.
99
+
100
+ This allows stateless JWT validation while still being able to look up
101
+ the corresponding upstream token when tools need to access upstream APIs.
102
+ """
103
+
104
+ jti: str # JWT ID from FastMCP-issued token
105
+ upstream_token_id: str # References UpstreamTokenSet
106
+ created_at: float # Unix timestamp
107
+
108
+
109
+ class RefreshTokenMetadata(BaseModel):
110
+ """Metadata for a refresh token, stored keyed by token hash.
111
+
112
+ We store only metadata (not the token itself) for security - if storage
113
+ is compromised, attackers get hashes they can't reverse into usable tokens.
114
+ """
115
+
116
+ client_id: str
117
+ scopes: list[str]
118
+ expires_at: int | None = None
119
+ created_at: float
120
+
121
+
122
+ def _hash_token(token: str) -> str:
123
+ """Hash a token for secure storage lookup.
124
+
125
+ Uses SHA-256 to create a one-way hash. The original token cannot be
126
+ recovered from the hash, providing defense in depth if storage is compromised.
127
+ """
128
+ return hashlib.sha256(token.encode()).hexdigest()
129
+
130
+
131
+ class ProxyDCRClient(OAuthClientInformationFull):
132
+ """Client for DCR proxy with configurable redirect URI validation.
133
+
134
+ This special client class is critical for the OAuth proxy to work correctly
135
+ with Dynamic Client Registration (DCR). Here's why it exists:
136
+
137
+ Problem:
138
+ --------
139
+ When MCP clients use OAuth, they dynamically register with random localhost
140
+ ports (e.g., http://localhost:55454/callback). The OAuth proxy needs to:
141
+ 1. Accept these dynamic redirect URIs from clients based on configured patterns
142
+ 2. Use its own fixed redirect URI with the upstream provider (Google, GitHub, etc.)
143
+ 3. Forward the authorization code back to the client's dynamic URI
144
+
145
+ Solution:
146
+ ---------
147
+ This class validates redirect URIs against configurable patterns,
148
+ while the proxy internally uses its own fixed redirect URI with the upstream
149
+ provider. This allows the flow to work even when clients reconnect with
150
+ different ports or when tokens are cached.
151
+
152
+ Without proper validation, clients could get "Redirect URI not registered" errors
153
+ when trying to authenticate with cached tokens, or security vulnerabilities could
154
+ arise from accepting arbitrary redirect URIs.
155
+ """
156
+
157
+ allowed_redirect_uri_patterns: list[str] | None = Field(default=None)
158
+ client_name: str | None = Field(default=None)
159
+
160
+ def validate_redirect_uri(self, redirect_uri: AnyUrl | None) -> AnyUrl:
161
+ """Validate redirect URI against allowed patterns.
162
+
163
+ Since we're acting as a proxy and clients register dynamically,
164
+ we validate their redirect URIs against configurable patterns.
165
+ This is essential for cached token scenarios where the client may
166
+ reconnect with a different port.
167
+ """
168
+ if redirect_uri is not None:
169
+ # Validate against allowed patterns
170
+ if validate_redirect_uri(
171
+ redirect_uri=redirect_uri,
172
+ allowed_patterns=self.allowed_redirect_uri_patterns,
173
+ ):
174
+ return redirect_uri
175
+ # Fall back to normal validation if not in allowed patterns
176
+ return super().validate_redirect_uri(redirect_uri)
177
+ # If no redirect_uri provided, use default behavior
178
+ return super().validate_redirect_uri(redirect_uri)