Skip to content

Commit e73c6aa

Browse files
authored
build: update MCP decorator API spec (#311)
* update mcp & openai api spec * fix tests
1 parent 3024820 commit e73c6aa

8 files changed

Lines changed: 120 additions & 123 deletions

File tree

azure/functions/decorators/function_app.py

Lines changed: 62 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@
4242
parse_iterable_param_to_enums, StringifyEnumJsonEncoder
4343
from azure.functions.http import HttpRequest
4444
from .generic import GenericInputBinding, GenericTrigger, GenericOutputBinding
45-
from .openai import AssistantSkillTrigger, OpenAIModels, TextCompletionInput, \
46-
AssistantCreateOutput, \
47-
AssistantQueryInput, AssistantPostInput, InputType, EmbeddingsInput, \
45+
from .openai import _AssistantSkillTrigger, OpenAIModels, _TextCompletionInput, \
46+
_AssistantCreateOutput, \
47+
_AssistantQueryInput, _AssistantPostInput, InputType, _EmbeddingsInput, \
4848
semantic_search_system_prompt, \
49-
SemanticSearchInput, EmbeddingsStoreOutput
50-
from .mcp import MCPToolTrigger, build_property_metadata
49+
_SemanticSearchInput, _EmbeddingsStoreOutput
50+
from .mcp import _MCPToolTrigger, build_property_metadata
5151
from .retry_policy import RetryPolicy
5252
from .function_name import FunctionName
5353
from .warmup import WarmUpTrigger
@@ -1533,8 +1533,7 @@ def mcp_tool_trigger(self,
15331533
tool_properties: Optional[str] = None,
15341534
data_type: Optional[Union[DataType, str]] = None,
15351535
**kwargs) -> Callable[..., Any]:
1536-
"""
1537-
The `mcp_tool_trigger` decorator adds :class:`MCPToolTrigger` to the
1536+
"""The `mcp_tool_trigger` decorator adds :class:`MCPToolTrigger` to the
15381537
:class:`FunctionBuilder` object for building a :class:`Function` object
15391538
used in the worker function indexing model.
15401539
@@ -1563,7 +1562,7 @@ def mcp_tool_trigger(self,
15631562
def wrap(fb):
15641563
def decorator():
15651564
fb.add_trigger(
1566-
trigger=MCPToolTrigger(
1565+
trigger=_MCPToolTrigger(
15671566
name=arg_name,
15681567
tool_name=tool_name,
15691568
description=description,
@@ -1578,12 +1577,12 @@ def decorator():
15781577
return wrap
15791578

15801579
def mcp_tool(self):
1581-
"""
1582-
Decorator to register an MCP tool function.
1580+
"""Decorator to register an MCP tool function.
1581+
Ref: https://aka.ms/remote-mcp-functions-python
15831582
1584-
Automatically:
1583+
This decorator performs the following actions automatically:
15851584
- Infers tool name from function name
1586-
- Extracts first line of docstring as description
1585+
- Extracts docstrings as description
15871586
- Extracts parameters and types for tool properties
15881587
- Handles MCPToolContext injection
15891588
"""
@@ -1645,7 +1644,7 @@ async def wrapper(context: str, *args, **kwargs):
16451644

16461645
# Add the MCP trigger
16471646
fb.add_trigger(
1648-
trigger=MCPToolTrigger(
1647+
trigger=_MCPToolTrigger(
16491648
name="context",
16501649
tool_name=tool_name,
16511650
description=description,
@@ -1663,23 +1662,16 @@ def mcp_tool_property(self, arg_name: str,
16631662
as_array: Optional[bool] = False):
16641663
"""
16651664
Decorator for defining explicit MCP tool property metadata for a specific argument.
1665+
Ref: https://aka.ms/remote-mcp-functions-python
16661666
1667-
:param arg_name: The name of the argument.
1668-
:param description: The description of the argument.
1669-
:param property_type: The type of the argument.
1670-
:param is_required: If the argument is required or not.
1671-
:param as_array: If the argument should be passed as an array or not.
1672-
1667+
:param str arg_name: The name of the argument.
1668+
:keyword str description: The description of the argument.
1669+
:keyword property_type: The type of the argument.
1670+
:type property_type:
1671+
~azure.functions.decorators.core.McpPropertyType
1672+
:keyword bool is_required: If the argument is required or not.
1673+
:keyword bool as_array: If the argument should be passed as an array or not.
16731674
:return: Decorator function.
1674-
1675-
Example:
1676-
@app.mcp_tool_property(
1677-
arg_name="snippetname",
1678-
description="The name of the snippet.",
1679-
property_type=func.McpPropertyType.STRING,
1680-
is_required=True,
1681-
as_array=False
1682-
)
16831675
"""
16841676
def decorator(func):
16851677
# If this function is already wrapped by FunctionBuilder or similar, unwrap it
@@ -1859,43 +1851,44 @@ def assistant_skill_trigger(self,
18591851
data_type: Optional[
18601852
Union[DataType, str]] = None,
18611853
**kwargs: Any) -> Callable[..., Any]:
1862-
"""
1863-
Assistants build on top of chat functionality by supporting custom skills
1854+
"""Assistants build on top of chat functionality by supporting custom skills
18641855
defined as functions. This internally uses OpenAI’s function calling
18651856
capabilities in GPT models to determine which functions to invoke and when.
18661857
18671858
Ref: https://platform.openai.com/docs/guides/function-calling
18681859
18691860
You can define functions to be triggered by assistants using the
1870-
`assistantSkillTrigger` trigger binding. These functions are invoked by the
1861+
assistantSkillTrigger trigger binding. These functions are invoked by the
18711862
extension when an assistant signals it would like to invoke a function in
18721863
response to a user prompt.
18731864
18741865
The function name, its description (provided via the trigger), and the
18751866
parameter descriptions are all used as hints by the language model to
18761867
determine when and how to invoke an assistant function.
18771868
1878-
:param arg_name: The name of the trigger parameter in the function code.
1879-
:param function_description: A description of the assistant function,
1869+
:param str arg_name: The name of the trigger parameter in the function code.
1870+
:param str function_description: A description of the assistant function,
18801871
which is provided to the model.
1881-
:param function_name: The name of the assistant function, which is
1872+
:keyword str function_name: The name of the assistant function, which is
18821873
passed to the language model.
1883-
:param parameter_description_json: A JSON-formatted description of the
1874+
:keyword str parameter_description_json: A JSON-formatted description of the
18841875
function parameters, provided to the model.
18851876
If omitted, the description is autogenerated.
1886-
:param data_type: Defines how the Functions runtime should treat the
1877+
:keyword data_type: Defines how the Functions runtime should treat the
18871878
parameter value.
1888-
:param kwargs: Additional keyword arguments for specifying binding fields
1879+
:type data_type:
1880+
~azure.functions.decorators.core.DataType or
1881+
str or None
1882+
:keyword kwargs: Additional keyword arguments for specifying binding fields
18891883
to include in the `function.json`.
1890-
18911884
:return: Decorator function.
18921885
"""
18931886

18941887
@self._configure_function_builder
18951888
def wrap(fb):
18961889
def decorator():
18971890
fb.add_trigger(
1898-
trigger=AssistantSkillTrigger(
1891+
trigger=_AssistantSkillTrigger(
18991892
name=arg_name,
19001893
function_description=function_description,
19011894
function_name=function_name,
@@ -3413,7 +3406,7 @@ def text_completion_input(self,
34133406
def wrap(fb):
34143407
def decorator():
34153408
fb.add_binding(
3416-
binding=TextCompletionInput(
3409+
binding=_TextCompletionInput(
34173410
name=arg_name,
34183411
prompt=prompt,
34193412
ai_connection_name=ai_connection_name,
@@ -3436,22 +3429,24 @@ def assistant_create_output(self, arg_name: str,
34363429
Union[DataType, str]] = None,
34373430
**kwargs) \
34383431
-> Callable[..., Any]:
3439-
"""
3440-
The `assistantCreate` output binding creates a new assistant with a specified system prompt.
3441-
3442-
:param arg_name: The name of the binding parameter in the function code.
3443-
:param data_type: Defines how the Functions runtime should treat the parameter value.
3444-
:param kwargs: Additional keyword arguments for specifying extra binding fields
3432+
"""The assistantCreate output binding creates a new assistant with a specified system
3433+
prompt.
3434+
3435+
:param str arg_name: The name of the binding parameter in the function code.
3436+
:keyword data_type: Defines how the Functions runtime should treat the parameter value.
3437+
:type data_type:
3438+
~azure.functions.decorators.core.DataType or
3439+
str or None
3440+
:keyword kwargs: Additional keyword arguments for specifying extra binding fields
34453441
to include in the `function.json`.
3446-
34473442
:return: Decorator function.
34483443
"""
34493444

34503445
@self._configure_function_builder
34513446
def wrap(fb):
34523447
def decorator():
34533448
fb.add_binding(
3454-
binding=AssistantCreateOutput(
3449+
binding=_AssistantCreateOutput(
34553450
name=arg_name,
34563451
data_type=parse_singular_param_to_enum(data_type,
34573452
DataType),
@@ -3472,27 +3467,29 @@ def assistant_query_input(self,
34723467
Union[DataType, str]] = None,
34733468
**kwargs) \
34743469
-> Callable[..., Any]:
3475-
"""
3476-
The `assistantQuery` input binding retrieves assistant chat history and
3470+
"""The `assistantQuery` input binding retrieves assistant chat history and
34773471
passes it to the function.
34783472
34793473
This is typically used to provide the function access to previous messages
34803474
in a conversation, enabling more context-aware responses.
34813475
3482-
:param arg_name: The name of the binding parameter in the function code.
3483-
:param timestamp_utc: The earliest timestamp (in UTC) for the messages to
3476+
:param str arg_name: The name of the binding parameter in the function code.
3477+
:param str id: The unique identifier of the assistant whose history is being
3478+
queried.
3479+
:param str timestamp_utc: The earliest timestamp (in UTC) for the messages to
34843480
retrieve from the chat history. Must be in ISO 8601 format, e.g.,
34853481
`"2023-08-01T00:00:00Z"`.
3486-
:param chat_storage_connection_setting: The name of the configuration section
3482+
:keyword str chat_storage_connection_setting: The name of the configuration section
34873483
containing the connection settings for assistant chat storage. Defaults to
3488-
`"AzureWebJobsStorage"`.
3489-
:param collection_name: The name of the table or collection used for assistant
3490-
chat storage. Defaults to `"ChatState"`.
3491-
:param id: The unique identifier of the assistant whose history is being
3492-
queried.
3493-
:param data_type: Defines how the Functions runtime should treat the
3484+
"AzureWebJobsStorage".
3485+
:keyword str collection_name: The name of the table or collection used for assistant
3486+
chat storage. Defaults to "ChatState".
3487+
:keyword data_type: Defines how the Functions runtime should treat the
34943488
parameter value.
3495-
:param kwargs: Additional keyword arguments for specifying binding fields to
3489+
:type data_type:
3490+
~azure.functions.decorators.core.DataType or
3491+
str or None
3492+
:keyword kwargs: Additional keyword arguments for specifying binding fields to
34963493
include in the `function.json`.
34973494
34983495
:return: Decorator function.
@@ -3502,7 +3499,7 @@ def assistant_query_input(self,
35023499
def wrap(fb):
35033500
def decorator():
35043501
fb.add_binding(
3505-
binding=AssistantQueryInput(
3502+
binding=_AssistantQueryInput(
35063503
name=arg_name,
35073504
id=id,
35083505
timestamp_utc=timestamp_utc,
@@ -3580,7 +3577,7 @@ def assistant_post_input(self, arg_name: str,
35803577
def wrap(fb):
35813578
def decorator():
35823579
fb.add_binding(
3583-
binding=AssistantPostInput(
3580+
binding=_AssistantPostInput(
35843581
name=arg_name,
35853582
id=id,
35863583
user_message=user_message,
@@ -3654,7 +3651,7 @@ def embeddings_input(self,
36543651
def wrap(fb):
36553652
def decorator():
36563653
fb.add_binding(
3657-
binding=EmbeddingsInput(
3654+
binding=_EmbeddingsInput(
36583655
name=arg_name,
36593656
input=input,
36603657
input_type=input_type,
@@ -3746,7 +3743,7 @@ def semantic_search_input(self,
37463743
def wrap(fb):
37473744
def decorator():
37483745
fb.add_binding(
3749-
binding=SemanticSearchInput(
3746+
binding=_SemanticSearchInput(
37503747
name=arg_name,
37513748
search_connection_name=search_connection_name,
37523749
collection=collection,
@@ -3829,7 +3826,7 @@ def embeddings_store_output(self,
38293826
def wrap(fb):
38303827
def decorator():
38313828
fb.add_binding(
3832-
binding=EmbeddingsStoreOutput(
3829+
binding=_EmbeddingsStoreOutput(
38333830
name=arg_name,
38343831
input=input,
38353832
input_type=input_type,

azure/functions/decorators/mcp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
}
2323

2424

25-
class MCPToolTrigger(Trigger):
25+
class _MCPToolTrigger(Trigger):
2626

2727
@staticmethod
2828
def get_binding_name() -> str:

azure/functions/decorators/openai.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class OpenAIModels(StringifyEnum):
2323
DefaultEmbeddingsModel = "text-embedding-ada-002"
2424

2525

26-
class AssistantSkillTrigger(Trigger):
26+
class _AssistantSkillTrigger(Trigger):
2727

2828
@staticmethod
2929
def get_binding_name() -> str:
@@ -42,7 +42,7 @@ def __init__(self,
4242
super().__init__(name=name, data_type=data_type)
4343

4444

45-
class TextCompletionInput(InputBinding):
45+
class _TextCompletionInput(InputBinding):
4646

4747
@staticmethod
4848
def get_binding_name() -> str:
@@ -71,7 +71,7 @@ def __init__(self,
7171
super().__init__(name=name, data_type=data_type)
7272

7373

74-
class AssistantQueryInput(InputBinding):
74+
class _AssistantQueryInput(InputBinding):
7575

7676
@staticmethod
7777
def get_binding_name():
@@ -92,7 +92,7 @@ def __init__(self,
9292
super().__init__(name=name, data_type=data_type)
9393

9494

95-
class EmbeddingsInput(InputBinding):
95+
class _EmbeddingsInput(InputBinding):
9696

9797
@staticmethod
9898
def get_binding_name() -> str:
@@ -137,7 +137,7 @@ def __init__(self,
137137
to the end of your answer on a separate line."""
138138

139139

140-
class SemanticSearchInput(InputBinding):
140+
class _SemanticSearchInput(InputBinding):
141141

142142
@staticmethod
143143
def get_binding_name() -> str:
@@ -179,7 +179,7 @@ def __init__(self,
179179
super().__init__(name=name, data_type=data_type)
180180

181181

182-
class AssistantPostInput(InputBinding):
182+
class _AssistantPostInput(InputBinding):
183183

184184
@staticmethod
185185
def get_binding_name():
@@ -214,7 +214,7 @@ def __init__(self, name: str,
214214
super().__init__(name=name, data_type=data_type)
215215

216216

217-
class EmbeddingsStoreOutput(OutputBinding):
217+
class _EmbeddingsStoreOutput(OutputBinding):
218218

219219
@staticmethod
220220
def get_binding_name() -> str:
@@ -246,7 +246,7 @@ def __init__(self,
246246
super().__init__(name=name, data_type=data_type)
247247

248248

249-
class AssistantCreateOutput(OutputBinding):
249+
class _AssistantCreateOutput(OutputBinding):
250250

251251
@staticmethod
252252
def get_binding_name():

azure/functions/mcp.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ class MCPToolContext(typing.Dict[str, typing.Any]):
1212
pass
1313

1414

15-
class MCPToolTriggerConverter(meta.InConverter, binding='mcpToolTrigger',
16-
trigger=True):
15+
class _MCPToolTriggerConverter(meta.InConverter, binding='mcpToolTrigger',
16+
trigger=True):
1717

1818
@classmethod
1919
def check_input_type_annotation(cls, pytype: type) -> bool:

eng/templates/official/jobs/publish-release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ jobs:
145145
146146
# Modify SDK Version in pyproject.toml
147147
Write-Host "Replacing SDK version in worker's pyproject.toml"
148-
((Get-Content workers/pyproject.toml) -replace '"azure-functions==(\d)+.(\d)+.*"','"azure-functions==$(NewLibraryVersion)"' -join "`n") + "`n" | Set-Content -NoNewline workers/pyproject.toml
148+
((Get-Content workers/pyproject.toml) -replace '"azure-functions==[\d\.a-z]+; python_version >= ''3\.10''"','"azure-functions==$(NewLibraryVersion); python_version >= ''3.10''"' -join "`n") + "`n" | Set-Content -NoNewline workers/pyproject.toml
149149
150150
# Commit Python Version
151151
Write-Host "Pushing $newBranch to azure-functions-python-worker repo"

0 commit comments

Comments
 (0)