[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "memshelf-mcp" dynamic = ["version"] description = "Working memory for AI agents: digest-indexed episodes on a git shelf, recalled a section at a time." readme = "README.md" requires-python = ">=3.10" license = { text = "MIT" } authors = [ { name = "Filipp Ignatenko", email = "ignatenkofi@gmail.com" } ] keywords = ["mcp", "model-context-protocol", "claude", "memory", "agent", "llm", "docshelf"] classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Text Processing :: Markup :: Markdown", ] # The shelve orchestration wraps docshelf's Shelf; the server/CLI surface adds # mcp + pydantic. The pure Layer-2/3 core (redaction, digest contract) still # needs none of these, so those modules and their tests run stdlib-only. dependencies = [ # Floor at 0.4.1: enumeration there stops treating H2 split files under # docs/// as shelf documents and reports the directory # itself (uncommitted-split-dir / split-out-of-sync), so a legacy split no # longer makes INDEX diverge between checkouts. Below 0.4.1 the same shelf # renders differently on the machine that holds the split — the #109 world # tests/test_splits.py used to document. "docshelf-mcp>=0.4.1,<1", # Floor at 2.0: server.py imports MCPServer from mcp.server.mcpserver, # which 1.x does not have (the 1.x name, mcp.server.fastmcp, was removed # in 2.0.0) — a 1.x install fails at import. Major-version ceiling: the # next major gets a port and a tests/test_stdio_protocol.py run, not a # widened range. The long version of this story: CHANGELOG 0.2.0. "mcp>=2.1.1,<3", "pydantic>=2.13.5,<3", ] [project.optional-dependencies] dev = [ "pytest>=9.1.1", "ruff>=0.16.6", ] # Embedding sidecar for search (#17). Static embeddings, no GPU, no service; # the default model downloads ~1 GB on first use. semantic = [ "model2vec>=0.9", ] [project.scripts] memshelf = "memshelf_mcp.cli:main" memshelf-mcp = "memshelf_mcp.server:main" [project.urls] Homepage = "https://github.com/ignatenkofi/memshelf-mcp" Repository = "https://github.com/ignatenkofi/memshelf-mcp" Issues = "https://github.com/ignatenkofi/memshelf-mcp/issues" Documentation = "https://ignatenkofi.github.io/memshelf-mcp/" Changelog = "https://github.com/ignatenkofi/memshelf-mcp/blob/main/CHANGELOG.md" "Measured results" = "https://github.com/ignatenkofi/memshelf-mcp/blob/main/docs/demo.md" [tool.hatch.version] path = "src/memshelf_mcp/__init__.py" [tool.hatch.build.targets.wheel] packages = ["src/memshelf_mcp"] [tool.hatch.build.targets.sdist] include = [ "src/", "tests/", "docs/", "README.md", "LICENSE", "pyproject.toml", ] [tool.pytest.ini_options] testpaths = ["tests"] addopts = "-ra --strict-markers" [tool.ruff] line-length = 100 target-version = "py310" [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "B", # flake8-bugbear "UP", # pyupgrade ] ignore = ["E501"] # line length handled by the formatter [tool.ruff.lint.isort] known-first-party = ["memshelf_mcp"]