-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathpyproject.toml
More file actions
236 lines (216 loc) · 7.63 KB
/
Copy pathpyproject.toml
File metadata and controls
236 lines (216 loc) · 7.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
[project]
name = "mcpg"
# Version is single-sourced from src/mcpg/__init__.py (__version__) and read
# here dynamically by hatchling — see [tool.hatch.version]. A release bumps
# exactly one line, so pip, `mcpg --version`, and the MCP serverInfo
# handshake can never disagree.
dynamic = ["version"]
description = "A production-grade PostgreSQL Model Context Protocol (MCP) server."
readme = "README.md"
requires-python = ">=3.12"
license = "MIT"
license-files = ["LICENSE", "src/mcpg/_vendor/LICENSE"]
authors = [
{name = "Devopam Mittra", email = "devopam@gmail.com"},
]
maintainers = [
{name = "Devopam Mittra", email = "devopam@gmail.com"},
]
keywords = [
"postgresql",
"postgres",
"mcp",
"model-context-protocol",
"ai-agents",
"llm-tools",
"database",
"claude",
"anthropic",
"dba",
"sql",
"rag",
]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: SQL",
"Topic :: Database",
"Topic :: Database :: Database Engines/Servers",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: System :: Systems Administration",
"Typing :: Typed",
]
dependencies = [
"mcp[cli]>=1.28.1,<2",
"psycopg[binary]>=3.3.2",
"psycopg-pool>=3.3.0",
"pglast==8.4",
"typing-extensions>=4.12",
# httpx ships transitively via mcp; declare it explicitly so the
# NL→SQL providers in mcpg.nl2sql have a guaranteed surface.
"httpx>=0.27",
# JWT validation for the OIDC auth path. ``[crypto]`` pulls in
# ``cryptography`` so RS256 / ES256 signature checks work.
"pyjwt[crypto]>=2.8",
]
# Optional extras the runtime picks up only on demand. ``otel`` adds
# OpenTelemetry tracing — one span per ``call_tool`` invocation —
# behind the ``MCPG_OTEL_ENABLED`` flag. The api/sdk pair are the
# trace machinery; the exporter ships traces to any OTLP-compatible
# collector over HTTP/protobuf.
[project.optional-dependencies]
otel = [
"opentelemetry-api>=1.27",
"opentelemetry-sdk>=1.27",
"opentelemetry-exporter-otlp-proto-http>=1.27",
]
# Cloud secrets backends — selected by ``MCPG_SECRETS_BACKEND=vault|aws|gcp``.
# Each is its own extra so a deployment doesn't pay for every cloud SDK
# when it only uses one. The SDKs are imported lazily inside the
# provider class, so the import / install error is surfaced with a
# clear "install mcpg[xxx]" message on first lookup if the operator
# selected a backend but forgot the extra.
vault = ["hvac>=1.0"]
aws = ["boto3>=1.28"]
gcp = ["google-cloud-secret-manager>=2.16"]
# Powers the "Project links" sidebar on https://pypi.org/project/mcpg/.
# Order is preserved on the page; first entry doubles as the page header
# "Homepage" link.
[project.urls]
Homepage = "https://github.com/devopam/MCPg"
Documentation = "https://github.com/devopam/MCPg#documentation"
Repository = "https://github.com/devopam/MCPg"
Issues = "https://github.com/devopam/MCPg/issues"
Changelog = "https://github.com/devopam/MCPg/blob/main/CHANGELOG.md"
"Release notes" = "https://github.com/devopam/MCPg/releases"
Security = "https://github.com/devopam/MCPg/blob/main/SECURITY.md"
[project.scripts]
mcpg = "mcpg.__main__:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
# Single source of truth for the version: hatchling reads ``__version__``
# from this file at build time (its built-in regex version source), so the
# project version, ``mcpg --version``, and the MCP serverInfo handshake all
# derive from one line. Bump src/mcpg/__init__.py and nothing else.
[tool.hatch.version]
path = "src/mcpg/__init__.py"
[tool.hatch.build.targets.wheel]
packages = ["src/mcpg"]
# Keep the sdist tight — ship the source tree + the prose a user
# actually wants when they unpack from PyPI, and leave dev-only
# noise (tests / CI / IDE / VCS cruft) on GitHub.
[tool.hatch.build.targets.sdist]
include = [
"src/mcpg",
"README.md",
"LICENSE",
"NOTICE",
"CHANGELOG.md",
"SECURITY.md",
"pyproject.toml",
]
[dependency-groups]
dev = [
"pytest>=9.0.2",
"pytest-asyncio>=1.3.0",
"pytest-cov>=6.0.0",
"docker>=7.1.0",
"ruff>=0.14.0",
"mypy>=1.15.0",
"pre-commit>=4.0.0",
"bandit>=1.7.8",
"pip-audit>=2.7",
# PyPI packaging toolchain — build the sdist/wheel, lint the
# rendered metadata, push to PyPI in the publish workflow.
"build>=1.2",
"twine>=5.1",
# OpenTelemetry SDK + OTLP HTTP exporter — pinned in dev so the
# otel-tracing unit tests can use the InMemorySpanExporter and so
# `mcpg[otel]` round-trips through CI. Production deployments
# opt in via the ``mcpg[otel]`` extra rather than dev install.
"opentelemetry-api>=1.27",
"opentelemetry-sdk>=1.27",
"opentelemetry-exporter-otlp-proto-http>=1.27",
]
# Benchmark suite (roadmap 19) — dev-only. Keeps the shipped package lean;
# `duckdb` generates the TPC-H dataset for benchmarks/datasets/load_tpch.py,
# `tiktoken` counts tokens for the Tier-A token-efficiency accounting
# (benchmarks/tokens/), and `anthropic` drives the costed Tier-B agent-loop
# study (benchmarks/tokens/tier_b/ — never run in CI).
bench = [
"duckdb>=1.1",
"tiktoken>=0.7",
"anthropic>=0.40",
]
[tool.pytest.ini_options]
# "." so the root-level ``benchmarks`` package (roadmap 19) is importable in
# its unit tests; "src" for mcpg, "tests" for the _fakes helpers.
pythonpath = ["src", "tests", "."]
testpaths = ["tests"]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
markers = [
"integration: requires a live PostgreSQL (set MCPG_TEST_DATABASE_URL)",
]
filterwarnings = [
# pytest resets warnings.filters per test, so the runtime filter
# mcpg/__init__.py installs (same pattern, kept in sync manually)
# doesn't survive into test collection — repeat it here so the ~180
# tool-return dataclasses with a `schema` field don't spam every test
# that touches Tool.output_schema.
'ignore:Field name ".*" in ".*" shadows an attribute in parent "BaseModel":UserWarning',
]
[tool.coverage.run]
source = ["src/mcpg"]
[tool.coverage.report]
# Coverage gate applies to all authored code — the SQL kernel is first-party.
fail_under = 90
show_missing = true
[tool.ruff]
line-length = 120
target-version = "py312"
extend-exclude = ["scratch", "demo.py"]
# Honour the exclusions even when files are passed explicitly (e.g. pre-commit).
force-exclude = true
[tool.ruff.lint]
select = ["E", "F", "I", "B", "W", "N", "UP", "RUF"]
[tool.ruff.lint.isort]
known-first-party = ["mcpg"]
[tool.mypy]
python_version = "3.14"
strict = true
exclude = ["scratch/"]
[[tool.mypy.overrides]]
# pglast ships partial type hints (as of v8); ignore import-resolution gaps
# for the submodules we don't have full types for.
module = ["pglast", "pglast.*"]
ignore_missing_imports = true
[[tool.mypy.overrides]]
# Optional cloud-secrets SDKs ship without typed stubs we want to lean
# on — the providers in mcpg.secrets import them lazily and convert
# everything to plain ``str | None`` before re-exposing the API.
module = [
"hvac",
"hvac.*",
"boto3",
"boto3.*",
"botocore",
"botocore.*",
"google.cloud",
"google.cloud.*",
"google.api_core",
"google.api_core.*",
]
ignore_missing_imports = true
[tool.bandit]
exclude_dirs = ["tests"]
skips = ["B101", "B608", "B110"]