Skip to content

Commit 20b4d28

Browse files
committed
2 parents 4c10e65 + 2ed668c commit 20b4d28

File tree

9 files changed

+1234
-49
lines changed

9 files changed

+1234
-49
lines changed

README.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,98 @@ def get_settings() -> str:
289289
"language": "en",
290290
"debug": false
291291
}"""
292+
293+
294+
# Form-style query expansion examples using RFC 6570 URI templates
295+
296+
297+
@mcp.resource("articles://{article_id}/view{?format,lang}")
298+
def view_article(article_id: str, format: str = "html", lang: str = "en") -> str:
299+
"""View an article with optional format and language selection.
300+
301+
Example URIs:
302+
- articles://123/view (uses defaults: format=html, lang=en)
303+
- articles://123/view?format=pdf (format=pdf, lang=en)
304+
- articles://123/view?format=pdf&lang=fr (format=pdf, lang=fr)
305+
"""
306+
if format == "pdf":
307+
content = f"PDF content for article {article_id} in {lang}"
308+
elif format == "json":
309+
content = f'{{"article_id": "{article_id}", "content": "...", "lang": "{lang}"}}'
310+
else:
311+
content = f"<html><body>Article {article_id} in {lang}</body></html>"
312+
313+
return content
314+
315+
316+
@mcp.resource("search://query/{search_term}{?page,limit,category,sort}")
317+
def search_content(
318+
search_term: str, page: int = 1, limit: int = 10, category: str = "all", sort: str = "relevance"
319+
) -> str:
320+
"""Search content with optional pagination and filtering.
321+
322+
Example URIs:
323+
- search://query/python (basic search)
324+
- search://query/python?page=2&limit=20 (pagination)
325+
- search://query/python?category=tutorial&sort=date (filtering)
326+
"""
327+
offset = (page - 1) * limit
328+
results = f"Search results for '{search_term}' (category: {category}, sort: {sort})"
329+
results += f"\nShowing {limit} results starting from {offset + 1}"
330+
331+
# Simulated search results
332+
for i in range(limit):
333+
result_num = offset + i + 1
334+
results += f"\n{result_num}. Result about {search_term} in {category}"
335+
336+
return results
337+
338+
339+
@mcp.resource("users://{user_id}/profile{?include_private,format}")
340+
def get_user_profile(user_id: str, include_private: bool = False, format: str = "summary") -> str:
341+
"""Get user profile with optional private data and format selection.
342+
343+
Example URIs:
344+
- users://123/profile (public data, summary format)
345+
- users://123/profile?include_private=true (includes private data)
346+
- users://123/profile?format=detailed&include_private=true (detailed with private)
347+
"""
348+
from typing import Any
349+
350+
profile_data: dict[str, Any] = {"user_id": user_id, "name": "John Doe", "public_bio": "Software developer"}
351+
352+
if include_private:
353+
profile_data.update({"email": "john@example.com", "phone": "+1234567890"})
354+
355+
if format == "detailed":
356+
profile_data.update({"last_active": "2024-01-20", "preferences": {"notifications": True}})
357+
358+
return str(profile_data)
359+
360+
361+
@mcp.resource("api://weather/{location}{?units,lang,include_forecast,days}")
362+
def get_weather_data(
363+
location: str, units: str = "metric", lang: str = "en", include_forecast: bool = False, days: int = 5
364+
) -> str:
365+
"""Get weather data with customizable options.
366+
367+
Example URIs:
368+
- api://weather/london (basic weather)
369+
- api://weather/london?units=imperial&lang=es (different units and language)
370+
- api://weather/london?include_forecast=true&days=7 (with 7-day forecast)
371+
"""
372+
temp_unit = "C" if units == "metric" else "F"
373+
base_temp = 22 if units == "metric" else 72
374+
375+
weather_info = f"Weather for {location}: {base_temp}{temp_unit}"
376+
377+
if include_forecast:
378+
weather_info += f"\n{days}-day forecast:"
379+
for day in range(1, days + 1):
380+
forecast_temp = base_temp + (day % 3)
381+
weather_info += f"\nDay {day}: {forecast_temp}{temp_unit}"
382+
383+
return weather_info
292384
```
293385

294386
_Full example: [examples/snippets/servers/basic_resource.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/basic_resource.py)_

examples/snippets/servers/basic_resource.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,95 @@ def get_settings() -> str:
1818
"language": "en",
1919
"debug": false
2020
}"""
21+
22+
23+
# Form-style query expansion examples using RFC 6570 URI templates
24+
25+
26+
@mcp.resource("articles://{article_id}/view{?format,lang}")
27+
def view_article(article_id: str, format: str = "html", lang: str = "en") -> str:
28+
"""View an article with optional format and language selection.
29+
30+
Example URIs:
31+
- articles://123/view (uses defaults: format=html, lang=en)
32+
- articles://123/view?format=pdf (format=pdf, lang=en)
33+
- articles://123/view?format=pdf&lang=fr (format=pdf, lang=fr)
34+
"""
35+
if format == "pdf":
36+
content = f"PDF content for article {article_id} in {lang}"
37+
elif format == "json":
38+
content = f'{{"article_id": "{article_id}", "content": "...", "lang": "{lang}"}}'
39+
else:
40+
content = f"<html><body>Article {article_id} in {lang}</body></html>"
41+
42+
return content
43+
44+
45+
@mcp.resource("search://query/{search_term}{?page,limit,category,sort}")
46+
def search_content(
47+
search_term: str, page: int = 1, limit: int = 10, category: str = "all", sort: str = "relevance"
48+
) -> str:
49+
"""Search content with optional pagination and filtering.
50+
51+
Example URIs:
52+
- search://query/python (basic search)
53+
- search://query/python?page=2&limit=20 (pagination)
54+
- search://query/python?category=tutorial&sort=date (filtering)
55+
"""
56+
offset = (page - 1) * limit
57+
results = f"Search results for '{search_term}' (category: {category}, sort: {sort})"
58+
results += f"\nShowing {limit} results starting from {offset + 1}"
59+
60+
# Simulated search results
61+
for i in range(limit):
62+
result_num = offset + i + 1
63+
results += f"\n{result_num}. Result about {search_term} in {category}"
64+
65+
return results
66+
67+
68+
@mcp.resource("users://{user_id}/profile{?include_private,format}")
69+
def get_user_profile(user_id: str, include_private: bool = False, format: str = "summary") -> str:
70+
"""Get user profile with optional private data and format selection.
71+
72+
Example URIs:
73+
- users://123/profile (public data, summary format)
74+
- users://123/profile?include_private=true (includes private data)
75+
- users://123/profile?format=detailed&include_private=true (detailed with private)
76+
"""
77+
from typing import Any
78+
79+
profile_data: dict[str, Any] = {"user_id": user_id, "name": "John Doe", "public_bio": "Software developer"}
80+
81+
if include_private:
82+
profile_data.update({"email": "john@example.com", "phone": "+1234567890"})
83+
84+
if format == "detailed":
85+
profile_data.update({"last_active": "2024-01-20", "preferences": {"notifications": True}})
86+
87+
return str(profile_data)
88+
89+
90+
@mcp.resource("api://weather/{location}{?units,lang,include_forecast,days}")
91+
def get_weather_data(
92+
location: str, units: str = "metric", lang: str = "en", include_forecast: bool = False, days: int = 5
93+
) -> str:
94+
"""Get weather data with customizable options.
95+
96+
Example URIs:
97+
- api://weather/london (basic weather)
98+
- api://weather/london?units=imperial&lang=es (different units and language)
99+
- api://weather/london?include_forecast=true&days=7 (with 7-day forecast)
100+
"""
101+
temp_unit = "C" if units == "metric" else "F"
102+
base_temp = 22 if units == "metric" else 72
103+
104+
weather_info = f"Weather for {location}: {base_temp}{temp_unit}"
105+
106+
if include_forecast:
107+
weather_info += f"\n{days}-day forecast:"
108+
for day in range(1, days + 1):
109+
forecast_temp = base_temp + (day % 3)
110+
weather_info += f"\nDay {day}: {forecast_temp}{temp_unit}"
111+
112+
return weather_info

0 commit comments

Comments
 (0)