[project]
name = "semantic-code-mcp"
version = "0.1.0"
description = "Local MCP server for semantic code search"
readme = "README.md"
requires-python = ">=3.14"
dependencies = [
"lancedb>=0.27.0",
"mcp>=1.26.0",
"pandas>=3.0.0",
"pydantic>=2.12.5",
"pydantic-settings>=2.12.0",
"sentence-transformers>=5.2.0",
"structlog>=25.5.0",
"torch>=2.10.0",
"tree-sitter>=0.25.2",
"tree-sitter-python>=0.25.0",
]
[project.scripts]
semantic-code-mcp = "semantic_code_mcp:main"
[tool.uv.sources]
torch = [{ index = "pytorch-cpu" }]
[[tool.uv.index]]
name = "pytorch-cpu"
url = "https://download.pytorch.org/whl/cpu"
explicit = true
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/semantic_code_mcp"]
[dependency-groups]
dev = [
"pre-commit>=4.5.1",
"pyinstrument>=5.1.2",
"pytest>=9.0.2",
"pytest-asyncio>=1.3.0",
"ruff>=0.14.14",
"ty>=0.0.13",
]
[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
testpaths = ["tests"]
[tool.ruff]
target-version = "py314"
line-length = 100
src = ["src"]
fix = true
exclude = [
".git",
".venv",
"__pycache__",
"*.pyc",
"build",
"dist",
]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
docstring-code-format = true
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"UP", # pyupgrade
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"C901", # mccabe complexity
"N", # pep8-naming
"SIM", # flake8-simplify
"TID", # tidy imports (banned relative imports, etc.)
"W", # pycodestyle warnings
"RUF", # Ruff-specific rules
"DTZ", # datetime timezone safety
"ASYNC", # async anti-patterns (blocking calls in async)
"SLF", # private member access from outside class
"PIE", # misc. lints (unnecessary pass, dict merge, etc.)
"T20", # no print() in source (use structlog)
"RSE", # unnecessary parens on raise
# "TCH" omitted — too aggressive, flags Path and other runtime imports
"PERF", # performance anti-patterns
"FURB", # refurb modernizations
"PLC0415", # import-outside-toplevel
]
ignore = [
"E712", # == True comparisons (sometimes needed for SQL expressions)
"SIM108", # ternary operator — if/else often more readable
"SIM103", # return condition directly — explicit if/return often more readable
"PERF203", # try/except in loop — often necessary, not always avoidable
"FURB140", # Use itertools.starmap — less readable than comprehensions
]
[tool.ruff.lint.mccabe]
max-complexity = 12
[tool.ruff.lint.isort]
combine-as-imports = true
known-first-party = ["semantic_code_mcp"]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
"tests/**/*.py" = ["D", "ANN", "SLF001", "T20", "DTZ", "PLC0415"]
[tool.ty.environment]
python-version = "3.14"
[tool.ty.rules]
possibly-missing-attribute = "warn"
no-matching-overload = "warn"
invalid-assignment = "warn"
invalid-return-type = "warn"
invalid-argument-type = "warn"
missing-argument = "warn"
[tool.bandit]
exclude_dirs = ["tests", ".venv"]
skips = ["B101"] # assert used in tests