SQMCPaL
Allows querying an Azure Database for PostgreSQL Flexible Server, including server discovery, catalog inspection, and read-only SQL execution using Azure CLI authentication.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@SQMCPaLwhat tables are in the database?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
SQMCPaL
An MCP server that lets any MCP-compatible AI tool query your Azure Database for PostgreSQL Flexible Server — no service principals, no connection strings in config files, no passwords anywhere. Just az login and go.
Works with Claude Code, GitHub Copilot CLI, Claude Desktop, GitHub Copilot in VS Code, and any other tool that speaks the Model Context Protocol.
You will never copy-paste a password from the Azure Portal. SQMCPaL authenticates with the Azure CLI session already on your machine, exchanging it for a short-lived Microsoft Entra token that is used as the database password. Nothing is stored, nothing to rotate, nothing to leak.
You don't need to know your schema. Ask your AI tool "what's in this database?" and it will walk the catalog — tables, columns, types, keys, indexes — before writing a single query.
It cannot write to your database. Read-only isn't a promise in the docs, it's enforced by PostgreSQL itself. See How read-only is enforced.
Background
SQMCPaL is the SQL sibling of two existing MCP servers built on the same idea — your az login session is already the credential, so a local read-only MCP server needs no infrastructure at all:
SQMCPaL | |||
Target | Cosmos DB (MongoDB API) | Azure Storage (Blob/Queue/File/Table) | PostgreSQL Flexible Server |
Auth |
|
|
|
Operations | Read-only | Read-only | Read-only |
Runs as | Local stdio server | Local stdio server | Local stdio server |
Same shape, same guarantees, different data store. If you already run one of the others, this one will feel identical.
Related MCP server: postgres-mcp-server
Features
Auto-discovery — lists every PostgreSQL flexible server your Azure credential can see, across all subscriptions
Session context — connect once, then query without repeating server/database/schema on every message
Catalog inspection — databases, schemas, tables, sizes, row estimates, columns, primary keys, indexes, foreign keys
Arbitrary read SQL — full
SELECTpower including joins, CTEs, window functions andEXPLAINConvenience tools —
count_rows,distinct_values,sample_rowsfor the questions you ask constantlyPasswordless — Entra token minted per session from your own CLI login, auto-refreshed before expiry
Read-only, enforced by the server — not by a regex
Prerequisites
Azure CLI (
brew install azure-cli), logged in withaz loginPython 3.11+ (or
uv, which is easier — see Setup)An Azure Database for PostgreSQL Flexible Server you can reach on the network
Your Entra identity must be able to log into that server (see below)
Granting your Entra identity access
PostgreSQL will reject your login unless your Entra principal exists as a role on the server. Either:
Set yourself as the Microsoft Entra admin on the server (Portal → your server → Authentication → Microsoft Entra admin), or
Have an existing Entra admin create a role for you:
SELECT * FROM pgaadauth_create_principal('you@example.com', false, false); GRANT CONNECT ON DATABASE yourdb TO "you@example.com"; GRANT USAGE ON SCHEMA public TO "you@example.com"; GRANT SELECT ON ALL TABLES IN SCHEMA public TO "you@example.com";
Entra authentication must be enabled on the server (Authentication → "Microsoft Entra authentication only" or "PostgreSQL and Microsoft Entra authentication").
Run check_auth from your AI tool at any time to see which role SQMCPaL will try to log in as.
Network access
Flexible servers are firewalled by default. Either add your IP under Networking → Firewall rules, or be on the server's VNet if it uses private access. If a connection hangs and then fails, this is almost always why.
Setup
Claude Code
claude mcp add sqmcpal -- uvx --from git+https://github.com/ChingEnLin/SQMCPaL sqmcpalGitHub Copilot CLI
Add to ~/.copilot/mcp-config.json:
{
"mcpServers": {
"sqmcpal": {
"type": "local",
"command": "uvx",
"args": ["--from", "git+https://github.com/ChingEnLin/SQMCPaL", "sqmcpal"],
"tools": ["*"]
}
}
}Then start copilot and run /mcp to confirm it loaded.
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"sqmcpal": {
"command": "uvx",
"args": ["--from", "git+https://github.com/ChingEnLin/SQMCPaL", "sqmcpal"]
}
}
}Restart Claude Desktop afterwards.
From a local clone
git clone https://github.com/ChingEnLin/SQMCPaL.git
cd SQMCPaL
uv venv --python 3.12 && uv pip install -e .then point command at /absolute/path/to/SQMCPaL/.venv/bin/sqmcpal with no args.
Usage
Talk to it in plain language. A typical first session:
You: What PostgreSQL servers do I have in Azure? AI: (list_postgres_servers) One —
database-patient-serverin germanywestcentral, PostgreSQL 16.You: Connect to it and show me what's in there. AI: (connect_server → list_databases → list_tables) Database
patientshas 8 tables inpublic; the biggest isappointmentsat ~1.2M rows.You: What does the appointments table look like, and how many are cancelled? AI: (describe_table → count_rows) 14 columns, PK on
id, FK topatients.id. 43,207 rows havestatus = 'cancelled'.You: Show me cancellations per month for the last year. AI: (run_query with a date_trunc + GROUP BY) …
You rarely name a tool yourself — set the context once and ask questions.
How authentication works
SQMCPaL asks
DefaultAzureCredentialfor a token scoped tohttps://management.azure.com/.defaultand uses it to enumerate flexible servers via ARM.For the database connection it requests a second token scoped to
https://ossrdbms-aad.database.windows.net/.default.That token is the PostgreSQL password. The login role is read from the token's own
upnclaim, so it always matches the identity you logged in as.Tokens are refreshed automatically five minutes before expiry; pooled connections are re-established with the fresh token.
No credential is ever written to disk or into config. On a laptop this resolves to your az login session; in a container or CI it resolves to whatever managed identity or service principal is present.
How read-only is enforced
Three independent layers, because one is not enough:
Every statement runs inside an explicit
BEGIN READ ONLYtransaction that is always rolled back. PostgreSQL rejectsINSERT/UPDATE/DELETE/CREATE/DROP/ALTER/GRANTitself — this is the real guarantee, not client-side filtering.The session default is read-only too (
default_transaction_read_only = on), covering anything outside an explicit transaction.Submitted SQL must be a single statement starting with
SELECT,WITH,TABLE,VALUES,EXPLAINorSHOW. This closes the one hole in layer 1:COMMIT; BEGIN READ WRITE; DELETE FROM …would otherwise escape the read-only transaction. The parser understands string literals, dollar-quoting and comments, so a semicolon inside'a;b'is not mistaken for a statement separator.
There are no write tools in the registry, so there is nothing for a model to call even if it wanted to. Queries also carry a 30s statement_timeout so a runaway scan can't sit on your production server.
For belt-and-braces, grant the Entra role SELECT only — then the database itself is the fourth layer.
Available tools
Tool | What it does |
| Verify the Azure credential and show the PostgreSQL login role it maps to |
| Every flexible server visible to your credential, across subscriptions |
| Connect by ARM resource ID; optionally set default database and schema |
| Databases on the connected server, with owner, encoding and size |
| Schemas in a database, with owner and table count |
| Tables, views and materialized views, with estimated rows and size |
| Columns, types, nullability, defaults, primary key, indexes, foreign keys |
| A few rows from a table, to see what the data actually looks like |
| Any single read-only SQL statement |
| Exact row count, optionally filtered by a |
| Distinct values of a column with frequencies, most common first |
| Inspect, change or reset the session |
Environment variables
Variable | Default | Purpose |
|
| Hard cap on rows returned by any tool |
|
| Server-side query timeout |
|
| Connection timeout in seconds |
|
| libpq sslmode |
|
| Server port |
| (token | Override the login role, if it differs from your UPN |
| — | Pre-fetched ARM token, for containers without the az CLI |
For developers
uv venv --python 3.12 && source .venv/bin/activate
uv pip install -e ".[dev]"
pre-commit installChecks (there is no integration suite — the DB layer is verified by connecting to a real server):
python test_sqmcpal.py # read-only SQL guard self-check
pre-commit run --all-files # ruff + ruff-format + mypy --strictSmoke test the MCP handshake
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}' \
| .venv/bin/sqmcpalExpect "serverInfo":{"name":"sqmcpal",...} on stdout.
Docker
docker build --platform linux/arm64 -t sqmcpal:dev . # linux/amd64 on Intel/LinuxMount ~/.azure read-only into the container so the CLI session is available, or pass AZURE_ACCESS_TOKEN.
Troubleshooting
password authentication failed for user "you@example.com"
Your Entra principal isn't a role on that server. See Granting your Entra identity access.
Connection hangs, then "could not reach host" Firewall. Add your IP under the server's Networking blade, or connect from its VNet.
Azure credential not found or expired
Run az login in a terminal, then restart your MCP client so it picks up the refreshed session.
Only read-only statements are permitted
Working as intended. If your query legitimately starts with something else, wrap it — e.g. WITH x AS (…) SELECT ….
Multiple SQL statements are not allowed
Send one statement at a time. This is the guard that keeps a read-only transaction from being committed out from under itself.
Permission denied for a table you can see
list_tables reads the catalog, which is world-readable; reading rows needs GRANT SELECT. Ask an admin for the grant.
Limitations
Flexible Server only. Single Server is retired and not supported; Cosmos DB for PostgreSQL is untested.
Microsoft Entra authentication only. Native PostgreSQL username/password logins are deliberately not supported — that would mean a secret in a config file.
One connection at a time. A single in-process session, matching one developer at one keyboard.
Read-only, permanently. Write tools will not be added. Point it at production on purpose.
License
MIT — see LICENSE.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityCmaintenanceAn open-source MCP server for PostgreSQL schema introspection and guarded read-only queries. It enables MCP clients to discover schemas, tables, columns, indexes, relationships, and safe queryable data from a configured PostgreSQL database.Last updated30MIT
- Flicense-qualityBmaintenanceA read-only MCP server for PostgreSQL. Connect any MCP-compatible AI agent to your PostgreSQL server and explore databases, schemas, tables, and run SELECT queries through natural language. Built with .NET 10.Last updated
- Alicense-qualityDmaintenanceA Model Context Protocol (MCP) Server that allows AI models to securely interact with data hosted in Azure Database for PostgreSQL. It enables natural language querying, schema exploration, and data management through MCP clients like Claude Desktop and Visual Studio Code.Last updatedMIT
- Alicense-qualityBmaintenanceA read-only MCP server for PostgreSQL that enables safe database introspection and querying via natural language.Last updated484MIT
Related MCP Connectors
Official Microsoft MCP Server to query Microsoft Entra data using natural language
MCP server for managing Prisma Postgres.
Analytical memory for AI agents: a real Postgres queried in plain English over MCP. One command.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ChingEnLin/SQMCPaL'
If you have feedback or need assistance with the MCP directory API, please join our Discord server