TL;DR: If your Postgres MCP server says the password is wrong but you know it is right, percent-encode special characters in the password inside the connection URL. `@` becomes `%40`, `#` becomes `%23`, `/` becomes `%2F`. This trips up almost everyone with a generated password.

```text
password authentication failed for user "appuser"
```

## Fix it

1. Check which special characters are in your password. The usual suspects are `@ : / ? #` and `%`. These get parsed as URL structure instead of password text.

2. Percent-encode each one. Quick reference:
   - `@` becomes `%40`
   - `#` becomes `%23`
   - `/` becomes `%2F`
   - `?` becomes `%3F`
   - `%` itself becomes `%25`

   So a password like `p@ss#word` becomes `p%40ss%23word`.

3. Update the connection string in your MCP client config. In Claude Desktop that is the `env` block of `claude_desktop_config.json`, e.g. `postgresql://db-host:5432/mydb`. Restart the client so the server picks up the new value.

   Expected: the Postgres tools (query, list tables) start working on the next tool call. No more auth error.

4. Sanity-check the raw URL with psql first if you are unsure:

```bash
psql "postgresql://db-host:5432/mydb" -c "select 1;"
```

   Expected output: `1`. If psql connects, the MCP server will too.

## When to use this

- The MCP Postgres server returns `password authentication failed` but the same credentials work when typed interactively into psql.
- The password contains `@`, `#`, `/`, `?` or other URL-reserved characters.

## When NOT to use this

- The username is wrong or the role does not exist (error names a different user).
- The failure mentions SSL, certificates, or timeouts. Those are different problems.

## Compatibility

- Any MCP Postgres server that takes a connection URL: @modelcontextprotocol/server-postgres, yawlabs/postgres-mcp, pgedge-postgres-mcp, Tabulus.
- Postgres 12+.

## Why it happens

A connection string is a URL, and URLs give special meaning to characters like `@` (separates credentials from host) and `/` (separates path). An unencoded `@` in the password makes the parser split the string at the wrong place, so the server receives a mangled password and rejects it. The fix is percent-encoding, which is how URLs are supposed to carry literal special characters.

## Edge cases

- If you already encoded and it still fails, check for a literal `%` in the password. It must be encoded as `%25` first, before encoding anything else.
- Some password managers copy a trailing space. Trim it.
- On Windows, env vars set in a terminal are not inherited by MCP servers launched from the client UI. Put the URL in the client config `env` block instead.