diff --git a/mcontainer/container.py b/mcontainer/container.py index 71e191f..79e5837 100644 --- a/mcontainer/container.py +++ b/mcontainer/container.py @@ -286,6 +286,7 @@ class ContainerManager: # Process MCPs if provided mcp_configs = [] mcp_names = [] + mcp_container_names = [] # Ensure MCP is a list mcps_to_process = mcp if isinstance(mcp, list) else [] @@ -308,11 +309,10 @@ class ContainerManager: try: print(f"Ensuring MCP server '{mcp_name}' is running...") self.mcp_manager.start_mcp(mcp_name) - - # Add MCP network to the list - mcp_network = self.mcp_manager._ensure_mcp_network() - if mcp_network not in network_list: - network_list.append(mcp_network) + + # Store container name for later network connection + container_name = self.mcp_manager.get_mcp_container_name(mcp_name) + mcp_container_names.append(container_name) # Get MCP status to extract endpoint information mcp_status = self.mcp_manager.get_mcp_status(mcp_name) @@ -356,6 +356,9 @@ class ContainerManager: except Exception as e: print(f"Warning: Failed to start MCP server '{mcp_name}': {e}") + # Remove from the container names list if failed + if container_name in mcp_container_names: + mcp_container_names.remove(container_name) elif mcp_config.get("type") == "remote": # For remote MCP, just set environment variables @@ -435,13 +438,33 @@ class ContainerManager: ) except DockerException as e: print(f"Error connecting to network {network_name}: {e}") + + # Reload the container to get updated network information + container.reload() + + # Connect directly to each MCP's dedicated network + for mcp_name in mcp_names: + try: + # Get the dedicated network for this MCP + dedicated_network_name = f"mc-mcp-{mcp_name}-network" + + try: + network = self.client.networks.get(dedicated_network_name) + + # Connect the session container to the MCP's dedicated network + network.connect(container, aliases=[session_name]) + print(f"Connected session to MCP '{mcp_name}' via dedicated network: {dedicated_network_name}") + except DockerException as e: + print(f"Error connecting to MCP dedicated network '{dedicated_network_name}': {e}") + + except Exception as e: + print(f"Error connecting session to MCP '{mcp_name}': {e}") # Connect to additional user-specified networks if networks: for network_name in networks: - if ( - network_name not in network_list - ): # Avoid connecting to the same network twice + # Check if already connected to this network + if network_name not in [net.name for net in container.attrs.get("NetworkSettings", {}).get("Networks", {}).values()]: try: # Get or create the network try: diff --git a/mcontainer/mcp.py b/mcontainer/mcp.py index 087d801..16160fc 100644 --- a/mcontainer/mcp.py +++ b/mcontainer/mcp.py @@ -34,13 +34,31 @@ class MCPManager: self.client = None def _ensure_mcp_network(self) -> str: - """Ensure the MCP network exists and return its name.""" + """Ensure the MCP network exists and return its name. + Note: This is used only by the inspector, not for session-to-MCP connections. + """ network_name = "mc-mcp-network" if self.client: networks = self.client.networks.list(names=[network_name]) if not networks: self.client.networks.create(network_name, driver="bridge") return network_name + + def _get_mcp_dedicated_network(self, mcp_name: str) -> str: + """Get or create a dedicated network for direct session-to-MCP connections. + + Args: + mcp_name: The name of the MCP server + + Returns: + The name of the dedicated network + """ + network_name = f"mc-mcp-{mcp_name}-network" + if self.client: + networks = self.client.networks.list(names=[network_name]) + if not networks: + self.client.networks.create(network_name, driver="bridge") + return network_name def list_mcps(self) -> List[Dict[str, Any]]: """List all configured MCP servers.""" @@ -279,11 +297,23 @@ class MCPManager: }, ) - # Connect to the network with aliases + # Connect to the inspector network network = self.client.networks.get(network_name) network.connect(container, aliases=[name]) logger.info( - f"Connected MCP server '{name}' to network {network_name} with alias '{name}'" + f"Connected MCP server '{name}' to inspector network {network_name} with alias '{name}'" + ) + + # Create and connect to a dedicated network for session connections + dedicated_network_name = self._get_mcp_dedicated_network(name) + try: + dedicated_network = self.client.networks.get(dedicated_network_name) + except DockerException: + dedicated_network = self.client.networks.create(dedicated_network_name, driver="bridge") + + dedicated_network.connect(container, aliases=[name]) + logger.info( + f"Connected MCP server '{name}' to dedicated network {dedicated_network_name} with alias '{name}'" ) return { @@ -442,11 +472,23 @@ ENTRYPOINT ["/entrypoint.sh"] ports=port_bindings, # Bind the SSE port to the host if configured ) - # Connect to the network with aliases + # Connect to the inspector network network = self.client.networks.get(network_name) network.connect(container, aliases=[name]) logger.info( - f"Connected MCP server '{name}' to network {network_name} with alias '{name}'" + f"Connected MCP server '{name}' to inspector network {network_name} with alias '{name}'" + ) + + # Create and connect to a dedicated network for session connections + dedicated_network_name = self._get_mcp_dedicated_network(name) + try: + dedicated_network = self.client.networks.get(dedicated_network_name) + except DockerException: + dedicated_network = self.client.networks.create(dedicated_network_name, driver="bridge") + + dedicated_network.connect(container, aliases=[name]) + logger.info( + f"Connected MCP server '{name}' to dedicated network {dedicated_network_name} with alias '{name}'" ) return {