diff --git a/docs/usage/how-to/cli-mode.mdx b/docs/usage/how-to/cli-mode.mdx index fcba586a57..c4fcca6b4c 100644 --- a/docs/usage/how-to/cli-mode.mdx +++ b/docs/usage/how-to/cli-mode.mdx @@ -20,7 +20,7 @@ for scripting. ### Running with Python -**Note** - OpenHands requires Python version 3.12 or higher (Python 3.14 is not currently supported) +**Note** - OpenHands requires Python version 3.12 or higher (Python 3.14 is not currently supported) and `uvx` for the default `fetch` MCP server (more details below). 1. Install OpenHands using pip: ```bash @@ -186,7 +186,7 @@ To configure Model Context Protocol (MCP) servers, you can refer to the document This command modifies your `~/.openhands/config.toml` file and will prompt you to restart OpenHands for changes to take effect. -To enable the [Tavily MCP server](https://github.com/tavily-ai/tavily-mcp) search engine, you can set the `search_api_key` under the `[core]` section in the `~/.openhands/config.toml` file. +By default, the [Fetch MCP server](https://github.com/modelcontextprotocol/servers/tree/main/src/fetch) will be automatically configured for OpenHands. You can also [enable search engine](../search-engine-setup) via the [Tavily MCP server](https://github.com/tavily-ai/tavily-mcp) by setting the `search_api_key` under the `[core]` section in the `~/.openhands/config.toml` file. ##### Example of the `config.toml` file with MCP server configuration: diff --git a/openhands/cli/main.py b/openhands/cli/main.py index b7c95a7c4f..1038da61ba 100644 --- a/openhands/cli/main.py +++ b/openhands/cli/main.py @@ -49,7 +49,9 @@ from openhands.core.config import ( setup_config_from_args, ) from openhands.core.config.condenser_config import NoOpCondenserConfig -from openhands.core.config.mcp_config import OpenHandsMCPConfigImpl +from openhands.core.config.mcp_config import ( + OpenHandsMCPConfigImpl, +) from openhands.core.config.utils import finalize_config from openhands.core.logger import openhands_logger as logger from openhands.core.loop import run_agent_until_done diff --git a/openhands/mcp/utils.py b/openhands/mcp/utils.py index 391ccfe8f1..4d50c5587b 100644 --- a/openhands/mcp/utils.py +++ b/openhands/mcp/utils.py @@ -1,4 +1,5 @@ import json +import shutil from typing import TYPE_CHECKING if TYPE_CHECKING: @@ -91,6 +92,14 @@ async def create_mcp_clients( for server in servers: if isinstance(server, MCPStdioServerConfig): + # Validate that the command exists before connecting + if not shutil.which(server.command): + logger.error( + f'Skipping MCP stdio server "{server.name}": command "{server.command}" not found. ' + f'Please install {server.command} or remove this server from your configuration.' + ) + continue + logger.info(f'Initializing MCP agent for {server} with stdio connection...') client = MCPClient() try: diff --git a/pyproject.toml b/pyproject.toml index af751c8a30..71f041b094 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,6 +20,7 @@ packages = [ ] include = [ "openhands/integrations/vscode/openhands-vscode-0.0.1.vsix", + "microagents/**/*", ] build = "build_vscode.py" # Build VSCode extension during Poetry build diff --git a/tests/unit/test_mcp_utils.py b/tests/unit/test_mcp_utils.py index 64b346e085..2289842da7 100644 --- a/tests/unit/test_mcp_utils.py +++ b/tests/unit/test_mcp_utils.py @@ -182,7 +182,7 @@ async def test_create_mcp_clients_stdio_success(mock_mcp_client): ), MCPStdioServerConfig( name='test-server-2', - command='/usr/bin/node', + command='node', args=['server2.js'], env={'NODE_ENV': 'development'}, ),