-
Notifications
You must be signed in to change notification settings - Fork 780
/
Copy pathtest_141_resource_templates.py
120 lines (94 loc) · 4.76 KB
/
test_141_resource_templates.py
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
110
111
112
113
114
115
116
117
118
119
120
import pytest
from pydantic import AnyUrl
from mcp.server.fastmcp import FastMCP
from mcp.shared.memory import (
create_connected_server_and_client_session as client_session,
)
from mcp.types import (
ListResourceTemplatesResult,
TextResourceContents,
)
@pytest.mark.anyio
async def test_resource_template_edge_cases():
"""Test server-side resource template validation"""
mcp = FastMCP("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:
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:
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:
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:
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(ValueError, match="Unknown resource"):
await mcp.read_resource("resource://users/123/posts") # Missing post_id
with pytest.raises(ValueError, 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 = FastMCP("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_session(mcp._mcp_server) as session:
# Initialize the session
await session.initialize()
# List available resources
resources = await session.list_resource_templates()
assert isinstance(resources, ListResourceTemplatesResult)
assert len(resources.resourceTemplates) == 2
# Verify resource templates are listed correctly
templates = [r.uriTemplate for r in resources.resourceTemplates]
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(AnyUrl("resource://users/123/posts/456"))
contents = result.contents[0]
assert isinstance(contents, TextResourceContents)
assert contents.text == "Post 456 by user 123"
assert contents.mimeType == "text/plain"
# Read another resource with valid parameters
result = await session.read_resource(AnyUrl("resource://users/789/profile"))
contents = result.contents[0]
assert isinstance(contents, TextResourceContents)
assert contents.text == "Profile for user 789"
assert contents.mimeType == "text/plain"
# Verify invalid resource URIs raise appropriate errors
with pytest.raises(Exception): # Specific exception type may vary
await session.read_resource(
AnyUrl("resource://users/123/posts")
) # Missing post_id
with pytest.raises(Exception): # Specific exception type may vary
await session.read_resource(
AnyUrl("resource://users/123/invalid")
) # Invalid template