43
43
from mcp .server .streamable_http_manager import StreamableHTTPSessionManager
44
44
from mcp .server .transport_security import TransportSecuritySettings
45
45
from mcp .shared .context import LifespanContextT , RequestContext , RequestT
46
- from mcp .types import AnyFunction , ContentBlock , GetPromptResult , ToolAnnotations
46
+ from mcp .types import AnyFunction , ContentBlock , GetPromptResult , Icon , ToolAnnotations
47
47
from mcp .types import Prompt as MCPPrompt
48
48
from mcp .types import PromptArgument as MCPPromptArgument
49
49
from mcp .types import Resource as MCPResource
@@ -120,10 +120,12 @@ async def wrap(_: MCPServer[LifespanResultT, Request]) -> AsyncIterator[Lifespan
120
120
121
121
122
122
class FastMCP (Generic [LifespanResultT ]):
123
- def __init__ (
123
+ def __init__ ( # noqa: PLR0913
124
124
self ,
125
125
name : str | None = None ,
126
126
instructions : str | None = None ,
127
+ website_url : str | None = None ,
128
+ icons : list [Icon ] | None = None ,
127
129
auth_server_provider : OAuthAuthorizationServerProvider [Any , Any , Any ] | None = None ,
128
130
token_verifier : TokenVerifier | None = None ,
129
131
event_store : EventStore | None = None ,
@@ -170,6 +172,8 @@ def __init__(
170
172
self ._mcp_server = MCPServer (
171
173
name = name or "FastMCP" ,
172
174
instructions = instructions ,
175
+ website_url = website_url ,
176
+ icons = icons ,
173
177
# TODO(Marcelo): It seems there's a type mismatch between the lifespan type from an FastMCP and Server.
174
178
# We need to create a Lifespan type that is a generic on the server type, like Starlette does.
175
179
lifespan = (lifespan_wrapper (self , self .settings .lifespan ) if self .settings .lifespan else default_lifespan ), # type: ignore
@@ -211,6 +215,14 @@ def name(self) -> str:
211
215
def instructions (self ) -> str | None :
212
216
return self ._mcp_server .instructions
213
217
218
+ @property
219
+ def website_url (self ) -> str | None :
220
+ return self ._mcp_server .website_url
221
+
222
+ @property
223
+ def icons (self ) -> list [Icon ] | None :
224
+ return self ._mcp_server .icons
225
+
214
226
@property
215
227
def session_manager (self ) -> StreamableHTTPSessionManager :
216
228
"""Get the StreamableHTTP session manager.
@@ -277,6 +289,7 @@ async def list_tools(self) -> list[MCPTool]:
277
289
inputSchema = info .parameters ,
278
290
outputSchema = info .output_schema ,
279
291
annotations = info .annotations ,
292
+ icons = info .icons ,
280
293
)
281
294
for info in tools
282
295
]
@@ -308,6 +321,7 @@ async def list_resources(self) -> list[MCPResource]:
308
321
title = resource .title ,
309
322
description = resource .description ,
310
323
mimeType = resource .mime_type ,
324
+ icons = resource .icons ,
311
325
)
312
326
for resource in resources
313
327
]
@@ -347,6 +361,7 @@ def add_tool(
347
361
title : str | None = None ,
348
362
description : str | None = None ,
349
363
annotations : ToolAnnotations | None = None ,
364
+ icons : list [Icon ] | None = None ,
350
365
structured_output : bool | None = None ,
351
366
) -> None :
352
367
"""Add a tool to the server.
@@ -371,6 +386,7 @@ def add_tool(
371
386
title = title ,
372
387
description = description ,
373
388
annotations = annotations ,
389
+ icons = icons ,
374
390
structured_output = structured_output ,
375
391
)
376
392
@@ -380,6 +396,7 @@ def tool(
380
396
title : str | None = None ,
381
397
description : str | None = None ,
382
398
annotations : ToolAnnotations | None = None ,
399
+ icons : list [Icon ] | None = None ,
383
400
structured_output : bool | None = None ,
384
401
) -> Callable [[AnyFunction ], AnyFunction ]:
385
402
"""Decorator to register a tool.
@@ -426,6 +443,7 @@ def decorator(fn: AnyFunction) -> AnyFunction:
426
443
title = title ,
427
444
description = description ,
428
445
annotations = annotations ,
446
+ icons = icons ,
429
447
structured_output = structured_output ,
430
448
)
431
449
return fn
@@ -466,6 +484,7 @@ def resource(
466
484
title : str | None = None ,
467
485
description : str | None = None ,
468
486
mime_type : str | None = None ,
487
+ icons : list [Icon ] | None = None ,
469
488
) -> Callable [[AnyFunction ], AnyFunction ]:
470
489
"""Decorator to register a function as a resource.
471
490
@@ -540,6 +559,7 @@ def decorator(fn: AnyFunction) -> AnyFunction:
540
559
title = title ,
541
560
description = description ,
542
561
mime_type = mime_type ,
562
+ # Note: Resource templates don't support icons
543
563
)
544
564
else :
545
565
# Register as regular resource
@@ -550,6 +570,7 @@ def decorator(fn: AnyFunction) -> AnyFunction:
550
570
title = title ,
551
571
description = description ,
552
572
mime_type = mime_type ,
573
+ icons = icons ,
553
574
)
554
575
self .add_resource (resource )
555
576
return fn
@@ -565,7 +586,11 @@ def add_prompt(self, prompt: Prompt) -> None:
565
586
self ._prompt_manager .add_prompt (prompt )
566
587
567
588
def prompt (
568
- self , name : str | None = None , title : str | None = None , description : str | None = None
589
+ self ,
590
+ name : str | None = None ,
591
+ title : str | None = None ,
592
+ description : str | None = None ,
593
+ icons : list [Icon ] | None = None ,
569
594
) -> Callable [[AnyFunction ], AnyFunction ]:
570
595
"""Decorator to register a prompt.
571
596
@@ -609,7 +634,7 @@ async def analyze_file(path: str) -> list[Message]:
609
634
)
610
635
611
636
def decorator (func : AnyFunction ) -> AnyFunction :
612
- prompt = Prompt .from_function (func , name = name , title = title , description = description )
637
+ prompt = Prompt .from_function (func , name = name , title = title , description = description , icons = icons )
613
638
self .add_prompt (prompt )
614
639
return func
615
640
@@ -980,6 +1005,7 @@ async def list_prompts(self) -> list[MCPPrompt]:
980
1005
)
981
1006
for arg in (prompt .arguments or [])
982
1007
],
1008
+ icons = prompt .icons ,
983
1009
)
984
1010
for prompt in prompts
985
1011
]
0 commit comments