Spaces:
Running
Running
Jeremiah Lowin commited on
Commit ·
2c6ad11
1
Parent(s): 9eb16ce
Do run pyright; update tests for coros
Browse files- .pre-commit-config.yaml +0 -1
- src/contrib/mcp_mixin/example.py +8 -6
- tests/contrib/test_mcp_mixin.py +37 -27
.pre-commit-config.yaml
CHANGED
|
@@ -27,4 +27,3 @@ repos:
|
|
| 27 |
hooks:
|
| 28 |
- id: pyright-pretty
|
| 29 |
files: ^src/|^tests/
|
| 30 |
-
exclude: ^examples/|^src/contrib/|^tests/contrib/
|
|
|
|
| 27 |
hooks:
|
| 28 |
- id: pyright-pretty
|
| 29 |
files: ^src/|^tests/
|
|
|
src/contrib/mcp_mixin/example.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
| 1 |
"""Sample code for FastMCP using MCPMixin."""
|
| 2 |
|
|
|
|
|
|
|
| 3 |
from contrib.mcp_mixin.mcp_mixin import (
|
| 4 |
MCPMixin,
|
| 5 |
mcp_prompt,
|
|
@@ -38,13 +40,13 @@ first_sample.register_all(mcp_server=mcp, prefix="first")
|
|
| 38 |
second_sample.register_all(mcp_server=mcp, prefix="second")
|
| 39 |
|
| 40 |
|
| 41 |
-
def
|
| 42 |
print("MCP Server running with registered components...")
|
| 43 |
-
print("Tools:", list(mcp.get_tools()
|
| 44 |
-
print("Resources:", list(mcp.get_resources()
|
| 45 |
-
print("Prompts:",
|
| 46 |
-
mcp.run()
|
| 47 |
|
| 48 |
|
| 49 |
if __name__ == "__main__":
|
| 50 |
-
|
|
|
|
|
|
| 1 |
"""Sample code for FastMCP using MCPMixin."""
|
| 2 |
|
| 3 |
+
import asyncio
|
| 4 |
+
|
| 5 |
from contrib.mcp_mixin.mcp_mixin import (
|
| 6 |
MCPMixin,
|
| 7 |
mcp_prompt,
|
|
|
|
| 40 |
second_sample.register_all(mcp_server=mcp, prefix="second")
|
| 41 |
|
| 42 |
|
| 43 |
+
async def list_components():
|
| 44 |
print("MCP Server running with registered components...")
|
| 45 |
+
print("Tools:", list(await mcp.get_tools()))
|
| 46 |
+
print("Resources:", list(await mcp.get_resources()))
|
| 47 |
+
print("Prompts:", list(await mcp.get_prompts()))
|
|
|
|
| 48 |
|
| 49 |
|
| 50 |
if __name__ == "__main__":
|
| 51 |
+
asyncio.run(list_components())
|
| 52 |
+
mcp.run()
|
tests/contrib/test_mcp_mixin.py
CHANGED
|
@@ -51,7 +51,9 @@ class TestMCPMixin:
|
|
| 51 |
],
|
| 52 |
ids=["No prefix", "Default separator", "Custom separator"],
|
| 53 |
)
|
| 54 |
-
def test_tool_registration(
|
|
|
|
|
|
|
| 55 |
"""Test tool registration with prefix and separator variations."""
|
| 56 |
mcp = FastMCP()
|
| 57 |
|
|
@@ -63,7 +65,7 @@ class TestMCPMixin:
|
|
| 63 |
instance = MyToolMixin()
|
| 64 |
instance.register_tools(mcp, prefix=prefix, separator=separator)
|
| 65 |
|
| 66 |
-
registered_tools = mcp.get_tools()
|
| 67 |
assert expected_key in registered_tools
|
| 68 |
assert unexpected_key not in registered_tools
|
| 69 |
|
|
@@ -94,7 +96,7 @@ class TestMCPMixin:
|
|
| 94 |
],
|
| 95 |
ids=["No prefix", "Default separator", "Custom separator"],
|
| 96 |
)
|
| 97 |
-
def test_resource_registration(
|
| 98 |
self, prefix, separator, expected_uri_key, expected_name, unexpected_uri_key
|
| 99 |
):
|
| 100 |
"""Test resource registration with prefix and separator variations."""
|
|
@@ -108,7 +110,7 @@ class TestMCPMixin:
|
|
| 108 |
instance = MyResourceMixin()
|
| 109 |
instance.register_resources(mcp, prefix=prefix, separator=separator)
|
| 110 |
|
| 111 |
-
registered_resources = mcp.get_resources()
|
| 112 |
assert expected_uri_key in registered_resources
|
| 113 |
assert registered_resources[expected_uri_key].name == expected_name
|
| 114 |
assert unexpected_uri_key not in registered_resources
|
|
@@ -137,7 +139,7 @@ class TestMCPMixin:
|
|
| 137 |
],
|
| 138 |
ids=["No prefix", "Default separator", "Custom separator"],
|
| 139 |
)
|
| 140 |
-
def test_prompt_registration(
|
| 141 |
self, prefix, separator, expected_name, unexpected_name
|
| 142 |
):
|
| 143 |
"""Test prompt registration with prefix and separator variations."""
|
|
@@ -151,11 +153,11 @@ class TestMCPMixin:
|
|
| 151 |
instance = MyPromptMixin()
|
| 152 |
instance.register_prompts(mcp, prefix=prefix, separator=separator)
|
| 153 |
|
| 154 |
-
|
| 155 |
-
assert expected_name in
|
| 156 |
-
assert unexpected_name not in
|
| 157 |
|
| 158 |
-
def test_register_all_no_prefix(self):
|
| 159 |
"""Test register_all method registers all types without a prefix."""
|
| 160 |
mcp = FastMCP()
|
| 161 |
|
|
@@ -175,11 +177,15 @@ class TestMCPMixin:
|
|
| 175 |
instance = MyFullMixin()
|
| 176 |
instance.register_all(mcp)
|
| 177 |
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
|
| 182 |
-
def test_register_all_with_prefix_default_separators(self):
|
| 183 |
"""Test register_all method registers all types with a prefix and default separators."""
|
| 184 |
mcp = FastMCP()
|
| 185 |
|
|
@@ -199,13 +205,15 @@ class TestMCPMixin:
|
|
| 199 |
instance = MyFullMixinPrefixed()
|
| 200 |
instance.register_all(mcp, prefix="all")
|
| 201 |
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
p.name for p in mcp.list_prompts()
|
| 206 |
-
}
|
| 207 |
|
| 208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 209 |
"""Test register_all method registers all types with a prefix and custom separators."""
|
| 210 |
mcp = FastMCP()
|
| 211 |
|
|
@@ -231,13 +239,15 @@ class TestMCPMixin:
|
|
| 231 |
prompt_separator=".",
|
| 232 |
)
|
| 233 |
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 237 |
|
| 238 |
# Check default separators weren't used
|
| 239 |
-
assert f"cust{_DEFAULT_SEPARATOR_TOOL}tool_cust" not in
|
| 240 |
-
assert f"cust{_DEFAULT_SEPARATOR_RESOURCE}res://cust" not in
|
| 241 |
-
assert f"cust{_DEFAULT_SEPARATOR_PROMPT}prompt_cust" not in
|
| 242 |
-
p.name for p in mcp.list_prompts()
|
| 243 |
-
}
|
|
|
|
| 51 |
],
|
| 52 |
ids=["No prefix", "Default separator", "Custom separator"],
|
| 53 |
)
|
| 54 |
+
async def test_tool_registration(
|
| 55 |
+
self, prefix, separator, expected_key, unexpected_key
|
| 56 |
+
):
|
| 57 |
"""Test tool registration with prefix and separator variations."""
|
| 58 |
mcp = FastMCP()
|
| 59 |
|
|
|
|
| 65 |
instance = MyToolMixin()
|
| 66 |
instance.register_tools(mcp, prefix=prefix, separator=separator)
|
| 67 |
|
| 68 |
+
registered_tools = await mcp.get_tools()
|
| 69 |
assert expected_key in registered_tools
|
| 70 |
assert unexpected_key not in registered_tools
|
| 71 |
|
|
|
|
| 96 |
],
|
| 97 |
ids=["No prefix", "Default separator", "Custom separator"],
|
| 98 |
)
|
| 99 |
+
async def test_resource_registration(
|
| 100 |
self, prefix, separator, expected_uri_key, expected_name, unexpected_uri_key
|
| 101 |
):
|
| 102 |
"""Test resource registration with prefix and separator variations."""
|
|
|
|
| 110 |
instance = MyResourceMixin()
|
| 111 |
instance.register_resources(mcp, prefix=prefix, separator=separator)
|
| 112 |
|
| 113 |
+
registered_resources = await mcp.get_resources()
|
| 114 |
assert expected_uri_key in registered_resources
|
| 115 |
assert registered_resources[expected_uri_key].name == expected_name
|
| 116 |
assert unexpected_uri_key not in registered_resources
|
|
|
|
| 139 |
],
|
| 140 |
ids=["No prefix", "Default separator", "Custom separator"],
|
| 141 |
)
|
| 142 |
+
async def test_prompt_registration(
|
| 143 |
self, prefix, separator, expected_name, unexpected_name
|
| 144 |
):
|
| 145 |
"""Test prompt registration with prefix and separator variations."""
|
|
|
|
| 153 |
instance = MyPromptMixin()
|
| 154 |
instance.register_prompts(mcp, prefix=prefix, separator=separator)
|
| 155 |
|
| 156 |
+
prompts = await mcp.get_prompts()
|
| 157 |
+
assert expected_name in prompts
|
| 158 |
+
assert unexpected_name not in prompts
|
| 159 |
|
| 160 |
+
async def test_register_all_no_prefix(self):
|
| 161 |
"""Test register_all method registers all types without a prefix."""
|
| 162 |
mcp = FastMCP()
|
| 163 |
|
|
|
|
| 177 |
instance = MyFullMixin()
|
| 178 |
instance.register_all(mcp)
|
| 179 |
|
| 180 |
+
tools = await mcp.get_tools()
|
| 181 |
+
resources = await mcp.get_resources()
|
| 182 |
+
prompts = await mcp.get_prompts()
|
| 183 |
+
|
| 184 |
+
assert "tool_all" in tools
|
| 185 |
+
assert "res://all" in resources
|
| 186 |
+
assert "prompt_all" in prompts
|
| 187 |
|
| 188 |
+
async def test_register_all_with_prefix_default_separators(self):
|
| 189 |
"""Test register_all method registers all types with a prefix and default separators."""
|
| 190 |
mcp = FastMCP()
|
| 191 |
|
|
|
|
| 205 |
instance = MyFullMixinPrefixed()
|
| 206 |
instance.register_all(mcp, prefix="all")
|
| 207 |
|
| 208 |
+
tools = await mcp.get_tools()
|
| 209 |
+
resources = await mcp.get_resources()
|
| 210 |
+
prompts = await mcp.get_prompts()
|
|
|
|
|
|
|
| 211 |
|
| 212 |
+
assert f"all{_DEFAULT_SEPARATOR_TOOL}tool_all_p" in tools
|
| 213 |
+
assert f"all{_DEFAULT_SEPARATOR_RESOURCE}res://all_p" in resources
|
| 214 |
+
assert f"all{_DEFAULT_SEPARATOR_PROMPT}prompt_all_p" in prompts
|
| 215 |
+
|
| 216 |
+
async def test_register_all_with_prefix_custom_separators(self):
|
| 217 |
"""Test register_all method registers all types with a prefix and custom separators."""
|
| 218 |
mcp = FastMCP()
|
| 219 |
|
|
|
|
| 239 |
prompt_separator=".",
|
| 240 |
)
|
| 241 |
|
| 242 |
+
tools = await mcp.get_tools()
|
| 243 |
+
resources = await mcp.get_resources()
|
| 244 |
+
prompts = await mcp.get_prompts()
|
| 245 |
+
|
| 246 |
+
assert "cust-tool_cust" in tools
|
| 247 |
+
assert "cust::res://cust" in resources
|
| 248 |
+
assert "cust.prompt_cust" in prompts
|
| 249 |
|
| 250 |
# Check default separators weren't used
|
| 251 |
+
assert f"cust{_DEFAULT_SEPARATOR_TOOL}tool_cust" not in tools
|
| 252 |
+
assert f"cust{_DEFAULT_SEPARATOR_RESOURCE}res://cust" not in resources
|
| 253 |
+
assert f"cust{_DEFAULT_SEPARATOR_PROMPT}prompt_cust" not in prompts
|
|
|
|
|
|