fastmcp 2.12.4__py3-none-any.whl → 2.13.0__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 (72) hide show
  1. fastmcp/cli/cli.py +7 -6
  2. fastmcp/cli/install/claude_code.py +6 -6
  3. fastmcp/cli/install/claude_desktop.py +3 -3
  4. fastmcp/cli/install/cursor.py +7 -7
  5. fastmcp/cli/install/gemini_cli.py +3 -3
  6. fastmcp/cli/install/mcp_json.py +3 -3
  7. fastmcp/cli/run.py +13 -8
  8. fastmcp/client/auth/oauth.py +100 -208
  9. fastmcp/client/client.py +11 -11
  10. fastmcp/client/logging.py +18 -14
  11. fastmcp/client/oauth_callback.py +85 -171
  12. fastmcp/client/transports.py +77 -22
  13. fastmcp/contrib/component_manager/component_service.py +6 -6
  14. fastmcp/contrib/mcp_mixin/README.md +32 -1
  15. fastmcp/contrib/mcp_mixin/mcp_mixin.py +14 -2
  16. fastmcp/experimental/utilities/openapi/json_schema_converter.py +4 -0
  17. fastmcp/experimental/utilities/openapi/parser.py +23 -3
  18. fastmcp/prompts/prompt.py +13 -6
  19. fastmcp/prompts/prompt_manager.py +16 -101
  20. fastmcp/resources/resource.py +13 -6
  21. fastmcp/resources/resource_manager.py +5 -164
  22. fastmcp/resources/template.py +107 -17
  23. fastmcp/resources/types.py +30 -24
  24. fastmcp/server/auth/auth.py +40 -32
  25. fastmcp/server/auth/handlers/authorize.py +324 -0
  26. fastmcp/server/auth/jwt_issuer.py +236 -0
  27. fastmcp/server/auth/middleware.py +96 -0
  28. fastmcp/server/auth/oauth_proxy.py +1256 -242
  29. fastmcp/server/auth/oidc_proxy.py +23 -6
  30. fastmcp/server/auth/providers/auth0.py +40 -21
  31. fastmcp/server/auth/providers/aws.py +29 -3
  32. fastmcp/server/auth/providers/azure.py +178 -127
  33. fastmcp/server/auth/providers/descope.py +4 -6
  34. fastmcp/server/auth/providers/github.py +29 -8
  35. fastmcp/server/auth/providers/google.py +30 -9
  36. fastmcp/server/auth/providers/introspection.py +281 -0
  37. fastmcp/server/auth/providers/jwt.py +8 -2
  38. fastmcp/server/auth/providers/scalekit.py +179 -0
  39. fastmcp/server/auth/providers/supabase.py +172 -0
  40. fastmcp/server/auth/providers/workos.py +32 -14
  41. fastmcp/server/context.py +122 -36
  42. fastmcp/server/http.py +58 -18
  43. fastmcp/server/low_level.py +121 -2
  44. fastmcp/server/middleware/caching.py +469 -0
  45. fastmcp/server/middleware/error_handling.py +6 -2
  46. fastmcp/server/middleware/logging.py +48 -37
  47. fastmcp/server/middleware/middleware.py +28 -15
  48. fastmcp/server/middleware/rate_limiting.py +3 -3
  49. fastmcp/server/middleware/tool_injection.py +116 -0
  50. fastmcp/server/proxy.py +6 -6
  51. fastmcp/server/server.py +683 -207
  52. fastmcp/settings.py +24 -10
  53. fastmcp/tools/tool.py +7 -3
  54. fastmcp/tools/tool_manager.py +30 -112
  55. fastmcp/tools/tool_transform.py +3 -3
  56. fastmcp/utilities/cli.py +62 -22
  57. fastmcp/utilities/components.py +5 -0
  58. fastmcp/utilities/inspect.py +77 -21
  59. fastmcp/utilities/logging.py +118 -8
  60. fastmcp/utilities/mcp_server_config/v1/environments/uv.py +6 -6
  61. fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py +3 -3
  62. fastmcp/utilities/mcp_server_config/v1/schema.json +3 -0
  63. fastmcp/utilities/tests.py +87 -4
  64. fastmcp/utilities/types.py +1 -1
  65. fastmcp/utilities/ui.py +617 -0
  66. {fastmcp-2.12.4.dist-info → fastmcp-2.13.0.dist-info}/METADATA +10 -6
  67. {fastmcp-2.12.4.dist-info → fastmcp-2.13.0.dist-info}/RECORD +70 -63
  68. fastmcp/cli/claude.py +0 -135
  69. fastmcp/utilities/storage.py +0 -204
  70. {fastmcp-2.12.4.dist-info → fastmcp-2.13.0.dist-info}/WHEEL +0 -0
  71. {fastmcp-2.12.4.dist-info → fastmcp-2.13.0.dist-info}/entry_points.txt +0 -0
  72. {fastmcp-2.12.4.dist-info → fastmcp-2.13.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,617 @@
1
+ """
2
+ Shared UI utilities for FastMCP HTML pages.
3
+
4
+ This module provides reusable HTML/CSS components for OAuth callbacks,
5
+ consent pages, and other user-facing interfaces.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import html
11
+
12
+ from starlette.responses import HTMLResponse
13
+
14
+ # FastMCP branding
15
+ FASTMCP_LOGO_URL = "https://gofastmcp.com/assets/brand/blue-logo.png"
16
+
17
+ # Base CSS styles shared across all FastMCP pages
18
+ BASE_STYLES = """
19
+ * {
20
+ margin: 0;
21
+ padding: 0;
22
+ box-sizing: border-box;
23
+ }
24
+
25
+ body {
26
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
27
+ margin: 0;
28
+ padding: 0;
29
+ min-height: 100vh;
30
+ display: flex;
31
+ align-items: center;
32
+ justify-content: center;
33
+ background: #f9fafb;
34
+ color: #0a0a0a;
35
+ }
36
+
37
+ .container {
38
+ background: #ffffff;
39
+ border: 1px solid #e5e7eb;
40
+ padding: 3rem 2.5rem;
41
+ border-radius: 1rem;
42
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
43
+ text-align: center;
44
+ max-width: 36rem;
45
+ margin: 1rem;
46
+ width: 100%;
47
+ }
48
+
49
+ @media (max-width: 640px) {
50
+ .container {
51
+ padding: 2rem 1.5rem;
52
+ margin: 0.5rem;
53
+ }
54
+ }
55
+
56
+ .logo {
57
+ width: 64px;
58
+ height: auto;
59
+ margin-bottom: 1.5rem;
60
+ display: block;
61
+ margin-left: auto;
62
+ margin-right: auto;
63
+ }
64
+
65
+ h1 {
66
+ font-size: 1.5rem;
67
+ font-weight: 600;
68
+ margin-bottom: 1.5rem;
69
+ color: #111827;
70
+ }
71
+ """
72
+
73
+ # Button styles
74
+ BUTTON_STYLES = """
75
+ .button-group {
76
+ display: flex;
77
+ gap: 0.75rem;
78
+ margin-top: 1.5rem;
79
+ justify-content: center;
80
+ }
81
+
82
+ button {
83
+ padding: 0.75rem 2rem;
84
+ font-size: 0.9375rem;
85
+ font-weight: 500;
86
+ border-radius: 0.5rem;
87
+ border: none;
88
+ cursor: pointer;
89
+ transition: all 0.15s;
90
+ font-family: inherit;
91
+ }
92
+
93
+ button:hover {
94
+ transform: translateY(-1px);
95
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
96
+ }
97
+
98
+ .btn-approve, .btn-primary {
99
+ background: #10b981;
100
+ color: #ffffff;
101
+ min-width: 120px;
102
+ }
103
+
104
+ .btn-deny, .btn-secondary {
105
+ background: #6b7280;
106
+ color: #ffffff;
107
+ min-width: 120px;
108
+ }
109
+ """
110
+
111
+ # Info box / message box styles
112
+ INFO_BOX_STYLES = """
113
+ .info-box {
114
+ background: #f0f9ff;
115
+ border: 1px solid #bae6fd;
116
+ border-radius: 0.5rem;
117
+ padding: 1rem;
118
+ margin-bottom: 1.5rem;
119
+ text-align: left;
120
+ font-size: 0.9375rem;
121
+ line-height: 1.5;
122
+ color: #374151;
123
+ }
124
+
125
+ .info-box p {
126
+ margin-bottom: 0.5rem;
127
+ }
128
+
129
+ .info-box p:last-child {
130
+ margin-bottom: 0;
131
+ }
132
+
133
+ .info-box.centered {
134
+ text-align: center;
135
+ }
136
+
137
+ .info-box.error {
138
+ background: #fef2f2;
139
+ border-color: #fecaca;
140
+ color: #991b1b;
141
+ }
142
+
143
+ .info-box strong {
144
+ color: #0ea5e9;
145
+ font-weight: 600;
146
+ }
147
+
148
+ .info-box .server-name-link {
149
+ color: #0ea5e9;
150
+ text-decoration: underline;
151
+ font-weight: 600;
152
+ cursor: pointer;
153
+ transition: opacity 0.15s;
154
+ }
155
+
156
+ .info-box .server-name-link:hover {
157
+ opacity: 0.8;
158
+ }
159
+
160
+ /* Monospace info box - gray styling with code font */
161
+ .info-box-mono {
162
+ background: #f9fafb;
163
+ border: 1px solid #e5e7eb;
164
+ border-radius: 0.5rem;
165
+ padding: 0.875rem;
166
+ margin: 1.25rem 0;
167
+ font-size: 0.875rem;
168
+ color: #6b7280;
169
+ font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace;
170
+ text-align: left;
171
+ }
172
+
173
+ .info-box-mono.centered {
174
+ text-align: center;
175
+ }
176
+
177
+ .info-box-mono.error {
178
+ background: #fef2f2;
179
+ border-color: #fecaca;
180
+ color: #991b1b;
181
+ }
182
+
183
+ .info-box-mono strong {
184
+ color: #111827;
185
+ font-weight: 600;
186
+ }
187
+
188
+ .warning-box {
189
+ background: #f0f9ff;
190
+ border: 1px solid #bae6fd;
191
+ border-radius: 0.5rem;
192
+ padding: 1rem;
193
+ margin-bottom: 1.5rem;
194
+ text-align: center;
195
+ }
196
+
197
+ .warning-box p {
198
+ margin-bottom: 0.5rem;
199
+ line-height: 1.5;
200
+ color: #6b7280;
201
+ font-size: 0.9375rem;
202
+ }
203
+
204
+ .warning-box p:last-child {
205
+ margin-bottom: 0;
206
+ }
207
+
208
+ .warning-box strong {
209
+ color: #0ea5e9;
210
+ font-weight: 600;
211
+ }
212
+
213
+ .warning-box a {
214
+ color: #0ea5e9;
215
+ text-decoration: underline;
216
+ font-weight: 600;
217
+ }
218
+
219
+ .warning-box a:hover {
220
+ color: #0284c7;
221
+ text-decoration: underline;
222
+ }
223
+ """
224
+
225
+ # Status message styles (for success/error indicators)
226
+ STATUS_MESSAGE_STYLES = """
227
+ .status-message {
228
+ display: flex;
229
+ align-items: center;
230
+ justify-content: center;
231
+ gap: 0.75rem;
232
+ margin-bottom: 1.5rem;
233
+ }
234
+
235
+ .status-icon {
236
+ font-size: 1.5rem;
237
+ line-height: 1;
238
+ display: inline-flex;
239
+ align-items: center;
240
+ justify-content: center;
241
+ width: 2rem;
242
+ height: 2rem;
243
+ border-radius: 0.5rem;
244
+ flex-shrink: 0;
245
+ }
246
+
247
+ .status-icon.success {
248
+ background: #10b98120;
249
+ }
250
+
251
+ .status-icon.error {
252
+ background: #ef444420;
253
+ }
254
+
255
+ .message {
256
+ font-size: 1.125rem;
257
+ line-height: 1.75;
258
+ color: #111827;
259
+ font-weight: 600;
260
+ text-align: left;
261
+ }
262
+ """
263
+
264
+ # Detail box styles (for key-value pairs)
265
+ DETAIL_BOX_STYLES = """
266
+ .detail-box {
267
+ background: #f9fafb;
268
+ border: 1px solid #e5e7eb;
269
+ border-radius: 0.5rem;
270
+ padding: 1rem;
271
+ margin-bottom: 1.5rem;
272
+ text-align: left;
273
+ }
274
+
275
+ .detail-row {
276
+ display: flex;
277
+ padding: 0.5rem 0;
278
+ border-bottom: 1px solid #e5e7eb;
279
+ }
280
+
281
+ .detail-row:last-child {
282
+ border-bottom: none;
283
+ }
284
+
285
+ .detail-label {
286
+ font-weight: 600;
287
+ min-width: 160px;
288
+ color: #6b7280;
289
+ font-size: 0.875rem;
290
+ flex-shrink: 0;
291
+ padding-right: 1rem;
292
+ }
293
+
294
+ .detail-value {
295
+ flex: 1;
296
+ font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace;
297
+ font-size: 0.75rem;
298
+ color: #111827;
299
+ word-break: break-all;
300
+ overflow-wrap: break-word;
301
+ }
302
+ """
303
+
304
+ # Redirect section styles (for OAuth redirect URI box)
305
+ REDIRECT_SECTION_STYLES = """
306
+ .redirect-section {
307
+ background: #fffbeb;
308
+ border: 1px solid #fcd34d;
309
+ border-radius: 0.5rem;
310
+ padding: 1rem;
311
+ margin-bottom: 1.5rem;
312
+ text-align: left;
313
+ }
314
+
315
+ .redirect-section .label {
316
+ font-size: 0.875rem;
317
+ color: #6b7280;
318
+ font-weight: 600;
319
+ margin-bottom: 0.5rem;
320
+ display: block;
321
+ }
322
+
323
+ .redirect-section .value {
324
+ font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace;
325
+ font-size: 0.875rem;
326
+ color: #111827;
327
+ word-break: break-all;
328
+ margin-top: 0.25rem;
329
+ }
330
+ """
331
+
332
+ # Collapsible details styles
333
+ DETAILS_STYLES = """
334
+ details {
335
+ margin-bottom: 1.5rem;
336
+ text-align: left;
337
+ }
338
+
339
+ summary {
340
+ cursor: pointer;
341
+ font-size: 0.875rem;
342
+ color: #6b7280;
343
+ font-weight: 600;
344
+ list-style: none;
345
+ padding: 0.5rem;
346
+ border-radius: 0.25rem;
347
+ }
348
+
349
+ summary:hover {
350
+ background: #f9fafb;
351
+ }
352
+
353
+ summary::marker {
354
+ display: none;
355
+ }
356
+
357
+ summary::before {
358
+ content: "▶";
359
+ display: inline-block;
360
+ margin-right: 0.5rem;
361
+ transition: transform 0.2s;
362
+ font-size: 0.75rem;
363
+ }
364
+
365
+ details[open] summary::before {
366
+ transform: rotate(90deg);
367
+ }
368
+ """
369
+
370
+ # Helper text styles
371
+ HELPER_TEXT_STYLES = """
372
+ .close-instruction, .help-text {
373
+ font-size: 0.875rem;
374
+ color: #6b7280;
375
+ margin-top: 1.5rem;
376
+ }
377
+ """
378
+
379
+ # Tooltip styles for hover help
380
+ TOOLTIP_STYLES = """
381
+ .help-link-container {
382
+ position: fixed;
383
+ bottom: 1.5rem;
384
+ right: 1.5rem;
385
+ font-size: 0.875rem;
386
+ }
387
+
388
+ .help-link {
389
+ color: #6b7280;
390
+ text-decoration: none;
391
+ cursor: help;
392
+ position: relative;
393
+ display: inline-block;
394
+ border-bottom: 1px dotted #9ca3af;
395
+ }
396
+
397
+ @media (max-width: 640px) {
398
+ .help-link {
399
+ background: #ffffff;
400
+ padding: 0.25rem 0.5rem;
401
+ border-radius: 0.25rem;
402
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
403
+ }
404
+ }
405
+
406
+ .help-link:hover {
407
+ color: #111827;
408
+ border-bottom-color: #111827;
409
+ }
410
+
411
+ .help-link:hover .tooltip {
412
+ opacity: 1;
413
+ visibility: visible;
414
+ }
415
+
416
+ .tooltip {
417
+ position: absolute;
418
+ bottom: 100%;
419
+ right: 0;
420
+ left: auto;
421
+ margin-bottom: 0.5rem;
422
+ background: #1f2937;
423
+ color: #ffffff;
424
+ padding: 0.75rem 1rem;
425
+ border-radius: 0.5rem;
426
+ font-size: 0.8125rem;
427
+ line-height: 1.5;
428
+ width: 280px;
429
+ max-width: calc(100vw - 3rem);
430
+ opacity: 0;
431
+ visibility: hidden;
432
+ transition: opacity 0.2s, visibility 0.2s;
433
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
434
+ text-align: left;
435
+ }
436
+
437
+ .tooltip::after {
438
+ content: '';
439
+ position: absolute;
440
+ top: 100%;
441
+ right: 1rem;
442
+ border: 6px solid transparent;
443
+ border-top-color: #1f2937;
444
+ }
445
+
446
+ .tooltip-link {
447
+ color: #60a5fa;
448
+ text-decoration: underline;
449
+ }
450
+ """
451
+
452
+
453
+ def create_page(
454
+ content: str,
455
+ title: str = "FastMCP",
456
+ additional_styles: str = "",
457
+ csp_policy: str = "default-src 'none'; style-src 'unsafe-inline'; img-src https:; base-uri 'none'",
458
+ ) -> str:
459
+ """
460
+ Create a complete HTML page with FastMCP styling.
461
+
462
+ Args:
463
+ content: HTML content to place inside the page
464
+ title: Page title
465
+ additional_styles: Extra CSS to include
466
+ csp_policy: Content Security Policy header value
467
+
468
+ Returns:
469
+ Complete HTML page as string
470
+ """
471
+ title = html.escape(title)
472
+ return f"""
473
+ <!DOCTYPE html>
474
+ <html lang="en">
475
+ <head>
476
+ <meta charset="UTF-8">
477
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
478
+ <title>{title}</title>
479
+ <style>
480
+ {BASE_STYLES}
481
+ {additional_styles}
482
+ </style>
483
+ <meta http-equiv="Content-Security-Policy" content="{csp_policy}" />
484
+ </head>
485
+ <body>
486
+ {content}
487
+ </body>
488
+ </html>
489
+ """
490
+
491
+
492
+ def create_logo(icon_url: str | None = None, alt_text: str = "FastMCP") -> str:
493
+ """Create logo HTML.
494
+
495
+ Args:
496
+ icon_url: Optional custom icon URL. If not provided, uses the FastMCP logo.
497
+ alt_text: Alt text for the logo image.
498
+
499
+ Returns:
500
+ HTML for logo image tag.
501
+ """
502
+ url = icon_url or FASTMCP_LOGO_URL
503
+ alt = html.escape(alt_text)
504
+ return f'<img src="{html.escape(url)}" alt="{alt}" class="logo" />'
505
+
506
+
507
+ def create_status_message(message: str, is_success: bool = True) -> str:
508
+ """
509
+ Create a status message with icon.
510
+
511
+ Args:
512
+ message: Status message text
513
+ is_success: True for success (✓), False for error (✕)
514
+
515
+ Returns:
516
+ HTML for status message
517
+ """
518
+ message = html.escape(message)
519
+ icon = "✓" if is_success else "✕"
520
+ icon_class = "success" if is_success else "error"
521
+
522
+ return f"""
523
+ <div class="status-message">
524
+ <span class="status-icon {icon_class}">{icon}</span>
525
+ <div class="message">{message}</div>
526
+ </div>
527
+ """
528
+
529
+
530
+ def create_info_box(
531
+ content: str,
532
+ is_error: bool = False,
533
+ centered: bool = False,
534
+ monospace: bool = False,
535
+ ) -> str:
536
+ """
537
+ Create an info box.
538
+
539
+ Args:
540
+ content: HTML content for the info box
541
+ is_error: True for error styling, False for normal
542
+ centered: True to center the text, False for left-aligned
543
+ monospace: True to use gray monospace font styling instead of blue
544
+
545
+ Returns:
546
+ HTML for info box
547
+ """
548
+ content = html.escape(content)
549
+ base_class = "info-box-mono" if monospace else "info-box"
550
+ classes = [base_class]
551
+ if is_error:
552
+ classes.append("error")
553
+ if centered:
554
+ classes.append("centered")
555
+ class_str = " ".join(classes)
556
+ return f'<div class="{class_str}">{content}</div>'
557
+
558
+
559
+ def create_detail_box(rows: list[tuple[str, str]]) -> str:
560
+ """
561
+ Create a detail box with key-value pairs.
562
+
563
+ Args:
564
+ rows: List of (label, value) tuples
565
+
566
+ Returns:
567
+ HTML for detail box
568
+ """
569
+ rows_html = "\n".join(
570
+ f"""
571
+ <div class="detail-row">
572
+ <div class="detail-label">{html.escape(label)}:</div>
573
+ <div class="detail-value">{html.escape(value)}</div>
574
+ </div>
575
+ """
576
+ for label, value in rows
577
+ )
578
+
579
+ return f'<div class="detail-box">{rows_html}</div>'
580
+
581
+
582
+ def create_button_group(buttons: list[tuple[str, str, str]]) -> str:
583
+ """
584
+ Create a group of buttons.
585
+
586
+ Args:
587
+ buttons: List of (text, value, css_class) tuples
588
+
589
+ Returns:
590
+ HTML for button group
591
+ """
592
+ buttons_html = "\n".join(
593
+ f'<button type="submit" name="action" value="{value}" class="{css_class}">{text}</button>'
594
+ for text, value, css_class in buttons
595
+ )
596
+
597
+ return f'<div class="button-group">{buttons_html}</div>'
598
+
599
+
600
+ def create_secure_html_response(html: str, status_code: int = 200) -> HTMLResponse:
601
+ """
602
+ Create an HTMLResponse with security headers.
603
+
604
+ Adds X-Frame-Options: DENY to prevent clickjacking attacks per MCP security best practices.
605
+
606
+ Args:
607
+ html: HTML content to return
608
+ status_code: HTTP status code
609
+
610
+ Returns:
611
+ HTMLResponse with security headers
612
+ """
613
+ return HTMLResponse(
614
+ content=html,
615
+ status_code=status_code,
616
+ headers={"X-Frame-Options": "DENY"},
617
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastmcp
3
- Version: 2.12.4
3
+ Version: 2.13.0
4
4
  Summary: The fast, Pythonic way to build MCP servers and clients.
5
5
  Project-URL: Homepage, https://gofastmcp.com
6
6
  Project-URL: Repository, https://github.com/jlowin/fastmcp
@@ -14,6 +14,7 @@ Classifier: License :: OSI Approved :: Apache Software License
14
14
  Classifier: Programming Language :: Python :: 3.10
15
15
  Classifier: Programming Language :: Python :: 3.11
16
16
  Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
17
18
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
19
  Classifier: Typing :: Typed
19
20
  Requires-Python: >=3.10
@@ -21,17 +22,18 @@ Requires-Dist: authlib>=1.5.2
21
22
  Requires-Dist: cyclopts>=3.0.0
22
23
  Requires-Dist: exceptiongroup>=1.2.2
23
24
  Requires-Dist: httpx>=0.28.1
24
- Requires-Dist: mcp<2.0.0,>=1.12.4
25
+ Requires-Dist: mcp<2.0.0,>=1.17.0
25
26
  Requires-Dist: openapi-core>=0.19.5
26
27
  Requires-Dist: openapi-pydantic>=0.5.1
28
+ Requires-Dist: platformdirs>=4.0.0
29
+ Requires-Dist: py-key-value-aio[disk,keyring,memory]<0.3.0,>=0.2.6
27
30
  Requires-Dist: pydantic[email]>=2.11.7
28
31
  Requires-Dist: pyperclip>=1.9.0
29
32
  Requires-Dist: python-dotenv>=1.1.0
30
33
  Requires-Dist: rich>=13.9.4
34
+ Requires-Dist: websockets>=15.0.1
31
35
  Provides-Extra: openai
32
36
  Requires-Dist: openai>=1.102.0; extra == 'openai'
33
- Provides-Extra: websockets
34
- Requires-Dist: websockets>=15.0.1; extra == 'websockets'
35
37
  Description-Content-Type: text/markdown
36
38
 
37
39
  <div align="center">
@@ -51,6 +53,7 @@ Description-Content-Type: text/markdown
51
53
  *Made with ☕️ by [Prefect](https://www.prefect.io/)*
52
54
 
53
55
  [![Docs](https://img.shields.io/badge/docs-gofastmcp.com-blue)](https://gofastmcp.com)
56
+ [![Discord](https://img.shields.io/badge/community-discord-5865F2?logo=discord&logoColor=white)](https://discord.gg/uu8dJCgttd)
54
57
  [![PyPI - Version](https://img.shields.io/pypi/v/fastmcp.svg)](https://pypi.org/project/fastmcp)
55
58
  [![Tests](https://github.com/jlowin/fastmcp/actions/workflows/run-tests.yml/badge.svg)](https://github.com/jlowin/fastmcp/actions/workflows/run-tests.yml)
56
59
  [![License](https://img.shields.io/github/license/jlowin/fastmcp.svg)](https://github.com/jlowin/fastmcp/blob/main/LICENSE)
@@ -106,6 +109,8 @@ There are two ways to access the LLM-friendly documentation:
106
109
  - [`llms.txt`](https://gofastmcp.com/llms.txt) is essentially a sitemap, listing all the pages in the documentation.
107
110
  - [`llms-full.txt`](https://gofastmcp.com/llms-full.txt) contains the entire documentation. Note this may exceed the context window of your LLM.
108
111
 
112
+ **Community:** Join our [Discord server](https://discord.gg/uu8dJCgttd) to connect with other FastMCP developers and share what you're building.
113
+
109
114
  ---
110
115
 
111
116
  <!-- omit in toc -->
@@ -244,7 +249,6 @@ Access MCP session capabilities within your tools, resources, or prompts by addi
244
249
 
245
250
  - **Logging:** Log messages to MCP clients with `ctx.info()`, `ctx.error()`, etc.
246
251
  - **LLM Sampling:** Use `ctx.sample()` to request completions from the client's LLM.
247
- - **HTTP Request:** Use `ctx.http_request()` to make HTTP requests to other servers.
248
252
  - **Resource Access:** Use `ctx.read_resource()` to access resources on the server
249
253
  - **Progress Reporting:** Use `ctx.report_progress()` to report progress to the client.
250
254
  - and more...
@@ -354,7 +358,7 @@ FastMCP provides comprehensive authentication support that sets it apart from ba
354
358
  Protecting a server takes just two lines:
355
359
 
356
360
  ```python
357
- from fastmcp.server.auth import GoogleProvider
361
+ from fastmcp.server.auth.providers.google import GoogleProvider
358
362
 
359
363
  auth = GoogleProvider(client_id="...", client_secret="...", base_url="https://myserver.com")
360
364
  mcp = FastMCP("Protected Server", auth=auth)