diff --git a/.gitignore b/.gitignore index 203fae4..f16fa57 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,9 @@ build/ # uv uv.lock +# Agent instructions +AGENTS.md + # IDE .idea/ .vscode/ diff --git a/.python-version b/.python-version deleted file mode 100644 index 2c07333..0000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.11 diff --git a/README.md b/README.md index 409a037..0ccaea4 100644 --- a/README.md +++ b/README.md @@ -181,6 +181,37 @@ docker run -d --name open-terminal -p 8000:8000 \ Each user automatically gets a dedicated Linux account with its own home directory. Files, commands, and terminals are isolated between users via standard Unix permissions. +## MCP Server + +Open Terminal ships with an [MCP](https://modelcontextprotocol.io) server that exposes every API endpoint as an MCP tool. Install the optional dependency first: + +```bash +pip install -e ".[mcp]" +``` + +### streamable-http (remote) + +To run the MCP server as a network service and connect from another machine: + +```bash +open-terminal mcp --transport streamable-http --host 0.0.0.0 --port 8000 --api-key your-secret-key +``` + +Then connect from VS Code `mcp.json`: + +```json +{ + "servers": { + "open-terminal": { + "url": "http://:8000/mcp", + "type": "http" + } + } +} +``` + +The `--api-key` flag (or `OPEN_TERMINAL_API_KEY` env var, or `api_key` in a config file) is required — it is used for both the MCP server and the underlying REST API. + ## API Docs Full interactive API documentation is available at [http://localhost:8000/docs](http://localhost:8000/docs) once your instance is running. diff --git a/open_terminal/cli.py b/open_terminal/cli.py index 15adb15..4911856 100644 --- a/open_terminal/cli.py +++ b/open_terminal/cli.py @@ -156,12 +156,19 @@ def run( default=None, help="Working directory for the server process.", ) +@click.option( + "--api-key", + default="", + envvar="OPEN_TERMINAL_API_KEY", + help="Bearer API key (or set OPEN_TERMINAL_API_KEY env var)", +) def mcp( transport: str, host: str | None, port: int | None, config_path: str | None, cwd: str | None, + api_key: str, ): """Start the MCP server (requires 'pip install open-terminal[mcp]').""" from open_terminal import config @@ -174,6 +181,19 @@ def mcp( if cwd: os.chdir(cwd) + # Resolve API key: CLI flag > env var > Docker secret file > config file. + # Must be set in os.environ BEFORE importing mcp_server so that env.py + # picks it up at module-import time (it captures API_KEY at import). + if not api_key: + file_path = os.environ.get("OPEN_TERMINAL_API_KEY_FILE") + if file_path: + with open(file_path) as f: + api_key = f.read().strip() + if not api_key: + api_key = cfg.get("api_key", "") + if api_key: + os.environ["OPEN_TERMINAL_API_KEY"] = api_key + try: from open_terminal.mcp_server import mcp as mcp_server except ImportError: