|
| 1 | +# Repository Guidelines |
| 2 | + |
| 3 | +These guidelines help contributors work effectively on the PostgreSQL MCP server in this repo. |
| 4 | + |
| 5 | +## StackQL Resource Key Encoding Quirk |
| 6 | + |
| 7 | +### Hierarchical Keys and URL Encoding |
| 8 | + |
| 9 | +StackQL resource methods (especially for GitHub refs/tags) require exact matches for hierarchical keys, such as `refs/tags/x1.3`. However, due to dependency library behavior (e.g., gorilla/mux in Go), forward slashes in parameters may be interpreted as path delimiters, causing query failures or incorrect resource matching. |
| 10 | + |
| 11 | +**Workaround:** Always URL encode forward slashes in resource keys when constructing queries. For example: |
| 12 | + |
| 13 | +- **Incorrect:** |
| 14 | + ```sql |
| 15 | + SELECT ref FROM github.git.refs WHERE owner = 'stackql' AND repo = 'mcp-stackql' AND ref = 'refs/tags/x2.0'; |
| 16 | + ``` |
| 17 | +- **Correct:** |
| 18 | + ```sql |
| 19 | + SELECT ref FROM github.git.refs WHERE owner = 'stackql' AND repo = 'mcp-stackql' AND ref = 'tags%2Fx2.0'; |
| 20 | + ``` |
| 21 | + |
| 22 | +This ensures the backend treats the parameter as a literal string, not a path. |
| 23 | + |
| 24 | +### Guidance for LLMs and Contributors |
| 25 | + |
| 26 | +- Always encode slashes in hierarchical resource keys for StackQL queries. |
| 27 | +- Do not use wildcards or inequalities for `WHERE` clauses that map to parameters (eg: HTTP path parameters); in such cases, only exact matches are supported. |
| 28 | +- Document this quirk in scripts, tests, and code comments to avoid confusion. |
| 29 | +- Example for LLM prompt: |
| 30 | + > "When querying StackQL resources with keys containing slashes, always URL encode the slash." |
| 31 | +
|
| 32 | +### Why This Is Necessary |
| 33 | + |
| 34 | +Many RESTful routing libraries (like gorilla/mux) treat slashes as path separators. Encoding slashes prevents misinterpretation and ensures correct resource access. |
| 35 | + |
| 36 | +Refer to this section whenever you encounter issues with resource keys containing slashes or hierarchical identifiers. |
| 37 | + |
| 38 | + |
| 39 | +## Project Structure & Module Organization |
| 40 | +- Root module: `postgres_server.py` — FastMCP server exposing PostgreSQL tools. |
| 41 | +- Config: `.env` (optional), `smithery.yaml` (publishing metadata). |
| 42 | +- Packaging/infra: `requirements.txt`, `Dockerfile`. |
| 43 | +- Docs: `README.md`, this `AGENTS.md`. |
| 44 | +- No dedicated `src/` or `tests/` directories yet; keep server logic cohesive and small, or start a `src/` layout if adding modules. |
| 45 | + |
| 46 | +## Build, Test, and Development Commands |
| 47 | +- Create env: `python -m venv .venv && source .venv/bin/activate` |
| 48 | +- Install deps: `pip install -r requirements.txt` |
| 49 | +- Run server (no DB): `python postgres_server.py` |
| 50 | +- Run with DB: `POSTGRES_CONNECTION_STRING="postgresql://user:pass@host:5432/db" python postgres_server.py` |
| 51 | +- Docker build/run: `docker build -t mcp-postgres .` then `docker run -e POSTGRES_CONNECTION_STRING=... -p 8000:8000 mcp-postgres` |
| 52 | + |
| 53 | +## Coding Style & Naming Conventions |
| 54 | +- Python 3.10+, 4-space indentation, PEP 8. |
| 55 | +- Use type hints (as in current code) and concise docstrings. |
| 56 | +- Functions/variables: `snake_case`; classes: `PascalCase`; MCP tool names: short `snake_case`. |
| 57 | +- Logging: use the existing `logger` instance; prefer informative, non-PII messages. |
| 58 | +- Optional formatting/linting: `black` and `ruff` (not enforced in repo). Example: `pip install black ruff && ruff check . && black .`. |
| 59 | + |
| 60 | +## Testing Guidelines |
| 61 | +- There is no test suite yet. Prefer adding `pytest` with tests under `tests/` named `test_*.py`. |
| 62 | +- For DB behaviors, use a disposable PostgreSQL instance or mock `psycopg2` connections. |
| 63 | +- Minimum smoke test: start server without DSN, verify each tool returns the friendly “connection string is not set” message. |
| 64 | + |
| 65 | +## Typed Tools & Resources |
| 66 | +- Preferred tools: `run_query(QueryInput)` and `run_query_json(QueryJSONInput)` with validated inputs (via Pydantic) and `row_limit` safeguards. |
| 67 | +- Legacy tools `query`/`query_json` remain for backward compatibility. |
| 68 | +- Table resources: `table://{schema}/{table}` (best-effort registration), with fallback tools `list_table_resources` and `read_table_resource`. |
| 69 | +- Prompts available as MCP prompts and tools: `write_safe_select`, `explain_plan_tips`. |
| 70 | + |
| 71 | +## Tests |
| 72 | +- Test deps: `dev-requirements.txt` (`pytest`, `pytest-cov`). |
| 73 | +- Layout: `tests/test_server_tools.py` includes no-DSN smoke tests and prompt checks. |
| 74 | +- Run: `pytest -q`. Ensure runtime deps installed from `requirements.txt`. |
| 75 | + |
| 76 | +## Commit & Pull Request Guidelines |
| 77 | +- Commit style: conventional commits preferred (`feat:`, `fix:`, `chore:`, `docs:`). Keep subjects imperative and concise. |
| 78 | +- PRs should include: purpose & scope, before/after behavior, example commands/queries, and any config changes (`POSTGRES_CONNECTION_STRING`, Docker, `mcp.json`). |
| 79 | +- When adding tools, document them in `README.md` (name, args, example) and ensure safe output formatting. |
| 80 | +- Never commit secrets. `.env`, `.venv`, and credentials are ignored by `.gitignore`. |
| 81 | + |
| 82 | +## Security & Configuration Tips |
| 83 | +- Pass DB credentials via `POSTGRES_CONNECTION_STRING` env var; avoid hardcoding. |
| 84 | +- Prefer least-privilege DB users and SSL options (e.g., add `?sslmode=require`). |
| 85 | +- The server runs without a DSN for inspection; database-backed tools should fail gracefully (maintain this behavior). |
0 commit comments