File size: 2,780 Bytes
c5ee465
 
457a7de
c5ee465
 
a853a78
c5ee465
 
 
 
 
 
 
 
 
 
 
 
 
 
506c09a
 
c5ee465
506c09a
c5ee465
 
457a7de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c5ee465
 
 
 
 
 
 
 
 
 
 
 
 
a853a78
 
 
 
 
 
c5ee465
 
506c09a
 
c5ee465
cf04a1f
c5ee465
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a853a78
 
 
 
 
 
c5ee465
 
 
 
 
 
aa46c09
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
from typing import Any

import pytest

from fastmcp import Client, FastMCP
from fastmcp.tools.tool import Tool


async def test_tool_exclude_args_in_tool_manager():
    """Test that tool args are excluded in the tool manager."""
    mcp = FastMCP("Test Server")

    @mcp.tool(exclude_args=["state"])
    def echo(message: str, state: dict[str, Any] | None = None) -> str:
        """Echo back the message provided."""
        if state:
            # State was read
            pass
        return message

    tools_dict = await mcp._tool_manager.get_tools()
    tools = list(tools_dict.values())
    assert len(tools) == 1
    assert "state" not in tools[0].parameters["properties"]


async def test_tool_exclude_args_without_default_value_raises_error():
    """Test that excluding args without default values raises ValueError"""
    mcp = FastMCP("Test Server")

    with pytest.raises(ValueError):

        @mcp.tool(exclude_args=["state"])
        def echo(message: str, state: dict[str, Any] | None) -> str:
            """Echo back the message provided."""
            if state:
                # State was read
                pass
            return message


async def test_add_tool_method_exclude_args():
    """Test that tool exclude_args work with the add_tool method."""
    mcp = FastMCP("Test Server")

    def create_item(
        name: str, value: int, state: dict[str, Any] | None = None
    ) -> dict[str, Any]:
        """Create a new item."""
        if state:
            # State was read
            pass
        return {"name": name, "value": value}

    tool = Tool.from_function(
        create_item,
        name="create_item",
        exclude_args=["state"],
    )
    mcp.add_tool(tool)

    # Check internal tool objects directly
    tools_dict = await mcp._tool_manager.get_tools()
    tools = list(tools_dict.values())
    assert len(tools) == 1
    assert "state" not in tools[0].parameters["properties"]


async def test_tool_functionality_with_exclude_args():
    """Test that tool functionality is preserved when using exclude_args."""
    mcp = FastMCP("Test Server")

    def create_item(
        name: str, value: int, state: dict[str, Any] | None = None
    ) -> dict[str, Any]:
        """Create a new item."""
        if state:
            # state was read
            pass
        return {"name": name, "value": value}

    tool = Tool.from_function(
        create_item,
        name="create_item",
        exclude_args=["state"],
    )
    mcp.add_tool(tool)

    # Use the tool to verify functionality is preserved
    async with Client(mcp) as client:
        result = await client.call_tool(
            "create_item", {"name": "test_item", "value": 42}
        )
        assert result.data == {"name": "test_item", "value": 42}