[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "dominican-open-data-mcp" version = "0.15.0" description = "MCP server for datos.gob.do — Dominican Republic open government data portal (CKAN 2.11)" readme = "README.md" requires-python = ">=3.10" license = { text = "MIT" } authors = [{ name = "Alberto Castillo Aroca" }] keywords = [ "mcp", "datos-abiertos", "republica-dominicana", "open-data", "ckan", "gobierno", ] classifiers = [ "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", ] dependencies = [ # This server is written against the v2 SDK (2026-07-28 spec), where the # class is MCPServer and mcp.server.fastmcp no longer exists. There is no # shim in either direction, so the lower bound is as load-bearing as the # upper one: on mcp 1.x the import fails outright. Do NOT widen either end # without running the suite against the version you are widening to. "mcp>=2.1,<3", "httpx>=0.27", "openpyxl>=3.1", "duckdb>=1.0", "chardet>=5.2", "odfpy>=1.4", ] [project.optional-dependencies] # Kept for `pip install .[dev]`. The same three are repeated in # [dependency-groups].dev below so that a plain `uv sync` installs them: uv # syncs groups by default and extras only when asked, and a Windows tester # following the README got dozens of "fixture 'httpx_mock' not found" and a # reasonable belief that the server was broken on their platform. Two lists # named `dev` is the cost of both installers working; keep them in sync. dev = [ "pytest>=8.0", "pytest-asyncio>=0.23", "pytest-httpx>=0.30", "pytest-timeout>=2.3", ] # PREVIEW. These tools have unit tests against simulated clients and have # never been run against a live GCP project. They stay outside the API # stability promise until they have been. Everything in the base install has # been exercised against the real portal over a real protocol session. gcp = [ "google-cloud-storage>=2.14", "google-cloud-bigquery>=3.17", ] [project.scripts] datosgobdo-mcp = "datosgobdo_mcp.server:main" # Alias matching the PyPI distribution name so that the command implied by the # MCP Registry entry (`uvx dominican-open-data-mcp`) resolves. Without it uvx # errors with "An executable named ... is not provided by package". dominican-open-data-mcp = "datosgobdo_mcp.server:main" [tool.pytest.ini_options] asyncio_mode = "auto" testpaths = ["tests"] python_files = ["test_*.py"] addopts = "-ra --strict-markers --cov=datosgobdo_mcp --cov-report=term-missing --cov-fail-under=85" # A ceiling, not a target: the slowest test in the suite takes 1.3 s, so 120 s # means "this will never finish" rather than "this is slow". It exists because # two tests can hang rather than fail — the query-timeout test relies on # `con.interrupt()` actually interrupting, and the concurrency tests join child # processes — and a hung job in CI burns the runner's whole time budget before # anyone learns which test it was. timeout = 120 [tool.coverage.run] # No omits — the whole shipped package counts toward the floor. server.py and # ckan.py were previously excluded as "live-tested", but live tests are opt-in. [tool.coverage.report] exclude_lines = ["pragma: no cover", "if __name__"] [tool.ruff] line-length = 100 [tool.ruff.lint] select = ["E", "F", "W", "I", "UP"] ignore = ["E501"] [tool.mypy] python_version = "3.10" ignore_missing_imports = true warn_unused_ignores = false [project.urls] Homepage = "https://github.com/alcastaro/datos.gob.do-MCP-server" Repository = "https://github.com/alcastaro/datos.gob.do-MCP-server" Changelog = "https://github.com/alcastaro/datos.gob.do-MCP-server/blob/main/CHANGELOG.md" "Bug Tracker" = "https://github.com/alcastaro/datos.gob.do-MCP-server/issues" Portal = "https://datos.gob.do" [tool.hatch.build.targets.wheel] packages = ["src/datosgobdo_mcp"] [dependency-groups] # Everything needed to run the suite, so `uv sync && uv run pytest` works from a # clean clone with no flags to remember. The first three mirror the `dev` extra # above (see the note there). dev = [ "pytest>=8.0", "pytest-asyncio>=0.23", "pytest-httpx>=0.30", "pytest-timeout>=2.3", "mypy>=2.1.0", "pytest-cov>=7.1.0", "ruff>=0.15.15", ]