Skip to content
This repository was archived by the owner on Mar 24, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/create_mcp_server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ def copy_template(
("__init__.py.jinja2", "__init__.py", target_dir),
("server.py.jinja2", "server.py", target_dir),
("README.md.jinja2", "README.md", path),
("test_server.py.jinja2", "test_server.py", target_dir),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is the right directory tests should live. This would entangle them with the package.

]

pyproject = PyProject(path / "pyproject.toml")
Expand Down Expand Up @@ -181,6 +182,7 @@ def create_project(
# Add mcp dependency using uv add
try:
subprocess.run(["uv", "add", "mcp"], cwd=path, check=True)
subprocess.run(["uv", "add", "pytest", '--dev'], cwd=path, check=True)
except subprocess.CalledProcessError:
click.echo("❌ Error: Failed to add mcp dependency.", err=True)
sys.exit(1)
Expand Down
50 changes: 50 additions & 0 deletions src/create_mcp_server/template/test_server.py.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import pytest
import os
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from mcp.types import ListResourcesResult, TextContent, TextResourceContents
from pydantic import AnyUrl


test_dir = os.path.dirname(os.path.abspath(__file__))

@pytest.mark.asyncio(loop_scope='module')
async def test_client_server_interactions():
"""Fixture that starts the actual server and provides a connected session"""
server_params = StdioServerParameters(
command=f"{test_dir}/template_server/src/template_server/server.py",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This path assumes that the server is called template_server, which does not hold true..

args=[],
env=None
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()

list_resources_result = await session.list_resources()
assert list_resources_result == ListResourcesResult(nextCursor=None, resources=[])

list_tools_result = await session.list_tools()
assert list_tools_result.tools[0].name == 'add-note'

get_prompt_result = await session.get_prompt(name="summarize-notes")
assert get_prompt_result.description == "Summarize the current notes"

list_prompts_result = await session.list_prompts()
assert list_prompts_result.prompts[0].name == 'summarize-notes'

call_tool_result = await session.call_tool("add-note", arguments={
"name": "example_note",
"content": "Example content"
})

tool_content = call_tool_result.content[0]
if isinstance(tool_content, TextContent):
assert tool_content.text == "Added note 'example_note' with content: Example content"

list_resources_result = await session.list_resources()
resource_uri = list_resources_result.resources[0].uri
assert resource_uri == AnyUrl("note://internal/example_note")

read_resource_result = await session.read_resource(resource_uri)
if isinstance(read_resource_result.contents[0], TextResourceContents):
assert read_resource_result.contents[0].text== 'Example content'