Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ body:
attributes:
label: Version
description: Output of `postgresql-sharp-mcp --version`, or the commit SHA when running from source.
placeholder: 0.4.0
placeholder: 0.5.0
validations:
required: true
- type: dropdown
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

## 0.5.0

Upgrade notes: a locked configuration whose login can execute server-file functions is now refused at startup, and npm installs that omit optional dependencies now fail (both below). Existing tool names, parameters, environment variables, CLI flags and the targets-file format remain compatible; additions such as the `parameters` input of `execute_sql`/`explain_query` are optional.
- npm: the 177 MB package that bundled all five platform runtimes is split into a main package of about 140 KB and five platform packages of 35–39 MB each (`@codegiveness/postgresql-sharp-mcp-win32-x64`, `-linux-x64`, `-linux-arm64`, `-darwin-x64`, `-darwin-arm64`). The main package lists them as `optionalDependencies`, so npm, npx and global installs download only the package matching the machine's OS, CPU and (on Linux) glibc. The install command, `--allow-scripts` approval, `bin` name and installed native server are unchanged. The upstream `run-script-os` runner and the installation-time `uname` call are no longer used. An install that omits optional dependencies (`--omit=optional`) or runs on an unsupported platform such as Alpine/musl now fails with `postgresql-sharp-mcp-npm-install: not found`, where the old installer printed the supported-platform list; see the README troubleshooting table. Releases stage the platform packages before the main package. Each new package name needs a one-time npm trusted-publisher setup; see CONTRIBUTING.
- Security: the database lock check now also refuses startup when the login, or any role it can `SET ROLE` to (including through `NOINHERIT` or `INHERIT FALSE` memberships), holds `EXECUTE` on a server-file function (`pg_read_file`, `pg_read_binary_file`, `pg_ls_dir`, server-side `lo_import`/`lo_export`, adminpack `pg_file_write`/`pg_file_unlink`/`pg_file_rename`) in any reachable locked database. Such a grant needs no `pg_read_server_files` membership, and `pg_read_binary_file` can read other databases' relation files from the data directory, bypassing the lock. Existing locked configurations with such grants are now refused; revoke the grant as described in the [hardening guide](SECURITY.md#database-lock-hardening).
- Fix: a connection-string database lock (`POSTGRES_DATABASES`) with more than 32 names, or with names × `POSTGRES_POOL_SIZE` above 256, was refused at startup with "Configure 1..32 database targets." Lock names are `target` aliases of one connection-string login profile; the 32-profile and profiles × pool-size limits now count only targets JSON/file profiles (a connection string counts as one). The runtime pool cache bound (`floor(256 / POSTGRES_POOL_SIZE)` data sources) is unchanged.
Expand Down
25 changes: 12 additions & 13 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,17 +263,17 @@ Enter the username at the prompt rather than copying a sibling secret. GitHub OI

#### Dispatch the exact existing release

Merge the reviewed release-tool/workflow changes to `main` before using them. Only dispatch after the account permissions, matching policies and the `v<version>` tag (for example `v0.4.0`) are ready. **Actions → Release → Run workflow** must select **main**. The equivalent commands below are alternatives; run only the intended target:
Merge the reviewed release-tool/workflow changes to `main` before using them. Only dispatch after the account permissions, matching policies and the `v<version>` tag (for example `v0.5.0`) are ready. **Actions → Release → Run workflow** must select **main**. The equivalent commands below are alternatives; run only the intended target:

```powershell
# Default all: GitHub Release + npm staging + NuGet publication.
gh workflow run release.yml --repo codegiveness/postgresql-sharp-mcp --ref main -f tag=v0.4.0 -f target=all
gh workflow run release.yml --repo codegiveness/postgresql-sharp-mcp --ref main -f tag=v0.5.0 -f target=all
# npm staging only; no GitHub Release or NuGet publication.
gh workflow run release.yml --repo codegiveness/postgresql-sharp-mcp --ref main -f tag=v0.4.0 -f target=npm
gh workflow run release.yml --repo codegiveness/postgresql-sharp-mcp --ref main -f tag=v0.5.0 -f target=npm
# NuGet publication only; no GitHub Release or npm staging.
gh workflow run release.yml --repo codegiveness/postgresql-sharp-mcp --ref main -f tag=v0.4.0 -f target=nuget
gh workflow run release.yml --repo codegiveness/postgresql-sharp-mcp --ref main -f tag=v0.5.0 -f target=nuget
# GitHub Release only; no registry staging/publication.
gh workflow run release.yml --repo codegiveness/postgresql-sharp-mcp --ref main -f tag=v0.4.0 -f target=github
gh workflow run release.yml --repo codegiveness/postgresql-sharp-mcp --ref main -f tag=v0.5.0 -f target=github
```

