{"_id":"@codegiveness/postgresql-sharp-mcp","_rev":"7-a19d54b7c86d138cb42bc927380feb86","name":"@codegiveness/postgresql-sharp-mcp","dist-tags":{"latest":"0.7.1"},"versions":{"0.3.2":{"name":"@codegiveness/postgresql-sharp-mcp","version":"0.3.2","keywords":["mcp","mcp-server","postgresql","database"],"author":{"name":"codegiveness"},"license":"MIT","_id":"@codegiveness/postgresql-sharp-mcp@0.3.2","maintainers":[{"name":"codegiveness","email":"codegiveness@gmail.com"}],"homepage":"https://github.com/codegiveness/postgresql-sharp-mcp#readme","bugs":{"url":"https://github.com/codegiveness/postgresql-sharp-mcp/issues"},"bin":{"postgresql-sharp-mcp":"bin/postgresql-sharp-mcp.exe"},"dist":{"shasum":"e6890cf12a176beb1fd54b1c57035fa271f87559","tarball":"https://registry.npmjs.org/@codegiveness/postgresql-sharp-mcp/-/postgresql-sharp-mcp-0.3.2.tgz","fileCount":57,"integrity":"sha512-SNSh/WH/o4vMAINtmaKIWV7ekc9OuMavnkAx65jZ4FRjI9P+kFkwAihOgGEu07xYyUQ7DpQYoyGGi6qYFJmHcg==","signatures":[{"sig":"MEQCIAiTB1/PFKxwa5mhcR2hmQQ40LOO11GRozaIVQcXxLDmAiAZ6T46cchQvywD7AfD40ftSl20B4mTEPr6QNm8rdcIcQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":5947011},"_from":"file:/tmp/postgresql-sharp-mcp-release-0.3.2/codegiveness-postgresql-sharp-mcp-0.3.2.tgz","engines":{"node":">=22"},"scripts":{"postinstall":"dotnet installer/PostgreSqlMcp.NpmInstall.dll"},"_npmUser":{"name":"codegiveness","email":"codegiveness@gmail.com"},"_resolved":"/tmp/postgresql-sharp-mcp-release-0.3.2/codegiveness-postgresql-sharp-mcp-0.3.2.tgz","_integrity":"sha512-SNSh/WH/o4vMAINtmaKIWV7ekc9OuMavnkAx65jZ4FRjI9P+kFkwAihOgGEu07xYyUQ7DpQYoyGGi6qYFJmHcg==","repository":{"url":"git+https://github.com/codegiveness/postgresql-sharp-mcp.git","type":"git"},"_npmVersion":"12.0.1","description":"Database-agnostic PostgreSQL MCP server with live discovery and bounded per-call selection. Requires the .NET 10 runtime; set DOTNET_ROOT for nonstandard installations. No runtime downloads.","directories":{},"_nodeVersion":"26.5.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/postgresql-sharp-mcp_0.3.2_1791348562695_0.7408795508399155","host":"s3://npm-registry-packages-npm-production"}},"0.3.3":{"name":"@codegiveness/postgresql-sharp-mcp","version":"0.3.3","keywords":["mcp","mcp-server","postgresql","database"],"author":{"name":"codegiveness"},"license":"MIT","_id":"@codegiveness/postgresql-sharp-mcp@0.3.3","maintainers":[{"name":"codegiveness","email":"codegiveness@gmail.com"}],"homepage":"https://github.com/codegiveness/postgresql-sharp-mcp#readme","bugs":{"url":"https://github.com/codegiveness/postgresql-sharp-mcp/issues"},"bin":{"postgresql-sharp-mcp":"bin/postgresql-sharp-mcp.exe"},"dist":{"shasum":"0dc3e42d9ed288cae03431c13d60226bd5a1f4be","tarball":"https://registry.npmjs.org/@codegiveness/postgresql-sharp-mcp/-/postgresql-sharp-mcp-0.3.3.tgz","fileCount":1194,"integrity":"sha512-6EKLeH4UBDcfrVRourv4ZcY7KX8VHvus8I+LYkEJLLccmvHLcOom5KrDOi9DHXL2vn7rbZnp1A//9kA8bAFwNg==","signatures":[{"sig":"MEUCIQCo4SB8Il6hHS1JfUYjGO4Jfg8cQrO9rNVN1wtCUXxWAgIgREEOkcPZqc4xDSEb4UgskU2sDRRx4tcWEZ34UMj5nHQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":446136440},"_from":"file:/tmp/postgresql-release-0.3.3-20261008/codegiveness-postgresql-sharp-mcp-0.3.3.tgz","engines":{"node":">=22"},"scripts":{"postinstall":"node installer/run-script-os/index.js","postinstall:linux":"\"runtimes/linux-$(uname -m)/PostgreSqlMcp.NpmInstall\"","postinstall:win32":"\"runtimes\\win-x64\\PostgreSqlMcp.NpmInstall.exe\"","postinstall:darwin":"\"runtimes/osx-$(uname -m)/PostgreSqlMcp.NpmInstall\""},"_npmUser":{"name":"codegiveness","email":"codegiveness@gmail.com","approver":{"name":"codegiveness","email":"codegiveness@gmail.com"}},"_resolved":"/tmp/postgresql-release-0.3.3-20261008/codegiveness-postgresql-sharp-mcp-0.3.3.tgz","_integrity":"sha512-6EKLeH4UBDcfrVRourv4ZcY7KX8VHvus8I+LYkEJLLccmvHLcOom5KrDOi9DHXL2vn7rbZnp1A//9kA8bAFwNg==","repository":{"url":"git+https://github.com/codegiveness/postgresql-sharp-mcp.git","type":"git"},"_npmVersion":"12.2.0","description":"Database-agnostic PostgreSQL MCP server with live discovery and bounded per-call selection. Bundles the .NET runtime; no .NET installation or runtime downloads required.","directories":{},"_nodeVersion":"26.11.1","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/postgresql-sharp-mcp_0.3.3_1791444709440_0.3263936691786773","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@codegiveness/postgresql-sharp-mcp","version":"0.4.0","keywords":["mcp","mcp-server","postgresql","database"],"author":{"name":"codegiveness"},"license":"MIT","_id":"@codegiveness/postgresql-sharp-mcp@0.4.0","maintainers":[{"name":"codegiveness","email":"codegiveness@gmail.com"}],"homepage":"https://github.com/codegiveness/postgresql-sharp-mcp#readme","bugs":{"url":"https://github.com/codegiveness/postgresql-sharp-mcp/issues"},"bin":{"postgresql-sharp-mcp":"bin/postgresql-sharp-mcp.exe"},"dist":{"shasum":"465a0ff1772e40836a2e1f16075c86705f981004","tarball":"https://registry.npmjs.org/@codegiveness/postgresql-sharp-mcp/-/postgresql-sharp-mcp-0.4.0.tgz","fileCount":1194,"integrity":"sha512-a+9wQvoz/2NZub9NM6v91CVZJQq06HnHwySnBjcFdTWVri/zh658fUJOTO5EQmpGXgZAYqbXimtAV2Hot4Ogjg==","signatures":[{"sig":"MEYCIQDv+d9wGtGQjC6xY9RJ+k2pJmY4G3XWbqryphGt19FXrwIhAOPBvAZwMWCZsSUM8dBpe/bWRzgyNsVKHyPKmoOYp5/b","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":446256792},"_from":"file:release-verification/codegiveness-postgresql-sharp-mcp-0.4.0.tgz","engines":{"node":">=22"},"scripts":{"postinstall":"node installer/run-script-os/index.js","postinstall:linux":"\"runtimes/linux-$(uname -m)/PostgreSqlMcp.NpmInstall\"","postinstall:win32":"\"runtimes\\win-x64\\PostgreSqlMcp.NpmInstall.exe\"","postinstall:darwin":"\"runtimes/osx-$(uname -m)/PostgreSqlMcp.NpmInstall\""},"_npmUser":{"name":"codegiveness","email":"codegiveness@gmail.com","approver":{"name":"codegiveness","email":"codegiveness@gmail.com"}},"_resolved":"/mnt/hgfs/Windows/postgresql-sharp-mcp/release-verification/codegiveness-postgresql-sharp-mcp-0.4.0.tgz","_integrity":"sha512-a+9wQvoz/2NZub9NM6v91CVZJQq06HnHwySnBjcFdTWVri/zh658fUJOTO5EQmpGXgZAYqbXimtAV2Hot4Ogjg==","repository":{"url":"git+https://github.com/codegiveness/postgresql-sharp-mcp.git","type":"git"},"_npmVersion":"12.2.0","description":"Database-agnostic PostgreSQL MCP server with live discovery and bounded per-call selection. Bundles the .NET runtime; no .NET installation or runtime downloads required.","directories":{},"_nodeVersion":"26.11.1","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/postgresql-sharp-mcp_0.4.0_1791629764835_0.2651064570891215","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@codegiveness/postgresql-sharp-mcp","version":"0.5.0","keywords":["mcp","mcp-server","postgresql","database"],"author":{"name":"codegiveness"},"license":"MIT","_id":"@codegiveness/postgresql-sharp-mcp@0.5.0","maintainers":[{"name":"codegiveness","email":"codegiveness@gmail.com"}],"homepage":"https://github.com/codegiveness/postgresql-sharp-mcp#readme","bugs":{"url":"https://github.com/codegiveness/postgresql-sharp-mcp/issues"},"os":["linux","darwin","win32"],"bin":{"postgresql-sharp-mcp":"bin/postgresql-sharp-mcp.exe"},"cpu":["x64","arm64"],"dist":{"shasum":"1b184847c6b018ff84791c6a3ed4baae800c5887","tarball":"https://registry.npmjs.org/@codegiveness/postgresql-sharp-mcp/-/postgresql-sharp-mcp-0.5.0.tgz","fileCount":11,"integrity":"sha512-3vZ0sQ9OC1+Op7ZNQW5evbyeXjnGaO0LjHgp2rzaKpLMEn290hTvzBYunpurAdoIc/sFfEUQF69zi/B5v2uHXQ==","signatures":[{"sig":"MEUCIQD+nkyArdKj191hGkytRRUCk5hRjeSdUPMiNs4WksQHmgIgMp6W5zK9Pc2L1ER9+bxLO6g4g7V87O/jEPttdE0+npQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":403324},"_from":"file:codegiveness-postgresql-sharp-mcp-0.5.0.tgz","engines":{"node":">=22"},"scripts":{"postinstall":"postgresql-sharp-mcp-npm-install"},"_npmUser":{"name":"codegiveness","email":"codegiveness@gmail.com","approver":{"name":"codegiveness","email":"codegiveness@gmail.com"}},"_resolved":"/tmp/rel050/codegiveness-postgresql-sharp-mcp-0.5.0.tgz","_integrity":"sha512-3vZ0sQ9OC1+Op7ZNQW5evbyeXjnGaO0LjHgp2rzaKpLMEn290hTvzBYunpurAdoIc/sFfEUQF69zi/B5v2uHXQ==","repository":{"url":"git+https://github.com/codegiveness/postgresql-sharp-mcp.git","type":"git"},"_npmVersion":"12.2.0","description":"Database-agnostic PostgreSQL MCP server with live discovery and bounded per-call selection. Installs one platform package with the .NET runtime bundled; no .NET installation or runtime downloads required.","directories":{},"_nodeVersion":"26.11.1","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"optionalDependencies":{"@codegiveness/postgresql-sharp-mcp-linux-x64":"0.5.0","@codegiveness/postgresql-sharp-mcp-win32-x64":"0.5.0","@codegiveness/postgresql-sharp-mcp-darwin-x64":"0.5.0","@codegiveness/postgresql-sharp-mcp-linux-arm64":"0.5.0","@codegiveness/postgresql-sharp-mcp-darwin-arm64":"0.5.0"},"_npmOperationalInternal":{"tmp":"tmp/postgresql-sharp-mcp_0.5.0_1791682088819_0.9896484301436488","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@codegiveness/postgresql-sharp-mcp","version":"0.6.0","keywords":["mcp","mcp-server","postgresql","database"],"author":{"name":"codegiveness"},"license":"MIT","_id":"@codegiveness/postgresql-sharp-mcp@0.6.0","maintainers":[{"name":"codegiveness","email":"codegiveness@gmail.com"}],"homepage":"https://github.com/codegiveness/postgresql-sharp-mcp#readme","bugs":{"url":"https://github.com/codegiveness/postgresql-sharp-mcp/issues"},"os":["linux","darwin","win32"],"bin":{"postgresql-sharp-mcp":"bin/postgresql-sharp-mcp.exe"},"cpu":["x64","arm64"],"dist":{"shasum":"227605fa3bbe6e0ea364dd20d11d52f4e6f7e504","tarball":"https://registry.npmjs.org/@codegiveness/postgresql-sharp-mcp/-/postgresql-sharp-mcp-0.6.0.tgz","fileCount":11,"integrity":"sha512-PHF0XPmQrxKhBz3FLBAsY/bVeypyz4tj+krW2Xy0cp2pN3QGKKtWa/bamBLQufeNS7SlIXaaytHCuENBNAnJuA==","signatures":[{"sig":"MEQCIE0GmPnPPN5QTvTsJAcuHCX+2WwrP16yq1jTUCmL0XBuAiAuIfNrIodWyouut8Tlp/KChozwhGlnbpd+u6c76z9TTg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@codegiveness%2fpostgresql-sharp-mcp@0.6.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":422445},"_from":"file:/home/runner/work/postgresql-sharp-mcp/postgresql-sharp-mcp/artifacts/packages/codegiveness-postgresql-sharp-mcp-0.6.0.tgz","engines":{"node":">=22"},"scripts":{"postinstall":"postgresql-sharp-mcp-npm-install"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"codegiveness","email":"codegiveness@gmail.com"},"trustedPublisher":{"id":"github","oidcConfigId":"6698fff6-b73a-4522-b3ca-5986a37e070d"}},"_resolved":"/home/runner/work/postgresql-sharp-mcp/postgresql-sharp-mcp/artifacts/packages/codegiveness-postgresql-sharp-mcp-0.6.0.tgz","_integrity":"sha512-PHF0XPmQrxKhBz3FLBAsY/bVeypyz4tj+krW2Xy0cp2pN3QGKKtWa/bamBLQufeNS7SlIXaaytHCuENBNAnJuA==","repository":{"url":"git+https://github.com/codegiveness/postgresql-sharp-mcp.git","type":"git"},"_npmVersion":"12.2.0","description":"Database-agnostic PostgreSQL MCP server with live discovery and bounded per-call selection. Installs one platform package with the .NET runtime bundled; no .NET installation or runtime downloads required.","directories":{},"_nodeVersion":"24.21.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"optionalDependencies":{"@codegiveness/postgresql-sharp-mcp-linux-x64":"0.6.0","@codegiveness/postgresql-sharp-mcp-win32-x64":"0.6.0","@codegiveness/postgresql-sharp-mcp-darwin-x64":"0.6.0","@codegiveness/postgresql-sharp-mcp-linux-arm64":"0.6.0","@codegiveness/postgresql-sharp-mcp-darwin-arm64":"0.6.0"},"_npmOperationalInternal":{"tmp":"tmp/postgresql-sharp-mcp_0.6.0_1791698352299_0.28130815335283255","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"@codegiveness/postgresql-sharp-mcp","version":"0.7.0","keywords":["mcp","mcp-server","postgresql","database"],"author":{"name":"codegiveness"},"license":"MIT","_id":"@codegiveness/postgresql-sharp-mcp@0.7.0","maintainers":[{"name":"codegiveness","email":"codegiveness@gmail.com"}],"homepage":"https://github.com/codegiveness/postgresql-sharp-mcp#readme","bugs":{"url":"https://github.com/codegiveness/postgresql-sharp-mcp/issues"},"os":["linux","darwin","win32"],"bin":{"postgresql-sharp-mcp":"bin/postgresql-sharp-mcp.exe"},"cpu":["x64","arm64"],"dist":{"shasum":"8eb58f207cd06a4ed4ee37a1c42c0d7eeabfe6a2","tarball":"https://registry.npmjs.org/@codegiveness/postgresql-sharp-mcp/-/postgresql-sharp-mcp-0.7.0.tgz","fileCount":11,"integrity":"sha512-NrfCyYGeBVNEjp+4C60JxTSUqisnAIqsTfdiu31IwTHHZVhwQ+mLmyZTm+UCpdN123nYfmiJu8EGlhXyCql64g==","signatures":[{"sig":"MEYCIQDiWH6ZJqTlzUINDX6oaXXBrE1sFALBgiUKYWOu6B36XgIhANSVZDWPvOA45GNj5DG/EXrRsc0WXi9NKFFnJsvc3ZhJ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@codegiveness%2fpostgresql-sharp-mcp@0.7.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":437718},"_from":"file:/home/runner/work/postgresql-sharp-mcp/postgresql-sharp-mcp/artifacts/packages/codegiveness-postgresql-sharp-mcp-0.7.0.tgz","engines":{"node":">=22"},"scripts":{"postinstall":"postgresql-sharp-mcp-npm-install"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"codegiveness","email":"codegiveness@gmail.com"},"trustedPublisher":{"id":"github","oidcConfigId":"6698fff6-b73a-4522-b3ca-5986a37e070d"}},"_resolved":"/home/runner/work/postgresql-sharp-mcp/postgresql-sharp-mcp/artifacts/packages/codegiveness-postgresql-sharp-mcp-0.7.0.tgz","_integrity":"sha512-NrfCyYGeBVNEjp+4C60JxTSUqisnAIqsTfdiu31IwTHHZVhwQ+mLmyZTm+UCpdN123nYfmiJu8EGlhXyCql64g==","repository":{"url":"git+https://github.com/codegiveness/postgresql-sharp-mcp.git","type":"git"},"_npmVersion":"12.2.0","description":"Database-agnostic PostgreSQL MCP server with live discovery and bounded per-call selection. Installs one platform package with the .NET runtime bundled; no .NET installation or runtime downloads required.","directories":{},"_nodeVersion":"24.21.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"optionalDependencies":{"@codegiveness/postgresql-sharp-mcp-linux-x64":"0.7.0","@codegiveness/postgresql-sharp-mcp-win32-x64":"0.7.0","@codegiveness/postgresql-sharp-mcp-darwin-x64":"0.7.0","@codegiveness/postgresql-sharp-mcp-linux-arm64":"0.7.0","@codegiveness/postgresql-sharp-mcp-darwin-arm64":"0.7.0"},"_npmOperationalInternal":{"tmp":"tmp/postgresql-sharp-mcp_0.7.0_1791731388106_0.7146657384065163","host":"s3://npm-registry-packages-npm-production"}},"0.7.1":{"os":["linux","darwin","win32"],"_id":"@codegiveness/postgresql-sharp-mcp@0.7.1","bin":{"postgresql-sharp-mcp":"bin/postgresql-sharp-mcp.exe"},"cpu":["x64","arm64"],"bugs":{"url":"https://github.com/codegiveness/postgresql-sharp-mcp/issues"},"dist":{"shasum":"becb603863d53ad9f052fed6b4fa8abb0d0f56ea","tarball":"https://registry.npmjs.org/@codegiveness/postgresql-sharp-mcp/-/postgresql-sharp-mcp-0.7.1.tgz","integrity":"sha512-osxs22PxDylK9YmGKf3oLkAIkOtb9Au3QuUJkfxdzwjf+FI6flzzn1+IPymYSPuSMidBCDI6fzvOhV+t2FPRDQ==","fileCount":11,"unpackedSize":437982,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@codegiveness%2fpostgresql-sharp-mcp@0.7.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFCXk0LGQ87DRz48FMI8V0isi9bX9JPPFwtM2vwNRtTvAiEAmpUAaoOBnqAqQf+yfpMxSZKSPzi4Hke9q27CstKrRoE="}]},"name":"@codegiveness/postgresql-sharp-mcp","_from":"file:/home/runner/work/postgresql-sharp-mcp/postgresql-sharp-mcp/artifacts/packages/codegiveness-postgresql-sharp-mcp-0.7.1.tgz","author":{"name":"codegiveness"},"engines":{"node":">=22"},"license":"MIT","scripts":{"postinstall":"postgresql-sharp-mcp-npm-install"},"version":"0.7.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"6698fff6-b73a-4522-b3ca-5986a37e070d"},"approver":{"name":"codegiveness","email":"codegiveness@gmail.com"}},"homepage":"https://github.com/codegiveness/postgresql-sharp-mcp#readme","keywords":["mcp","mcp-server","postgresql","database"],"_resolved":"/home/runner/work/postgresql-sharp-mcp/postgresql-sharp-mcp/artifacts/packages/codegiveness-postgresql-sharp-mcp-0.7.1.tgz","_integrity":"sha512-osxs22PxDylK9YmGKf3oLkAIkOtb9Au3QuUJkfxdzwjf+FI6flzzn1+IPymYSPuSMidBCDI6fzvOhV+t2FPRDQ==","repository":{"url":"git+https://github.com/codegiveness/postgresql-sharp-mcp.git","type":"git"},"_npmVersion":"12.2.1","description":"Database-agnostic PostgreSQL MCP server with live discovery and bounded per-call selection. Installs one platform package with the .NET runtime bundled; no .NET installation or runtime downloads required.","directories":{},"maintainers":[{"name":"codegiveness","email":"codegiveness@gmail.com"}],"_nodeVersion":"24.22.1","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"optionalDependencies":{"@codegiveness/postgresql-sharp-mcp-linux-x64":"0.7.1","@codegiveness/postgresql-sharp-mcp-win32-x64":"0.7.1","@codegiveness/postgresql-sharp-mcp-darwin-x64":"0.7.1","@codegiveness/postgresql-sharp-mcp-linux-arm64":"0.7.1","@codegiveness/postgresql-sharp-mcp-darwin-arm64":"0.7.1"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/postgresql-sharp-mcp_0.7.1_1792659125481_0.15867965439835063"},"_hasShrinkwrap":false}},"time":{"created":"2026-10-07T04:49:22.449Z","modified":"2026-10-22T08:52:05.836Z","0.3.2":"2026-10-07T04:49:22.884Z","0.3.3":"2026-10-08T07:31:51.728Z","0.4.0":"2026-10-10T10:56:07.177Z","0.5.0":"2026-10-11T01:28:08.920Z","0.6.0":"2026-10-11T05:59:12.432Z","0.7.0":"2026-10-11T15:09:48.249Z","0.7.1":"2026-10-22T08:52:05.582Z"},"bugs":{"url":"https://github.com/codegiveness/postgresql-sharp-mcp/issues"},"author":{"name":"codegiveness"},"license":"MIT","homepage":"https://github.com/codegiveness/postgresql-sharp-mcp#readme","keywords":["mcp","mcp-server","postgresql","database"],"repository":{"url":"git+https://github.com/codegiveness/postgresql-sharp-mcp.git","type":"git"},"description":"Database-agnostic PostgreSQL MCP server with live discovery and bounded per-call selection. Installs one platform package with the .NET runtime bundled; no .NET installation or runtime downloads required.","maintainers":[{"name":"codegiveness","email":"codegiveness@gmail.com"}],"readme":"# postgresql-sharp-mcp — PostgreSQL tools for your AI assistant\n\n<img src=\"docs/assets/social-preview.png\" width=\"640\" alt=\"postgresql-sharp-mcp: an MCP server in C#/.NET that gives your AI assistant PostgreSQL tools to discover databases, inspect schemas, run SQL, read query plans, analyze indexes and check health; read-only SQL by default; installs with npx or as a .NET tool on Linux, macOS and Windows.\">\n\n[![CI](https://github.com/codegiveness/postgresql-sharp-mcp/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/codegiveness/postgresql-sharp-mcp/actions/workflows/ci.yml) [![GitHub release](https://img.shields.io/github/v/release/codegiveness/postgresql-sharp-mcp)](https://github.com/codegiveness/postgresql-sharp-mcp/releases) [![npm](https://img.shields.io/npm/v/@codegiveness/postgresql-sharp-mcp?logo=npm)](https://www.npmjs.com/package/@codegiveness/postgresql-sharp-mcp) [![NuGet](https://img.shields.io/nuget/v/codegiveness.postgresql-sharp-mcp?logo=nuget)](https://www.nuget.org/packages/codegiveness.postgresql-sharp-mcp) [![License](https://img.shields.io/github/license/codegiveness/postgresql-sharp-mcp)](LICENSE)\n\n**Let your AI assistant connect to PostgreSQL, list the databases you can access, inspect tables and run SQL, with query plans, index analysis and database health checks built in.**\n\n**Who it is for:** developers, DBAs and data engineers who have a PostgreSQL login and use an MCP-compatible AI assistant or coding agent that starts local (stdio) servers. This app is a [Model Context Protocol](https://modelcontextprotocol.io/) server written in C# with Npgsql. Your MCP client starts the app when needed; it does not create a PostgreSQL database for you.\n\nSQL calls are read-only by default, but the server's default access mode permits explicitly requested writes. A least-privileged database login is recommended, but any login that can connect works for a first run, including a superuser such as `postgres`; `--validate` then prints advisory `[warning]` lines. Before you use real or shared data, follow [Hardening for advanced users](#hardening-for-advanced-users). Keep an existing explicit `restricted` setting; [access boundaries](#access-and-resource-boundaries) explain how to refuse writes entirely.\n\n**Fastest start:** Node.js 22+ and npm are enough, because npm installs the .NET runtime with the server. This downloads and runs version 0.7.1:\n\n```sh\nnpx -y --allow-scripts=@codegiveness/postgresql-sharp-mcp @codegiveness/postgresql-sharp-mcp@0.7.1 --version\n```\n\nIt should print `postgresql-sharp-mcp 0.7.1.0`. Then register it with your MCP client and enter your connection string: the [quick start](#quick-start) has three steps. Prefer a .NET tool or a standalone archive for Linux, macOS or Windows? See [step 1](#1-install-or-run). To build and run a container image from the Dockerfile, see [CONTRIBUTING.md](CONTRIBUTING.md#self-contained-executable-and-container).\n\n> **Upgrading from 0.6.0 or earlier?** Since 0.7.0, two 0.6.0 defaults are looser so that a plain connection string works (0.7.1 itself adds no behavior change): a connection string without `SSL Mode` now uses `Prefer` (TLS when the server offers it, certificate not verified) instead of `VerifyFull`, and the database lock is now advisory by default (the server's tools still enforce the list, but PostgreSQL grant findings are warnings) instead of refusing startup. To keep the 0.6.0 behavior, put `SSL Mode=VerifyFull` in the connection string and set `POSTGRES_DATABASE_LOCK_MODE=strict`; a string with `Root Certificate` and no `SSL Mode` keeps `VerifyFull` unchanged. Run `--validate` before reconnecting, and read [the upgrade note](#upgrading-an-existing-installation), which also covers upgrades from 0.5.0 or earlier.\n\n**What you can ask once it is connected:**\n\n| You ask your assistant | Tools it calls |\n|---|---|\n| \"Which databases can I access on this server?\" | `list_databases` |\n| \"Show the columns and indexes of `public.orders` in `app_db`.\" | `list_objects`, `get_object_details` |\n| \"How many orders were placed yesterday?\" | `execute_sql`, read-only by default |\n| \"Why is this query slow? Would an index on `customer` help?\" | `explain_query`, optionally with hypothetical [HypoPG](#plans-and-optional-extensions) indexes |\n| \"Are any indexes unused or duplicated? Is vacuum keeping up?\" | `analyze_indexes`, `analyze_db_health` |\n| \"Which statements take the most total time?\" | `get_top_queries`, with [`pg_stat_statements`](#plans-and-optional-extensions) |\n\nEvery result is a row- and byte-bounded page that the assistant can continue with `next_offset` ([result format](#bounded-results-and-pagination)). The [tool reference](#tools) lists all nine tools and their options.\n\n## Quick start\n\n**For one PostgreSQL server, you need one connection string—not a targets file or an entry for every database.** You also need access to an existing database and an installed MCP client. The walkthrough below uses **OMP**. It stores only the executable path and nonsensitive options in OMP's configuration; you enter credentials privately each session.\n\n**Already installed and registered?** Skip to [step 2](#2-prepare-the-connection-environment). Switching from a targets file? Open **Advanced setup, troubleshooting and legacy profiles** below first. Keep your existing file.\n\n### 1. Install or run\n\nChoose **npx** for on-demand execution or a **.NET tool** for a persistent command. Starting with **0.3.3**, npm bundles the .NET runtime: npx requires only Node.js 22+ and npm, not an installed .NET runtime or SDK. The .NET tool still requires the [.NET 10 runtime](https://dotnet.microsoft.com/download/dotnet/10.0), and installing it requires the .NET 10 SDK.\n\nThis guide targets **0.7.1**. Registry commands require the corresponding published version; if it is unavailable, [build and install the local npm artifact](CONTRIBUTING.md#build-and-install-package-artifacts). npm **0.3.2** still requires .NET; installing it globally does not remove that prerequisite.\n\n**npx — run without a global install:**\n\n```sh\nnpx -y --allow-scripts=@codegiveness/postgresql-sharp-mcp @codegiveness/postgresql-sharp-mcp@0.7.1 --version\n```\n\nThe package-specific `--allow-scripts` approves installation on npm 12. Do not use `--ignore-scripts` for automatic setup. npm downloads only the platform package matching your OS/CPU (about 35–39 MB; the main package is under 1 MB). Its self-contained C# installer then installs the server and runtime. Starting with 0.5.0, npm no longer downloads all five platform runtimes. The installer downloads nothing itself. The installed server command is native; it needs neither Node.js nor `dotnet` to run.\n\n**.NET tool — install once, then run by name:**\n\n```sh\ndotnet tool install --global codegiveness.postgresql-sharp-mcp --version 0.7.1\npostgresql-sharp-mcp --version\n```\n\nIf the command is not found, add the .NET tools directory to your PATH (`$HOME/.dotnet/tools` on Linux/macOS; `%USERPROFILE%\\.dotnet\\tools` on Windows), or use its absolute executable path. Do not reinstall to fix PATH.\n\nThe command should report **0.7.1** (or assembly version **0.7.1.0**). Continue with registration below, then prepare your connection environment in step 2. Package versions are immutable; a published release archive is an alternative if your registry is unavailable.\n\n<details>\n<summary>Standalone archives — no .NET, Node.js or npm installation needed</summary>\n\nDownload **one archive** and `SHA256SUMS` from [release 0.7.1](https://github.com/codegiveness/postgresql-sharp-mcp/releases/tag/v0.7.1). These archives include the .NET runtime: you do not need the .NET SDK, npm, Node.js or Docker for this installation.\n\n| Your computer | Archive |\n|---|---|\n| Linux, Intel/AMD 64-bit | `postgresql-sharp-mcp-linux-x64.tar.gz` |\n| Linux, ARM64 | `postgresql-sharp-mcp-linux-arm64.tar.gz` |\n| Mac, Apple Silicon (M-series) | `postgresql-sharp-mcp-osx-arm64.tar.gz` |\n| Mac, Intel | `postgresql-sharp-mcp-osx-x64.tar.gz` |\n| Windows, Intel/AMD 64-bit | `postgresql-sharp-mcp-win-x64.zip` |\n\nExtract into **`postgresql-mcp/app` inside your home folder**, keeping all the extracted files together. Open the instructions for your OS below to check the download, extract it and check the version. Commands assume you saved the archive in `Downloads`.\n\n<details>\n<summary>Linux: verify and extract</summary>\n\nCompare the hash printed by the first command with your archive's entry in the downloaded `SHA256SUMS`. Stop if they differ; extract only after they match. For ARM64, replace both archive filenames with `postgresql-sharp-mcp-linux-arm64.tar.gz`.\n\n```sh\nsha256sum \"$HOME/Downloads/postgresql-sharp-mcp-linux-x64.tar.gz\"\n```\n\n```sh\nmkdir -p \"$HOME/postgresql-mcp/app\"\ntar -xzf \"$HOME/Downloads/postgresql-sharp-mcp-linux-x64.tar.gz\" -C \"$HOME/postgresql-mcp/app\"\n\"$HOME/postgresql-mcp/app/PostgreSqlMcp\" --version\n```\n\n</details>\n\n<details>\n<summary>macOS: verify and extract</summary>\n\nCompare the hash printed by the first command with your archive's entry in the downloaded `SHA256SUMS`. Stop if they differ; extract only after they match. For an Intel Mac, replace both archive filenames with `postgresql-sharp-mcp-osx-x64.tar.gz`.\n\n```sh\nshasum -a 256 \"$HOME/Downloads/postgresql-sharp-mcp-osx-arm64.tar.gz\"\n```\n\n```sh\nmkdir -p \"$HOME/postgresql-mcp/app\"\ntar -xzf \"$HOME/Downloads/postgresql-sharp-mcp-osx-arm64.tar.gz\" -C \"$HOME/postgresql-mcp/app\"\n\"$HOME/postgresql-mcp/app/PostgreSqlMcp\" --version\n```\n\n</details>\n\n<details>\n<summary>Windows: verify and extract in PowerShell</summary>\n\nCompare the hash printed by the first command with your archive's entry in the downloaded `SHA256SUMS` (case does not matter). Stop if they differ; extract only after they match.\n\n```powershell\nGet-FileHash \"$HOME\\Downloads\\postgresql-sharp-mcp-win-x64.zip\" -Algorithm SHA256\n```\n\n```powershell\nNew-Item -ItemType Directory -Force \"$HOME\\postgresql-mcp\\app\" | Out-Null\nExpand-Archive -Path \"$HOME\\Downloads\\postgresql-sharp-mcp-win-x64.zip\" -DestinationPath \"$HOME\\postgresql-mcp\\app\"\n& \"$HOME\\postgresql-mcp\\app\\PostgreSqlMcp.exe\" --version\n```\n\n</details>\n\nThe executable should report **0.7.1**. If you already have an older installation, read [upgrade notes](#upgrading-an-existing-installation) before reusing its configuration.\n\n</details>\n\n**Register with OMP once.** Edit or create `~/.omp/agent/mcp.json` on Linux/macOS, or `%USERPROFILE%\\.omp\\agent\\mcp.json` on Windows (for a named OMP profile, use that profile's MCP configuration). Installing this app does not register it automatically.\n\nFor **npx**, use this JSON for a new file. If the file already has other servers, add only the `\"postgresql\"` entry inside its existing `mcpServers` object; preserve every other entry and separate adjacent entries with a comma.\n\n```json\n{\n  \"mcpServers\": {\n    \"postgresql\": {\n      \"type\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"--allow-scripts=@codegiveness/postgresql-sharp-mcp\", \"@codegiveness/postgresql-sharp-mcp@0.7.1\"]\n    }\n  }\n}\n```\n\nFor a **.NET tool**, replace `command` with `\"postgresql-sharp-mcp\"` and remove `args`; the client must inherit the tools directory on PATH. Alternatively, use the absolute tool path (`/home/YOUR_USER/.dotnet/tools/postgresql-sharp-mcp` on Linux, `/Users/YOUR_USER/.dotnet/tools/postgresql-sharp-mcp` on macOS, or `\"C:\\\\Users\\\\YOUR_USER\\\\.dotnet\\\\tools\\\\postgresql-sharp-mcp.exe\"` in Windows JSON).\n\nFor a **standalone archive**, remove `args` and use the **absolute executable path**, not the folder or archive:\n\n- Linux: `/home/YOUR_USER/postgresql-mcp/app/PostgreSqlMcp`\n- macOS: `/Users/YOUR_USER/postgresql-mcp/app/PostgreSqlMcp`\n- Windows JSON: `\"C:\\\\Users\\\\YOUR_USER\\\\postgresql-mcp\\\\app\\\\PostgreSqlMcp.exe\"`\n\nReplace `YOUR_USER` with your home-folder name, or adjust the whole home prefix if yours differs. `echo \"$HOME\"` on Linux/macOS or `$HOME` in PowerShell shows your home path. JSON does not expand `~`, `$HOME` or `%USERPROFILE%`. **Do not add credentials to this file.** Preserve any intentional `\"POSTGRES_ACCESS_MODE\": \"restricted\"` setting when updating an existing entry.\n\n### 2. Prepare the connection environment\n\nEnter one complete **.NET/Npgsql `key=value` connection string** at the hidden prompt below. Your provider's .NET/Npgsql string is accepted; a raw `postgres://` or `postgresql://` URL is not. Replace all `<...>` placeholders, including angle brackets, with your database details. This example is a format guide, **not a command**:\n\n```text\nHost=<YOUR_HOST>;Port=5432;Database=<YOUR_DATABASE>;Username=<YOUR_DATABASE_USER>;Password=<YOUR_PASSWORD>\n```\n\n`Database` is an accessible starting database, such as your existing database or `postgres`; the same login can discover other accessible databases on that server. For special characters or a provider-supplied URL, open [connection-string guidance](#connection-string-quoting-and-tls).\n\n**Linux/macOS — paste into your current Bash or Zsh terminal.** No shell change or startup-file edit is needed. Then type or paste the connection string at the hidden prompt and press Enter:\n\n```sh\nunset POSTGRES_TARGETS POSTGRES_TARGETS_FILE POSTGRES_CONNECTION_STRING\nprintf 'PostgreSQL connection string (hidden): ' >&2\nIFS= read -r -s POSTGRES_CONNECTION_STRING && export POSTGRES_CONNECTION_STRING\nprintf '\\n' >&2\n```\n\n**Windows — use the built-in Windows PowerShell (5.1 or newer) in an interactive terminal:**\n\n```powershell\nRemove-Item Env:POSTGRES_TARGETS, Env:POSTGRES_TARGETS_FILE, Env:POSTGRES_CONNECTION_STRING -ErrorAction SilentlyContinue\n$connection = Read-Host 'PostgreSQL connection string (hidden)' -AsSecureString\ntry {\n    $env:POSTGRES_CONNECTION_STRING = [System.Net.NetworkCredential]::new('', $connection).Password\n} finally {\n    $connection.Dispose()\n    Remove-Variable connection\n}\n```\n\nKeep this terminal open. Enter the secret **at the prompt**, never in a command, MCP JSON, chat or shell startup file. Do not print the variable to check it. Hidden entry prevents display/history exposure; the exported environment is still plaintext process memory, inherited by child processes—not encrypted storage.\n\n### 3. Validate, start OMP and ask for databases\n\n**Fully quit any existing OMP process first.** In the same terminal from step 2, run the command for your OS. It checks connectivity and starts a **new** OMP process only if validation succeeds:\n\nUse the command for your installation method. If you use a standalone archive, replace the command with its absolute executable path followed by `--validate`.\n\n**npx, Linux/macOS:**\n\n```sh\nnpx -y --allow-scripts=@codegiveness/postgresql-sharp-mcp @codegiveness/postgresql-sharp-mcp@0.7.1 --validate && omp\n```\n\n**.NET tool, Linux/macOS:**\n\n```sh\npostgresql-sharp-mcp --validate && omp\n```\n\n**Windows PowerShell (.NET tool):**\n\n```powershell\npostgresql-sharp-mcp --validate\nif ($LASTEXITCODE -eq 0) {\n    omp\n} else {\n    throw 'Connection validation failed; repeat step 2 or check your database details.'\n}\n```\n\nFor npx in PowerShell, replace the first line with `npx -y --allow-scripts=@codegiveness/postgresql-sharp-mcp @codegiveness/postgresql-sharp-mcp@0.7.1 --validate`; keep the `$LASTEXITCODE` check and launch block.\n\nValidation is read-only and exits; its successful stderr output includes your database name, so keep it private. Empty input is rejected before OMP starts. Lines that start with `[warning]` (about TLS, a superuser login or the database lock) are advice: they do not stop validation or the server, and [Hardening for advanced users](#hardening-for-advanced-users) explains how to act on them. If it fails, fix your connection details and repeat step 2; [troubleshooting](#if-setup-does-not-work) covers common failures.\n\nIn OMP, ask: **“Use the PostgreSQL MCP server to list the databases I can access, then run `SELECT 1 AS connection_ok` in the starting database using alias `primary`.”** You are ready when it lists real database names and the query returns `1`.\n\nThe client must inherit this terminal's environment. A desktop/Start-menu launch, an already-running client, or `/mcp reload` cannot pick up a newly entered secret. For a later session or changed password, fully quit OMP, repeat step 2, and launch it again from that prepared terminal. You do **not** repeat registration or edit a file for new databases. Other MCP clients need their own configuration schema and a launcher that starts a new process with the inherited environment; GUI clients that cannot do this need the [advanced file alternative](#optional-protected-targets-file).\n\nWhen finished, fully quit OMP/server and clear the terminal's secret with `unset POSTGRES_CONNECTION_STRING` (Bash/Zsh) or `Remove-Item Env:POSTGRES_CONNECTION_STRING -ErrorAction SilentlyContinue` (PowerShell). This does not erase copies in children that are still running.\n\n**Optional help:** Click a section title below to open it.\n\n<details>\n<summary>Advanced setup, troubleshooting and legacy profiles</summary>\n\n### Connection-string quoting and TLS\n\nUse the database host and port supplied by your provider, an accessible bootstrap database, and a PostgreSQL login role with CONNECT to the intended databases and only the object privileges it needs. The database username is not necessarily your computer's username.\n\nAt the hidden prompt, quoting has **one layer: Npgsql**, not JSON or shell syntax. Quote a value containing a semicolon, for example the synthetic fragment `Password=\"sample;value\"`. Inside a double-quoted value, double a literal double quote (`Password=\"sample\"\"value\"`). Backslashes are entered literally; do not add JSON's `\\\"` or double backslashes for JSON. Prefer a provider-generated .NET/Npgsql string over constructing one by hand.\n\nIf your provider supplies only a PostgreSQL URL, map its host, port, database, username and password to the example's fields, decode URL-escaped values, and preserve required TLS/authentication options. The URL itself cannot be entered unchanged; startup says so and names the expected `Host`, `Port`, `Database`, `Username` and `Password` keys.\n\n**TLS is used when the server offers it, and is not verified by default.** If a connection string does not set `SSL Mode`, the server uses `SSL Mode=Prefer` for every host, loopback included: TLS when the server offers it, plaintext otherwise, and the server certificate is **never verified**. This works with a PostgreSQL server with or without TLS and needs no TLS setup. The trade-off: on a network you do not control, someone on the network path could force plaintext, read the traffic or impersonate the server and capture your credentials. That is acceptable on a trusted network or for local development. For a host that is not loopback or a Unix-domain socket, the server prints a `[warning]` at startup and in `--validate`. To verify the server, add `SSL Mode=VerifyFull` to the connection string, plus `Root Certificate=<absolute-path-to-provider-CA-file>` for a provider or private CA ([hardening](#hardening-for-advanced-users); see also Npgsql's [TLS requirements](https://www.npgsql.org/doc/security.html)). The host name you connect to must then appear in the certificate.\n\nAn explicit `SSL Mode` (any value) is your decision and is used unchanged. One exception to the `Prefer` default: a connection string with `Root Certificate=<CA file>` but no `SSL Mode` gets `SSL Mode=VerifyFull`, because a CA file is only useful for verification (Npgsql's `Prefer` would ignore it). With `VerifyCA` or `VerifyFull`, the certificate chain (and for `VerifyFull` the host name) is verified before any credential is sent and the connection never falls back to plaintext. A non-loopback profile whose mode is not `VerifyCA`/`VerifyFull` still works but prints the `[warning]`; it is advice, not an error. `--validate` also warns when the login is a superuser or holds server-file, signal or checkpoint roles ([details](SECURITY.md#credentials-and-diagnostics)), and these warnings never block startup.\n\n### Upgrading an existing installation\n\n**0.7.0 change: two stricter 0.6.0 defaults are now opt-ins.**\n\n1. **TLS.** A connection string without `SSL Mode` now gets `SSL Mode=Prefer` for every host, loopback included: TLS when the server offers it, plaintext otherwise, certificate never verified. 0.6.0 used `VerifyFull` for non-loopback hosts and `Disable` for loopback and Unix-socket hosts. Security impact: on an untrusted network an on-path attacker can read the traffic or impersonate the server. **To restore verification,** put `SSL Mode=VerifyFull` in the connection string (in each targets profile), plus `Root Certificate=<CA file>` for a private CA. A profile that already has `Root Certificate` without `SSL Mode` (the 0.6.0 `tls_verification_failed` advice) still gets `VerifyFull` and needs no change. There is no `POSTGRES_TLS_MODE` setting; the connection string's `SSL Mode` is the single place TLS is configured, and targets profiles can differ. A PostgreSQL without TLS, such as one reached as `host.docker.internal`, now works by default.\n2. **Database lock.** `POSTGRES_DATABASES` is still enforced by the server's tools in both modes, but the PostgreSQL grant check is now advisory by default: findings print as `[warning] database lock (advisory)` lines, startup continues, and `--validate` exits 0 when connections succeed. Security impact: PostgreSQL does not confine the login, so SQL can still reach other databases where the login's privileges allow. **To restore the 0.6.0 refusal,** set `POSTGRES_DATABASE_LOCK_MODE=strict` (or `--database-lock-mode strict`) after hardening the role ([database lock hardening](SECURITY.md#database-lock-hardening)). Also, an unreachable locked profile no longer blocks advisory startup: the server starts and tool calls report the connection error, whereas `strict` still refuses.\n\nAutomatic discovery and the unrestricted default require **0.3.1 or newer**: the contract was developed under source version 0.3.0, which was never tagged or released, so 0.3.1 is the first release that contains it. npm runtime bundling requires **0.3.3 or newer**. **0.4.0** added the [database lock](#database-lock): an existing `POSTGRES_DATABASES` configuration refused to start unless PostgreSQL grants matched the list (see the [hardening guide](SECURITY.md#database-lock-hardening)); since 0.7.0 that check only warns unless `POSTGRES_DATABASE_LOCK_MODE=strict`. **0.5.0** extended that check: it also refuses a login that can execute server-file functions such as `pg_read_binary_file` in a locked database, so revoke such grants before upgrading a configuration that uses strict mode. This guide targets **0.7.0**, which loosens the defaults 0.6.0 tightened (see above). Older 0.2.0 executables use configured database aliases and a restricted default. Changing configuration does not upgrade an old executable.\n\n**History: 0.6.0 made TLS verified by default.** From 0.6.0, a profile that did not set `SSL Mode` got `SSL Mode=VerifyFull` for a non-loopback host and `SSL Mode=Disable` for loopback/Unix-socket hosts, instead of Npgsql's `Prefer`; a remote server with a private CA then failed with `tls_verification_failed` and one without TLS with `tls_unavailable`. 0.7.0 reverted that default to `Prefer` (see above); profiles that already set `SSL Mode` were never changed. Pinning **0.5.0** (`dotnet tool update --global codegiveness.postgresql-sharp-mcp --version 0.5.0`, or `@0.5.0` in the npx `args`) restores the pre-0.6.0 `Prefer` default together with the 0.5.0 strict lock check; 0.5.0 reads the same configuration.\n\nAfter publication, update an existing global .NET tool with `dotnet tool update --global codegiveness.postgresql-sharp-mcp --version 0.7.1`. For npx, update the version in your client's `args` to `@codegiveness/postgresql-sharp-mcp@0.7.1`; retain package-specific script approval. For archives, fully quit the client/server and replace the extracted files together. Recheck `--version` before reconnecting.\n\n**Breaking behavior:** a targets-file entry is now a host/login connection profile, not a database allowlist. The same credentials can select other physical databases on that PostgreSQL server. Omitted access mode means `unrestricted`; `list_databases` returns live databases rather than configured aliases. Preserve an existing explicit `POSTGRES_ACCESS_MODE=restricted` and review PostgreSQL grants before upgrading.\n\n**Rolling back the 0.4.0 lock startup refusal (history):** this applies to upgrades to 0.4.0 through 0.6.0. Since 0.7.0 the grant check refuses startup only with `POSTGRES_DATABASE_LOCK_MODE=strict`. If an existing `POSTGRES_DATABASES`/`--databases` configuration is refused after upgrading, you do not have to give up the upgrade permanently. Read the refusal findings on stderr, then either (a) pin the previous release (**0.3.3**: `dotnet tool update --global codegiveness.postgresql-sharp-mcp --version 0.3.3`, or `@0.3.3` in the npx `args`), which enforces the list inside the server without the PostgreSQL grant check, and **remove `--require-database-lock` from `args`** because 0.3.3 does not recognize it and exits with \"Unknown option\" (a `POSTGRES_REQUIRE_DATABASE_LOCK` environment variable is ignored by 0.3.3, so it is harmless there but no longer enforces anything), or (b) temporarily remove `POSTGRES_DATABASES`/`--databases` and any `POSTGRES_REQUIRE_DATABASE_LOCK`/`--require-database-lock` setting so the server starts on 0.4.0. Both are stopgaps: 0.3.3 accepts a lock only with a connection string (not with targets JSON/file), and removing the lock leaves the login's full PostgreSQL privileges reachable, so keep that login least-privileged and restore the lock soon. Fix the findings with the [hardening guide](SECURITY.md#database-lock-hardening), restore the lock, and re-run `--validate` before reconnecting the client.\n\nTo migrate an existing MCP entry to the environment workflow, remove `POSTGRES_TARGETS`, `POSTGRES_TARGETS_FILE` and literal `POSTGRES_CONNECTION_STRING` from its PostgreSQL `env`, plus `--targets-file`/`--connection-string` arguments. Preserve other nonsensitive settings, especially restricted access mode. Step 2 clears conflicting variables only in the current shell. Combining a connection string with targets JSON/file fails closed. Protected files can remain on disk; do not delete or rename them merely to switch workflows.\n\n### Optional reusable Bash/Zsh prompt in your rc file\n\nThis is optional; the quick start needs no rc changes. The **same function works in Bash and Zsh** and validates before a chained launch. Save only the function definition, never a credential or an automatic invocation. Preserve your existing startup configuration.\n\n```sh\npostgres_mcp_env() {\n  unset POSTGRES_TARGETS POSTGRES_TARGETS_FILE POSTGRES_CONNECTION_STRING\n  printf 'PostgreSQL connection string (hidden): ' >&2\n  IFS= read -r -s POSTGRES_CONNECTION_STRING && export POSTGRES_CONNECTION_STRING\n  printf '\\n' >&2\n  \"$HOME/postgresql-mcp/app/PostgreSqlMcp\" --validate\n}\n```\n\nAdjust the executable path if yours differs. EOF does not export partially entered input; validation rejects missing/empty credentials. Call `postgres_mcp_env && omp` only after fully quitting the existing client and completing registration. Do not call the function in a subprocess and expect it to change the parent environment. It does not modify credential files.\n\n- **Bash:** an interactive non-login shell reads `~/.bashrc`. Login Bash reads the first existing readable file among `~/.bash_profile`, `~/.bash_login`, `~/.profile`, not all three; it does not automatically read `.bashrc`. If needed, let your existing login file conditionally source `.bashrc` for interactive Bash. Do not replace your files or put shell-specific commands into a shared `.profile`. See [Bash startup files](https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html).\n- **Zsh:** use `~/.zshrc`, or `$ZDOTDIR/.zshrc` if customized, for interactive shells. `.zprofile` is login-only; `.zshenv` also runs in noninteractive shells and is not a place for secret prompts. See [Zsh startup files](https://zsh.sourceforge.io/Doc/Release/Files.html).\n\nAfter reviewing and saving the chosen file, source **only your current shell's rc file**: `source \"$HOME/.bashrc\"` in Bash or `source \"${ZDOTDIR:-$HOME}/.zshrc\"` in Zsh. Sourcing executes all commands in the file. No shell-specific prompt option is used.\n\n### Optional protected targets file\n\nChoose this **instead of the connection-string environment** for multiple hosts/logins or GUI/automation launches where session inheritance is impractical. It is not required for one-server discovery. Existing `targets.json`, `targets-0.2.0.json` or other protected filenames remain supported; use the actual path without a rename or per-database entries.\n\nBefore switching, fully quit the client/server. Clear `POSTGRES_CONNECTION_STRING` from the launching environment (`unset POSTGRES_CONNECTION_STRING` in Bash/Zsh; `Remove-Item Env:POSTGRES_CONNECTION_STRING -ErrorAction SilentlyContinue` in PowerShell), and remove its client `env` entry and `--connection-string` argument. Clear stale `POSTGRES_TARGETS` too: that JSON source takes precedence over a file. Combining a base string with targets JSON/file is rejected.\n\nFor a **new** Linux/macOS file, create private permissions before adding credentials:\n\n```sh\nmkdir -p \"$HOME/postgresql-mcp\"\nchmod 700 \"$HOME/postgresql-mcp\"\ntouch \"$HOME/postgresql-mcp/targets.json\"\nchmod 600 \"$HOME/postgresql-mcp/targets.json\"\n```\n\nOn Windows, restrict the file/folder to your account and administrators with Windows permissions. In Notepad's Save As dialog select **All files** to avoid `targets.json.txt`. Avoid shared/publicly synced folders. OS permissions do not encrypt contents; consider backup/sync exposure and privileged access.\n\nPopulate it with a plain-text editor, using the connection-string/TLS guidance above:\n\n```json\n{\n  \"primary\": \"Host=<YOUR_HOST>;Port=5432;Database=<YOUR_DATABASE>;Username=<YOUR_DATABASE_USER>;Password=<YOUR_PASSWORD>\"\n}\n```\n\nA file has **two escaping layers**: Npgsql, then JSON. The synthetic Npgsql fragment `Password=\"sample;value\"` becomes `Password=\\\"sample;value\\\"` in a JSON string. Double a literal quote inside an Npgsql quoted value, then escape each quote for JSON; double JSON backslashes too. A JSON-aware editor/serializer helps. No trailing commas are allowed. Never commit the file or paste it into chat/public reports.\n\nFor separate hosts/logins, add case-sensitive profile keys such as `reporting`, each with its own bootstrap string—not an entry per database. A profile is **not an allowlist**; add a [database lock](SECURITY.md#database-lock-hardening) (`POSTGRES_DATABASES`) to limit every profile's database selection to named databases (set `POSTGRES_DATABASE_LOCK_MODE=strict` as well to make PostgreSQL enforce it). Optional `target` selects a profile explicitly; see [selection rules](#database-selection-and-live-discovery).\n\nIn the MCP entry, add only `\"POSTGRES_TARGETS_FILE\"` in `env` with the actual absolute file path, alongside nonsensitive options. Linux: `/home/YOUR_USER/postgresql-mcp/targets.json`; macOS: `/Users/YOUR_USER/postgresql-mcp/targets.json`; Windows JSON: `\"C:\\\\Users\\\\YOUR_USER\\\\postgresql-mcp\\\\targets.json\"`. This path points to the credentials file, not MCP JSON. Do not also add a connection string.\n\nValidate from the shell where conflicting variables were cleared:\n\n```sh\n\"$HOME/postgresql-mcp/app/PostgreSqlMcp\" --targets-file \"$HOME/postgresql-mcp/targets.json\" --validate\n```\n\n```powershell\n& \"$HOME\\postgresql-mcp\\app\\PostgreSqlMcp.exe\" --targets-file \"$HOME\\postgresql-mcp\\targets.json\" --validate\n```\n\nUse your actual paths and keep validation stderr private. Reload the saved MCP configuration (OMP: `/mcp reload`) or fully restart the client. After changing credentials/profiles, restart the server; new databases/grant changes require no edits or restart. The file route avoids relying on a session secret, but conflicting inherited connection strings must still be removed before launching.\n\n### If setup does not work\n\n| What you see | What to check |\n|---|---|\n| Executable not found / spawn error | Use an absolute executable path including `.exe` on Windows, not an archive/folder; keep extracted files together. |\n| Wrong architecture / cannot execute binary | Match the archive to your OS and CPU. |\n| npm reports blocked install scripts / native command cannot execute | Use the full npx command above with package-specific `--allow-scripts`; if a previous install skipped scripts, use a fresh npm cache for the corrected command. |\n| npm install fails with `postgresql-sharp-mcp-npm-install: not found` (or \"is not recognized\") | npm did not install the platform package for this machine. Remove `--omit=optional`/`--no-optional` and any `omit=optional` npm setting. If a project `package-lock.json` was created on another OS, npm can omit this platform's package ([npm/cli#4828](https://github.com/npm/cli/issues/4828)); delete `node_modules` and the lockfile, then reinstall. Supported platforms are Windows x64, glibc Linux x64/arm64 and macOS x64/arm64; on Alpine/musl, Windows on Arm or other platforms, use the [.NET tool](#1-install-or-run) or a container. |\n| npx or an MCP client's npx entry fails and prints nothing (on Linux, exit code 127) | npx hides install-script output. Rerun the same command in a terminal with `--foreground-scripts` added after `npx -y` to see it, then follow the row above if it shows `postgresql-sharp-mcp-npm-install: not found` (or \"is not recognized\"), or the installer's own `postgresql-sharp-mcp: ...` message otherwise. |\n| .NET runtime not found | npm 0.3.2 and earlier require .NET; upgrade to 0.3.3 or newer after publication or use a local fixed artifact. The .NET tool still requires .NET 10 and `DOTNET_ROOT` for custom runtime locations. npm 0.3.3 and newer and standalone archives bundle the runtime. |\n| Invalid configuration / missing credentials | Read the `[startup]` line: it names the setting and the expected form (for example a `postgres://` URL, an invalid connection string, a `POSTGRES_DATABASES` value that is not a JSON array, or an unreadable targets file) without showing the value. Repeat the hidden prompt, clear stale credential sources from the shell/client entry, and start a new client from that shell. For files, check the path, JSON escaping and accidental `.txt` extension. |\n| Connection refused, timeout or authentication error | Run `--validate`; check host, port, database, login/password, network/VPN and PostgreSQL access rules. Installing this app does not grant access. |\n| `tls_verification_failed` (certificate validation error) | Only with an explicit `SSL Mode=VerifyCA`/`VerifyFull`: the server certificate is not signed by a trusted CA or does not name the host you connect to. Use the provider's host name and add `Root Certificate=<absolute-path-to-CA-file>`. Do not hide the error by weakening the mode unless you accept an unverified server. `Trust Server Certificate=true` does not bypass `VerifyFull`. |\n| `tls_unavailable` | The server does not offer TLS and the profile explicitly requires it (`SSL Mode=VerifyCA`, `VerifyFull` or `Require`). Enable TLS on the server, or remove `SSL Mode` (the default `Prefer` works without TLS) for a trusted network. |\n| No PostgreSQL tools in OMP | Check MCP configuration location/schema and executable path, then fully quit and launch OMP from the prepared shell. Reload alone cannot supply a missing inherited secret. |\n| Invalid target / database missing or denied | `target` must match a configured profile; `database` may be a real name. Check spelling, CONNECT and object privileges. Selection never falls back. |\n| Server waits silently without `--validate` | Normal: stdio mode waits for MCP messages. Let the client launch it; use `--validate` for a terminal check. |\n\nNormal stdout is reserved for MCP JSON-RPC; diagnostics use stderr. Keep credentials, SQL and results out of public reports. OMP `timeout` is in milliseconds (`30000` = 30 seconds); `POSTGRES_QUERY_TIMEOUT` is in seconds (`10` = 10 seconds).\n\n### Other installation methods\n\nChoose one installation method from step 1 and follow the same environment/client setup. If registry installation is unavailable, use the self-contained archive, a [verified local NuGet package](CONTRIBUTING.md#install-a-verified-release-artifact), or a [source build](CONTRIBUTING.md#build-from-source). Downloadable npm/NuGet release package files alone do not establish registry publication.\n\nAfter publication, get a global npm command with `npm install --global --allow-scripts=@codegiveness/postgresql-sharp-mcp @codegiveness/postgresql-sharp-mcp@0.7.1`, then `postgresql-sharp-mcp --version`. No .NET installation is required. Use `\"command\": \"postgresql-sharp-mcp\"` with no `args` in MCP JSON, or its absolute executable path if the client does not inherit npm's global bin directory on PATH.\n\nFor a source build, use `dotnet` as MCP `command` and the absolute path to `PostgreSqlMcp.dll` as the first `args` item. Keep nonsensitive settings and launch the client from the prepared shell. Self-contained builds still need native OS libraries; Debian/Ubuntu GSS/Kerberos may require `libgssapi-krb5-2`.\n\n**Docker (build from source).** No container image is published to a registry, so build one from a clone of this repository (the [Dockerfile](Dockerfile) is at its root):\n\n```sh\ndocker build -t postgresql-sharp-mcp .\n```\n\nMCP client entry. It carries no credential: `-e POSTGRES_CONNECTION_STRING` without a value makes Docker copy the variable from the environment of the process that starts `docker`, so launch the client from the shell prepared in [step 2](#2-prepare-the-connection-environment). `-i` keeps stdin open for MCP stdio; `--rm` removes the stopped container.\n\n**With `\"command\": \"docker\"`, the MCP entry's `env` block reaches only the `docker` CLI, not the server inside the container.** The container receives only what you pass explicitly: forward every setting (`POSTGRES_ACCESS_MODE`, `POSTGRES_DATABASES`, `POSTGRES_DATABASE_LOCK_MODE`, `POSTGRES_REQUIRE_DATABASE_LOCK`, `POSTGRES_QUERY_TIMEOUT`, ...) with its own `-e NAME` **before the image name**, or pass it as a CLI option **after the image name** (for example `--access-mode restricted`). The image sets no defaults, so a setting that is not forwarded is silently absent: the server runs `unrestricted` with no database lock and no error, and a forwarded lock without `POSTGRES_DATABASE_LOCK_MODE` is advisory. The example keeps restricted mode, a required database lock and strict lock mode:\n\n```json\n{\n  \"mcpServers\": {\n    \"postgresql\": {\n      \"type\": \"stdio\",\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"-i\", \"--rm\",\n        \"-e\", \"POSTGRES_CONNECTION_STRING\",\n        \"-e\", \"POSTGRES_ACCESS_MODE\",\n        \"-e\", \"POSTGRES_DATABASES\",\n        \"-e\", \"POSTGRES_DATABASE_LOCK_MODE\",\n        \"-e\", \"POSTGRES_REQUIRE_DATABASE_LOCK\",\n        \"postgresql-sharp-mcp\"\n      ],\n      \"env\": {\n        \"POSTGRES_ACCESS_MODE\": \"restricted\",\n        \"POSTGRES_DATABASES\": \"[\\\"<app_db>\\\"]\",\n        \"POSTGRES_DATABASE_LOCK_MODE\": \"strict\",\n        \"POSTGRES_REQUIRE_DATABASE_LOCK\": \"true\"\n      }\n    }\n  }\n}\n```\n\nOmit the `POSTGRES_DATABASES`/`POSTGRES_DATABASE_LOCK_MODE`/`POSTGRES_REQUIRE_DATABASE_LOCK` lines (both `-e` pairs and `env` entries) if you do not use a [database lock](#database-lock); omit only `POSTGRES_DATABASE_LOCK_MODE` to get the advisory default. Strict mode needs the PostgreSQL grants described in the [hardening guide](SECURITY.md#database-lock-hardening).\n\n- **`Host=127.0.0.1` or `localhost` inside the container is the container itself,** not your computer. For PostgreSQL on the Docker host use a host name the container can resolve, such as `host.docker.internal` (Docker Desktop; on Linux Engine add `\"--add-host=host.docker.internal:host-gateway\"` to `args` before the image name), or `\"--network\", \"host\"` on Linux. `host.docker.internal` is not loopback, so the default `Prefer` applies: a host PostgreSQL without TLS works unchanged, with a `[warning]` that the server is not verified. For a remote server use its real host name and, to verify it, add `SSL Mode=VerifyFull`.\n- The container environment is plaintext to Docker inspection and privileged operators; it is not a secret store. Restart the container after credential changes.\n- For a [protected targets file](#optional-protected-targets-file) instead, clear `POSTGRES_CONNECTION_STRING` and add a read-only bind mount plus `-e POSTGRES_TARGETS_FILE=/run/postgres.targets.json` (full command in [CONTRIBUTING](CONTRIBUTING.md#self-contained-executable-and-container)). The container runs as a **non-root user**, so a `chmod 600` file owned by your account is unreadable inside it and startup fails with \"Cannot read the targets file named by POSTGRES_TARGETS_FILE/--targets-file\". Grant that user read access through a suitable group/UID or a secret mount; do not make the file world-readable.\n\n</details>\n\n## Hardening for advanced users\n\nThe quick start favors a first success: TLS is used when the server offers it but the server is not verified, the PostgreSQL login may be a superuser, and a database lock (if you set one) is enforced by this server's tools rather than by PostgreSQL. Each of the following is an explicit opt-in; use the ones that fit your deployment. `--validate` then fails closed: it exits non-zero on strict lock findings and on TLS errors, so run it before launching the client.\n\n1. **Verified TLS.** Add `SSL Mode=VerifyFull` to the connection string (or to each targets profile), so the certificate chain and host name are verified before any credential is sent and the connection never falls back to plaintext. For a provider or private CA also add `Root Certificate=<absolute-path-to-CA-file>` (a `Root Certificate` without `SSL Mode` also selects `VerifyFull`). A failure returns `tls_verification_failed` or `tls_unavailable` ([troubleshooting](#if-setup-does-not-work)).\n\n   ```text\n   Host=<YOUR_HOST>;Port=5432;Database=<YOUR_DATABASE>;Username=<YOUR_DATABASE_USER>;Password=<YOUR_PASSWORD>;SSL Mode=VerifyFull;Root Certificate=<ABSOLUTE_PATH_TO_CA_FILE>\n   ```\n\n2. **A database lock that PostgreSQL enforces.** Set `POSTGRES_DATABASES` to the databases the server may use and `POSTGRES_DATABASE_LOCK_MODE=strict` (or `--database-lock-mode strict`). Startup and `--validate` then refuse a login whose PostgreSQL grants reach any other database. Optionally add `POSTGRES_REQUIRE_DATABASE_LOCK=true` so a missing `POSTGRES_DATABASES` is also a startup error. See [Database lock](#database-lock).\n3. **A dedicated least-privileged role.** Use a login that is not a superuser, has CONNECT only on the intended databases and only the object privileges it needs. The [role and database lock hardening guide](SECURITY.md#database-lock-hardening) lists the grants strict mode checks.\n4. **Restricted access mode.** Set `POSTGRES_ACCESS_MODE=restricted` (or `--access-mode restricted`) to refuse writes entirely.\n\nThese settings are not secrets, so they can go in the MCP entry's `env` block (the connection string stays in the hidden prompt). For example:\n\n```json\n\"env\": {\n  \"POSTGRES_ACCESS_MODE\": \"restricted\",\n  \"POSTGRES_DATABASES\": \"[\\\"<app_db>\\\"]\",\n  \"POSTGRES_DATABASE_LOCK_MODE\": \"strict\",\n  \"POSTGRES_REQUIRE_DATABASE_LOCK\": \"true\"\n}\n```\n\n<details>\n<summary>Tool and database-selection reference</summary>\n\n## Tools\n\nExcept `list_databases`, every tool **requires `database`**. Every tool accepts optional `target` to select a configured connection profile. Query and metadata page defaults are `min(100, POSTGRES_MAX_ROWS)`; top-query pages default to `min(10, POSTGRES_MAX_ROWS)`.\n\n| Tool | Capability | Options |\n|---|---|---|\n| `list_databases` | Live accessible physical databases, selected profile, access mode, whether a database lock applies (and its mode), and limits | `target`, `limit`, `offset` |\n| `list_schemas` | Schemas with USAGE privilege | literal `prefix`, `include_system`, page |\n| `list_objects` | Tables, views, materialized views, sequences, functions, procedures and extensions | `schema`, `type`, literal `search`, `include_system`, page |\n| `get_object_details` | One object's metadata section | `schema`, `name`, `section`: columns/constraints/indexes/triggers/definition/parameters; `type`, `identity_arguments`, page |\n| `execute_sql` | One SQL statement; bounded results or explicitly enabled writes | `sql`, `parameters` (values for `$1..$n`), `read_only`, page |\n| `explain_query` | Estimated/actual JSON plan and compact major-node summary | `sql`, `parameters`, `format`: summary/json, `analyze`, optional HypoPG `indexes` |\n| `analyze_indexes` | Index size, usage, validity, constraints and structural duplicate evidence | `schema`, `table`, page |\n| `get_top_queries` | Current-database `pg_stat_statements` workload | `order_by`: total_time/mean_time/calls/rows/reads, page |\n| `analyze_db_health` | Summary or focused PostgreSQL health evidence | `section`: summary/vacuum/index/constraints/sequences/replication/blocking; `schema` where applicable, page |\n\n`parameters` binds up to 256 JSON scalars (string, number, boolean or `null`) to `$1..$n` in order. Values are sent separately from the SQL text, never interpolated, so quotes and statement-like text in a value stay data. Each value is sent as PostgreSQL's untyped `unknown`, so the server infers its type from context exactly as for a quoted literal (`WHERE created_at > $1` with `\"2026-01-20\"`). Cast where context is ambiguous (`$1::int`, `$1::jsonb`); objects and arrays are refused, so pass JSON documents as strings and cast. Too few values for the highest `$n` returns SQLSTATE `08P01`; extra values, or a skipped placeholder number such as `$2` without `$1`, return `42P18` (the server cannot infer a type for an unreferenced parameter, so cast the placeholders you use and send no more values than the statement references). The server is stateless: to fetch the next page, resend the same `sql` and `parameters` with `next_offset`, which are re-bound on each call. Parameters do not change read-only enforcement.\n\nRoutine overloads require the exact `identity_arguments` from `list_objects`, including parameter names; an empty string selects zero arguments. Use `type` to disambiguate relation/routine name collisions. Discovery filters by role privileges; missing or hidden objects return an error. Table definitions are structural fragments, not a round-trip DDL export.\n\nWhat clients and agents are told follows the enforced configuration. In unrestricted mode `execute_sql` is annotated `readOnlyHint: false`, `destructiveHint: true` and its description explains the `read_only=false` write opt-in; in restricted mode it is annotated read-only and its description says writes are refused. All other tools are annotated read-only in both modes. The MCP `initialize` result carries server instructions naming the access mode, whether a database lock applies, and the result/time limits; under a lock, `list_databases` and `execute_sql` descriptions say only listed databases can be selected and state the lock mode: `strict` means PostgreSQL grants were verified at startup to confine the login to those databases, while `advisory` means grants were not required to confine the login, so SQL may still reach other databases where the login's privileges allow. Annotations are hints about this server's own enforcement, not a guarantee about side effects of privileged PostgreSQL functions; see [access boundaries](#access-and-resource-boundaries).\n\nEach call independently resolves its physical database and leases a connection with that database in its connection string. Concurrent calls do not share a current database or issue `USE`; a failed selection never falls back to another database.\n\nFocused inspection:\n\n```json\n{\"name\":\"list_objects\",\"arguments\":{\"database\":\"primary\",\"schema\":\"public\",\"type\":\"table\",\"search\":\"order\",\"limit\":20}}\n```\n\n```json\n{\"name\":\"get_object_details\",\"arguments\":{\"database\":\"primary\",\"schema\":\"public\",\"name\":\"orders\",\"section\":\"indexes\",\"limit\":10}}\n```\n\n### Database selection and live discovery\n\nA profile is a case-sensitive name mapped to a bootstrap connection string: `POSTGRES_CONNECTION_STRING` alone creates `primary`, while optional targets JSON/file defines named profiles. The default profile is `primary` when configured, otherwise the ordinal-first profile name.\n\n- **Without `target`:** an exact configured alias in `database` selects that alias's bootstrap database for compatibility. Any other value is a physical database name on the default profile.\n- **With `target`:** that profile supplies the host, authentication and TLS settings; `database` is always a physical database name. Use this form to select a database whose name happens to match an alias.\n- Only the connection string's `Database` changes. Tool calls cannot supply credentials, change the host, or rewrite the protected file. An unknown profile returns `invalid_target`; a nonexistent physical database returns PostgreSQL SQLSTATE `3D000`, and insufficient privilege returns `42501`. Connectivity failures remain errors, not fallback requests.\n- **With a database lock** (`POSTGRES_DATABASES`), every resolved physical database—from `database`, an alias's bootstrap database or `target`—must be on the list, otherwise the call returns `invalid_target` without connecting. See [Database lock](#database-lock).\n\nFor example, discover and select databases on the `primary` profile:\n\n```json\n{\"name\":\"list_databases\",\"arguments\":{\"target\":\"primary\",\"limit\":20,\"offset\":0}}\n```\n\n```json\n{\"name\":\"execute_sql\",\"arguments\":{\"target\":\"primary\",\"database\":\"tenant_b\",\"sql\":\"SELECT current_database() AS selected_database\",\"limit\":1}}\n```\n\n`list_databases` queries live `pg_catalog.pg_database` on the selected profile's bootstrap database (under a database lock, the first locked database when the bootstrap database is not locked). It excludes templates, databases with connections disabled and databases for which the current role lacks CONNECT; a database lock further filters the page. Names are ordered with PostgreSQL `COLLATE \"C\"`, and `is_current` marks the database used for that listing. New databases and grant/revoke changes appear on subsequent calls without restarting; listing does not guarantee network/authentication or object access for a later connection.\n\nThe response is `{ \"target\": \"...\", \"databases\": { ... }, \"access_mode\": \"...\", \"database_lock\": true|false, \"database_lock_mode\": \"advisory\"|\"strict\", \"limits\": { ... } }`; `database_lock_mode` is present only when `database_lock` is `true`. `databases` is the same bounded query-page shape described below, with `columns` named `name` and `is_current`, positional `rows` such as `[[\"postgres\",true],[\"tenant_b\",false]]`, and `offset`, `next_offset`, `truncated`, `truncation_reason` and `clipped_cells`. Follow `databases.next_offset` using the same `target` and `limit`; pages are live queries, not a shared snapshot. The obsolete `targets` alias-list payload is no longer returned. Catalog failures are reported rather than silently replaced with configured aliases.\n\n### Database lock\n\nTo protect databases that must never be touched, run one server instance per PostgreSQL server and set `POSTGRES_DATABASES` (or `--databases`) to a JSON array of the exact databases that instance may use, for example `[\"<app_db>\"]`. It works with either a connection string or a targets JSON/file and does not change their formats. In **both** lock modes this server enforces the list on every path: a call that selects another database returns `invalid_target` before connecting, `list_databases` lists only the locked names, and the server itself never opens a session on an out-of-lock database. Set `POSTGRES_REQUIRE_DATABASE_LOCK=true` (or `--require-database-lock`) to make a missing lock a startup error.\n\n`POSTGRES_DATABASE_LOCK_MODE` (or `--database-lock-mode`, which overrides the environment) chooses whether PostgreSQL itself must also confine the login:\n\n- **`advisory` (default).** At startup and in `--validate` the server still checks PostgreSQL grants: whether the role can connect to any other database, is or can become a superuser, has `CREATEDB`/`CREATEROLE`, owns an out-of-lock database, holds server-file roles or explicit `EXECUTE` on server-file functions such as `pg_read_binary_file`, or has `dblink`/`postgres_fdw`/foreign servers in a locked database. Each finding, and a check that cannot connect, prints as a `[warning] database lock (advisory)` line; startup continues and `--validate` exits 0 when connections succeed. SQL run inside an allowed database can still reach other databases when the login's privileges allow ([what advisory mode does and does not protect against](SECURITY.md#what-advisory-mode-does-and-does-not-protect-against)).\n- **`strict`.** The same findings, or a check that cannot complete, refuse startup (exit 1; `--validate` exits non-zero), so PostgreSQL itself enforces the list. Use it after hardening the role. `strict` without a configured lock, or any value other than `advisory`/`strict`, is a startup error.\n\nDefault PostgreSQL grants give `PUBLIC` CONNECT on `postgres` and `template1`, so most roles need hardening before strict mode passes: follow the [database lock hardening guide](SECURITY.md#database-lock-hardening), which also includes a multi-instance harness example.\n\n### Supported PostgreSQL versions\n\n**PostgreSQL 13 or newer** is supported. The integration verifier runs the MCP scenarios against official Docker images of majors 13 through 18 in CI. PostgreSQL 13 reached community end of life in November 2025, so the minimum can rise in a later release. Older servers are untested and unsupported; some catalog queries need 13 (`regcollation`) and there is no compatibility layer below it.\n\n**PostgreSQL 19 is tested as a pre-release.** As of 2026-10-22 the PostgreSQL project had published [19 RC 1](https://www.postgresql.org/about/news/postgresql-19-rc-1-released-3409/) but no final release, and its supported-versions list ends at 18. CI runs the same integration scenarios against the official `postgres:19rc1-bookworm` image, an informational `Integration (PostgreSQL 19)` job that is not a required check. Pre-release behavior can still change before the final release, so 19 is not a support commitment until the fixture moves to the released image and passes.\n\n| Area | Requirement and behavior |\n|---|---|\n| All tools | PostgreSQL 13+ |\n| `get_top_queries` | `pg_stat_statements` extension 1.8+ (the PostgreSQL 13 layout). The `toplevel` column is filled with extension 1.9+ (PostgreSQL 14+ default); with 1.8 the column is still returned, always null, and the notes say so. A cluster upgraded with `pg_upgrade` keeps its old extension version until `ALTER EXTENSION pg_stat_statements UPDATE` runs in each database; below 1.8 the tool returns `extension_outdated` with that instruction instead of a generic column error. |\n| `get_object_details` | Column collations use `regcollation` (13+). PostgreSQL 18 virtual generated columns are shown as such. |\n| `analyze_indexes` | `NULLS NOT DISTINCT` (PostgreSQL 15+) is compared when the server has it. |\n| `explain_query` with `indexes` | HypoPG package for the server's major version (no preload needed). |\n\n### Plans and optional extensions\n\nNo extensions are installed automatically. An authorized administrator must configure extensions in the databases where they are needed:\n\n- **`pg_stat_statements`:** install the server extension package, preload it at server start (`shared_preload_libraries` in the server configuration, or the equivalent parameter-group/console setting of a managed service, without removing existing entries), restart PostgreSQL as that setting requires, and run `CREATE EXTENSION pg_stat_statements` in each selected database. After a major-version upgrade, also run `ALTER EXTENSION pg_stat_statements UPDATE` there. It is needed only for workload statistics.\n- **HypoPG:** install the extension package matching the PostgreSQL server major version, then run `CREATE EXTENSION hypopg` in the selected database. HypoPG itself does not require preload or a restart. It is needed only for hypothetical `indexes` in `explain_query`.\n\nExtension schemas are discovered and quoted rather than assumed to be `public`. Missing or unready extensions produce explicit errors. Check availability and installation before changing a database:\n\n```sql\nSELECT name, default_version, installed_version\nFROM pg_available_extensions\nWHERE name IN ('hypopg', 'pg_stat_statements');\n```\n\nExample what-if call:\n\n```json\n{\"name\":\"explain_query\",\"arguments\":{\"database\":\"primary\",\"sql\":\"SELECT * FROM public.orders WHERE customer=42\",\"indexes\":[\"CREATE INDEX ON public.orders(customer)\"]}}\n```\n\nHypothetical candidates are passed to HypoPG, **not executed as permanent DDL**. The tool compares baseline and combined-candidate planner costs in one session, cleans hypothetical indexes after success or failure, and clears the pool if cleanup fails. At most 16 candidates are accepted; `analyze=true` cannot be combined with hypothetical indexes. Independent candidate commands are batched into one database round trip.\n\nPlanner costs are estimates, not measured speedups or automatic recommendations. The summary ranks at most eight nodes by inclusive subtree cost, reports omitted nodes and does not sum overlapping costs. Health checks likewise report catalog/statistics evidence rather than universal severity thresholds. Sequence estimates depend on increment direction, caching and cycling. Replication reports database-local logical slots, not server-wide physical replication. Blocking PIDs are textual PostgreSQL arrays; another database's blocking query text is omitted.\n\nWorkload text is filtered by current database OID even for roles with server-wide monitoring privileges. Tracked statements may include transaction/session setup when `pg_stat_statements.track_utility` is enabled. High call counts alone do not identify expensive application queries; choose a relevant time, I/O or row ranking.\n\n</details>\n\n<details>\n<summary>Result format, bounded results and pagination</summary>\n\n## Bounded results and pagination\n\nSuccessful results provide a JSON object in MCP `structuredContent` and a compact JSON text compatibility block. Consume one representation rather than inserting both into model context. Column names/types appear once and rows use positional arrays, preserving duplicate column names:\n\n```json\n{\n  \"database\":\"primary\",\n  \"columns\":[{\"name\":\"id\",\"type\":\"integer\"},{\"name\":\"customer\",\"type\":\"integer\"}],\n  \"rows\":[[1,42],[2,17]],\n  \"offset\":0,\n  \"next_offset\":2,\n  \"truncated\":true,\n  \"truncation_reason\":\"row_limit\",\n  \"clipped_cells\":[]\n}\n```\n\nMetadata sections wrap the page in `page`; health/index/workload tools use `result`; `list_databases` uses `databases`. Optional null envelope fields are omitted; SQL NULL remains null. DML without `RETURNING` includes `rows_affected` when known; DDL returns an empty rowset. `bytea` values are base64 strings with their PostgreSQL type retained.\n\n- Repeat the **same read-only operation and filters** with `next_offset`. SELECT/WITH/VALUES/TABLE reads use PostgreSQL `LIMIT limit+1 OFFSET offset`; other read-only statement types use streaming row bounds.\n- Pages re-execute SQL and **do not share a snapshot**. Use a stable unique `ORDER BY`; use keyset SQL for changing datasets or deep pagination. Offsets are capped at 1,000,000.\n- `truncation_reason` is `row_limit` or `byte_limit`. The next offset advances by returned rows, so a byte-truncated row is not skipped.\n- `clipped_cells` identifies zero-based returned-row/column coordinates. Text is bounded by UTF-16 characters without splitting surrogate pairs; binary uses a corresponding base64 budget. Remaining byte space may shorten cells further. Cell clipping is distinct from row truncation.\n- Retrieve long values deliberately with SQL projections such as `substring(large_text FROM 257 FOR 256)` or `substring(binary_column FROM 193 FOR 192)`. PostgreSQL text substring positions count Unicode characters, not JSON escape bytes.\n- Results allow at most 128 columns. Arrays and unbounded provider-specific composite mappings require slicing or casting in SQL. Calendar-month intervals and numbers outside .NET's scalar range return `unsupported_result_value` with projection guidance.\n- A row, plan or envelope that cannot fit produces an error requesting a narrower projection/section, smaller limit or operator-approved larger budget. Complete planner JSON must fit even in summary mode; it is not silently cut into invalid JSON.\n- **Writes are never paginated or replayed.** A truncated `RETURNING` response has no next offset; the full statement still commits once. Inspect committed data separately. No automatic query retries are performed.\n\n`POSTGRES_MAX_RESULT_BYTES` bounds each payload representation, not the complete JSON-RPC envelope. Structured JSON plus compatibility text increases wire size. Actual context/token usage depends on the client and model; no cross-server efficiency claim is made.\n\nA local restricted-mode `tools/list` run of this version returned nine tools in **10,516 UTF-8 bytes** for the compact tool array (0.4.0: 6,780 bytes); every parameter now carries a short description with its allowed values or default. The `initialize` instructions add about 500 bytes once per session. These are discovery bytes, not model-token counts, query timings or a comparison with an “average MCP.” Client/model tokenization and result selection determine context cost.\n\nOperation errors set MCP `isError=true` and include target, error code and PostgreSQL SQLSTATE when available, with a fixed SQLSTATE-specific summary. For SQL submitted to `execute_sql` or `explain_query`, `position` gives PostgreSQL's 1-based character position within that statement. Syntax and access-rule errors that PostgreSQL positions inside the submitted statement (SQLSTATE class `42`, plus `42501` privilege errors; not raised inside a routine or internal query) add PostgreSQL's `server_message` and `server_hint`, for example `syntax error at or near \"WHERE\"` or `column \"x\" does not exist`; integrity errors (class `23`) add the violated `constraint` name. Other PostgreSQL messages, hints and details are withheld because they may contain data values ([details](SECURITY.md#credentials-and-diagnostics)). Protocol/SDK argument-validation errors use the SDK envelope.\n\n</details>\n\n<details>\n<summary>Security, access and resource boundaries</summary>\n\n## Access and resource boundaries\n\n**Unrestricted mode is the default when access mode is omitted.** Each read-only operation owns a transaction with `SET TRANSACTION READ ONLY`. Client SQL is lexically limited to one statement and cannot issue transaction/session control. The statement-boundary lexer handles comments and PostgreSQL quoting; it is **not a SQL authorization AST**.\n\nFor authorized writes, explicitly pass `read_only=false` to `execute_sql`; the PostgreSQL role must also have the necessary privileges. The server commits once on success and rolls back on failure. Default calls remain read-only in unrestricted mode. To refuse writes, opt into `POSTGRES_ACCESS_MODE=restricted` or `--access-mode restricted`; existing explicit restricted settings remain effective. `explain_query` and metadata/operations tools remain read-only; tool annotations advertise potentially destructive SQL execution in unrestricted mode.\n\nTransaction/session controls, COPY, DO, CALL, PREPARE and VACUUM are unsupported in SQL tools; use an administrative client. Routine metadata inspection is supported and functions can be queried with SELECT.\n\n**A least-privileged role is strongly recommended; a superuser works but is not recommended.** Read-only transactions do not sandbox PostgreSQL functions, SECURITY DEFINER routines, foreign servers/dblink, external side effects, session settings or privileged monitoring. Profiles constrain host/authentication/TLS, not which physical databases those credentials can access. PostgreSQL must enforce CONNECT, schema/table/column privileges and RLS; review `PUBLIC` CONNECT grants. Use separate credentials for tenants requiring separate authorization. An optional explicit database allowlist narrows selection but is not database authorization unless `POSTGRES_DATABASE_LOCK_MODE=strict` has verified a hardened role. Treat SQL results as untrusted data, not agent instructions. The server exposes stdio, not an authenticated remote transport.\n\nSession credentials are plaintext environment state readable by sufficiently privileged local processes and inherited by children. They are not automatically persisted, but supervisors, launchers, containers or deliberate persistence can store them. Protected files are persistent plaintext with OS permissions, not encryption. Neither route is inherently safer in every deployment; see [credential storage tradeoffs](SECURITY.md#credentials-and-diagnostics). Hidden PowerShell input uses a SecureString only while reading; conversion to the environment is plaintext.\n\nResource management:\n\n- Lazy, thread-safe `NpgsqlDataSource` per effective normalized connection configuration, including physical database, credentials and TLS; equivalent pro","readmeFilename":"README.md"}