Compare commits
8 Commits
620f7b3153
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 489419a7d4 | |||
| f815e64499 | |||
| e5606c64c5 | |||
| a08bdaa3b1 | |||
| 36a1ad0b84 | |||
| 80cb971308 | |||
| 6483453437 | |||
| 1221350ed6 |
@@ -11,6 +11,7 @@ from app.cache import cache
|
|||||||
from app.routers import equipment, health, admin, rental_requests, contact
|
from app.routers import equipment, health, admin, rental_requests, contact
|
||||||
from app.services.sync_service import SyncService
|
from app.services.sync_service import SyncService
|
||||||
from app.services.email_service import EmailService
|
from app.services.email_service import EmailService
|
||||||
|
from app.mcp_server import get_mcp_app, mcp_session_manager
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
settings = get_settings()
|
settings = get_settings()
|
||||||
@@ -41,6 +42,9 @@ async def lifespan(app: FastAPI):
|
|||||||
await init_db()
|
await init_db()
|
||||||
await cache.connect()
|
await cache.connect()
|
||||||
|
|
||||||
|
_mcp_cm = mcp_session_manager.run()
|
||||||
|
await _mcp_cm.__aenter__()
|
||||||
|
|
||||||
scheduler.add_job(run_equipment_sync, trigger="cron", hour="*/6", id="equipment_sync", replace_existing=True)
|
scheduler.add_job(run_equipment_sync, trigger="cron", hour="*/6", id="equipment_sync", replace_existing=True)
|
||||||
scheduler.add_job(run_email_retry, trigger="cron", minute="*/15", id="email_retry", replace_existing=True)
|
scheduler.add_job(run_email_retry, trigger="cron", minute="*/15", id="email_retry", replace_existing=True)
|
||||||
scheduler.start()
|
scheduler.start()
|
||||||
@@ -49,6 +53,7 @@ async def lifespan(app: FastAPI):
|
|||||||
yield
|
yield
|
||||||
|
|
||||||
scheduler.shutdown(wait=False)
|
scheduler.shutdown(wait=False)
|
||||||
|
await _mcp_cm.__aexit__(None, None, None)
|
||||||
await cache.disconnect()
|
await cache.disconnect()
|
||||||
await engine.dispose()
|
await engine.dispose()
|
||||||
|
|
||||||
@@ -63,3 +68,5 @@ app.include_router(health.router)
|
|||||||
app.include_router(admin.router)
|
app.include_router(admin.router)
|
||||||
app.include_router(rental_requests.router)
|
app.include_router(rental_requests.router)
|
||||||
app.include_router(contact.router)
|
app.include_router(contact.router)
|
||||||
|
|
||||||
|
app.mount("/mcp", get_mcp_app())
|
||||||
|
|||||||
@@ -122,20 +122,9 @@ _STATIC_COMPONENTS = [
|
|||||||
# streamable_http_path="/" so that when mounted at /mcp the endpoint is /mcp/
|
# streamable_http_path="/" so that when mounted at /mcp the endpoint is /mcp/
|
||||||
# stateless_http=True: each request is independent (no session management)
|
# stateless_http=True: each request is independent (no session management)
|
||||||
# Disable DNS rebinding protection for Docker deployment
|
# Disable DNS rebinding protection for Docker deployment
|
||||||
try:
|
from mcp.server.transport_security import TransportSecuritySettings
|
||||||
from mcp.server.fastmcp.settings import TransportSecuritySettings
|
|
||||||
_ts = TransportSecuritySettings(enable_dns_rebinding_protection=False)
|
|
||||||
except Exception:
|
|
||||||
_ts = None
|
|
||||||
|
|
||||||
_mcp_kwargs: dict[str, Any] = {
|
mcp = FastMCP("hms-cms", streamable_http_path="/", stateless_http=True, transport_security=TransportSecuritySettings(enable_dns_rebinding_protection=False))
|
||||||
"streamable_http_path": "/",
|
|
||||||
"stateless_http": True,
|
|
||||||
}
|
|
||||||
if _ts is not None:
|
|
||||||
_mcp_kwargs["transport_security"] = _ts
|
|
||||||
|
|
||||||
mcp = FastMCP("hms-cms", **_mcp_kwargs)
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------#
|
# ---------------------------------------------------------------------------#
|
||||||
# Bearer token authentication wrapper
|
# Bearer token authentication wrapper
|
||||||
|
|||||||
+3
-30
@@ -1,24 +1,11 @@
|
|||||||
services:
|
services:
|
||||||
frontend:
|
frontend:
|
||||||
build: ./frontend
|
build: ./frontend
|
||||||
ports:
|
labels:
|
||||||
- 3000:3000
|
- traefik.http.services.https-0-wvus7va5u0f9dmg27ggca7rl-frontend.loadbalancer.server.port=3000
|
||||||
depends_on:
|
depends_on:
|
||||||
backend:
|
backend:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.middlewares.hms-gzip.compress=true
|
|
||||||
- traefik.http.middlewares.hms-redirect.redirectscheme.scheme=https
|
|
||||||
- traefik.http.routers.hms-http.entryPoints=http
|
|
||||||
- traefik.http.routers.hms-http.middlewares=hms-redirect
|
|
||||||
- traefik.http.routers.hms-http.rule=Host(`hms.media-on.de`) && PathPrefix(`/`)
|
|
||||||
- traefik.http.routers.hms-https.entryPoints=https
|
|
||||||
- traefik.http.routers.hms-https.middlewares=hms-gzip
|
|
||||||
- traefik.http.routers.hms-https.rule=Host(`hms.media-on.de`) && PathPrefix(`/`)
|
|
||||||
- traefik.http.routers.hms-https.tls=true
|
|
||||||
- traefik.http.routers.hms-https.tls.certresolver=letsencrypt
|
|
||||||
- traefik.http.services.hms.loadbalancer.server.port=3000
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test:
|
test:
|
||||||
@@ -53,8 +40,6 @@ services:
|
|||||||
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
|
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
|
||||||
- MCP_AUTH_TOKEN=${MCP_AUTH_TOKEN:-}
|
- MCP_AUTH_TOKEN=${MCP_AUTH_TOKEN:-}
|
||||||
volumes:
|
volumes:
|
||||||
- ./:/data/repo
|
|
||||||
- ./images:/data/images
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
healthcheck:
|
healthcheck:
|
||||||
@@ -62,25 +47,13 @@ services:
|
|||||||
- CMD
|
- CMD
|
||||||
- python
|
- python
|
||||||
- -c
|
- -c
|
||||||
- import urllib.request; urllib.request.urlopen('http://localhost:8000/api/health')
|
- import urllib.request; urllib.request.urlopen("http://localhost:8000/api/health")
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: 10s
|
start_period: 10s
|
||||||
networks:
|
networks:
|
||||||
- hms-network
|
- hms-network
|
||||||
- coolify
|
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.hms-mcp-http.entryPoints=http
|
|
||||||
- traefik.http.routers.hms-mcp-http.rule=Host(`hms.media-on.de`) && PathPrefix(`/mcp`)
|
|
||||||
- traefik.http.routers.hms-mcp-http.middlewares=hms-redirect
|
|
||||||
- traefik.http.routers.hms-mcp-https.entryPoints=https
|
|
||||||
- traefik.http.routers.hms-mcp-https.rule=Host(`hms.media-on.de`) && PathPrefix(`/mcp`)
|
|
||||||
- traefik.http.routers.hms-mcp-https.tls=true
|
|
||||||
- traefik.http.routers.hms-mcp-https.tls.certresolver=letsencrypt
|
|
||||||
- traefik.http.routers.hms-mcp-https.middlewares=hms-gzip
|
|
||||||
- traefik.http.services.hms-mcp.loadbalancer.server.port=8000
|
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:16-alpine
|
image: postgres:16-alpine
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
@@ -12,6 +12,18 @@ server {
|
|||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
location /mcp {
|
||||||
|
proxy_pass http://backend:8000/mcp;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user