`target` choices are `all`, `github`, `npm` and `nuget`, defaulting to `all`. Every target retains common preflight, package/installed-distribution verification and attestation. npm-only and NuGet-only jobs tolerate an intentionally skipped GitHub Release job **only for their dedicated target**; failed/canceled prerequisites cannot reach a publisher. In `all` mode both registry jobs require successful GitHub Release publication. The npm command stages the exact attested tarball using `npm stage publish`, never approves it or calls direct `npm publish`. Its successful summary means **staged, pending Windows 2FA approval**, not published.
Expand All @@ -284,21 +284,21 @@ For a failed current main-dispatched workflow, `gh run rerun <run-id> --failed -

After the npm staging job succeeds, review each stage ID and intended `latest` tag. The job stages the five platform packages before the main package. Approve them in the same order, **platform packages first**, so the public main package never points at unpublished optional dependencies. Every public npm publication requires the maintainer's Windows 2FA approval. A successful dispatch, login, OIDC exchange or staging response is not approval.

Repeat this review for each package, setting `$Package` and its tarball name `$Tarball` in turn: `@codegiveness/postgresql-sharp-mcp-<os>-<cpu>` with `codegiveness-postgresql-sharp-mcp-<os>-<cpu>-0.4.0.tgz` for the five platforms, and finally `@codegiveness/postgresql-sharp-mcp` with `codegiveness-postgresql-sharp-mcp-0.4.0.tgz`:
Repeat this review for each package, setting `$Package` and its tarball name `$Tarball` in turn: `@codegiveness/postgresql-sharp-mcp-<os>-<cpu>` with `codegiveness-postgresql-sharp-mcp-<os>-<cpu>-0.5.0.tgz` for the five platforms, and finally `@codegiveness/postgresql-sharp-mcp` with `codegiveness-postgresql-sharp-mcp-0.5.0.tgz`:

```powershell
$Package = '@codegiveness/postgresql-sharp-mcp-win32-x64'
$Tarball = 'codegiveness-postgresql-sharp-mcp-win32-x64-0.4.0.tgz'
$Tarball = 'codegiveness-postgresql-sharp-mcp-win32-x64-0.5.0.tgz'
npm.cmd stage list $Package --registry https://registry.npmjs.org/
$StageId = Read-Host "Stage ID for $Package 0.4.0"
$StageId = Read-Host "Stage ID for $Package 0.5.0"
npm.cmd stage view $StageId --registry https://registry.npmjs.org/
npm.cmd stage download $StageId --registry https://registry.npmjs.org/
```

Confirm the stage is **`$Package@0.4.0`**, comes from the intended run and uses the intended dist-tag. Compare the downloaded staged tarball's SHA-256 against the attested release tarball before approval. For the 0.4.0 GitHub release:
Confirm the stage is **`$Package@0.5.0`**, comes from the intended run and uses the intended dist-tag. Compare the downloaded staged tarball's SHA-256 against the attested release tarball before approval. For the 0.5.0 GitHub release:

```powershell
gh release download v0.4.0 --repo codegiveness/postgresql-sharp-mcp --pattern $Tarball --dir release-verification
gh release download v0.5.0 --repo codegiveness/postgresql-sharp-mcp --pattern $Tarball --dir release-verification
gh attestation verify ./release-verification/$Tarball --repo codegiveness/postgresql-sharp-mcp --signer-workflow codegiveness/postgresql-sharp-mcp/.github/workflows/release.yml
Get-FileHash ./release-verification/$Tarball -Algorithm SHA256
$StagedTarball = Read-Host 'Path printed by npm stage download'
Expand All @@ -311,16 +311,15 @@ Only after that review, approve the exact stage:

