61 lines
2.3 KiB
Bash
61 lines
2.3 KiB
Bash
|
|
#!/bin/sh
|
||
|
|
# Entrypoint for the OpenPencil Vue container: runs the static SPA server on
|
||
|
|
# :3100 and the @open-pencil/mcp Streamable-HTTP server on :7600 in the same
|
||
|
|
# container. Forwards SIGTERM/SIGINT to both so docker stop is clean.
|
||
|
|
# POSIX sh only (no `wait -n`) — the runtime image is Alpine/dash.
|
||
|
|
|
||
|
|
set -eu
|
||
|
|
|
||
|
|
WEB_PORT="${OPENPENCIL_WEB_PORT:-3100}"
|
||
|
|
MCP_PORT="${OPENPENCIL_MCP_PORT:-7600}"
|
||
|
|
|
||
|
|
# The MCP server creates a Unix socket + discovery file by default. In the
|
||
|
|
# container we direct them under /data (writable volume) so the socket never
|
||
|
|
# collides with /run/user/... and documents land on the persisted volume.
|
||
|
|
export OPENPENCIL_MCP_ROOT="${OPENPENCIL_MCP_ROOT:-/data}"
|
||
|
|
export OPENPENCIL_MCP_SOCKET="${OPENPENCIL_MCP_SOCKET:-/data/mcp.sock}"
|
||
|
|
export OPENPENCIL_MCP_DISCOVERY_PATH="${OPENPENCIL_MCP_DISCOVERY_PATH:-/data/mcp.json}"
|
||
|
|
export OPENPENCIL_MCP_CORS_ORIGIN="${OPENPENCIL_MCP_CORS_ORIGIN:-}"
|
||
|
|
# Bind MCP on all interfaces so sibling containers (chatapi) can reach it by
|
||
|
|
# service name (openpencil:7600), not just via localhost port-forwarding.
|
||
|
|
export OPENPENCIL_MCP_HOST="${OPENPENCIL_MCP_HOST:-0.0.0.0}"
|
||
|
|
|
||
|
|
mkdir -p "$OPENPENCIL_MCP_ROOT" "$(dirname "$OPENPENCIL_MCP_SOCKET")" "$(dirname "$OPENPENCIL_MCP_DISCOVERY_PATH")"
|
||
|
|
|
||
|
|
echo "[openpencil] starting static SPA on :${WEB_PORT} and MCP on :${MCP_PORT}"
|
||
|
|
|
||
|
|
# Static SPA.
|
||
|
|
OPENPENCIL_WEB_PORT="$WEB_PORT" bun static-server.mjs &
|
||
|
|
WEB_PID=$!
|
||
|
|
|
||
|
|
# MCP server (Streamable HTTP at /mcp). Bun runs the node-targeted bin.
|
||
|
|
PORT="$MCP_PORT" bun packages/mcp/bin/openpencil-mcp-http.js &
|
||
|
|
MCP_PID=$!
|
||
|
|
|
||
|
|
shutdown() {
|
||
|
|
echo "[openpencil] shutting down (MCP=$MCP_PID, web=$WEB_PID) ..."
|
||
|
|
kill -TERM "$MCP_PID" "$WEB_PID" 2>/dev/null || true
|
||
|
|
exit 0
|
||
|
|
}
|
||
|
|
trap shutdown TERM INT
|
||
|
|
|
||
|
|
# Wait for both processes; stop the container when either exits.
|
||
|
|
STATUS=0
|
||
|
|
while :; do
|
||
|
|
WEB_ALIVE=0; MCP_ALIVE=0
|
||
|
|
kill -0 "$WEB_PID" 2>/dev/null && WEB_ALIVE=1
|
||
|
|
kill -0 "$MCP_PID" 2>/dev/null && MCP_ALIVE=1
|
||
|
|
if [ "$WEB_ALIVE" = "0" ] || [ "$MCP_ALIVE" = "0" ]; then
|
||
|
|
STATUS=1
|
||
|
|
break
|
||
|
|
fi
|
||
|
|
# Poll every second; a SIGTERM/SIGINT wakes the loop via the trap's exit.
|
||
|
|
sleep 1
|
||
|
|
done
|
||
|
|
|
||
|
|
echo "[openpencil] a child process exited; stopping the container"
|
||
|
|
kill -TERM "$MCP_PID" "$WEB_PID" 2>/dev/null || true
|
||
|
|
wait "$MCP_PID" 2>/dev/null || true
|
||
|
|
wait "$WEB_PID" 2>/dev/null || true
|
||
|
|
exit "$STATUS"
|