1313
1414from azure .functions .decorators .blob import BlobTrigger , BlobInput , BlobOutput
1515from azure .functions .decorators .core import Binding , Trigger , DataType , \
16- AuthLevel , SCRIPT_FILE_NAME , Cardinality , AccessRights , Setting , BlobSource
16+ AuthLevel , SCRIPT_FILE_NAME , Cardinality , AccessRights , Setting , BlobSource , \
17+ McpPropertyType
1718from azure .functions .decorators .cosmosdb import CosmosDBTrigger , \
1819 CosmosDBOutput , CosmosDBInput , CosmosDBTriggerV3 , CosmosDBInputV3 , \
1920 CosmosDBOutputV3
4445 AssistantQueryInput , AssistantPostInput , InputType , EmbeddingsInput , \
4546 semantic_search_system_prompt , \
4647 SemanticSearchInput , EmbeddingsStoreOutput
47- from .mcp import MCPToolTrigger , _TYPE_MAPPING , check_property_type , check_is_array , check_is_required
48+ from .mcp import MCPToolTrigger , check_property_type , check_is_array , check_is_required
4849from .retry_policy import RetryPolicy
4950from .function_name import FunctionName
5051from .warmup import WarmUpTrigger
5556 MySqlTrigger
5657
5758
58- logger = logging .getLogger ('azure.functions.WsgiMiddleware' )
59-
6059class Function (object ):
6160 """
6261 The function object represents a function in Function App. It
@@ -1593,7 +1592,6 @@ def decorator(fb: FunctionBuilder) -> FunctionBuilder:
15931592
15941593 # Pull any explicitly declared MCP tool properties
15951594 explicit_properties = getattr (target_func , "__mcp_tool_properties__" , {})
1596- logger .info (f"Explicit MCP tool properties: { explicit_properties } " )
15971595
15981596 # Parse tool name and description from function signature
15991597 tool_name = target_func .__name__
@@ -1613,26 +1611,27 @@ def decorator(fb: FunctionBuilder) -> FunctionBuilder:
16131611 if param_type_hint is MCPToolContext :
16141612 continue
16151613
1616- # Check if explicit metadata exists for this param
1617- if param_name in explicit_properties :
1618- logger .info (f"Using explicit MCP tool property for param: { param_name } " ) # noqa
1619- prop = explicit_properties [param_name ].copy ()
1620- prop ["propertyName" ] = param_name
1621- tool_properties .append (prop )
1622- continue
1623-
1624- # Otherwise infer it
1614+ # Inferred defaults
16251615 is_required = check_is_required (param , param_type_hint )
16261616 is_array = check_is_array (param_type_hint )
16271617 property_type = check_property_type (param_type_hint , is_array )
16281618
1629- tool_properties . append ( {
1619+ property_data = {
16301620 "propertyName" : param_name ,
16311621 "propertyType" : property_type ,
16321622 "description" : "" ,
16331623 "isArray" : is_array ,
16341624 "isRequired" : is_required
1635- })
1625+ }
1626+
1627+ # Merge in any explicit overrides
1628+ if param_name in explicit_properties :
1629+ overrides = explicit_properties [param_name ]
1630+ for key , value in overrides .items ():
1631+ if value is not None :
1632+ property_data [key ] = value
1633+
1634+ tool_properties .append (property_data )
16361635
16371636 tool_properties_json = json .dumps (tool_properties )
16381637
@@ -1682,39 +1681,46 @@ async def wrapper(context: str, *args, **kwargs):
16821681 return decorator
16831682
16841683 def mcp_tool_property (self , arg_name : str ,
1685- description : Optional [str ] = "" ,
1686- property_type : Optional [str ] = None ,
1687- is_required : Optional [bool ] = True ,
1688- is_array : Optional [bool ] = False ):
1684+ description : Optional [str ] = None ,
1685+ property_type : Optional [McpPropertyType ] = None ,
1686+ is_required : Optional [bool ] = True ,
1687+ is_array : Optional [bool ] = False ):
16891688 """
16901689 Decorator for defining explicit MCP tool property metadata for a specific argument.
16911690
1691+ :param arg_name: The name of the argument.
1692+ :param description: The description of the argument.
1693+ :param property_type: The type of the argument.
1694+ :param is_required: If the argument is required or not.
1695+ :param is_array: If the argument is array or not.
1696+
1697+ :return: Decorator function.
1698+
16921699 Example:
16931700 @app.mcp_tool_property(
16941701 arg_name="snippetname",
16951702 description="The name of the snippet.",
1696- property_type="string" ,
1703+ property_type=func.McpPropertyType.STRING ,
16971704 is_required=True,
16981705 is_array=False
16991706 )
17001707 """
17011708 def decorator (func ):
1702- # If this function is already wrapped by FunctionBuilder or similar, unwrap it
1709+ # If this function is already wrapped by FunctionBuilder or similar, unwrap it
17031710 target_func = getattr (func , "_function" , func )
17041711 target_func = getattr (target_func , "_func" , target_func )
17051712
17061713 existing = getattr (target_func , "__mcp_tool_properties__" , {})
17071714 existing [arg_name ] = {
1708- "description" : description or "" ,
1709- "propertyType" : property_type or "string" ,
1715+ "description" : description ,
1716+ "propertyType" : property_type . value if property_type else None , # Get enum value
17101717 "isRequired" : is_required ,
17111718 "isArray" : is_array ,
17121719 }
17131720 setattr (target_func , "__mcp_tool_properties__" , existing )
17141721 return func
17151722 return decorator
17161723
1717-
17181724 def dapr_service_invocation_trigger (self ,
17191725 arg_name : str ,
17201726 method_name : str ,
0 commit comments