FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
python-sdk/tests/docs_src/test_apps.py at main · modelcontextprotocol/python-sdk · GitHub
Uh oh!
There was an error while loading.
Please reload this page
.
modelcontextprotocol
/
python-sdk
Public
Notifications
You must be signed in to change notification settings
Fork
3.8k
Star
24.2k
Code
Issues
206
Pull requests
184
Actions
Projects
Security and quality
6
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
python-sdk
/
tests
/
docs_src
/
test_apps.py
Copy path
More file actions
More file actions
Latest commit
History
History
History
103 lines (83 loc) · 4.89 KB
Breadcrumbs
python-sdk
/
tests
/
docs_src
/
test_apps.py
Copy path
File metadata and controls
103 lines (83 loc) · 4.89 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
"""`docs/advanced/apps.md`: every claim the page makes, proved against the real SDK."""
from
typing
import
Any
import
pytest
from
mcp_types
import
TextContent
,
TextResourceContents
from
docs_src
.
apps
import
tutorial001
,
tutorial002
,
tutorial003
from
mcp
import
Client
from
mcp
.
client
import
advertise
from
mcp
.
server
.
apps
import
APP_MIME_TYPE
,
EXTENSION_ID
# See test_index.py for why this is a per-module mark and not a conftest hook.
pytestmark
=
[
pytest
.
mark
.
anyio
,
pytest
.
mark
.
filterwarnings
(
"error::mcp.MCPDeprecationWarning"
)]
async
def
test_the_tool_carries_the_ui_resource_reference
()
->
None
:
"""tutorial001: `@apps.tool(resource_uri=...)` stamps `_meta.ui.resourceUri` on the tool."""
async
with
Client
(
tutorial001
.
mcp
)
as
client
:
listed
=
await
client
.
list_tools
()
assert
listed
.
tools
[
0
].
meta
==
{
"ui"
: {
"resourceUri"
:
"ui://clock/app.html"
}}
async
def
test_the_ui_resource_is_served_as_the_app_mime_type
()
->
None
:
"""tutorial001: `add_html_resource` serves the HTML at `text/html;profile=mcp-app`,
the MIME type that tells a host "this is an app, render it"."""
async
with
Client
(
tutorial001
.
mcp
)
as
client
:
result
=
await
client
.
read_resource
(
"ui://clock/app.html"
)
contents
=
result
.
contents
[
0
]
assert
isinstance
(
contents
,
TextResourceContents
)
assert
contents
.
mime_type
==
APP_MIME_TYPE
assert
contents
.
text
==
tutorial001
.
CLOCK_HTML
async
def
test_one_tool_two_answers
()
->
None
:
"""tutorial001: the canonical degradation pattern: raw data for a client that
negotiated Apps, a human sentence for one that did not."""
async
with
Client
(
tutorial001
.
mcp
,
extensions
=
[
advertise
(
EXTENSION_ID
, {
"mimeTypes"
: [
APP_MIME_TYPE
]})]
)
as
ui_client
:
rich
=
await
ui_client
.
call_tool
(
"get_time"
, {})
async
with
Client
(
tutorial001
.
mcp
)
as
text_client
:
plain
=
await
text_client
.
call_tool
(
"get_time"
, {})
assert
rich
.
content
==
[
TextContent
(
type
=
"text"
,
text
=
"2026-06-26T12:00:00Z"
)]
assert
plain
.
content
==
[
TextContent
(
type
=
"text"
,
text
=
"The time is 2026-06-26T12:00:00Z."
)]
async
def
test_the_clock_client_program_runs_as_shown
(
capsys
:
pytest
.
CaptureFixture
[
str
])
->
None
:
"""tutorial001: `main()` declares Apps support with the required `mimeTypes` and
receives the rich answer the page promises."""
await
tutorial001
.
main
()
assert
"2026-06-26T12:00:00Z"
in
capsys
.
readouterr
().
out
async
def
test_capability_advertised_under_server_extensions
()
->
None
:
"""tutorial001: passing `extensions=[apps]` advertises `io.modelcontextprotocol/ui`."""
async
with
Client
(
tutorial001
.
mcp
)
as
client
:
assert
client
.
server_capabilities
.
extensions
==
{
EXTENSION_ID
: {}}
async
def
test_csp_permissions_domain_and_border_ride_the_resource_meta
()
->
None
:
"""tutorial002: the iframe lockdown fields land under `_meta.ui` on both the list
entry and the read content item, with the spec's camelCase wire keys."""
expected
:
dict
[
str
,
Any
]
=
{
"ui"
: {
"csp"
: {
"connectDomains"
: [
"https://api.example.com"
]},
"permissions"
: {
"clipboardWrite"
: {}},
"domain"
:
"dashboard.example.com"
,
"prefersBorder"
:
True
,
}
}
async
with
Client
(
tutorial002
.
mcp
)
as
client
:
listed
=
await
client
.
list_resources
()
result
=
await
client
.
read_resource
(
"ui://dashboard/app.html"
)
assert
listed
.
resources
[
0
].
meta
==
expected
contents
=
result
.
contents
[
0
]
assert
isinstance
(
contents
,
TextResourceContents
)
assert
contents
.
meta
==
expected
async
def
test_an_app_only_tool_is_still_listed_and_callable
()
->
None
:
"""tutorial002: `visibility=["app"]` is metadata for the host; the server lists the
tool like any other and serves its calls. Filtering is the host's job."""
async
with
Client
(
tutorial002
.
mcp
)
as
client
:
listed
=
await
client
.
list_tools
()
result
=
await
client
.
call_tool
(
"refresh_dashboard"
, {})
assert
listed
.
tools
[
0
].
meta
==
{
"ui"
: {
"resourceUri"
:
"ui://dashboard/app.html"
,
"visibility"
: [
"app"
]}}
assert
result
.
content
==
[
TextContent
(
type
=
"text"
,
text
=
"refreshed"
)]
async
def
test_a_file_resource_is_served_with_the_app_mime_type_filled_in
()
->
None
:
"""tutorial003: `add_resource` accepts a pre-built `FileResource` and fills in the
`text/html;profile=mcp-app` MIME type the resource didn't set explicitly."""
async
with
Client
(
tutorial003
.
mcp
)
as
client
:
listed
=
await
client
.
list_tools
()
called
=
await
client
.
call_tool
(
"refresh_report"
, {})
result
=
await
client
.
read_resource
(
"ui://report/app.html"
)
assert
listed
.
tools
[
0
].
meta
==
{
"ui"
: {
"resourceUri"
:
"ui://report/app.html"
}}
assert
called
.
content
==
[
TextContent
(
type
=
"text"
,
text
=
"report refreshed"
)]
contents
=
result
.
contents
[
0
]
assert
isinstance
(
contents
,
TextResourceContents
)
assert
contents
.
mime_type
==
APP_MIME_TYPE
assert
contents
.
text
==
tutorial003
.
REPORT_HTML
.
read_text
(
encoding
=
"utf-8"
)
Back
|
FazBrowse Home
|
New Git URL