diff --git a/backend/alembic/versions/006_notes_urls.py b/backend/alembic/versions/0061_notes_urls.py similarity index 56% rename from backend/alembic/versions/006_notes_urls.py rename to backend/alembic/versions/0061_notes_urls.py index 49b2adc..60cc7f4 100644 --- a/backend/alembic/versions/006_notes_urls.py +++ b/backend/alembic/versions/0061_notes_urls.py @@ -1,16 +1,19 @@ -"""006 - ajout colonne urls (JSONB) sur notes.items +"""0061 - ajout colonne urls (JSONB) sur notes.items -Revision ID: 006 -Revises: 005 +Revision ID: 0061 +Revises: 006 Create Date: 2026-05-30 + +Note : renumérotée 0061 (au lieu de 006) pour résoudre une collision avec +006_product_tags. Chaînée après product_tags : 005 -> 006 -> 0061 -> 007. """ from alembic import op import sqlalchemy as sa from sqlalchemy.dialects.postgresql import JSONB -revision = '006' -down_revision = '005' +revision = '0061' +down_revision = '006' branch_labels = None depends_on = None diff --git a/backend/alembic/versions/007_shopping_list_type_and_item_enrichment.py b/backend/alembic/versions/007_shopping_list_type_and_item_enrichment.py index c843130..c23aef5 100644 --- a/backend/alembic/versions/007_shopping_list_type_and_item_enrichment.py +++ b/backend/alembic/versions/007_shopping_list_type_and_item_enrichment.py @@ -1,7 +1,7 @@ """007 - list_type sur shopping.lists, url/description/image_url sur list_items Revision ID: 007 -Revises: 006 +Revises: 0061 Create Date: 2026-05-30 """ @@ -9,7 +9,7 @@ from alembic import op import sqlalchemy as sa revision = '007' -down_revision = '006' +down_revision = '0061' branch_labels = None depends_on = None diff --git a/backend/app/api/mcp_server.py b/backend/app/api/mcp_server.py index 2ab8f65..f76244b 100644 --- a/backend/app/api/mcp_server.py +++ b/backend/app/api/mcp_server.py @@ -4,6 +4,7 @@ from datetime import datetime, timedelta, timezone, date as date_type from decimal import Decimal from mcp.server.fastmcp import FastMCP +from mcp.server.transport_security import TransportSecuritySettings from sqlalchemy import select, and_, text, or_ from sqlalchemy.orm import selectinload @@ -15,7 +16,20 @@ from app.models.shopping import ShoppingList, ListItem, Product _VALID_STATUSES = {"pending", "done", "cancelled"} _VALID_PRIORITIES = {"low", "medium", "high"} -mcp = FastMCP("HomeHub", stateless_http=True, streamable_http_path="/") +# La protection DNS rebinding (défaut FastMCP) valide le header Host contre +# ["127.0.0.1:*", "localhost:*", "[::1]:*"]. Elle est conçue contre les attaques +# navigateur sur des services localhost. Ici l'accès se fait depuis des agents +# externes (Hermes) via l'IP du serveur, et la vraie barrière est le Bearer token +# MCP_API_KEY (cf. MCPAuthMiddleware). On désactive donc cette protection devenue +# redondante et bloquante (sinon 421 "Invalid Host header" sur toute IP non-localhost). +mcp = FastMCP( + "HomeHub", + stateless_http=True, + streamable_http_path="/", + transport_security=TransportSecuritySettings( + enable_dns_rebinding_protection=False, + ), +) def _serialize(obj): diff --git a/frontend/nginx.conf b/frontend/nginx.conf index c95d5e9..2e99e20 100644 --- a/frontend/nginx.conf +++ b/frontend/nginx.conf @@ -27,7 +27,7 @@ server { location /mcp { proxy_pass http://backend:8000/mcp; - proxy_set_header Host localhost; + proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_http_version 1.1; proxy_set_header Connection ""; diff --git a/frontend/package.json b/frontend/package.json index d4869ed..f26a67a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "homehub-frontend", "private": true, - "version": "0.5.14", + "version": "0.5.15", "type": "module", "scripts": { "dev": "vite",