Skip to content
Merged
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
Binary file added .coverage
Binary file not shown.
31 changes: 31 additions & 0 deletions tests/test_tools.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
"""Tests for MCP server tools."""

import pytest
from pydantic import ValidationError, validate_call

from my_mcp_server.server import greet


Expand All @@ -13,3 +16,31 @@ async def test_greet_custom_name():
"""Greet handles custom names."""
result = await greet(name="Ploidy")
assert result == "Hello, Ploidy!"


# --- input bound enforcement -----------------------------------------------
# Calling the tool function directly bypasses FastMCP's protocol-level
# schema validation. Wrapping with `validate_call` is the same enforcement
# FastMCP applies, so we cover Annotated[..., Field(min_length, max_length)]
# without spinning up the MCP transport.

_validated_greet = validate_call(greet)


async def test_greet_rejects_empty_name():
"""min_length=1 — empty string must be rejected at the protocol layer."""
with pytest.raises(ValidationError):
await _validated_greet(name="")


async def test_greet_rejects_oversize_name():
"""max_length=200 — long strings must be rejected."""
with pytest.raises(ValidationError):
await _validated_greet(name="x" * 201)


async def test_greet_accepts_boundary_lengths():
"""1 and 200 are inclusive bounds and must pass."""
assert await _validated_greet(name="a") == "Hello, a!"
long_name = "a" * 200
assert await _validated_greet(name=long_name) == f"Hello, {long_name}!"