diff --git a/pyproject.toml b/pyproject.toml index 1031cd1..4aee13d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath-mcp" -version = "0.0.97" +version = "0.0.98" description = "UiPath MCP SDK" readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" diff --git a/src/uipath_mcp/_cli/_runtime/_context.py b/src/uipath_mcp/_cli/_runtime/_context.py index 7864334..5c00306 100644 --- a/src/uipath_mcp/_cli/_runtime/_context.py +++ b/src/uipath_mcp/_cli/_runtime/_context.py @@ -11,6 +11,33 @@ class UiPathMcpRuntimeContext(UiPathRuntimeContext): config: Optional[McpConfig] = None folder_key: Optional[str] = None + server_id: Optional[str] = None + server_slug: Optional[str] = None + + @classmethod + def from_config(cls, config_path=None): + """Load configuration from uipath.json file with MCP-specific handling.""" + # Use the parent's implementation + instance = super().from_config(config_path) + + # Convert to our type (since parent returns UiPathRuntimeContext) + mcp_instance = cls(**instance.model_dump()) + + # Add AgentHub-specific configuration handling + import json + import os + + path = config_path or "uipath.json" + if os.path.exists(path): + with open(path, "r") as f: + config = json.load(f) + + if "fpsContext" in config: + fps_context = config["fpsContext"] + mcp_instance.server_id = fps_context.get("Id") + mcp_instance.server_slug = fps_context.get("Slug") + + return mcp_instance class UiPathServerType(Enum): diff --git a/src/uipath_mcp/_cli/_runtime/_runtime.py b/src/uipath_mcp/_cli/_runtime/_runtime.py index 9f1c0ad..c276a3c 100644 --- a/src/uipath_mcp/_cli/_runtime/_runtime.py +++ b/src/uipath_mcp/_cli/_runtime/_runtime.py @@ -96,7 +96,7 @@ async def execute(self) -> Optional[UiPathRuntimeResult]: logger.info(f"Folder key: {self.context.folder_key}") - with tracer.start_as_current_span(self._server.name) as root_span: + with tracer.start_as_current_span(self.slug) as root_span: root_span.set_attribute("runtime_id", self._runtime_id) root_span.set_attribute("command", self._server.command) root_span.set_attribute("args", self._server.args) @@ -257,7 +257,7 @@ async def _handle_signalr_message(self, args: list) -> None: # Check if we have a session server for this session_id if session_id not in self._session_servers: # Create and start a new session server - session_server = SessionServer(self._server, session_id) + session_server = SessionServer(self._server, self.slug, session_id) try: await session_server.start() except Exception as e: @@ -368,8 +368,9 @@ async def _register(self) -> None: try: client_info = { "server": { - "Name": self._server.name, - "Slug": self._server.name, + "Id": self.context.server_id, + "Name": self.slug, + "Slug": self.slug, "Version": "1.0.0", "Type": self.server_type.value, }, @@ -390,7 +391,7 @@ async def _register(self) -> None: # Register with UiPath MCP Server await self._uipath.api_client.request_async( "POST", - f"agenthub_/mcp/{self._server.name}/runtime/start?runtimeId={self._runtime_id}", + f"agenthub_/mcp/{self.slug}/runtime/start?runtimeId={self._runtime_id}", json=client_info, headers={"X-UIPATH-FolderKey": self.context.folder_key}, ) @@ -417,14 +418,14 @@ async def _on_session_start_error(self, session_id: str) -> None: try: response = await self._uipath.api_client.request_async( "POST", - f"agenthub_/mcp/{self._server.name}/out/message?sessionId={session_id}", + f"agenthub_/mcp/{self.slug}/out/message?sessionId={session_id}", json=JSONRPCResponse( jsonrpc="2.0", id=0, result={ "protocolVersion": "initialize-failure", "capabilities": {}, - "serverInfo": {"name": self._server.name, "version": "1.0"}, + "serverInfo": {"name": self.slug, "version": "1.0"}, }, ).model_dump(), ) @@ -496,7 +497,7 @@ async def _on_runtime_abort(self) -> None: try: response = await self._uipath.api_client.request_async( "POST", - f"agenthub_/mcp/{self._server.name}/runtime/abort?runtimeId={self._runtime_id}", + f"agenthub_/mcp/{self.slug}/runtime/abort?runtimeId={self._runtime_id}", ) if response.status_code == 202: logger.info( @@ -536,6 +537,10 @@ def packaged(self) -> bool: and process_key != "00000000-0000-0000-0000-000000000000" ) + @property + def slug(self) -> str: + return self.context.server_slug or self._server.name + @property def server_type(self) -> UiPathServerType: """ diff --git a/src/uipath_mcp/_cli/_runtime/_session.py b/src/uipath_mcp/_cli/_runtime/_session.py index aedc748..e0b97cb 100644 --- a/src/uipath_mcp/_cli/_runtime/_session.py +++ b/src/uipath_mcp/_cli/_runtime/_session.py @@ -28,8 +28,9 @@ class SessionServer: """Manages a server process for a specific session.""" - def __init__(self, server_config: McpServer, session_id: str): + def __init__(self, server_config: McpServer, server_slug: str, session_id: str): self._server_config = server_config + self._server_slug = server_slug self._session_id = session_id self._read_stream = None self._write_stream = None @@ -244,7 +245,7 @@ async def _send_message(self, message: JSONRPCMessage, request_id: str) -> None: message, session_id=self._session_id, request_id=request_id, - server_name=self._server_config.name, + server_name=self._server_slug, ) as _: for attempt in range(MAX_RETRIES + 1): try: @@ -268,7 +269,7 @@ async def _send_message_internal( ) -> None: response = await self._uipath.api_client.request_async( "POST", - f"agenthub_/mcp/{self._server_config.name}/out/message?sessionId={self._session_id}&requestId={request_id}", + f"agenthub_/mcp/{self._server_slug}/out/message?sessionId={self._session_id}&requestId={request_id}", json=message.model_dump(), ) if response.status_code == 202: @@ -279,7 +280,7 @@ async def _send_message_internal( async def _get_messages_internal(self, request_id: str) -> None: response = await self._uipath.api_client.request_async( "GET", - f"agenthub_/mcp/{self._server_config.name}/in/messages?sessionId={self._session_id}&requestId={request_id}", + f"agenthub_/mcp/{self._server_slug}/in/messages?sessionId={self._session_id}&requestId={request_id}", ) if response.status_code == 200: self._last_request_id = request_id @@ -296,7 +297,7 @@ async def _get_messages_internal(self, request_id: str) -> None: json_message, session_id=self._session_id, request_id=request_id, - server_name=self._server_config.name, + server_name=self._server_slug, ) as _: await self._message_queue.put(json_message) elif 500 <= response.status_code < 600: