|
1 | 1 | from typing import Optional |
2 | 2 | from typing import Any, Dict, Tuple, get_args, get_origin, Annotated |
| 3 | +import logging |
3 | 4 |
|
4 | 5 | from azure.functions.decorators.constants import ( |
5 | 6 | MCP_TOOL_TRIGGER |
6 | 7 | ) |
7 | 8 | from azure.functions.decorators.core import Trigger, DataType |
| 9 | +from azure.functions.decorators.function_app import FunctionBuilder |
8 | 10 |
|
9 | 11 | # Mapping Python types to MCP property types |
10 | 12 | _TYPE_MAPPING = { |
@@ -46,3 +48,28 @@ def _extract_type_and_description(param_name: str, type_hint: Any) -> Tuple[Any, |
46 | 48 | param_description = next((a for a in args[1:] if isinstance(a, str)), f"The {param_name} parameter.") |
47 | 49 | return actual_type, param_description |
48 | 50 | return type_hint, f"The {param_name} parameter." |
| 51 | + |
| 52 | +def _get_user_function(target_func): |
| 53 | + """ |
| 54 | + Unwraps decorated or builder-wrapped functions to find the original |
| 55 | + user-defined function (the one starting with 'def' or 'async def'). |
| 56 | + """ |
| 57 | + logging.info("HELLO FROM THE SDK") |
| 58 | + # Case 1: It's a FunctionBuilder object |
| 59 | + if isinstance(target_func, FunctionBuilder): |
| 60 | + # Access the internal user function |
| 61 | + try: |
| 62 | + return target_func._function.get_user_function() |
| 63 | + except AttributeError: |
| 64 | + pass |
| 65 | + |
| 66 | + # Case 2: It's already the user-defined function |
| 67 | + if callable(target_func) and hasattr(target_func, "__name__"): |
| 68 | + return target_func |
| 69 | + |
| 70 | + # Case 3: It might be a partially wrapped callable |
| 71 | + if hasattr(target_func, "__wrapped__"): |
| 72 | + return _get_user_function(target_func.__wrapped__) |
| 73 | + |
| 74 | + # Default fallback |
| 75 | + return target_func |
0 commit comments