Add: Web UI (React 19 + Vite + shadcn/ui) + FastAPI REST layer
Adds a self-contained web interface that wraps the MCP tools so end users
don't need to issue MCP commands. Single Docker container serves:
/ → React SPA (RTL Hebrew, Heebo font, shadcn/ui components)
/api/* → FastAPI REST endpoints used by the SPA
/api/docs → OpenAPI / Swagger
/mcp → existing FastMCP streamable-http endpoint
/health → liveness probe
REST endpoints (in nadlan_mcp/web_app.py):
GET /api/search/address?q=... — autocomplete + best-effort gush/חלקה
via Govmap PARCEL_ALL layer
POST /api/search/deals — Govmap deals around an address
POST /api/search/appraisals — Decisive-appraiser search (gov.il)
GET /api/appraisals/pdf?url=.. — Stream PDFs through this server,
carrying the upstream x-client-id
header (a normal browser fetch fails)
UI flow:
- Address search → resolves gush/חלקה → shows BOTH deals (Govmap) AND
appraiser decisions (gov.il) for the same parcel side-by-side in tabs.
- Block+plot search → goes straight to appraisals.
- Appraiser-name search → all decisions by that appraiser.
Stack chosen for RTL-first usability and longevity: React 19, Vite 6,
TypeScript, Tailwind, shadcn/ui (Radix primitives), TanStack Query,
Lucide icons. ~295KB gzipped JS, no SSR overhead.
Multi-stage Dockerfile: Node 22 builds web/ in stage 1, Python 3.13
runtime serves the dist + the FastAPI app in stage 2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+26
-22
@@ -1,45 +1,49 @@
|
||||
# Dockerfile for Nadlan-MCP HTTP Server
|
||||
# Supports deployment to Render, Railway, Docker, and other container platforms
|
||||
# ─── Stage 1: build the React UI ────────────────────────────────────────
|
||||
FROM node:22-alpine AS web-build
|
||||
WORKDIR /web
|
||||
|
||||
# Cache deps separately from sources.
|
||||
COPY web/package.json web/package-lock.json* ./
|
||||
RUN npm ci --no-audit --no-fund
|
||||
|
||||
COPY web/ .
|
||||
RUN npm run build
|
||||
|
||||
# ─── Stage 2: Python runtime ────────────────────────────────────────────
|
||||
FROM python:3.13-slim
|
||||
|
||||
# Set environment variables
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
PIP_NO_CACHE_DIR=1 \
|
||||
PIP_DISABLE_PIP_VERSION_CHECK=1
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies if needed
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
gcc \
|
||||
# Build deps for curl_cffi (needs libcurl-impersonate). curl_cffi vendors
|
||||
# its own libs but a C toolchain is still useful for any pure-Python whls
|
||||
# without prebuilt wheels for slim.
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends gcc \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy package files for better layer caching
|
||||
COPY pyproject.toml .
|
||||
COPY README.md .
|
||||
|
||||
# Install Python dependencies
|
||||
# Install Python deps from pyproject.
|
||||
COPY pyproject.toml README.md ./
|
||||
RUN pip install --no-cache-dir .
|
||||
|
||||
# Copy application code
|
||||
# App code.
|
||||
COPY nadlan_mcp/ ./nadlan_mcp/
|
||||
COPY run_http_server.py .
|
||||
COPY run_http_server.py ./
|
||||
|
||||
# Create non-root user for security
|
||||
RUN useradd -m -u 1000 appuser && \
|
||||
chown -R appuser:appuser /app
|
||||
# React build artifacts → web/dist (where web_app.py looks for them).
|
||||
COPY --from=web-build /web/dist ./web/dist
|
||||
|
||||
# Non-root user.
|
||||
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
|
||||
USER appuser
|
||||
|
||||
# Expose port (will be overridden by PORT env var in production)
|
||||
EXPOSE 8000
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=15s --retries=3 \
|
||||
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:${PORT:-8000}/health')" || exit 1
|
||||
|
||||
# Run the HTTP server
|
||||
CMD ["python", "run_http_server.py"]
|
||||
|
||||
Reference in New Issue
Block a user