|
| 1 | +# Copyright (c) Microsoft Corporation. All rights reserved. |
| 2 | +# Licensed under the MIT License. |
| 3 | +import typing |
1 | 4 | import unittest |
2 | 5 |
|
3 | | -from azure.functions import DataType |
| 6 | +import azure.functions as func |
| 7 | +from azure.functions import DataType, MCPToolContext |
4 | 8 | from azure.functions.decorators.core import BindingDirection |
5 | 9 | from azure.functions.decorators.mcp import MCPToolTrigger |
6 | 10 | from azure.functions.mcp import MCPToolTriggerConverter |
@@ -44,3 +48,85 @@ def test_trigger_converter(self): |
44 | 48 | result_json = MCPToolTriggerConverter.decode(datum_json, trigger_metadata={}) |
45 | 49 | self.assertEqual(result_json, {"arguments": {}}) |
46 | 50 | self.assertIsInstance(result_json, dict) |
| 51 | + |
| 52 | + |
| 53 | +class TestMcpToolDecorator(unittest.TestCase): |
| 54 | + def setUp(self): |
| 55 | + self.app = func.FunctionApp() |
| 56 | + |
| 57 | + def tearDown(self): |
| 58 | + self.app = None |
| 59 | + |
| 60 | + def test_simple_signature(self): |
| 61 | + @self.app.mcp_tool() |
| 62 | + def add_numbers(a: int, b: int) -> int: |
| 63 | + """Add two numbers.""" |
| 64 | + return a + b |
| 65 | + |
| 66 | + trigger = add_numbers._function._bindings[0] |
| 67 | + self.assertEqual(trigger.description, "Add two numbers.") |
| 68 | + self.assertEqual(trigger.name, "context") |
| 69 | + self.assertEqual(trigger.tool_name, "add_numbers") |
| 70 | + self.assertEqual(trigger.tool_properties, |
| 71 | + '[{"propertyName": "a", ' |
| 72 | + '"propertyType": "integer", ' |
| 73 | + '"description": "The a parameter."}, ' |
| 74 | + '{"propertyName": "b", "propertyType": "integer", ' |
| 75 | + '"description": "The b parameter."}]') |
| 76 | + |
| 77 | + def test_with_binding_argument(self): |
| 78 | + @self.app.mcp_tool() |
| 79 | + def save_snippet(file, snippetname: str, snippet: str): |
| 80 | + """Save snippet.""" |
| 81 | + return f"Saved {snippetname}" |
| 82 | + |
| 83 | + trigger = save_snippet._function._bindings[0] |
| 84 | + self.assertEqual(trigger.description, "Save snippet.") |
| 85 | + self.assertEqual(trigger.name, "context") |
| 86 | + self.assertEqual(trigger.tool_name, "save_snippet") |
| 87 | + self.assertEqual(trigger.tool_properties, |
| 88 | + '[{"propertyName": "file", ' |
| 89 | + '"propertyType": "string", ' |
| 90 | + '"description": "The file parameter."}, ' |
| 91 | + '{"propertyName": "snippetname", ' |
| 92 | + '"propertyType": "string", ' |
| 93 | + '"description": "The snippetname parameter."}, ' |
| 94 | + '{"propertyName": "snippet", ' |
| 95 | + '"propertyType": "string", ' |
| 96 | + '"description": "The snippet parameter."}]') |
| 97 | + |
| 98 | + def test_with_context_argument(self): |
| 99 | + @self.app.mcp_tool() |
| 100 | + def process_data(data: str, context: MCPToolContext): |
| 101 | + """Process data with context.""" |
| 102 | + return f"Processed {data}" |
| 103 | + |
| 104 | + trigger = process_data._function._bindings[0] |
| 105 | + self.assertEqual(trigger.description, "Process data with context.") |
| 106 | + self.assertEqual(trigger.name, "context") |
| 107 | + self.assertEqual(trigger.tool_name, "process_data") |
| 108 | + self.assertEqual(trigger.tool_properties, |
| 109 | + '[{"propertyName": "data", ' |
| 110 | + '"propertyType": "string", ' |
| 111 | + '"description": "The data parameter."}]') |
| 112 | + |
| 113 | + def test_with_annotated(self): |
| 114 | + @self.app.mcp_tool() |
| 115 | + def add_numbers( |
| 116 | + a: typing.Annotated[int, "First number"], |
| 117 | + b: typing.Annotated[int, "Second number"] |
| 118 | + ) -> str: |
| 119 | + """Add two integers.""" |
| 120 | + return str(a + b) |
| 121 | + |
| 122 | + trigger = add_numbers._function._bindings[0] |
| 123 | + self.assertEqual(trigger.description, "Add two integers.") |
| 124 | + self.assertEqual(trigger.name, "context") |
| 125 | + self.assertEqual(trigger.tool_name, "add_numbers") |
| 126 | + self.assertEqual(trigger.tool_properties, |
| 127 | + '[{"propertyName": "a", ' |
| 128 | + '"propertyType": "integer", ' |
| 129 | + '"description": "First number"}, ' |
| 130 | + '{"propertyName": "b", ' |
| 131 | + '"propertyType": "integer", ' |
| 132 | + '"description": "Second number"}]') |
0 commit comments