# Backend dependency SPEC — the versions Synapse supports.
#
# Every entry carries an upper bound. This is not stylistic: `mcp` was once a
# bare name here, a fresh install resolved the mcp 2.0.0 rewrite, and every
# native tool server died at import while the backend started with no tools.
# A floor-only spec ships the next major release straight to users.
#
# Installers and CI resolve backend/requirements.lock (exact, transitive) rather
# than this file. Regenerate the lock with scripts/lock-deps.sh after editing.
#
# mcp<2 is load-bearing: 2.0 removed the lowlevel Server decorator API that all
# of backend/tools/ uses and changed ClientSession read_timeout_seconds from
# timedelta to float. Upstream's guidance for anyone not ready to migrate is to
# stay on 1.x, which is in maintenance mode.
#
# The cost of staying (F175, measured 2026-09-26, D134): 1.x speaks MCP up to
# 2025-11-25 — 1.30.0, the newest 1.x, too. Only 2.x speaks 2026-07-28. A
# 2026-07-28 client probes with `server/discover`, our endpoint answers 400
# "Unsupported protocol version", and the client falls back to `initialize`
# and works (mcp 2.2.0's own Client, measured). Moving to 2.x means porting
# every lowlevel `Server` (backend/tools/*, core/mcp_server/server.py).

cffi>=2.0.0,<3
fastapi>=0.110,<1
uvicorn>=0.29,<1
httpx>=0.27,<1
google-api-python-client>=2.0,<3
google-auth-oauthlib>=1.0,<2
# Website logins' encryption and webhook signatures import it directly (BRW2, F1079); google-auth already pulls it in.
cryptography>=42,<51
mcp>=1.29,<2
chromadb>=0.5,<2
ollama>=0.2,<1
beautifulsoup4>=4.12,<5
playwright>=1.44,<2
# The web scraper (tools/web_scraper.py) drives Playwright itself: stealth on each
# context, pages read as Markdown (F1157, in place of crawl4ai).
playwright-stealth>=2.0.3,<3
html-to-markdown>=3.19,<4
boto3>=1.34,<2
# The in-app browser's host and its client (core/browser). Already resolved
# through chromadb; named because the engine imports it directly.
aiohttp>=3.9,<4
sqlalchemy>=2.0,<3
sqlalchemy[asyncio]>=2.0,<3
# The default store. A plain install runs on SQLite and needs nothing else
# running; asyncpg is only reached when SYNAPSE_DB_URL points at Postgres.
aiosqlite>=0.19,<1
asyncpg>=0.29,<1
psycopg2-binary>=2.9,<3
pymysql>=1.1,<2
pdfplumber>=0.10,<1
pandas>=2.0,<4
# Knowledge's vector leg: an exact cosine scan over float32 embeddings
# (core/knowledge/index_sql.py). Already resolved through pandas and chromadb;
# named because the engine imports it directly.
numpy>=1.26,<3
openpyxl>=3.1,<4
# Knowledge's parsers (A2, D162), imported directly: pypdfium2 opens and renders PDFs,
# Pillow writes the pages OCR reads, psutil caps the parsing process's memory,
# defusedxml reads Office XML safely, olefile reads Outlook .msg files. All but
# olefile were already installed through pdfplumber and chromadb.
pypdfium2>=4.30,<6
pillow>=10.0,<13
psutil>=5.9,<8
defusedxml>=0.7,<1
olefile>=0.46,<1
requests>=2.31,<3
anthropic>=0.28,<1
google-genai>=1.0,<3
pyinstrument>=4.6,<6
croniter>=2.0,<7
arq>=0.26,<1
redis[hiredis]>=5.0,<9
async-timeout>=4.0,<6
pyyaml>=6.0,<7
