[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "shelfmark" version = "0.4.9" description = "Give AI agents the right context, not your entire filesystem. A local, governed, metadata-only catalogue of the documents you already have — built for MCP." readme = "README.md" requires-python = ">=3.11" license = "MIT" license-files = ["LICENSE"] authors = [{ name = "Dankaro" }] # Both bounds are tested, not guessed. Upper: mcp 2.0.0 removed # `mcp.server.fastmcp`, so lifting it means porting server.py first. # Lower: 1.8 through 1.13 raise TypeError on import against current # pydantic-settings, so a wider floor would declare support for versions # that do not work. CI runs the floor and the latest on every push. dependencies = ["mcp>=1.14,<2"] keywords = ["mcp", "search", "documents", "catalogue", "local-first", "claude"] classifiers = [ "Development Status :: 4 - Beta", "Environment :: Console", "Operating System :: MacOS", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3", "Topic :: System :: Filesystems", "Topic :: Text Processing :: Indexing", ] [project.optional-dependencies] # .pst / .msg email archive ingestion, split by what each one costs to # install. extract-msg resolves to wheels; libpff-python publishes none and # compiles from C source, so it needs a toolchain and fails outright on any # machine without one. Joining them meant a folder of .msg files could not # be read without a compiler that .msg never required. msg = ["extract-msg"] pst = ["libpff-python"] email = ["extract-msg", "libpff-python"] # both; kept for compatibility [dependency-groups] dev = ["pytest>=8", "pytest-timeout>=2"] [tool.pytest.ini_options] testpaths = ["tests"] # tests/ is not a package; conftest helpers are imported by module name. pythonpath = ["src", "tests"] addopts = "-q --strict-markers" # The server runs a refresh loop, so a regression can hang rather than fail # -- and a hung test reads as a pass until someone kills the job. Every test # here finishes in well under a second; the cap is a backstop, not a budget. timeout = 60 [project.urls] Homepage = "https://github.com/Dankaro-projects/shelfmark" Repository = "https://github.com/Dankaro-projects/shelfmark" Issues = "https://github.com/Dankaro-projects/shelfmark/issues" [project.scripts] shelfmark = "shelfmark.cli:main" shelfmark-mcp = "shelfmark.server:main" [tool.hatch.build.targets.wheel] packages = ["src/shelfmark"] # A published version is permanent -- it can be yanked, never unpublished -- # so the sdist ships exactly what an installing user needs and nothing more. # CLAUDE.md is the internal contributor guide and stays out of releases. # only-include means anything added at the repo root is EXCLUDED BY DEFAULT: # opt a file in deliberately, rather than discover it in a release. # (.gitignore rides along regardless -- hatchling always ships it, and its # contents are already public in the repo.) [tool.hatch.build.targets.sdist] # `tests` ships: a declared test suite that cannot be run from the release # artifact is a claim the recipient has to take on trust. only-include = ["src/shelfmark", "tests", "README.md", "LICENSE", "SECURITY.md", "CHANGELOG.md", "config.example.toml", "server.json", "pyproject.toml"]