microsoft-agents-a365-tooling-extensions-semantickernel 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+
4
+ """
5
+ Semantic Kernel extensions for Microsoft Agent 365 Tooling SDK
6
+
7
+ Tooling and utilities specifically for Semantic Kernel framework integration.
8
+ Provides Semantic Kernel-specific helper utilities.
9
+ """
10
+
11
+ from .services import McpToolRegistrationService
12
+
13
+ __version__ = "1.0.0"
14
+
15
+ __all__ = [
16
+ "McpToolRegistrationService",
17
+ ]
@@ -0,0 +1,14 @@
1
+ # Copyright (c) Microsoft. All rights reserved.
2
+
3
+ """
4
+ Services module for Semantic Kernel tooling.
5
+
6
+ This package contains service implementations for MCP tool registration
7
+ and management within the Semantic Kernel framework.
8
+ """
9
+
10
+ from .mcp_tool_registration_service import McpToolRegistrationService
11
+
12
+ __all__ = [
13
+ "McpToolRegistrationService",
14
+ ]
@@ -0,0 +1,228 @@
1
+ # Copyright (c) Microsoft. All rights reserved.
2
+
3
+ """
4
+ MCP Tool Registration Service implementation for Semantic Kernel.
5
+
6
+ This module provides the concrete implementation of the MCP (Model Context Protocol)
7
+ tool registration service that integrates with Semantic Kernel to add MCP tool
8
+ servers to agents.
9
+ """
10
+
11
+ # Standard library imports
12
+ import logging
13
+ import os
14
+ import re
15
+ from typing import Any, Optional
16
+ from semantic_kernel import kernel as sk
17
+ from semantic_kernel.connectors.mcp import MCPStreamableHttpPlugin
18
+ from microsoft_agents.hosting.core import Authorization, TurnContext
19
+ from microsoft_agents_a365.runtime.utility import Utility
20
+ from microsoft_agents_a365.tooling.services.mcp_tool_server_configuration_service import (
21
+ McpToolServerConfigurationService,
22
+ )
23
+ from microsoft_agents_a365.tooling.models.mcp_server_config import MCPServerConfig
24
+ from microsoft_agents_a365.tooling.utils.constants import Constants
25
+ from microsoft_agents_a365.tooling.utils.utility import (
26
+ get_tools_mode,
27
+ get_mcp_platform_authentication_scope,
28
+ )
29
+
30
+
31
+ class McpToolRegistrationService:
32
+ """
33
+ Provides services related to tools in the Semantic Kernel.
34
+
35
+ This service handles registration and management of MCP (Model Context Protocol)
36
+ tool servers with Semantic Kernel agents.
37
+ """
38
+
39
+ def __init__(
40
+ self,
41
+ logger: Optional[logging.Logger] = None,
42
+ ):
43
+ """
44
+ Initialize the MCP Tool Registration Service for Semantic Kernel.
45
+
46
+ Args:
47
+ logger: Logger instance for logging operations.
48
+ """
49
+ self._logger = logger or logging.getLogger(self.__class__.__name__)
50
+ self._mcp_server_configuration_service = McpToolServerConfigurationService(
51
+ logger=self._logger
52
+ )
53
+
54
+ # Store connected plugins to keep them alive
55
+ self._connected_plugins = []
56
+
57
+ # Enable debug logging if configured
58
+ if os.getenv("MCP_DEBUG_LOGGING", "false").lower() == "true":
59
+ self._logger.setLevel(logging.DEBUG)
60
+
61
+ # Configure strict parameter validation (prevents dynamic property creation)
62
+ self._strict_parameter_validation = (
63
+ os.getenv("MCP_STRICT_PARAMETER_VALIDATION", "true").lower() == "true"
64
+ )
65
+ if self._strict_parameter_validation:
66
+ self._logger.info(
67
+ "๐Ÿ”’ Strict parameter validation enabled - only schema-defined parameters are allowed"
68
+ )
69
+ else:
70
+ self._logger.info(
71
+ "๐Ÿ”“ Strict parameter validation disabled - dynamic parameters are allowed"
72
+ )
73
+
74
+ # ============================================================================
75
+ # Public Methods
76
+ # ============================================================================
77
+
78
+ async def add_tool_servers_to_agent(
79
+ self,
80
+ kernel: sk.Kernel,
81
+ auth: Authorization,
82
+ auth_handler_name: str,
83
+ context: TurnContext,
84
+ auth_token: Optional[str] = None,
85
+ ) -> None:
86
+ """
87
+ Adds the A365 MCP Tool Servers to the specified kernel.
88
+
89
+ Args:
90
+ kernel: The Semantic Kernel instance to which the tools will be added.
91
+ auth: Authorization handler for token exchange.
92
+ auth_handler_name: Name of the authorization handler.
93
+ context: Turn context for the current operation.
94
+ auth_token: Authentication token to access the MCP servers.
95
+
96
+ Raises:
97
+ ValueError: If kernel is None or required parameters are invalid.
98
+ Exception: If there's an error connecting to or configuring MCP servers.
99
+ """
100
+
101
+ if not auth_token:
102
+ scopes = get_mcp_platform_authentication_scope()
103
+ authToken = await auth.exchange_token(context, scopes, auth_handler_name)
104
+ auth_token = authToken.token
105
+
106
+ agentic_app_id = Utility.resolve_agent_identity(context, auth_token)
107
+ self._validate_inputs(kernel, agentic_app_id, auth_token)
108
+
109
+ # Get and process servers
110
+ servers = await self._mcp_server_configuration_service.list_tool_servers(
111
+ agentic_app_id, auth_token
112
+ )
113
+ self._logger.info(f"๐Ÿ”ง Adding MCP tools from {len(servers)} servers")
114
+
115
+ # Get tools mode
116
+ tools_mode = get_tools_mode()
117
+
118
+ # Process each server (matching C# foreach pattern)
119
+ for server in servers:
120
+ try:
121
+ if tools_mode == "HardCodedTools":
122
+ await self._add_hardcoded_tools_for_server(kernel, server)
123
+ continue
124
+
125
+ headers = {}
126
+
127
+ if tools_mode == "MockMCPServer":
128
+ if mock_auth_header := os.getenv("MOCK_MCP_AUTHORIZATION"):
129
+ headers[Constants.Headers.AUTHORIZATION] = mock_auth_header
130
+ else:
131
+ headers = {
132
+ Constants.Headers.AUTHORIZATION: f"{Constants.Headers.BEARER_PREFIX} {auth_token}",
133
+ }
134
+
135
+ plugin = MCPStreamableHttpPlugin(
136
+ name=server.mcp_server_name,
137
+ url=server.mcp_server_unique_name,
138
+ headers=headers or None,
139
+ )
140
+
141
+ # Connect the plugin
142
+ await plugin.connect()
143
+
144
+ # Add plugin to kernel
145
+ kernel.add_plugin(plugin, server.mcp_server_name)
146
+
147
+ # Store reference to keep plugin alive throughout application lifecycle
148
+ # By storing plugin references in _connected_plugins, we prevent Python's garbage collector from cleaning up the plugin objects
149
+ # The connections remain active throughout the application lifecycle
150
+ # Tools can be successfully invoked because their underlying connections are still alive
151
+ self._connected_plugins.append(plugin)
152
+
153
+ self._logger.info(
154
+ f"โœ… Connected and added MCP plugin ({tools_mode}) for: {server.mcp_server_name}"
155
+ )
156
+
157
+ except Exception as e:
158
+ self._logger.error(f"Failed to add tools from {server.mcp_server_name}: {str(e)}")
159
+
160
+ self._logger.info("โœ… Successfully configured MCP tool servers for the agent!")
161
+
162
+ # ============================================================================
163
+ # Private Methods - Input Validation & Processing
164
+ # ============================================================================
165
+
166
+ def _validate_inputs(self, kernel: Any, agentic_app_id: str, auth_token: str) -> None:
167
+ """Validate all required inputs."""
168
+ if kernel is None:
169
+ raise ValueError("kernel cannot be None")
170
+ if not agentic_app_id or not agentic_app_id.strip():
171
+ raise ValueError("agentic_app_id cannot be null or empty")
172
+ if not auth_token or not auth_token.strip():
173
+ raise ValueError("auth_token cannot be null or empty")
174
+
175
+ async def _add_hardcoded_tools_for_server(self, kernel: Any, server: MCPServerConfig) -> None:
176
+ """Add hardcoded tools for a specific server (equivalent to C# hardcoded tool logic)."""
177
+ server_name = server.mcp_server_name
178
+
179
+ if server_name.lower() == "mcp_mailtools":
180
+ # TODO: Implement hardcoded mail tools
181
+ # kernel.plugins.add(KernelPluginFactory.create_from_type(HardCodedMailTools, server.mcp_server_name, self._service_provider))
182
+ self._logger.info(f"Adding hardcoded mail tools for {server_name}")
183
+ elif server_name.lower() == "mcp_sharepointtools":
184
+ # TODO: Implement hardcoded SharePoint tools
185
+ # kernel.plugins.add(KernelPluginFactory.create_from_type(HardCodedSharePointTools, server.mcp_server_name, self._service_provider))
186
+ self._logger.info(f"Adding hardcoded SharePoint tools for {server_name}")
187
+ elif server_name.lower() == "onedrivemcpserver":
188
+ # TODO: Implement hardcoded OneDrive tools
189
+ # kernel.plugins.add(KernelPluginFactory.create_from_type(HardCodedOneDriveTools, server.mcp_server_name, self._service_provider))
190
+ self._logger.info(f"Adding hardcoded OneDrive tools for {server_name}")
191
+ elif server_name.lower() == "wordmcpserver":
192
+ # TODO: Implement hardcoded Word tools
193
+ # kernel.plugins.add(KernelPluginFactory.create_from_type(HardCodedWordTools, server.mcp_server_name, self._service_provider))
194
+ self._logger.info(f"Adding hardcoded Word tools for {server_name}")
195
+ else:
196
+ self._logger.warning(f"No hardcoded tools available for server: {server_name}")
197
+
198
+ # ============================================================================
199
+ # Private Methods - Kernel Function Creation
200
+ # ============================================================================
201
+
202
+ def _get_plugin_name_from_server_name(self, server_name: str) -> str:
203
+ """Generate a clean plugin name from server name."""
204
+ clean_name = re.sub(r"[^a-zA-Z0-9_]", "_", server_name)
205
+ return f"{clean_name}Tools"
206
+
207
+ # ============================================================================
208
+ # Cleanup Methods
209
+ # ============================================================================
210
+
211
+ async def cleanup_connections(self) -> None:
212
+ """Clean up all connected MCP plugins."""
213
+ self._logger.info(f"๐Ÿงน Cleaning up {len(self._connected_plugins)} MCP plugin connections")
214
+
215
+ for plugin in self._connected_plugins:
216
+ try:
217
+ if hasattr(plugin, "close"):
218
+ await plugin.close()
219
+ elif hasattr(plugin, "disconnect"):
220
+ await plugin.disconnect()
221
+ self._logger.debug(
222
+ f"โœ… Closed connection for plugin: {getattr(plugin, 'name', 'unknown')}"
223
+ )
224
+ except Exception as e:
225
+ self._logger.warning(f"โš ๏ธ Error closing plugin connection: {e}")
226
+
227
+ self._connected_plugins.clear()
228
+ self._logger.info("โœ… All MCP plugin connections cleaned up")
@@ -0,0 +1,66 @@
1
+ Metadata-Version: 2.4
2
+ Name: microsoft-agents-a365-tooling-extensions-semantickernel
3
+ Version: 0.1.0
4
+ Summary: Semantic Kernel integration for Agent 365 Tooling SDK
5
+ Author-email: Microsoft <support@microsoft.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/microsoft/Agent365-python
8
+ Project-URL: Repository, https://github.com/microsoft/Agent365-python
9
+ Project-URL: Issues, https://github.com/microsoft/Agent365-python/issues
10
+ Project-URL: Documentation, https://github.com/microsoft/Agent365-python/tree/main/libraries/microsoft-agents-a365-tooling-extensions-semantickernel
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Requires-Python: >=3.11
20
+ Description-Content-Type: text/markdown
21
+ Requires-Dist: microsoft-agents-a365-tooling>=0.0.0
22
+ Requires-Dist: semantic-kernel>=1.0.0
23
+ Requires-Dist: aiohttp>=3.8.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
26
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
27
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
28
+ Requires-Dist: black>=23.0.0; extra == "dev"
29
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
30
+ Provides-Extra: test
31
+ Requires-Dist: pytest>=7.0.0; extra == "test"
32
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
33
+
34
+ # microsoft-agents-a365-tooling-extensions-semantickernel
35
+
36
+ [![PyPI](https://img.shields.io/pypi/v/microsoft-agents-a365-tooling-extensions-semantickernel?label=PyPI&logo=pypi)](https://pypi.org/project/microsoft-agents-a365-tooling-extensions-semantickernel)
37
+ [![PyPI Downloads](https://img.shields.io/pypi/dm/microsoft-agents-a365-tooling-extensions-semantickernel?label=Downloads&logo=pypi)](https://pypi.org/project/microsoft-agents-a365-tooling-extensions-semantickernel)
38
+
39
+ Semantic Kernel specific tools and services for AI agent development. Provides MCP (Model Context Protocol) tool registration service for dynamically adding MCP servers to Semantic Kernel-based agents.
40
+
41
+ ## Installation
42
+
43
+ ```bash
44
+ pip install microsoft-agents-a365-tooling-extensions-semantickernel
45
+ ```
46
+
47
+ ## Usage
48
+
49
+ For usage examples and detailed documentation, see the [Tooling documentation](https://learn.microsoft.com/microsoft-agent-365/developer/tooling?tabs=python) on Microsoft Learn.
50
+
51
+ ## Support
52
+
53
+ For issues, questions, or feedback:
54
+
55
+ - File issues in the [GitHub Issues](https://github.com/microsoft/Agent365-python/issues) section
56
+ - See the [main documentation](../../../README.md) for more information
57
+
58
+ ## Trademarks
59
+
60
+ *Microsoft, Windows, Microsoft Azure and/or other Microsoft products and services referenced in the documentation may be either trademarks or registered trademarks of Microsoft in the United States and/or other countries. The licenses for this project do not grant you rights to use any Microsoft names, logos, or trademarks. Microsoft's general trademark guidelines can be found at http://go.microsoft.com/fwlink/?LinkID=254653.*
61
+
62
+ ## License
63
+
64
+ Copyright (c) Microsoft Corporation. All rights reserved.
65
+
66
+ Licensed under the MIT License - see the [LICENSE](../../../LICENSE.md) file for details.
@@ -0,0 +1,7 @@
1
+ microsoft_agents_a365/tooling/extensions/semantickernel/__init__.py,sha256=IvWvvW3Yajk0vX0Il0zisWbN0F-2EIWBmSpAkTeEETw,398
2
+ microsoft_agents_a365/tooling/extensions/semantickernel/services/__init__.py,sha256=uao2omD_YpBZJFqHuK-Lnk7Hy0d2_3blvZcXWI-1dRg,348
3
+ microsoft_agents_a365/tooling/extensions/semantickernel/services/mcp_tool_registration_service.py,sha256=sxPzkg41K0FjE4UaoAWrYm91_1iYuMGsc1b5BoJ0R5I,10095
4
+ microsoft_agents_a365_tooling_extensions_semantickernel-0.1.0.dist-info/METADATA,sha256=Mgernpqhv7KB3t7r9elYUMCEe4_9SadGV2_dzJd1vFQ,3365
5
+ microsoft_agents_a365_tooling_extensions_semantickernel-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
6
+ microsoft_agents_a365_tooling_extensions_semantickernel-0.1.0.dist-info/top_level.txt,sha256=G3c2_4sy5_EM_BWO67SbK2tKj4G8XFn-QXRbh8g9Lgk,22
7
+ microsoft_agents_a365_tooling_extensions_semantickernel-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+