Skip to main content
Glama

MCP Code Analysis Server

MIT License
5
pyproject.toml12.5 kB
[project] name = "mcp-code-analysis-server" version = "0.1.0" description = "MCP server for intelligent code analysis and search capabilities" readme = "README.md" requires-python = ">=3.11" authors = [ {name = "MCP Code Analysis Team", email = "team@example.com"} ] license = {text = "MIT"} keywords = ["mcp", "code-analysis", "treesitter", "embeddings", "search"] classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", ] dependencies = [ # MCP Framework "fastmcp>=0.1.0", # LangChain/LangGraph "langchain-core>=0.1.0", "langgraph>=0.0.20", "langchain-openai>=0.0.5", # Database "psycopg2-binary>=2.9.9", "sqlalchemy>=2.0.0", "alembic>=1.13.0", "asyncpg>=0.29.0", "pgvector>=0.2.4", # Code Parsing "tree-sitter>=0.20.4", "tree-sitter-python>=0.20.4", "tree-sitter-php>=0.23.0", "tree-sitter-java>=0.23.0", "tree-sitter-typescript>=0.23.0", "tree-sitter-javascript>=0.23.0", "GitPython>=3.1.40", # Web Framework "fastapi>=0.109.0", "uvicorn>=0.25.0", "httpx>=0.25.0", "pydantic>=2.5.0", "pydantic-settings>=2.1.0", # Utilities "pyyaml>=6.0.1", "click>=8.1.7", "python-dotenv>=1.0.0", "rich>=13.7.0", "tenacity>=8.2.3", "aiofiles>=23.2.1", # Configuration and Logging "dynaconf>=3.2.0", "structlog>=24.0.0", # OpenAI "openai>=1.10.0", "tiktoken>=0.5.2", # Data Processing "numpy>=1.26.0", "pandas>=2.1.0", # Graph Analysis "networkx>=3.2", "igraph>=0.11.3", # Python 3.12 compatible python-igraph for Leiden algorithm ] [project.urls] Homepage = "https://github.com/johannhartmann/mcp-code-analysis-server" Repository = "https://github.com/johannhartmann/mcp-code-analysis-server" Issues = "https://github.com/johannhartmann/mcp-code-analysis-server/issues" [project.optional-dependencies] dev = [ # Testing "pytest>=7.4.0", "pytest-asyncio>=0.21.0", "pytest-cov>=4.1.0", "pytest-mock>=3.12.0", "aiosqlite>=0.19.0", # For async SQLite in tests "pytest-xdist>=3.5.0", # parallel test execution "pytest-timeout>=2.2.0", # test timeouts "pytest-benchmark>=4.0.0", # performance testing "hypothesis>=6.92.0", # property-based testing "faker>=22.0.0", # test data generation # Code Quality "black>=23.12.0", "ruff>=0.1.0", "mypy>=1.8.0", "pre-commit>=3.6.0", "isort>=5.13.0", # import sorting "bandit>=1.7.5", # security linting "safety>=3.0.0", # dependency security check "pylint>=3.0.0", # additional linting "pyupgrade>=3.15.0", # upgrade Python syntax "vulture>=2.10", # dead code detection # Type stubs "types-pyyaml>=6.0.0", "types-requests>=2.31.0", "pandas-stubs>=2.1.0", "types-click>=7.1.0", # Documentation "mkdocs>=1.5.0", "mkdocs-material>=9.5.0", "mkdocstrings[python]>=0.24.0", # Development tools "ipdb>=0.13.13", # debugger "python-semantic-release>=8.7.0", # versioning ] [project.scripts] mcp-code-server = "src.mcp_server.main:main" mcp-scanner = "src.scanner.main:main" mcp-indexer = "src.indexer.main:main" [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["src"] [tool.black] line-length = 88 target-version = ['py311'] include = '\.pyi?$' extend-exclude = ''' /( # directories \.eggs | \.git | \.hg | \.mypy_cache | \.tox | \.venv | build | dist )/ ''' [tool.ruff] target-version = "py311" line-length = 88 [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "C", # flake8-comprehensions "B", # flake8-bugbear "UP", # pyupgrade "N", # pep8-naming "YTT", # flake8-2020 "ANN", # flake8-annotations "ASYNC",# flake8-async "S", # flake8-bandit "BLE", # flake8-blind-except "FBT", # flake8-boolean-trap "A", # flake8-builtins "COM", # flake8-commas "C4", # flake8-comprehensions "DTZ", # flake8-datetimez "T10", # flake8-debugger "ISC", # flake8-implicit-str-concat "ICN", # flake8-import-conventions "G", # flake8-logging-format "INP", # flake8-no-pep420 "PIE", # flake8-pie "PT", # flake8-pytest-style "Q", # flake8-quotes "RSE", # flake8-raise "RET", # flake8-return "SLF", # flake8-self "SLOT", # flake8-slots "SIM", # flake8-simplify "TID", # flake8-tidy-imports "TCH", # flake8-type-checking "ARG", # flake8-unused-arguments "PTH", # flake8-use-pathlib "TD", # flake8-todos "FIX", # flake8-fixme "ERA", # eradicate "PGH", # pygrep-hooks "PL", # Pylint "TRY", # tryceratops "FLY", # flynt "NPY", # NumPy-specific rules "PERF", # Perflint "RUF", # Ruff-specific rules ] ignore = [ "E501", # line too long (handled by black) "B008", # do not perform function calls in argument defaults "C901", # too complex "W191", # indentation contains tabs "ANN401",# dynamically typed expressions (Any) "S101", # use of assert detected "TD003", # missing issue link on TODO "FIX002",# line contains TODO "PLR0913",# too many arguments "ANN001",# missing type annotation for function argument "ANN002",# missing type annotation for *args "ANN003",# missing type annotation for **kwargs "ANN201",# missing return type annotation for public function "ANN202",# missing return type annotation for private function "ANN204",# missing return type annotation for special method "ANN205",# missing return type annotation for staticmethod "ANN206",# missing return type annotation for classmethod "D100", # Missing docstring in public module "D101", # Missing docstring in public class "D102", # Missing docstring in public method "D103", # Missing docstring in public function "D104", # Missing docstring in public package "D105", # Missing docstring in magic method "D106", # Missing docstring in public nested class "D107", # Missing docstring in __init__ "UP006", # Use `list` instead of `List` for type annotations "UP007", # Use `X | Y` for type annotations "UP037", # Remove quotes from type annotation (needed for SQLAlchemy forward refs) "SLF001", # Private member access (sometimes necessary) "COM812", # Trailing comma missing (style preference) "PLC0415", # Import outside top level (needed for lazy loading) "TRY300", # Try-consider-else (often not practical) "INP001", # Implicit namespace package (not all dirs need __init__.py) "S607", # Start process with partial path (handled by environment) "S106", # Hardcoded password func arg (false positives on test fixtures) "S108", # Hardcoded temp file (test fixtures) "RUF006", # Asyncio dangling task (we handle task lifecycle properly) "ASYNC221", # Run process in async function (necessary for git operations) "ASYNC110", # Async busy wait (sometimes necessary for polling) "S104", # Hardcoded bind all interfaces (config controlled) "S105", # Hardcoded password string (test data) "FBT001", # Boolean type hint positional (API design choice) "FBT002", # Boolean default value positional (API design choice) "FBT003", # Boolean positional value in function call (Pydantic Field) "PLR2004", # Magic value used in comparison (tolerance values) ] fixable = ["ALL"] unfixable = [] [tool.ruff.lint.per-file-ignores] "__init__.py" = ["F401", "D104"] "tests/**/*.py" = ["S101", "ARG", "FBT", "PLR2004", "PLR0913", "TRY003", "SIM117"] "src/mcp_server/tools/*.py" = ["ANN201", "PLR0911", "PLR0912", "PLR0915"] # MCP tools complexity "src/query/ranking.py" = ["PLR0915", "PLR0912"] #TODO "src/query/search_engine.py" = ["PLR0912"] #TODO "src/mcp_server/server.py" = ["PLW0603"] # global statements for shared resources "src/mcp_server/config.py" = ["PLW0603"] # global statements for singleton config "src/mcp_server/tools/explain.py" = ["PERF401"] # false positive on list append "src/parser/code_extractor.py" = ["PERF401"] # false positive on list append "src/scanner/github_monitor.py" = ["PERF401"] # false positive on list append "src/embeddings/embedding_generator.py" = ["PLR0912"] # complex chunking logic [tool.ruff.lint.isort] known-third-party = ["fastapi", "pydantic", "sqlalchemy", "langchain", "langgraph", "fastmcp"] combine-as-imports = true force-wrap-aliases = true [tool.ruff.lint.flake8-tidy-imports] ban-relative-imports = "all" [tool.ruff.lint.flake8-pytest-style] fixture-parentheses = false mark-parentheses = false [tool.ruff.lint.pydocstyle] convention = "google" [tool.mypy] python_version = "3.11" warn_return_any = true warn_unused_configs = true disallow_untyped_defs = true disallow_incomplete_defs = true check_untyped_defs = true no_implicit_optional = true warn_redundant_casts = true warn_unused_ignores = true warn_no_return = true follow_imports = "normal" ignore_missing_imports = true plugins = ['pydantic.mypy', 'sqlalchemy.ext.mypy.plugin'] [tool.pydantic-mypy] init_forbid_extra = true init_typed = true warn_required_dynamic_aliases = true [tool.pytest.ini_options] minversion = "7.0" addopts = [ "-ra", "-q", "--strict-markers", "--strict-config", "--cov=src", "--cov-branch", "--cov-report=term-missing:skip-covered", "--cov-report=html", "--cov-report=xml", "--cov-fail-under=0", "--no-cov-on-fail", "--timeout=300", "--durations=10", ] testpaths = ["tests"] pythonpath = ["src"] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" markers = [ "slow: marks tests as slow (deselect with '-m \"not slow\"')", "integration: marks tests as integration tests", "unit: marks tests as unit tests", "requires_db: marks tests that require database", "requires_openai: marks tests that require OpenAI API", ] filterwarnings = [ "error", "ignore::UserWarning", "ignore::DeprecationWarning", ] [tool.coverage.run] source = ["src"] omit = [ "*/tests/*", "*/test_*.py", "*/__init__.py", "*/migrations/*", "*/conftest.py", ] parallel = true [tool.coverage.report] precision = 2 show_missing = true skip_covered = false exclude_lines = [ "pragma: no cover", "def __repr__", "if self.debug:", "if settings.DEBUG", "raise AssertionError", "raise NotImplementedError", "if 0:", "if __name__ == .__main__.:", "if TYPE_CHECKING:", "class .*\\bProtocol\\):", "@(abc\\.)?abstractmethod", ] [tool.coverage.html] directory = "htmlcov" [tool.isort] profile = "black" multi_line_output = 3 include_trailing_comma = true force_grid_wrap = 0 use_parentheses = true ensure_newline_before_comments = true line_length = 88 known_third_party = ["fastapi", "pydantic", "sqlalchemy", "langchain", "langgraph", "fastmcp"] known_first_party = ["src"] sections = ["FUTURE", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"] [tool.bandit] targets = ["src"] exclude_dirs = ["tests", "docs"] severity = "medium" confidence = "medium" skips = ["B101", "B601"] [tool.pylint.main] py-version = "3.11" jobs = 0 persistent = true suggestion-mode = true exit-zero = false [tool.pylint.messages_control] enable = ["all"] disable = [ "missing-module-docstring", "missing-class-docstring", "missing-function-docstring", "too-few-public-methods", "too-many-arguments", "too-many-instance-attributes", "too-many-locals", "too-many-branches", "fixme", "import-outside-toplevel", ] [tool.pylint.format] max-line-length = 88 [tool.pylint.basic] good-names = ["i", "j", "k", "e", "x", "y", "z", "id", "db", "df"] [tool.semantic_release] version_toml = ["pyproject.toml:project.version"] version_pattern = ["src/__init__.py:__version__"] branch = "main" upload_to_pypi = false upload_to_release = true build_command = "python -m build" commit_subject = "chore(release): v{version}" [tool.vulture] min_confidence = 80 paths = ["src", "tests"] exclude = ["vulture_whitelist.py"] [dependency-groups] dev = [ "httpx>=0.28.1", ]

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/johannhartmann/mcpcodeanalysis'

If you have feedback or need assistance with the MCP directory API, please join our Discord server