An MCP server that lets Claude read a SAP SQL Anywhere database and answer questions in plain language — no SQL by hand.
Example: ask "how many customers do we have in Lombardy?" and Claude writes and runs the query for you.
Read-only by design. It can only run
SELECTqueries — it cannot insert, update, delete, or alter anything. See Security.
- Python 3.10+
- The SQL Anywhere ODBC driver and a configured DSN for your database
- A dedicated, read-only database user (this project never creates users or changes permissions)
- Claude Code or Claude Desktop
git clone https://github.com/TeoDreams/sqlanywhere-mcp-server.git
cd sqlanywhere-mcp-server
pip install -r requirements.txtSet four values via a .env file or environment variables.
.env file (copy the template, then edit — it is gitignored):
cp .env.example .envSQLANY_DSN=YOUR_DSN
SQLANY_UID=readonly_user
SQLANY_PWD=your_password
SQLANY_MAX_ROWS=200
SQLANY_QUERY_TIMEOUT=30Or environment variables:
# Windows (PowerShell)
[Environment]::SetEnvironmentVariable("SQLANY_DSN", "YOUR_DSN", "User")
[Environment]::SetEnvironmentVariable("SQLANY_UID", "readonly_user", "User")
[Environment]::SetEnvironmentVariable("SQLANY_PWD", "your_password", "User")# Linux / macOS
export SQLANY_DSN=YOUR_DSN
export SQLANY_UID=readonly_user
export SQLANY_PWD=your_passwordClaude Code — pick a scope:
# Global: available in all your projects
claude mcp add --scope user sqlanywhere-readonly -- python /path/to/sqlanywhere_mcp_server.py
# Project: only this repo, shared with the team via a committed .mcp.json
claude mcp add --scope project sqlanywhere-readonly -- python /path/to/sqlanywhere_mcp_server.py
claude mcp listThe default scope (local, if you omit --scope) registers the server only for you in the
current project. Credentials stay out of a committed .mcp.json because they come from your
environment variables / .env, not the command.
Claude Desktop — add this to the config file (%APPDATA%\Claude\claude_desktop_config.json
on Windows, ~/Library/Application Support/Claude/claude_desktop_config.json on macOS,
~/.config/Claude/claude_desktop_config.json on Linux), then restart the app:
{
"mcpServers": {
"sqlanywhere-readonly": {
"command": "python",
"args": ["/path/to/sqlanywhere_mcp_server.py"]
}
}
}Ask Claude things like:
- "Describe the structure of the customers table"
- "Show me the first rows of the products table"
- "How many orders were placed this month?"
- "Will this query use an index, or scan the whole table?"
Claude uses the two tools on its own:
| Tool | What it does |
|---|---|
list_tables |
Lists table names (handy for large schemas) |
describe_schema |
Lists tables and columns (structure only, no data) |
run_query |
Runs a SELECT and returns the rows (up to the row cap) |
explain_query |
Shows the execution plan of a SELECT without running it |
- Only queries starting with
SELECTrun; write/DDL keywords (INSERT,UPDATE,DELETE,DROP,ALTER, etc.) are rejected before connecting. - Returned rows are capped (default 200). This caps the response, not the query — the
SELECTstill runs in full on the server. A per-query timeout (SQLANY_QUERY_TIMEOUT, default 30s,0= no limit) aborts queries that run too long. - Credentials come only from environment variables or
.env, and are never printed in error messages.
explain_query uses SQL Anywhere's EXPLANATION() function, which returns the optimizer's
access plan without executing the query. (GRAPHICAL_PLAN() is deliberately not used —
it can execute the statement to collect statistics.)
SQL Anywhere gates plan access behind a database option that is off by default. If
explain_query reports that plans are unavailable, a DBA must enable it for your read-only user:
SET OPTION readonly_user.QUERY_PLAN_TEXT_ACCESS = ON;If
describe_schemareturns nothing, your SQL Anywhere version may expose the schema throughSYS.SYSTAB/SYS.SYSTABCOLinstead of theSYS.SYSTABLE/SYS.SYSCOLUMNviews used here — adjust the query indescribe_schemaaccordingly.