-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Expand file tree
/
Copy pathtest_141_resource_templates.py
More file actions
109 lines (84 loc) · 4.62 KB
/
test_141_resource_templates.py
File metadata and controls
109 lines (84 loc) · 4.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import pytest
from mcp import Client
from mcp.server.mcpserver import MCPServer
from mcp.server.mcpserver.exceptions import ResourceError
from mcp.types import (
ListResourceTemplatesResult,
TextResourceContents,
)
@pytest.mark.anyio
async def test_resource_template_edge_cases():
"""Test server-side resource template validation"""
mcp = MCPServer("Demo")
# Test case 1: Template with multiple parameters
@mcp.resource("resource://users/{user_id}/posts/{post_id}")
def get_user_post(user_id: str, post_id: str) -> str:
return f"Post {post_id} by user {user_id}"
# Test case 2: Template with optional parameter (should fail)
with pytest.raises(ValueError, match="Mismatch between URI parameters"):
@mcp.resource("resource://users/{user_id}/profile")
def get_user_profile(user_id: str, optional_param: str | None = None) -> str: # pragma: no cover
return f"Profile for user {user_id}"
# Test case 3: Template with mismatched parameters
with pytest.raises(ValueError, match="Mismatch between URI parameters"):
@mcp.resource("resource://users/{user_id}/profile")
def get_user_profile_mismatch(different_param: str) -> str: # pragma: no cover
return f"Profile for user {different_param}"
# Test case 4: Template with extra function parameters
with pytest.raises(ValueError, match="Mismatch between URI parameters"):
@mcp.resource("resource://users/{user_id}/profile")
def get_user_profile_extra(user_id: str, extra_param: str) -> str: # pragma: no cover
return f"Profile for user {user_id}"
# Test case 5: Template with missing function parameters
with pytest.raises(ValueError, match="Mismatch between URI parameters"):
@mcp.resource("resource://users/{user_id}/profile/{section}")
def get_user_profile_missing(user_id: str) -> str: # pragma: no cover
return f"Profile for user {user_id}"
# Verify valid template works
result = await mcp.read_resource("resource://users/123/posts/456")
result_list = list(result)
assert len(result_list) == 1
assert result_list[0].content == "Post 456 by user 123"
assert result_list[0].mime_type == "text/plain"
# Verify invalid parameters raise error
with pytest.raises(ResourceError, match="Unknown resource"):
await mcp.read_resource("resource://users/123/posts") # Missing post_id
with pytest.raises(ResourceError, match="Unknown resource"):
await mcp.read_resource("resource://users/123/posts/456/extra") # Extra path component
@pytest.mark.anyio
async def test_resource_template_client_interaction():
"""Test client-side resource template interaction"""
mcp = MCPServer("Demo")
# Register some templated resources
@mcp.resource("resource://users/{user_id}/posts/{post_id}")
def get_user_post(user_id: str, post_id: str) -> str:
return f"Post {post_id} by user {user_id}"
@mcp.resource("resource://users/{user_id}/profile")
def get_user_profile(user_id: str) -> str:
return f"Profile for user {user_id}"
async with Client(mcp) as session:
# List available resources
resources = await session.list_resource_templates()
assert isinstance(resources, ListResourceTemplatesResult)
assert len(resources.resource_templates) == 2
# Verify resource templates are listed correctly
templates = [r.uri_template for r in resources.resource_templates]
assert "resource://users/{user_id}/posts/{post_id}" in templates
assert "resource://users/{user_id}/profile" in templates
# Read a resource with valid parameters
result = await session.read_resource("resource://users/123/posts/456")
contents = result.contents[0]
assert isinstance(contents, TextResourceContents)
assert contents.text == "Post 456 by user 123"
assert contents.mime_type == "text/plain"
# Read another resource with valid parameters
result = await session.read_resource("resource://users/789/profile")
contents = result.contents[0]
assert isinstance(contents, TextResourceContents)
assert contents.text == "Profile for user 789"
assert contents.mime_type == "text/plain"
# Verify invalid resource URIs raise appropriate errors
with pytest.raises(Exception): # Specific exception type may vary
await session.read_resource("resource://users/123/posts") # Missing post_id
with pytest.raises(Exception): # Specific exception type may vary
await session.read_resource("resource://users/123/invalid") # Invalid template