```powershell
npm.cmd stage approve $StageId --registry https://registry.npmjs.org/
npm.cmd view "$Package@0.4.0" version dist.integrity dist.tarball --registry https://registry.npmjs.org/
npm.cmd view "$Package@0.5.0" version dist.integrity dist.tarball --registry https://registry.npmjs.org/
npm.cmd view $Package dist-tags --registry https://registry.npmjs.org/
```

After approving the main package last, check the public installation:

```powershell
npx.cmd --yes --allow-scripts=@codegiveness/postgresql-sharp-mcp --cache ./release-verification/npm-cache-0.4.0 '@codegiveness/postgresql-sharp-mcp@0.4.0' --version
npx.cmd --yes --allow-scripts=@codegiveness/postgresql-sharp-mcp --cache ./release-verification/npm-cache-0.5.0 '@codegiveness/postgresql-sharp-mcp@0.5.0' --version
```

Complete the command's **2FA/browser challenge on Windows** promptly; an expired or canceled challenge does not publish. npmjs.com's **Staged Packages → Approve** is an alternative with the same required 2FA, not an automated bypass. Approval cannot use workflow OIDC. Check public version, integrity/tarball equality and fresh-cache execution before announcing availability; check actual provenance evidence separately. A workstation-staged recovery must use the exact verified tarball with `npm.cmd stage publish ./release-verification/$Tarball --ignore-scripts --access public --tag latest --registry https://registry.npmjs.org/` and the same review/2FA approval; it does not gain CI provenance. Do not restage a version already pending approval or already published.

#### Recorded publication evidence
Expand Down
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@

SQL calls are read-only by default, but the server's default access mode permits explicitly requested writes. Use a least-privileged database login, never a superuser. Keep an existing explicit `restricted` setting; [access boundaries](#access-and-resource-boundaries) explain how to refuse writes entirely.

**Fastest start:** Node.js 22+ and npm are enough, because npm installs the .NET runtime with the server. This downloads and runs version 0.4.0:
**Fastest start:** Node.js 22+ and npm are enough, because npm installs the .NET runtime with the server. This downloads and runs version 0.5.0:

```sh
npx -y --allow-scripts=@codegiveness/postgresql-sharp-mcp @codegiveness/postgresql-sharp-mcp@0.4.0 --version
npx -y --allow-scripts=@codegiveness/postgresql-sharp-mcp @codegiveness/postgresql-sharp-mcp@0.5.0 --version
```

It should print `postgresql-sharp-mcp 0.4.0.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).
It should print `postgresql-sharp-mcp 0.5.0.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).

**What you can ask once it is connected:**

Expand All @@ -41,31 +41,31 @@ Every result is a row- and byte-bounded page that the assistant can continue wit

Choose **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.

This guide targets **0.4.0**. 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.
This guide targets **0.5.0**. 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.

**npx — run without a global install:**

```sh
npx -y --allow-scripts=@codegiveness/postgresql-sharp-mcp @codegiveness/postgresql-sharp-mcp@0.4.0 --version
npx -y --allow-scripts=@codegiveness/postgresql-sharp-mcp @codegiveness/postgresql-sharp-mcp@0.5.0 --version
```

The 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.

**.NET tool — install once, then run by name:**

```sh
dotnet tool install --global codegiveness.postgresql-sharp-mcp --version 0.4.0
dotnet tool install --global codegiveness.postgresql-sharp-mcp --version 0.5.0
postgresql-sharp-mcp --version
```

If 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.

