Remote Demo MCP
Local MCP server that deploys a pre-built static directory to a remote host with rsync.
What It Does
- Uses fixed
deployUserfrom MCP config - Derives
projectfromlocalDirbasename - Uploads
localDircontents to:/var/www/html/demo-remote/{user}/{project}/
- Uses local
rsynccommand - Supports OTP/interactive SSH flows by attaching rsync session to
/dev/tty - On failure, asks whether to retry until user cancels
Install
npm install
npm run build
Config
Default config path:
~/.config/remote-demo-mcp/config.json
Override path with:
REMOTE_DEMO_MCP_CONFIG=/abs/path/config.json
Example:
{
"deployUser": "demo_user-01",
"publicBaseUrl": "https://example.com",
"sessionLog": {
"enabled": false,
"path": "/tmp/remote-demo-mcp-session.log",
"logInputValue": false
},
"ssh": {
"host": "xxx.xxx.xxx.xxx",
"port": 2222,
"username": "alice123#ec2-user#52.76.147.44",
"interactiveAuth": true,
"password": "",
"hostKeyPolicy": "accept-new",
"autoFillPassword": true
},
"rsyncOptions": ["-az", "--delete"]
}
The server automatically enables resumable uploads by appending:
--partial--append-verify--progress(unlessrsyncOptionsalready includes--progressor--info=...)
Remote target base path is hard-coded and cannot be overridden:
/var/www/html/demo-remote
Tool
deploy_static
Keywords:
- EN:
deploy to remote,deploy demo,publish demo,upload static site - 中文:
部署到远程,部署demo,部署 demo,发布demo,上传静态网页
user rules:
deployUseris app user id for remote path, not SSHusername- Allowed chars:
A-Z a-z 0-9 _ - - Not allowed:
.,.., spaces,/,\\, and other special characters
Input:
{
"localDir": "/abs/path/to/dist",
"clientCwd": "/abs/path/on-mcp-client",
"dryRun": false
}
localDir path resolution:
- Absolute path: used directly
- Relative path: resolved against
clientCwdif provided - Fallback for relative path:
CODEX_START_DIRif set, otherwiseprocess.cwd()(server start directory)
Project name resolution:
- If
clientCwdis provided, project name uses the last path segment ofclientCwd - Otherwise, project name uses the last path segment of resolved
localDir
Behavior note:
- If
ssh.interactiveAuth=trueanddryRun=false,deploy_staticwill fail fast by design. - For OTP/password interactive deploy, use:
start_deploy_sessionpoll_deploy_sessionsubmit_deploy_inputwhennextAction=submit_input
- Host-key confirm (
yes/no) and password prompts are auto-handled in session mode. - OTP is still manual: call
submit_deploy_inputwhennextAction=submit_input.
Output (structuredContent):
{
"ok": true,
"attempts": 1,
"user": "alice",
"project": "my-site",
"remotePath": "/var/www/html/demo-remote/alice/my-site/",
"publicUrl": "https://example.com/alice/my-site/index.html",
"message": "Deploy succeeded after 1 attempt(s)."
}
verify_deploy
Input:
{
"url": "https://example.com/alice/my-site/index.html",
"timeoutMs": 8000
}
Interactive OTP Session Tools
Use these when OTP/password must be entered during deploy in non-TTY hosts:
start_deploy_sessionpoll_deploy_session(read output and progress; ifstate=waiting_input, submit code)submit_deploy_input(send OTP/password)- repeat step 2 until
stateissucceededorfailed - optional
cancel_deploy_session
poll_deploy_session supports incremental output by cursor and returns nextCursor.
Session tools return nextAction to make orchestration deterministic:
submit_input: callsubmit_deploy_inputpoll: callpoll_deploy_sessiondone: workflow finished (succeeded/failed/cancelled)
Session logging:
- Configure in MCP config file under
sessionLog. sessionLog.enableddefault isfalse.sessionLog.pathdefault is/tmp/remote-demo-mcp-session.log.sessionLog.logInputValuedefault isfalse(only input length is logged).- Interactive session tools run rsync in a PTY, so password/OTP prompts can be detected via
poll_deploy_session.
SSH host key policy:
accept-new(default): first-time host key is auto-accepted; changed key is rejected.strict: never auto-accept unknown host key.insecure: disable host key validation (high risk; for temporary/debug use only).
Codex CLI interactive flow:
- Call
start_deploy_session - Loop
poll_deploy_session - If
needsInput=trueornextAction=submit_input, callsubmit_deploy_inputwith OTP/password. The tip display to user is "Please Enter MFA Code." or "Please Enter Password." - Continue polling until
nextAction=done
Agent protocol contract (for MCP clients like Codex):
- Call
start_deploy_sessiononce. - Read
nextActionfrom response. - If
nextAction=submit_input, callsubmit_deploy_input. - If
nextAction=poll, callpoll_deploy_session. - Repeat steps 2-4 until
nextAction=done. - Never call
deploy_staticfor OTP flows; use session tools only. - While polling, relay transfer progress from
outputto the end user continuously.
Output (structuredContent):
{
"ok": true,
"url": "https://example.com/alice/my-site/index.html",
"status": 200,
"statusText": "OK",
"responseTimeMs": 123,
"message": "URL is reachable: HTTP 200 in 123ms"
}
Run
npm run dev
# or
npm run build && npm start
Initialize config file:
remote-demo-mcp init
It creates:
~/.config/remote-demo-mcp/config.json- Interactive mode shows each current field value for editing.
- Press Enter without input to keep the current value unchanged.
- If config already exists,
initasks whether to modify, then asks final confirmation before overwrite.
codex 使用
安裝 npm 包
npm install -g @jake.e-com365/remote-demo-mcp
codex 添加 mcp
codex mcp add remote-demo-mcp remote-demo-mcp
remote-demo-mcp 的配置
remote-demo-mcp init
vi ~/.config/remote-demo-mcp/config.json
{
"deployUser": "jake",
"publicBaseUrl": "https://demo-remote.e-com365.com/",
"ssh": {
"host": "xxx.xxx.xxx.xxx",
"username": "alice123#ec2-user#18.140.183.126",
"interactiveAuth": true,
"port": 2222,
"password": "xxx",
"hostKeyPolicy": "accept-new",
"autoFillPassword": true
},
"rsyncOptions": ["-az", "--delete"]
}