loading…
Search for a command to run...
loading…
Enables human-in-the-loop checkpoints for AI agents, allowing them to pause and wait for human input via a web UI, then seamlessly resume execution.
Enables human-in-the-loop checkpoints for AI agents, allowing them to pause and wait for human input via a web UI, then seamlessly resume execution.
Turn a single agent request into a durable human-in-the-loop conversation.
turn-mcp-web is a self-hosted MCP server with a browser console. An agent calls turn.wait, execution pauses, a human replies in the web UI, and the same run continues without starting over.
Most agent integrations treat a human checkpoint as a dead end:
turn-mcp-web keeps that checkpoint inside the same execution loop.
work -> turn.wait -> human reply -> work -> turn.wait -> human reply
That makes it useful for approvals, branching decisions, operator handoffs, review queues, and long-running assisted workflows.
turn.wait, turn_wait, turnDouble-click start.command
Double-click start.bat
bash start.sh
npm install
npm run build
npm start
Web console: http://127.0.0.1:3737/
MCP endpoint: http://127.0.0.1:3737/mcp
http://127.0.0.1:3737/mcp or launch the stdio entrypoint.turn.wait.Use this for Cursor, Windsurf, VS Code, Claude Code, Antigravity, and other MCP clients that support remote HTTP servers.
{
"mcpServers": {
"turn-mcp-web": {
"url": "http://127.0.0.1:3737/mcp"
}
}
}
Windsurf uses serverUrl instead of url.
Use this when the client launches MCP servers as local child processes.
{
"mcpServers": {
"turn-mcp-web": {
"command": "node",
"args": ["/absolute/path/to/dist/server-stdio.js"]
}
}
}
The stdio process still opens the same web console on port 3737.
Use the bundled Python client when your framework does not speak MCP directly.
pip install ./python-client
from turn_mcp_client import TurnMcpClient, TurnMcpCanceled, TurnMcpTimeout
client = TurnMcpClient("http://127.0.0.1:3737")
try:
reply = client.wait(
context="About to apply a production migration.",
question="Should I proceed?",
options=["Proceed", "Show SQL", "Cancel"],
agent_name="MigrationAgent",
)
print(reply)
except TurnMcpTimeout:
print("No reply before timeout.")
except TurnMcpCanceled:
print("Canceled by operator.")
More examples: python-client/README.md
Give the agent one of these files:
Those files tell the agent to use turn.wait as the communication boundary instead of replying directly.
GET /healthzGET /api/public-configGET /api/waitsGET /api/waits/:idPOST /api/waits/:id/respondPOST /api/waits/:id/cancelPOST /api/waits/:id/extendPOST /api/waits/cancel-allPOST /api/waits/create-and-waitGET /api/historyGET /api/history/timelineGET /api/eventsGET /api/streamGET /api/auth-checkGET /api/sessionsPOST /api/settingsPOST /api/auto-configurePOST /api/auto-unconfigure| Variable | Default | Purpose |
|---|---|---|
TURN_MCP_HTTP_HOST |
127.0.0.1 |
HTTP bind host |
TURN_MCP_HTTP_PORT |
3737 |
HTTP bind port |
TURN_MCP_HTTP_PATH |
/mcp |
MCP endpoint path |
TURN_MCP_DEFAULT_TIMEOUT_SECONDS |
600 |
Default wait timeout |
TURN_MCP_API_KEY |
unset | Operator key |
TURN_MCP_VIEWER_API_KEY |
unset | Viewer key |
TURN_MCP_REQUIRE_API_KEY |
auto | Enable auth |
TURN_MCP_EVENT_LOG_FILE |
unset | JSONL event log path |
TURN_MCP_HISTORY_FILE |
unset | JSONL history path |
TURN_MCP_WEBHOOK_URL |
unset | Outbound webhook target |
TURN_MCP_WEBHOOK_EVENTS |
unset | Comma-separated webhook events |
TURN_MCP_WEBHOOK_SECRET |
unset | HMAC signing secret |
TURN_MCP_WEBHOOK_FORMAT |
json |
json, slack, or discord |
TURN_MCP_TELEGRAM_BOT_TOKEN |
unset | Telegram bot token |
TURN_MCP_TELEGRAM_CHAT_ID |
unset | Telegram target chat |
TURN_MCP_TELEGRAM_EVENTS |
wait_created |
Telegram event filter |
TURN_MCP_RATE_LIMIT_MAX |
120 |
Requests per IP |
TURN_MCP_RATE_LIMIT_WINDOW_SECONDS |
60 |
Rate limit window |
TURN_MCP_MAX_CONCURRENT_WAITS_PER_SESSION |
10 |
Per-session concurrency cap |
TURN_MCP_REINFORCEMENT_SUFFIX |
built-in | Appended reminder text |
Auth is off by default. When enabled, send either of these headers:
x-turn-mcp-api-key: <key>
Authorization: Bearer <key>
Roles:
operator: full controlviewer: read-only inspection and SSE subscriptiondocker build -t turn-mcp-web .
docker run --rm -p 3737:3737 \
-e TURN_MCP_HTTP_HOST=0.0.0.0 \
-e TURN_MCP_API_KEY=your_key \
turn-mcp-web
Compose file: docker-compose.yml
src/ TypeScript server
public/ Browser console
python-client/ Python client package
assets/ README screenshots and demo video
See CONTRIBUTING.md.
MIT
Run in your terminal:
claude mcp add turn-mcp-web -- npx Security
Low riskAutomated heuristic from public metadata — not a security guarantee.