1+ """Test icon and metadata support (SEP-973)."""
2+
3+ import pytest
4+
5+ from mcp .server .fastmcp import FastMCP
6+ from mcp .types import Icon
7+
8+ pytestmark = pytest .mark .anyio
9+
10+
11+ async def test_icons_and_website_url ():
12+ """Test that icons and websiteUrl are properly returned in API calls."""
13+
14+ # Create test icon
15+ test_icon = Icon (
16+ src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==" ,
17+ mimeType = "image/png" ,
18+ sizes = "1x1"
19+ )
20+
21+ # Create server with website URL and icon
22+ mcp = FastMCP (
23+ "TestServer" ,
24+ website_url = "https://example.com" ,
25+ icons = [test_icon ]
26+ )
27+
28+ # Create tool with icon
29+ @mcp .tool (icons = [test_icon ])
30+ def test_tool (message : str ) -> str :
31+ """A test tool with an icon."""
32+ return message
33+
34+ # Create resource with icon
35+ @mcp .resource ("test://resource" , icons = [test_icon ])
36+ def test_resource () -> str :
37+ """A test resource with an icon."""
38+ return "test content"
39+
40+ # Create prompt with icon
41+ @mcp .prompt ("test_prompt" , icons = [test_icon ])
42+ def test_prompt (text : str ) -> str :
43+ """A test prompt with an icon."""
44+ return text
45+
46+ # Test server metadata includes websiteUrl and icons
47+ assert mcp .name == "TestServer"
48+ assert mcp .website_url == "https://example.com"
49+ assert mcp .icons is not None
50+ assert len (mcp .icons ) == 1
51+ assert mcp .icons [0 ].src == test_icon .src
52+ assert mcp .icons [0 ].mimeType == test_icon .mimeType
53+ assert mcp .icons [0 ].sizes == test_icon .sizes
54+
55+ # Test tool includes icon
56+ tools = await mcp .list_tools ()
57+ assert len (tools ) == 1
58+ tool = tools [0 ]
59+ assert tool .name == "test_tool"
60+ assert tool .icons is not None
61+ assert len (tool .icons ) == 1
62+ assert tool .icons [0 ].src == test_icon .src
63+
64+ # Test resource includes icon
65+ resources = await mcp .list_resources ()
66+ assert len (resources ) == 1
67+ resource = resources [0 ]
68+ assert str (resource .uri ) == "test://resource"
69+ assert resource .icons is not None
70+ assert len (resource .icons ) == 1
71+ assert resource .icons [0 ].src == test_icon .src
72+
73+ # Test prompt includes icon
74+ prompts = await mcp .list_prompts ()
75+ assert len (prompts ) == 1
76+ prompt = prompts [0 ]
77+ assert prompt .name == "test_prompt"
78+ assert prompt .icons is not None
79+ assert len (prompt .icons ) == 1
80+ assert prompt .icons [0 ].src == test_icon .src
81+
82+
83+ async def test_multiple_icons ():
84+ """Test that multiple icons can be added to tools, resources, and prompts."""
85+
86+ # Create multiple test icons
87+ icon1 = Icon (src = "data:image/png;base64,icon1" , mimeType = "image/png" , sizes = "16x16" )
88+ icon2 = Icon (src = "data:image/png;base64,icon2" , mimeType = "image/png" , sizes = "32x32" )
89+ icon3 = Icon (src = "data:image/png;base64,icon3" , mimeType = "image/png" , sizes = "64x64" )
90+
91+ mcp = FastMCP ("MultiIconServer" )
92+
93+ # Create tool with multiple icons
94+ @mcp .tool (icons = [icon1 , icon2 , icon3 ])
95+ def multi_icon_tool () -> str :
96+ """A tool with multiple icons."""
97+ return "success"
98+
99+ # Test tool has all icons
100+ tools = await mcp .list_tools ()
101+ assert len (tools ) == 1
102+ tool = tools [0 ]
103+ assert tool .icons is not None
104+ assert len (tool .icons ) == 3
105+ assert tool .icons [0 ].sizes == "16x16"
106+ assert tool .icons [1 ].sizes == "32x32"
107+ assert tool .icons [2 ].sizes == "64x64"
108+
109+
110+ async def test_no_icons_or_website ():
111+ """Test that server works without icons or websiteUrl."""
112+
113+ mcp = FastMCP ("BasicServer" )
114+
115+ @mcp .tool ()
116+ def basic_tool () -> str :
117+ """A basic tool without icons."""
118+ return "success"
119+
120+ # Test server metadata has no websiteUrl or icons
121+ assert mcp .name == "BasicServer"
122+ assert mcp .website_url is None
123+ assert mcp .icons is None
124+
125+ # Test tool has no icons
126+ tools = await mcp .list_tools ()
127+ assert len (tools ) == 1
128+ tool = tools [0 ]
129+ assert tool .name == "basic_tool"
130+ assert tool .icons is None
0 commit comments