The command should report **0.4.0** (or assembly version **0.4.0.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.
The command should report **0.5.0** (or assembly version **0.5.0.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.

<details>
<summary>Standalone archives — no .NET, Node.js or npm installation needed</summary>

Download **one archive** and `SHA256SUMS` from [release 0.4.0](https://github.com/codegiveness/postgresql-sharp-mcp/releases/tag/v0.4.0). These archives include the .NET runtime: you do not need the .NET SDK, npm, Node.js or Docker for this installation.
Download **one archive** and `SHA256SUMS` from [release 0.5.0](https://github.com/codegiveness/postgresql-sharp-mcp/releases/tag/v0.5.0). These archives include the .NET runtime: you do not need the .NET SDK, npm, Node.js or Docker for this installation.

| Your computer | Archive |
|---|---|
Expand Down Expand Up @@ -128,7 +128,7 @@ Expand-Archive -Path "$HOME\Downloads\postgresql-sharp-mcp-win-x64.zip" -Destina

</details>

The executable should report **0.4.0**. If you already have an older installation, read [upgrade notes](#upgrading-an-existing-installation) before reusing its configuration.
The executable should report **0.5.0**. If you already have an older installation, read [upgrade notes](#upgrading-an-existing-installation) before reusing its configuration.

</details>

Expand All @@ -142,7 +142,7 @@ For **npx**, use this JSON for a new file. If the file already has other servers
"postgresql": {
"type": "stdio",
"command": "npx",
"args": ["-y", "--allow-scripts=@codegiveness/postgresql-sharp-mcp", "@codegiveness/postgresql-sharp-mcp@0.4.0"]
"args": ["-y", "--allow-scripts=@codegiveness/postgresql-sharp-mcp", "@codegiveness/postgresql-sharp-mcp@0.5.0"]
}
}
}
Expand Down Expand Up @@ -201,7 +201,7 @@ Use the command for your installation method. If you use a standalone archive, r
**npx, Linux/macOS:**

```sh
npx -y --allow-scripts=@codegiveness/postgresql-sharp-mcp @codegiveness/postgresql-sharp-mcp@0.4.0 --validate && omp
npx -y --allow-scripts=@codegiveness/postgresql-sharp-mcp @codegiveness/postgresql-sharp-mcp@0.5.0 --validate && omp
```

**.NET tool, Linux/macOS:**
Expand All @@ -221,7 +221,7 @@ if ($LASTEXITCODE -eq 0) {
}
```

For npx in PowerShell, replace the first line with `npx -y --allow-scripts=@codegiveness/postgresql-sharp-mcp @codegiveness/postgresql-sharp-mcp@0.4.0 --validate`; keep the `$LASTEXITCODE` check and launch block.
For npx in PowerShell, replace the first line with `npx -y --allow-scripts=@codegiveness/postgresql-sharp-mcp @codegiveness/postgresql-sharp-mcp@0.5.0 --validate`; keep the `$LASTEXITCODE` check and launch block.

Validation is read-only and exits; its successful stderr output includes your database name, so keep it private. Empty input is rejected before OMP starts. If it fails, fix your connection details and repeat step 2; [troubleshooting](#if-setup-does-not-work) covers common failures.

Expand All @@ -248,9 +248,9 @@ For a remote server needing a provider CA certificate, retain `SSL Mode=VerifyFu

### Upgrading an existing installation

Automatic 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**. This guide targets **0.4.0**, which adds the [database lock](#database-lock): an existing `POSTGRES_DATABASES` configuration now refuses to start unless PostgreSQL grants match the list (see the [hardening guide](SECURITY.md#database-lock-hardening)). Older 0.2.0 executables use configured database aliases and a restricted default. Changing configuration does not upgrade an old executable.
Automatic 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 refuses to start unless PostgreSQL grants match the list (see the [hardening guide](SECURITY.md#database-lock-hardening)). This guide targets **0.5.0**, whose lock check also refuses a login that can execute server-file functions such as `pg_read_binary_file` in a locked database; revoke such grants before upgrading a locked configuration. Older 0.2.0 executables use configured database aliases and a restricted default. Changing configuration does not upgrade an old executable.

After publication, update an existing global .NET tool with `dotnet tool update --global codegiveness.postgresql-sharp-mcp --version 0.4.0`. For npx, update the version in your client's `args` to `@codegiveness/postgresql-sharp-mcp@0.4.0`; retain package-specific script approval. For archives, fully quit the client/server and replace the extracted files together. Recheck `--version` before reconnecting.
After publication, update an existing global .NET tool with `dotnet tool update --global codegiveness.postgresql-sharp-mcp --version 0.5.0`. For npx, update the version in your client's `args` to `@codegiveness/postgresql-sharp-mcp@0.5.0`; retain package-specific script approval. For archives, fully quit the client/server and replace the extracted files together. Recheck `--version` before reconnecting.

**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.

Expand Down
Loading
Loading