serverkit-mcp
# serverkit-mcp
Stdio MCP server that proxies a [ServerKit](https://github.com/ServerkitOfficial) phone's
in-app MCP server (SSH command execution) to any MCP-capable agent - Claude Code, Codex,
or anything else that can run a local MCP server over stdio.
## Why this exists
The phone's own MCP server is Streamable HTTP, reachable at `http://<phone-ip>:<port>/mcp`.
That's fine for a client that supports remote HTTP connectors directly (Claude Desktop,
claude.ai), but a CLI agent normally needs that URL registered up front, and the phone's
IP/port isn't stable across sessions. This package sits in between as a stdio MCP server:
it can broadcast on the LAN to find the phone automatically, or take a URL you give it, then
forwards tool calls to it for the rest of the conversation - no config file edit each time.
## Get the ServerKit app
This package is only useful if the phone side exists: ServerKit is the Android app that
turns a phone into an SSH & microservice manager for Ubuntu servers, and runs the MCP
server this package connects to. Install it, enable its MCP server, then point an agent
at it with the tools below.
[<img alt="Get it on Google Play" src="https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png" width="200"/>](https://play.google.com/store/apps/details?id=com.iishanto.servermanager)
## Tools
- `start_here` - the onboarding/guide tool. Agents are told (via the server's
`instructions`) to call this first. It explains what ServerKit is, the
production-safety rules, how to connect/select a server, run commands, handle
disconnects, reconnect, and update this proxy, and it reports the connected
app's version plus a compatibility verdict. Works with or without a connection.
- `serverkit_mcp_version` - reports this proxy's installed version, the latest
on npm, the update command (when outdated), and the connected app's version +
compatibility. Local-only, no phone connection needed.
- `discover_servers` - UDP-broadcasts on the LAN, returns any ServerKit phones that answer
(`{ name, url }[]`).
- `connect(url)` - connects to a phone's MCP server (from discovery, or an ip:port the user
gives you directly).
- `disconnect()` - closes the connection.
- `request_pairing_code()`, `start_session(pairing_code)`, `end_session()`,
`run_command(command, cwd?)`, `run_command_sudo(command, cwd?)`, `cancel_command()` -
forwarded 1:1 to the phone's own tools. The phone mints a pairing code and shows it in
the app automatically the moment a client connects; `request_pairing_code` re-mints when
it expires. The code is shown only in the app - ask the user to read it out. See
`ssh_server_manager/lib/features/mcp_server/data/mcp_tools.dart` in the main app repo for
what these actually do server-side; keep this file's tool list in sync with that one.
- `list_servers()`, `add_server(name, host, port, username, os, version, password?,
private_key?, key_passphrase?)`, `connect_server(server_id, password?)` - "management
mode": bootstrap a fresh ServerKit install (save a server, then connect to it) without
the phone owner touching the Servers tab first. Also 1:1 forwards, also require
`start_session` first. See
`ssh_server_manager/lib/features/mcp_server/data/mcp_management_tools.dart`.
- `list_database_connections()`, `add_database_connection(name, engine, host, port,
username, database, password, ssl?)`, `update_database_connection(connection_id, ...)`,
`remove_database_connection(connection_id)`, `connect_database(connection_id)` - RDBMS
connection management, also 1:1 forwards, also require `start_session` first.
- `run_ddl_sql(sql)`, `run_dml_sql(sql)`, `run_control_sql(sql)` - execute SQL on the
connection opened by `connect_database`. The phone classifies the leading keyword and
refuses a statement belonging to a different tool. `run_ddl_sql` is destructive
(DROP/TRUNCATE) - confirm with the user first. See
`ssh_server_manager/lib/features/mcp_server/data/mcp_rdbms_tools.dart`.
- `download_file(remote_path, local_path)`, `upload_file(local_path, remote_path)` -
desktop-side only, not forwarded to the phone. Only this Node process has real desktop
filesystem access, so the actual byte-moving happens here, against the phone's raw
`/mcp/file` route. The agent's tool result is a byte count, never the file content.
## Install
```bash
npx -y serverkit-mcp@latest
```
No install step needed - `npx` fetches and runs the published package. For local
development against this repo instead, clone it and run `npm install`.
## Update
The proxy gains tools over time; an outdated copy silently lacks tools the phone
already exposes. Always register with the `@latest` tag so `npx` re-resolves on
each launch:
```bash
claude mcp remove serverkit && claude mcp add --transport stdio serverkit -- npx -y serverkit-mcp@latest
```
Or, if installed globally, `npm i -g serverkit-mcp@latest`. An agent can check
this for you via the `serverkit_mcp_version` tool and run the update itself.
## Compatibility
The phone advertises its app version (`name+build`, e.g. `2.5.2+118`) in the MCP
handshake. This proxy declares the oldest app build it supports in
`package.json`:
```json
"serverkit": { "minAppVersionCode": 118 }
```
`start_here` and `serverkit_mcp_version` compare the two and report
`appCompatible`. When it is `false`, the agent tells the user to update the
ServerKit app. Bump `minAppVersionCode` whenever the proxy starts relying on a
newer phone-side tool or field.
## Register with an agent
```bash
claude mcp add --transport stdio serverkit -- npx -y serverkit-mcp@latest
```
This is a one-time setup step (unlike the phone's raw-HTTP prompt, which has no persistent
registration). After that, in any session: ask the agent to discover or connect, then use
the SSH tools normally.
## Discovery protocol
Self-defined, no external dependency. UDP port `41234`.
- Request (broadcast to `255.255.255.255:41234`): `{"type":"serverkit-discover","v":1}`
- Response (unicast back to sender): `{"type":"serverkit-announce","v":1,"name":"<device>","url":"http://<ip>:<port>/mcp"}`
TDQS
Scored across 7 tools
Each tool maps to a distinct stage in a clear lifecycle: discovery, connection, session, and command execution. The only near-overlap is run_command vs run_command_sudo, but the sudo distinction is spelled out explicitly in both descriptions. An agent can easily pick the right tool at each step.
Almost everything follows a consistent snake_case verb_noun pattern (discover_servers, start_session, end_session, run_command, run_command_sudo). The only minor deviations are the bare connect/disconnect pair, which are still predictable and readable, plus the _sudo suffix variant.
Seven tools is well-scoped for a remote-command bridge: discovery, connection management, session management, and command execution. Every tool earns its place with no redundant or filler entries.
The connection-to-command lifecycle is fully covered (discover, connect, start/end session, run, run with sudo). Minor gaps exist around introspection such as checking connection/session status or transferring files, but core workflows have no dead ends.