[project] name = "handoff-mcp" version = "0.4.0" description = "Persistent cross-session memory and structured hand-off for Claude, exposed over the Model Context Protocol." readme = "README.md" requires-python = ">=3.10" license = { text = "MIT" } authors = [{ name = "Kirill Sviridov", email = "solrangeroom@gmail.com" }] keywords = ["mcp", "claude", "memory", "llm", "agent", "handoff"] classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Topic :: Software Development :: Libraries", ] dependencies = [ # <2: mcp 2.0 is a breaking rewrite (FastMCP -> MCPServer); migrate deliberately. "mcp>=1.27,<2", "pydantic>=2.6", ] [project.optional-dependencies] # Semantic recall. The deterministic core (FTS5 + recency/importance/ # supersession ranking) does NOT require any of these. # semantic — sqlite-vec accelerator for KNN (optional even for semantic) # semantic-openai — OpenAI-compatible embeddings (OpenAI, Together, self-hosted proxy, …) # semantic-local — offline embeddings via sentence-transformers semantic = [ "sqlite-vec>=0.1.3", ] semantic-openai = [ "openai>=1.0", ] semantic-local = [ "sentence-transformers>=2.2", ] dev = [ "pytest>=8.0", "pytest-asyncio>=0.23", "ruff>=0.6", "mypy>=1.10", "tomli; python_version < '3.11'", ] [project.scripts] handoff-mcp = "handoff_mcp.server:main" handoff-import = "handoff_mcp.cli_import:main" handoff-init = "handoff_mcp.cli_init:main" handoff-sync = "handoff_mcp.cli_sync:main" [project.urls] Homepage = "https://github.com/kirill-sviridov/handoff-mcp" Repository = "https://github.com/kirill-sviridov/handoff-mcp" [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["src/handoff_mcp"] [tool.hatch.build.targets.wheel.force-include] "src/handoff_mcp/py.typed" = "handoff_mcp/py.typed" [tool.ruff] line-length = 100 target-version = "py310" src = ["src", "tests"] [tool.ruff.lint] select = ["E", "F", "I", "UP", "B", "SIM", "C4", "RUF"] # We intentionally use Cyrillic in user-facing strings (bilingual trigger # phrases like "го дальше"), so the ambiguous-unicode checks are noise here. ignore = ["RUF001", "RUF002", "RUF003"] [tool.mypy] python_version = "3.10" strict = true files = ["src", "tests", "benchmarks"] plugins = ["pydantic.mypy"] [[tool.mypy.overrides]] module = ["sqlite_vec.*", "openai.*", "sentence_transformers.*"] ignore_missing_imports = true [[tool.mypy.overrides]] module = ["tomli", "tomllib"] ignore_missing_imports = true [tool.pytest.ini_options] asyncio_mode = "auto" testpaths = ["tests"] addopts = "-q"