Skip to content

Commit 6fc9c44

Browse files
JesuTerrazJesus Terrazas
andauthored
Add User-Agent Header Usage (#88)
* Add User-Agent header to list servers call and to server calls * format --------- Co-authored-by: Jesus Terrazas <[email protected]>
1 parent 03dc279 commit 6fc9c44

File tree

9 files changed

+83
-13
lines changed

9 files changed

+83
-13
lines changed

libraries/microsoft-agents-a365-runtime/microsoft_agents_a365/runtime/utility.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def resolve_agent_identity(context: Any, auth_token: Optional[str]) -> str:
8686
return Utility.get_app_id_from_token(auth_token)
8787

8888
@staticmethod
89-
def get_user_agent_header(orchestrator: str = "") -> str:
89+
def get_user_agent_header(orchestrator: Optional[str] = None) -> str:
9090
"""
9191
Generates a User-Agent header string for SDK requests.
9292

libraries/microsoft-agents-a365-tooling-extensions-agentframework/microsoft_agents_a365/tooling/extensions/agentframework/services/mcp_tool_registration_service.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from microsoft_agents_a365.tooling.services.mcp_tool_server_configuration_service import (
1414
McpToolServerConfigurationService,
1515
)
16+
from microsoft_agents_a365.tooling.models import ToolOptions
1617
from microsoft_agents_a365.tooling.utils.constants import Constants
1718

1819
from microsoft_agents_a365.tooling.utils.utility import (
@@ -28,6 +29,8 @@ class McpToolRegistrationService:
2829
tool servers with Agent Framework agents.
2930
"""
3031

32+
_orchestrator_name: str = "AgentFramework"
33+
3134
def __init__(self, logger: Optional[logging.Logger] = None):
3235
"""
3336
Initialize the MCP Tool Registration Service for Agent Framework.
@@ -77,10 +80,13 @@ async def add_tool_servers_to_agent(
7780

7881
self._logger.info(f"Listing MCP tool servers for agent {agentic_app_id}")
7982

83+
options = ToolOptions(orchestrator_name=self._orchestrator_name)
84+
8085
# Get MCP server configurations
8186
server_configs = await self._mcp_server_configuration_service.list_tool_servers(
8287
agentic_app_id=agentic_app_id,
8388
auth_token=auth_token,
89+
options=options,
8490
)
8591

8692
self._logger.info(f"Loaded {len(server_configs)} MCP server configurations")
@@ -105,6 +111,10 @@ async def add_tool_servers_to_agent(
105111
f"{Constants.Headers.BEARER_PREFIX} {auth_token}"
106112
)
107113

114+
headers[Constants.Headers.USER_AGENT] = Utility.get_user_agent_header(
115+
self._orchestrator_name
116+
)
117+
108118
server_name = getattr(config, "mcp_server_name", "Unknown")
109119

110120
# Create and configure MCPStreamableHTTPTool

libraries/microsoft-agents-a365-tooling-extensions-azureaifoundry/microsoft_agents_a365/tooling/extensions/azureaifoundry/services/mcp_tool_registration_service.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from microsoft_agents_a365.tooling.services.mcp_tool_server_configuration_service import (
2222
McpToolServerConfigurationService,
2323
)
24+
from microsoft_agents_a365.tooling.models import ToolOptions
2425
from microsoft_agents_a365.tooling.utils.constants import Constants
2526
from microsoft_agents_a365.tooling.utils.utility import get_mcp_platform_authentication_scope
2627

@@ -45,6 +46,8 @@ class McpToolRegistrationService:
4546
>>> service.add_tool_servers_to_agent(project_client, agent_id, token)
4647
"""
4748

49+
_orchestrator_name: str = "AzureAIFoundry"
50+
4851
def __init__(
4952
self,
5053
logger: Optional[logging.Logger] = None,
@@ -139,9 +142,10 @@ async def _get_mcp_tool_definitions_and_resources(
139142
return ([], None)
140143

141144
# Get MCP server configurations
145+
options = ToolOptions(orchestrator_name=self._orchestrator_name)
142146
try:
143147
servers = await self._mcp_server_configuration_service.list_tool_servers(
144-
agentic_app_id, auth_token
148+
agentic_app_id, auth_token, options
145149
)
146150
except Exception as ex:
147151
self._logger.error(
@@ -189,6 +193,10 @@ async def _get_mcp_tool_definitions_and_resources(
189193
)
190194
mcp_tool.update_headers(Constants.Headers.AUTHORIZATION, header_value)
191195

196+
mcp_tool.update_headers(
197+
Constants.Headers.USER_AGENT, Utility.get_user_agent_header(self._orchestrator_name)
198+
)
199+
192200
# Add to collections
193201
tool_definitions.extend(mcp_tool.definitions)
194202
if mcp_tool.resources and mcp_tool.resources.mcp:

libraries/microsoft-agents-a365-tooling-extensions-openai/microsoft_agents_a365/tooling/extensions/openai/mcp_tool_registration_service.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
McpToolServerConfigurationService,
1818
)
1919

20+
from microsoft_agents_a365.tooling.models import ToolOptions
21+
from microsoft_agents_a365.tooling.utils.constants import Constants
2022
from microsoft_agents_a365.tooling.utils.utility import (
2123
get_mcp_platform_authentication_scope,
2224
)
@@ -38,6 +40,8 @@ class MCPServerInfo:
3840
class McpToolRegistrationService:
3941
"""Service for managing MCP tools and servers for an agent"""
4042

43+
_orchestrator_name: str = "OpenAI"
44+
4145
def __init__(self, logger: Optional[logging.Logger] = None):
4246
"""
4347
Initialize the MCP Tool Registration Service for OpenAI.
@@ -83,11 +87,13 @@ async def add_tool_servers_to_agent(
8387
# mcp_server_configs = []
8488
# TODO: radevika: Update once the common project is merged.
8589

90+
options = ToolOptions(orchestrator_name=self._orchestrator_name)
8691
agentic_app_id = Utility.resolve_agent_identity(context, auth_token)
8792
self._logger.info(f"Listing MCP tool servers for agent {agentic_app_id}")
8893
mcp_server_configs = await self.config_service.list_tool_servers(
8994
agentic_app_id=agentic_app_id,
9095
auth_token=auth_token,
96+
options=options,
9197
)
9298

9399
self._logger.info(f"Loaded {len(mcp_server_configs)} MCP server configurations")
@@ -132,7 +138,13 @@ async def add_tool_servers_to_agent(
132138
# Prepare headers with authorization
133139
headers = si.headers or {}
134140
if auth_token:
135-
headers["Authorization"] = f"Bearer {auth_token}"
141+
headers[Constants.Headers.AUTHORIZATION] = (
142+
f"{Constants.Headers.BEARER_PREFIX} {auth_token}"
143+
)
144+
145+
headers[Constants.Headers.USER_AGENT] = Utility.get_user_agent_header(
146+
self._orchestrator_name
147+
)
136148

137149
# Create MCPServerStreamableHttpParams with proper configuration
138150
params = MCPServerStreamableHttpParams(url=si.url, headers=headers)

libraries/microsoft-agents-a365-tooling-extensions-semantickernel/microsoft_agents_a365/tooling/extensions/semantickernel/services/mcp_tool_registration_service.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from microsoft_agents_a365.tooling.services.mcp_tool_server_configuration_service import (
2121
McpToolServerConfigurationService,
2222
)
23-
from microsoft_agents_a365.tooling.models.mcp_server_config import MCPServerConfig
23+
from microsoft_agents_a365.tooling.models import MCPServerConfig, ToolOptions
2424
from microsoft_agents_a365.tooling.utils.constants import Constants
2525
from microsoft_agents_a365.tooling.utils.utility import (
2626
get_tools_mode,
@@ -36,6 +36,8 @@ class McpToolRegistrationService:
3636
tool servers with Semantic Kernel agents.
3737
"""
3838

39+
_orchestrator_name: str = "SemanticKernel"
40+
3941
def __init__(
4042
self,
4143
logger: Optional[logging.Logger] = None,
@@ -107,8 +109,9 @@ async def add_tool_servers_to_agent(
107109
self._validate_inputs(kernel, agentic_app_id, auth_token)
108110

109111
# Get and process servers
112+
options = ToolOptions(orchestrator_name=self._orchestrator_name)
110113
servers = await self._mcp_server_configuration_service.list_tool_servers(
111-
agentic_app_id, auth_token
114+
agentic_app_id, auth_token, options
112115
)
113116
self._logger.info(f"🔧 Adding MCP tools from {len(servers)} servers")
114117

@@ -132,6 +135,10 @@ async def add_tool_servers_to_agent(
132135
Constants.Headers.AUTHORIZATION: f"{Constants.Headers.BEARER_PREFIX} {auth_token}",
133136
}
134137

138+
headers[Constants.Headers.USER_AGENT] = Utility.get_user_agent_header(
139+
self._orchestrator_name
140+
)
141+
135142
plugin = MCPStreamableHttpPlugin(
136143
name=server.mcp_server_name,
137144
url=server.mcp_server_unique_name,

libraries/microsoft-agents-a365-tooling/microsoft_agents_a365/tooling/models/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
"""
88

99
from .mcp_server_config import MCPServerConfig
10+
from .tool_options import ToolOptions
1011

11-
__all__ = ["MCPServerConfig"]
12+
__all__ = ["MCPServerConfig", "ToolOptions"]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright (c) Microsoft. All rights reserved.
2+
3+
"""
4+
Tooling Options model.
5+
"""
6+
7+
from dataclasses import dataclass
8+
from typing import Optional
9+
10+
11+
@dataclass
12+
class ToolOptions:
13+
"""Configuration options for tooling operations."""
14+
15+
#: Gets or sets the name of the orchestrator.
16+
orchestrator_name: Optional[str]

libraries/microsoft-agents-a365-tooling/microsoft_agents_a365/tooling/services/mcp_tool_server_configuration_service.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,13 @@
2828
import aiohttp
2929

3030
# Local imports
31-
from ..models import MCPServerConfig
31+
from ..models import MCPServerConfig, ToolOptions
3232
from ..utils import Constants
3333
from ..utils.utility import get_tooling_gateway_for_digital_worker, build_mcp_server_url
3434

35+
# Runtime Imports
36+
from microsoft_agents_a365.runtime.utility import Utility as RuntimeUtility
37+
3538

3639
# ==============================================================================
3740
# MAIN SERVICE CLASS
@@ -66,14 +69,15 @@ def __init__(self, logger: Optional[logging.Logger] = None):
6669
# --------------------------------------------------------------------------
6770

6871
async def list_tool_servers(
69-
self, agentic_app_id: str, auth_token: str
72+
self, agentic_app_id: str, auth_token: str, options: Optional[ToolOptions] = None
7073
) -> List[MCPServerConfig]:
7174
"""
7275
Gets the list of MCP Servers that are configured for the agent.
7376
7477
Args:
7578
agentic_app_id: Agentic App ID for the agent.
7679
auth_token: Authentication token to access the MCP servers.
80+
options: Optional ToolOptions instance containing optional parameters.
7781
7882
Returns:
7983
List[MCPServerConfig]: Returns the list of MCP Servers that are configured.
@@ -85,13 +89,17 @@ async def list_tool_servers(
8589
# Validate input parameters
8690
self._validate_input_parameters(agentic_app_id, auth_token)
8791

92+
# Use default options if none provided
93+
if options is None:
94+
options = ToolOptions(orchestrator_name=None)
95+
8896
self._logger.info(f"Listing MCP tool servers for agent {agentic_app_id}")
8997

9098
# Determine configuration source based on environment
9199
if self._is_development_scenario():
92100
return self._load_servers_from_manifest()
93101
else:
94-
return await self._load_servers_from_gateway(agentic_app_id, auth_token)
102+
return await self._load_servers_from_gateway(agentic_app_id, auth_token, options)
95103

96104
# --------------------------------------------------------------------------
97105
# ENVIRONMENT DETECTION
@@ -275,14 +283,15 @@ def _log_manifest_search_failure(self) -> None:
275283
# --------------------------------------------------------------------------
276284

277285
async def _load_servers_from_gateway(
278-
self, agentic_app_id: str, auth_token: str
286+
self, agentic_app_id: str, auth_token: str, options: ToolOptions
279287
) -> List[MCPServerConfig]:
280288
"""
281289
Reads MCP server configurations from tooling gateway endpoint for production scenario.
282290
283291
Args:
284292
agentic_app_id: Agentic App ID for the agent.
285293
auth_token: Authentication token to access the tooling gateway.
294+
options: ToolOptions instance containing optional parameters.
286295
287296
Returns:
288297
List[MCPServerConfig]: List of MCP server configurations from tooling gateway.
@@ -294,7 +303,7 @@ async def _load_servers_from_gateway(
294303

295304
try:
296305
config_endpoint = get_tooling_gateway_for_digital_worker(agentic_app_id)
297-
headers = self._prepare_gateway_headers(auth_token)
306+
headers = self._prepare_gateway_headers(auth_token, options)
298307

299308
self._logger.info(f"Calling tooling gateway endpoint: {config_endpoint}")
300309

@@ -323,18 +332,22 @@ async def _load_servers_from_gateway(
323332

324333
return mcp_servers
325334

326-
def _prepare_gateway_headers(self, auth_token: str) -> Dict[str, str]:
335+
def _prepare_gateway_headers(self, auth_token: str, options: ToolOptions) -> Dict[str, str]:
327336
"""
328337
Prepares headers for tooling gateway requests.
329338
330339
Args:
331340
auth_token: Authentication token.
341+
options: ToolOptions instance containing optional parameters.
332342
333343
Returns:
334344
Dictionary of HTTP headers.
335345
"""
336346
return {
337-
"Authorization": f"{Constants.Headers.BEARER_PREFIX} {auth_token}",
347+
Constants.Headers.AUTHORIZATION: f"{Constants.Headers.BEARER_PREFIX} {auth_token}",
348+
Constants.Headers.USER_AGENT: RuntimeUtility.get_user_agent_header(
349+
options.orchestrator_name
350+
),
338351
}
339352

340353
async def _parse_gateway_response(

libraries/microsoft-agents-a365-tooling/microsoft_agents_a365/tooling/utils/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ class Headers:
2020

2121
#: The prefix used for Bearer authentication tokens in HTTP headers.
2222
BEARER_PREFIX = "Bearer"
23+
24+
#: The header name for User-Agent information.
25+
USER_AGENT = "User-Agent"

0 commit comments

Comments
 (0)