tabulus 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,75 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, "pivot/**"]
6
+ tags: ["v*.*.*"]
7
+ pull_request:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: ci-${{ github.ref }}
14
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
15
+
16
+ jobs:
17
+ test:
18
+ name: Python ${{ matrix.python }}
19
+ runs-on: ubuntu-latest
20
+ strategy:
21
+ fail-fast: false
22
+ matrix:
23
+ python: ["3.11", "3.12"]
24
+
25
+ services:
26
+ postgres:
27
+ image: postgres:16
28
+ env:
29
+ POSTGRES_PASSWORD: test
30
+ ports:
31
+ - 5432:5432
32
+ options: >-
33
+ --health-cmd pg_isready
34
+ --health-interval 5s
35
+ --health-timeout 3s
36
+ --health-retries 5
37
+
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+
41
+ - uses: actions/setup-python@v5
42
+ with:
43
+ python-version: ${{ matrix.python }}
44
+ cache: pip
45
+ cache-dependency-path: pyproject.toml
46
+
47
+ - name: Install
48
+ run: pip install -e ".[dev]"
49
+
50
+ - name: Lint
51
+ run: ruff check .
52
+
53
+ - name: Format check
54
+ run: ruff format --check .
55
+
56
+ - name: Unit tests
57
+ run: pytest tests/ -v --tb=short
58
+
59
+ - name: Integration smoke (live Postgres)
60
+ env:
61
+ DATABASE_URL: postgres://postgres:test@localhost:5432/postgres
62
+ run: |
63
+ python -c "
64
+ import asyncio
65
+ from vigil.config import load
66
+ from vigil.db import get_pool, list_tables, close_pool
67
+ async def main():
68
+ pool = await get_pool(load())
69
+ await pool.execute('CREATE TABLE smoke (id int)')
70
+ tables = await list_tables(pool)
71
+ assert any(t['name'] == 'smoke' for t in tables), 'smoke table missing'
72
+ print('Integration OK')
73
+ await close_pool()
74
+ asyncio.run(main())
75
+ "
@@ -0,0 +1,51 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*.*.*"]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+ id-token: write # required for PyPI trusted publishing
11
+
12
+ jobs:
13
+ build:
14
+ name: Build wheel + sdist
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.12"
22
+
23
+ - name: Install build tools
24
+ run: pip install build
25
+
26
+ - name: Build
27
+ run: python -m build
28
+
29
+ - name: Upload artifacts
30
+ uses: actions/upload-artifact@v4
31
+ with:
32
+ name: dist
33
+ path: dist/
34
+
35
+ publish:
36
+ name: Publish to PyPI
37
+ runs-on: ubuntu-latest
38
+ needs: build
39
+ if: startsWith(github.ref, 'refs/tags/v')
40
+ environment:
41
+ name: pypi
42
+ url: https://pypi.org/p/tabulus
43
+ steps:
44
+ - name: Download artifacts
45
+ uses: actions/download-artifact@v4
46
+ with:
47
+ name: dist
48
+ path: dist/
49
+
50
+ - name: Publish via OIDC (no API token)
51
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,17 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .pytest_cache/
5
+ .ruff_cache/
6
+ .venv/
7
+ venv/
8
+ build/
9
+ dist/
10
+ *.whl
11
+
12
+ .env
13
+ .env.local
14
+
15
+ .vscode/
16
+ .idea/
17
+ .DS_Store
@@ -0,0 +1,14 @@
1
+ {
2
+ "mcpServers": {
3
+ "vigil": {
4
+ "command": ".venv/bin/vigil",
5
+ "args": [],
6
+ "env": {
7
+ "DATABASE_URL": "postgres://postgres:dev@localhost:5433/postgres",
8
+ "VIGIL_MAX_ROWS": "100",
9
+ "VIGIL_SAMPLE_SIZE": "3",
10
+ "VIGIL_STATEMENT_TIMEOUT_MS": "5000"
11
+ }
12
+ }
13
+ }
14
+ }
tabulus-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 WalkingMountain
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
tabulus-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,144 @@
1
+ Metadata-Version: 2.4
2
+ Name: tabulus
3
+ Version: 0.0.1
4
+ Summary: Postgres MCP server — agent-first database workbench
5
+ Project-URL: Repository, https://github.com/WalkingMountain/vigilmcp
6
+ Project-URL: Issues, https://github.com/WalkingMountain/vigilmcp/issues
7
+ Author: WalkingMountain
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: agent,claude,cursor,database,mcp,postgres,sql
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Database
17
+ Requires-Python: >=3.11
18
+ Requires-Dist: asyncpg>=0.30
19
+ Requires-Dist: mcp>=1.0.0
20
+ Requires-Dist: pydantic>=2.0
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
23
+ Requires-Dist: pytest>=8.0; extra == 'dev'
24
+ Requires-Dist: ruff>=0.7; extra == 'dev'
25
+ Description-Content-Type: text/markdown
26
+
27
+ # Vigil
28
+
29
+ **A Postgres MCP server built for AI agents.**
30
+
31
+ Vigil is the database workbench for the AI-augmented developer. Connect Claude
32
+ Code, Cursor, or any MCP-compatible client to your Postgres database and let
33
+ the agent introspect the schema, sample data, and write safe queries — without
34
+ copy-pasting schemas into chat windows.
35
+
36
+ ## Why
37
+
38
+ Every modern dev workflow now includes an AI agent. Every DB GUI was designed
39
+ before that was true. Vigil flips the model: **the agent is a first-class user,
40
+ not a sidebar feature.**
41
+
42
+ What that means in practice:
43
+
44
+ - Schema introspection optimized for LLM context windows (compact JSON, foreign
45
+ keys flattened, sample rows inline).
46
+ - Read-only by default — `INSERT`/`UPDATE`/`DELETE`/`DDL` are rejected at the
47
+ gateway. Agent can't drop your tables.
48
+ - `EXPLAIN` exposed as a tool so the agent can reason about query plans before
49
+ proposing optimizations.
50
+ - Statement timeout + row cap enforced server-side. No agent can DOS your
51
+ database by accident.
52
+
53
+ ## Status
54
+
55
+ **v0.0.1 — alpha.** Postgres only. Stdio MCP transport only. No GUI yet.
56
+
57
+ ## Install
58
+
59
+ ```bash
60
+ pip install tabulus
61
+ ```
62
+
63
+ ## Run
64
+
65
+ ```bash
66
+ export DATABASE_URL=postgres://user:pass@host:5432/dbname
67
+ vigil
68
+ ```
69
+
70
+ Then point your MCP client at the `vigil` command.
71
+
72
+ ### Claude Code (project-level)
73
+
74
+ Create `.mcp.json` in your project root:
75
+
76
+ ```jsonc
77
+ {
78
+ "mcpServers": {
79
+ "vigil": {
80
+ "command": "vigil",
81
+ "args": [],
82
+ "env": {
83
+ "DATABASE_URL": "postgres://user:pass@host:5432/dbname"
84
+ }
85
+ }
86
+ }
87
+ }
88
+ ```
89
+
90
+ Restart Claude Code in that directory and approve the trust prompt.
91
+
92
+ ### Claude Code (user-level via CLI)
93
+
94
+ ```bash
95
+ claude mcp add vigil "$(which vigil)" --env DATABASE_URL=postgres://user:pass@host:5432/dbname
96
+ ```
97
+
98
+ ### Cursor
99
+
100
+ Add to `~/.cursor/mcp_servers.json`:
101
+
102
+ ```jsonc
103
+ {
104
+ "mcpServers": {
105
+ "vigil": {
106
+ "command": "vigil",
107
+ "env": { "DATABASE_URL": "postgres://user:pass@host:5432/dbname" }
108
+ }
109
+ }
110
+ }
111
+ ```
112
+
113
+ ## Tools
114
+
115
+ | Tool | Description |
116
+ |---|---|
117
+ | `list_tables` | All tables with row count estimates + sizes |
118
+ | `describe_schema` | Columns, PK, FKs, indexes, sample rows for a table |
119
+ | `sample_rows` | Random sample from a table |
120
+ | `safe_select` | Run a read-only SELECT (write keywords rejected) |
121
+ | `explain` | Get query plan (EXPLAIN FORMAT JSON) |
122
+
123
+ ## Configuration
124
+
125
+ | Variable | Default | Purpose |
126
+ |---|---|---|
127
+ | `DATABASE_URL` | — (required) | Postgres connection URL |
128
+ | `VIGIL_MAX_ROWS` | `100` | Hard cap on rows returned by any tool |
129
+ | `VIGIL_SAMPLE_SIZE` | `3` | Sample rows included in `describe_schema` |
130
+ | `VIGIL_STATEMENT_TIMEOUT_MS` | `5000` | Server-side query timeout |
131
+ | `VIGIL_REDACT` | `off` | Set `on` to scrub PII (emails, API keys, JWTs, credit cards, phones, IPs) from `sample_rows`, `safe_select`, and `describe_schema` output before the agent sees it. Recommended for production. |
132
+ | `VIGIL_ALLOW_WRITES` | `false` | Set `true` to disable the write block (NOT recommended) |
133
+
134
+ ## Roadmap
135
+
136
+ - v0.1 — Postgres parity, polished install
137
+ - v0.2 — SQLite adapter
138
+ - v0.3 — MySQL / MariaDB adapter
139
+ - v0.x — Tauri desktop GUI shell on top of the same core
140
+ - v1.0 — Stable, cross-platform, multi-DB
141
+
142
+ ## License
143
+
144
+ MIT. See [LICENSE](./LICENSE).
@@ -0,0 +1,118 @@
1
+ # Vigil
2
+
3
+ **A Postgres MCP server built for AI agents.**
4
+
5
+ Vigil is the database workbench for the AI-augmented developer. Connect Claude
6
+ Code, Cursor, or any MCP-compatible client to your Postgres database and let
7
+ the agent introspect the schema, sample data, and write safe queries — without
8
+ copy-pasting schemas into chat windows.
9
+
10
+ ## Why
11
+
12
+ Every modern dev workflow now includes an AI agent. Every DB GUI was designed
13
+ before that was true. Vigil flips the model: **the agent is a first-class user,
14
+ not a sidebar feature.**
15
+
16
+ What that means in practice:
17
+
18
+ - Schema introspection optimized for LLM context windows (compact JSON, foreign
19
+ keys flattened, sample rows inline).
20
+ - Read-only by default — `INSERT`/`UPDATE`/`DELETE`/`DDL` are rejected at the
21
+ gateway. Agent can't drop your tables.
22
+ - `EXPLAIN` exposed as a tool so the agent can reason about query plans before
23
+ proposing optimizations.
24
+ - Statement timeout + row cap enforced server-side. No agent can DOS your
25
+ database by accident.
26
+
27
+ ## Status
28
+
29
+ **v0.0.1 — alpha.** Postgres only. Stdio MCP transport only. No GUI yet.
30
+
31
+ ## Install
32
+
33
+ ```bash
34
+ pip install tabulus
35
+ ```
36
+
37
+ ## Run
38
+
39
+ ```bash
40
+ export DATABASE_URL=postgres://user:pass@host:5432/dbname
41
+ vigil
42
+ ```
43
+
44
+ Then point your MCP client at the `vigil` command.
45
+
46
+ ### Claude Code (project-level)
47
+
48
+ Create `.mcp.json` in your project root:
49
+
50
+ ```jsonc
51
+ {
52
+ "mcpServers": {
53
+ "vigil": {
54
+ "command": "vigil",
55
+ "args": [],
56
+ "env": {
57
+ "DATABASE_URL": "postgres://user:pass@host:5432/dbname"
58
+ }
59
+ }
60
+ }
61
+ }
62
+ ```
63
+
64
+ Restart Claude Code in that directory and approve the trust prompt.
65
+
66
+ ### Claude Code (user-level via CLI)
67
+
68
+ ```bash
69
+ claude mcp add vigil "$(which vigil)" --env DATABASE_URL=postgres://user:pass@host:5432/dbname
70
+ ```
71
+
72
+ ### Cursor
73
+
74
+ Add to `~/.cursor/mcp_servers.json`:
75
+
76
+ ```jsonc
77
+ {
78
+ "mcpServers": {
79
+ "vigil": {
80
+ "command": "vigil",
81
+ "env": { "DATABASE_URL": "postgres://user:pass@host:5432/dbname" }
82
+ }
83
+ }
84
+ }
85
+ ```
86
+
87
+ ## Tools
88
+
89
+ | Tool | Description |
90
+ |---|---|
91
+ | `list_tables` | All tables with row count estimates + sizes |
92
+ | `describe_schema` | Columns, PK, FKs, indexes, sample rows for a table |
93
+ | `sample_rows` | Random sample from a table |
94
+ | `safe_select` | Run a read-only SELECT (write keywords rejected) |
95
+ | `explain` | Get query plan (EXPLAIN FORMAT JSON) |
96
+
97
+ ## Configuration
98
+
99
+ | Variable | Default | Purpose |
100
+ |---|---|---|
101
+ | `DATABASE_URL` | — (required) | Postgres connection URL |
102
+ | `VIGIL_MAX_ROWS` | `100` | Hard cap on rows returned by any tool |
103
+ | `VIGIL_SAMPLE_SIZE` | `3` | Sample rows included in `describe_schema` |
104
+ | `VIGIL_STATEMENT_TIMEOUT_MS` | `5000` | Server-side query timeout |
105
+ | `VIGIL_REDACT` | `off` | Set `on` to scrub PII (emails, API keys, JWTs, credit cards, phones, IPs) from `sample_rows`, `safe_select`, and `describe_schema` output before the agent sees it. Recommended for production. |
106
+ | `VIGIL_ALLOW_WRITES` | `false` | Set `true` to disable the write block (NOT recommended) |
107
+
108
+ ## Roadmap
109
+
110
+ - v0.1 — Postgres parity, polished install
111
+ - v0.2 — SQLite adapter
112
+ - v0.3 — MySQL / MariaDB adapter
113
+ - v0.x — Tauri desktop GUI shell on top of the same core
114
+ - v1.0 — Stable, cross-platform, multi-DB
115
+
116
+ ## License
117
+
118
+ MIT. See [LICENSE](./LICENSE).
@@ -0,0 +1,51 @@
1
+ [project]
2
+ name = "tabulus"
3
+ version = "0.0.1"
4
+ description = "Postgres MCP server — agent-first database workbench"
5
+ authors = [{name = "WalkingMountain"}]
6
+ license = {text = "MIT"}
7
+ requires-python = ">=3.11"
8
+ readme = "README.md"
9
+ keywords = ["postgres", "mcp", "claude", "cursor", "database", "agent", "sql"]
10
+ classifiers = [
11
+ "Development Status :: 3 - Alpha",
12
+ "Intended Audience :: Developers",
13
+ "License :: OSI Approved :: MIT License",
14
+ "Programming Language :: Python :: 3.11",
15
+ "Programming Language :: Python :: 3.12",
16
+ "Topic :: Database",
17
+ ]
18
+ dependencies = [
19
+ "mcp>=1.0.0",
20
+ "asyncpg>=0.30",
21
+ "pydantic>=2.0",
22
+ ]
23
+
24
+ [project.optional-dependencies]
25
+ dev = [
26
+ "pytest>=8.0",
27
+ "pytest-asyncio>=0.24",
28
+ "ruff>=0.7",
29
+ ]
30
+
31
+ [project.scripts]
32
+ vigil = "vigil.cli:main"
33
+
34
+ [project.urls]
35
+ Repository = "https://github.com/WalkingMountain/vigilmcp"
36
+ Issues = "https://github.com/WalkingMountain/vigilmcp/issues"
37
+
38
+ [build-system]
39
+ requires = ["hatchling"]
40
+ build-backend = "hatchling.build"
41
+
42
+ [tool.hatch.build.targets.wheel]
43
+ packages = ["src/vigil"]
44
+
45
+ [tool.ruff]
46
+ line-length = 100
47
+ target-version = "py311"
48
+
49
+ [tool.pytest.ini_options]
50
+ asyncio_mode = "auto"
51
+ testpaths = ["tests"]
@@ -0,0 +1,3 @@
1
+ """Vigil — Postgres MCP server for AI agents."""
2
+
3
+ __version__ = "0.0.1"
@@ -0,0 +1,69 @@
1
+ """CLI entry point — `vigil` command.
2
+
3
+ Wraps startup errors in friendly messages so the agent / user sees actionable
4
+ hints instead of stack traces.
5
+ """
6
+
7
+ import sys
8
+
9
+ from vigil import __version__
10
+
11
+
12
+ def main() -> None:
13
+ if "--version" in sys.argv or "-V" in sys.argv:
14
+ print(f"vigil {__version__}")
15
+ return
16
+
17
+ if "--help" in sys.argv or "-h" in sys.argv:
18
+ print(
19
+ "vigil — Postgres MCP server for AI agents\n"
20
+ "\n"
21
+ "Usage:\n"
22
+ " DATABASE_URL=postgres://user:pass@host:5432/dbname vigil\n"
23
+ "\n"
24
+ "Environment variables:\n"
25
+ " DATABASE_URL required — Postgres connection string\n"
26
+ " VIGIL_MAX_ROWS default 100 — cap on rows returned\n"
27
+ " VIGIL_SAMPLE_SIZE default 3 — rows in describe_schema sample\n"
28
+ " VIGIL_STATEMENT_TIMEOUT_MS default 5000 — server-side query timeout\n"
29
+ " VIGIL_REDACT default off — set 'on' to scrub PII from output\n"
30
+ " VIGIL_ALLOW_WRITES default false — keep false (read-only)\n"
31
+ "\n"
32
+ "Repo: https://github.com/WalkingMountain/vigilmcp"
33
+ )
34
+ return
35
+
36
+ try:
37
+ # Defer import so --version/--help don't pay the asyncio + mcp cost
38
+ from vigil.config import load
39
+ from vigil.server import main as run_server
40
+
41
+ # Fast-fail config validation BEFORE we open the stdio MCP loop —
42
+ # otherwise the agent waits until first tool call to learn DATABASE_URL
43
+ # is missing, which makes the failure mode confusing.
44
+ load()
45
+ run_server()
46
+ except RuntimeError as e:
47
+ # Config errors (missing DATABASE_URL, etc.) — already friendly
48
+ print(f"vigil: {e}", file=sys.stderr)
49
+ sys.exit(2)
50
+ except KeyboardInterrupt:
51
+ sys.exit(0)
52
+ except Exception as e:
53
+ # Last resort — show error class + message, hint at common causes
54
+ print(
55
+ f"vigil: unexpected error: {type(e).__name__}: {e}\n"
56
+ f"\n"
57
+ f"Common causes:\n"
58
+ f" - DATABASE_URL points at an unreachable host\n"
59
+ f" - Postgres requires SSL but the URL lacks ?sslmode=require\n"
60
+ f" - User in DATABASE_URL lacks CONNECT or USAGE privileges\n"
61
+ f"\n"
62
+ f"File an issue: https://github.com/WalkingMountain/vigilmcp/issues",
63
+ file=sys.stderr,
64
+ )
65
+ sys.exit(1)
66
+
67
+
68
+ if __name__ == "__main__":
69
+ main()
@@ -0,0 +1,29 @@
1
+ """Runtime config from environment variables."""
2
+
3
+ import os
4
+ from dataclasses import dataclass
5
+
6
+
7
+ @dataclass(frozen=True)
8
+ class Config:
9
+ database_url: str
10
+ max_rows: int # cap on rows returned by any tool
11
+ sample_size: int # rows per describe_schema sample
12
+ statement_timeout_ms: int
13
+ allow_writes: bool # default False — agent gets read-only
14
+
15
+
16
+ def load() -> Config:
17
+ url = os.environ.get("DATABASE_URL")
18
+ if not url:
19
+ raise RuntimeError(
20
+ "DATABASE_URL is required. Set to a Postgres connection string "
21
+ "(postgres://user:pass@host:5432/dbname)."
22
+ )
23
+ return Config(
24
+ database_url=url,
25
+ max_rows=int(os.environ.get("VIGIL_MAX_ROWS", "100")),
26
+ sample_size=int(os.environ.get("VIGIL_SAMPLE_SIZE", "3")),
27
+ statement_timeout_ms=int(os.environ.get("VIGIL_STATEMENT_TIMEOUT_MS", "5000")),
28
+ allow_writes=os.environ.get("VIGIL_ALLOW_WRITES", "false").lower() == "true",
29
+ )