English | 中文
Rust-based MCP server for remote interactive control over SSH and Telnet. It supports both STDIO and HTTP transports, session management, and a cursor-based output buffer for reliable interactive reads.
- MCP tools:
ptyctl_session,ptyctl_session_exec,ptyctl_session_io,ptyctl_session_config. - Protocols: SSH and Telnet (in-process Telnet protocol handling).
- Transports: STDIO, HTTP (JSON-RPC + SSE).
- Output cursors: independent readers can follow a session buffer without interfering.
- Exit code extraction: default marker + ASCII fallback when control characters are stripped.
cargo build --release
cargo testcargo build --releaseThe binary will be at target/release/ptyctl. To install it into /usr/local/bin:
sudo install -m 0755 target/release/ptyctl /usr/local/bin/ptyctlOne-liner install (Linux/macOS, auto-detect):
curl -fsSL https://raw.githubusercontent.com/nfshanq/pytctl/main/install.sh | bashManual download (if you prefer):
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
case "$OS-$ARCH" in
linux-x86_64) ASSET=ptyctl-linux-amd64.tar.gz ;;
darwin-arm64) ASSET=ptyctl-macos-arm64.tar.gz ;;
*) echo "Unsupported OS/arch: $OS-$ARCH" && exit 1 ;;
esac
curl -L -o /tmp/$ASSET https://github.com/nfshanq/pytctl/releases/latest/download/$ASSET
tar -xzf /tmp/$ASSET -C /tmp
BIN_NAME=${ASSET%.tar.gz}
sudo install -m 0755 /tmp/$BIN_NAME /usr/local/bin/ptyctlptyctl serve --transport stdioptyctl serve --transport http --http-listen 127.0.0.1:8765 --auth-token YOUR_TOKENHTTP endpoint:
- Streamable HTTP:
http://127.0.0.1:8765/mcp(POST JSON-RPC, GET SSE)
ptyctl serve --transport both --http-listen 127.0.0.1:8765 --auth-token YOUR_TOKENFor local read-only monitoring (e.g., ptyctl sessions, ptyctl tail, ptyctl attach):
ptyctl serve --transport stdio --control-socket /tmp/ptyctl.sock --control-mode readonlyOpen Cursor settings and add an MCP server. Example config:
STDIO transport:
{
"mcpServers": {
"ptyctl-stdio": {
"command": "/usr/local/bin/ptyctl",
"args": ["serve", "--transport", "stdio"],
"env": {
"PTYCTL_LOG_LEVEL": "info"
}
}
}
}HTTP transport:
{
"mcpServers": {
"ptyctl-http": {
"url": "http://127.0.0.1:8765/mcp",
"headers": {
"Authorization": "Bearer YOUR_TOKEN"
}
}
}
}Notes:
- Use the full path to the
ptyctlbinary. - If you build release:
cargo build --releasethen usetarget/release/ptyctl. - The HTTP server uses MCP streamable HTTP at
/mcp(POST JSON-RPC, GET SSE).
Add ptyctl as an MCP server in your Codex configuration. The exact file location may vary by installation; common locations are:
~/.codex/mcp.json~/.config/codex/mcp.json
Add via codex mcp add (STDIO):
codex mcp add ptyctl-stdio \
--env PTYCTL_LOG_LEVEL=info \
-- /usr/local/bin/ptyctl serve --transport stdioSTDIO example:
{
"mcpServers": {
"ptyctl-stdio": {
"command": "/usr/local/bin/ptyctl",
"args": ["serve", "--transport", "stdio"],
"env": {
"PTYCTL_LOG_LEVEL": "info"
}
}
}
}HTTP example:
{
"mcpServers": {
"ptyctl-http": {
"url": "http://127.0.0.1:8765/mcp",
"headers": {
"Authorization": "Bearer YOUR_TOKEN"
}
}
}
}Open an SSH session (MCP tools/call):
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "ptyctl_session",
"arguments": {
"action": "open",
"protocol": "ssh",
"host": "example.com",
"port": 22,
"pty": { "enabled": true, "cols": 120, "rows": 40, "term": "xterm-256color" }
}
}
}Execute a command (exit code via markers):
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "ptyctl_session_exec",
"arguments": {
"session_id": "SESSION_ID",
"cmd": "echo hello",
"timeout_ms": 20000
}
}
}Read output with cursor:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "ptyctl_session_io",
"arguments": {
"action": "read",
"session_id": "SESSION_ID",
"cursor": "0",
"timeout_ms": 2000,
"max_bytes": 65536,
"encoding": "utf-8"
}
}
}