diff --git a/docs/architecture.md b/docs/architecture.md
index 6b2f052a..57499347 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -54,3 +54,82 @@ graph TB
style Row1 fill:none,stroke:none
style Row2 fill:none,stroke:none
```
+
+## Where Each Component Runs
+
+Understanding where the **client**, **MCP server**, and **target Linux system** run is helpful for deployment and development alike.
+
+| Component | Location | Description |
+|-----------|----------|-------------|
+| **Client** | User's machine | The MCP client (Cursor, Claude Desktop, Goose, etc.) runs on the machine where the user works. It spawns the Linux MCP Server as a **subprocess** and communicates over **stdio** (stdin/stdout) using the MCP protocol (JSON-RPC). |
+| **MCP Server** | Same host as client, or in a container | The server process is started by the client (e.g. `linux-mcp-server` or `podman run ... linux-mcp-server`). With a native install it runs on the **same machine as the client**. With a container deploy it runs **inside the container** on that same machine. In both cases the server receives tool calls over stdio and performs command execution. |
+| **Target Linux system** | Same host as client, or any host reachable via SSH | Commands are executed either **locally** on the same host where the MCP server is running (subprocess or container), or **remotely** on another machine. Remote execution is done by the server opening an **SSH connection from the server host to the target host** and running commands there. The client never talks to the target directly. |
+
+This means:
+
+- **Client ↔ Server**: Communication is **always** over stdio, using the MCP JSON-RPC protocol. The client does not connect to the target directly.
+- **Server ↔ Target**: If `host` is omitted, execution is **local** (same host as the server). If `host` is set, the server **SSHs from its own host** to that host to run commands.
+- **Containers**: When the server runs in a container, “local” means inside the container. Local execution can be disabled via the `disallow_local_execution_in_containers` decorator (tools then require a `host` parameter for remote SSH).
+
+## Detailed Tool Call Flow
+
+End-to-end flow of a single MCP tool call: from the client request through the server to command execution on the target, and back.
+
+```mermaid
+sequenceDiagram
+ participant User
+ participant Client as MCP Client
(e.g. Cursor)
+ participant LLM as LLM Service
+ participant Server as MCP Server Process
(same host or container)
+ participant FastMCP as FastMCP
+ participant Tool as Tool (e.g. get_system_information)
+ participant Cmd as CommandSpec / COMMANDS
+ participant Exec as execute_command
+ participant Target as Target Linux System
(local or remote)
+
+ User->>Client: "What's my system info?"
+ Client->>LLM: Send prompt request
+ LLM->>Client: Decide to call tool
+ Client->>Server: MCP JSON-RPC: tools/call get_system_information
+ Note over Client,Server: stdio (stdin/stdout)
+
+ Server->>FastMCP: Dispatch tool call
+ FastMCP->>Tool: get_system_information(host=...)
+ Tool->>Tool: @log_tool_call, @disallow_local_execution_in_containers
+ Tool->>Cmd: get_command_group("system_info") etc.
+ Tool->>Cmd: cmd.run(host=host) for each subcommand
+
+ Cmd->>Exec: execute_command(command, host=host)
+
+ alt host is None (local)
+ Exec->>Target: asyncio.create_subprocess_exec (local)
+ Note over Server,Target: Target = same host as server
+ else host is set (remote)
+ Exec->>Server: SSHConnectionManager.get_connection(host)
+ Exec->>Target: conn.run(cmd) over SSH
+ Note over Server,Target: Target = remote host
+ end
+
+ Target-->>Exec: return_code, stdout, stderr
+ Exec-->>Cmd: return code, stdout, stderr
+ Cmd-->>Tool: results
+ Tool->>Tool: parse_*, format_*
+ Tool-->>FastMCP: formatted string
+ FastMCP-->>Server: MCP response
+ Server-->>Client: JSON-RPC result
+ Client->>LLM: Tool call result
+ LLM->>Client: Inference completion
+ Client->>User: Answer with system info
+```
+
+1. User asks a question in the MCP client (e.g. Cursor).
+2. Client sends the prompt to the LLM; the LLM decides to call a tool.
+3. Client sends MCP JSON-RPC `tools/call` (e.g. `get_system_information`) over **stdio** to the MCP server (same host or container).
+4. FastMCP dispatches the call to the tool.
+5. Tool runs decorators (`@log_tool_call`, `@disallow_local_execution_in_containers`), resolves commands via `CommandSpec`/`COMMANDS`, and invokes `cmd.run(host=host)` for each subcommand.
+6. `execute_command` runs on the target: **local** (`asyncio.create_subprocess_exec` when `host` is omitted) or **remote** (SSH via `SSHConnectionManager` when `host` is set).
+7. Target returns return code, stdout, and stderr to `execute_command`.
+8. Results flow back: Exec → Cmd → Tool; tool parses and formats (e.g. `parse_*`, `format_*`).
+9. Tool returns formatted string to FastMCP; server sends MCP response over stdio to the client.
+10. Client passes the tool result to the LLM; LLM produces the answer; client presents it to the user.
+