ajan-sql
v0.1.9
Published
AI-safe MCP server for schema-aware, read-only SQL access.
Maintainers
Readme
Overview
ajan-sql is an npm package for running an MCP server over stdio with SQL database backends.
The project now provides multi-dialect SQL support, with PostgreSQL, MySQL, and SQLite available behind the same MCP surface.
Goals
- Safe, read-only database access for AI agents
- Schema inspection and table discovery
- Reliable read-only SQL query execution with strict guardrails
- Simple, maintainable implementation
Tech Stack
- Node.js
- TypeScript
- MCP TypeScript SDK v1.x
- PostgreSQL via
pg - MySQL via
mysql2 - SQLite via
better-sqlite3
Security Model
All executed queries must follow these rules:
SELECTonly- Reject
INSERT - Reject
UPDATE - Reject
DELETE - Reject
DROP - Reject
ALTER - Reject
TRUNCATE - Enforce
LIMITwith a default of100 - Enforce query timeout with a maximum of
5seconds - Enforce maximum result size
- Reject multi-statement SQL
- Reject SQL comments
These rules should never be bypassed.
Schema metadata calls such as list_tables, describe_table, and list_relationships are cached briefly in-memory to avoid repeated catalog queries during the same client session.
Available MCP Tools
list_tablesdescribe_tablelist_relationshipsserver_infosearch_schemarun_readonly_queryexplain_querysample_rows
Tool Matrix
| Tool | Purpose | Inputs | Guarded | Structured Output |
| --- | --- | --- | --- | --- |
| list_tables | List visible database tables with comments and row estimates | None | N/A | TableSummary[] |
| describe_table | Describe columns and types for one table | name, optional schema | N/A | TableDescription |
| list_relationships | List foreign key relationships | None | N/A | RelationshipSummary[] |
| server_info | Return runtime server details for onboarding and diagnostics | None | N/A | ServerInfoResult |
| search_schema | Search table and column names across the schema | query, optional schema, optional limit | N/A | SearchSchemaResult |
| run_readonly_query | Execute a readonly SELECT query | sql | Yes | ReadonlyQueryResult |
| explain_query | Return JSON execution plan for a readonly query | sql | Yes | ExplainQueryResult |
| sample_rows | Return a limited sample from a table | name, optional schema, optional limit, optional columns | Yes | ReadonlyQueryResult |
Structured Output
All tools return:
contentfor a short human-readable summarystructuredContentfor machine-friendly MCP client consumption
For tool failures, structuredContent returns a standard error object with ok: false, plus error.code and error.message.
Detailed payload examples are available in docs/tools.md.
Available MCP Resources
schema://snapshotschema://table/{name}
Detailed resource payload examples are available in docs/resources.md.
Install
Install the CLI globally from npm:
npm install -g ajan-sqlRun it with a PostgreSQL, MySQL, or SQLite connection target:
DATABASE_DIALECT=postgres \
DATABASE_URL=postgres://USER:PASSWORD@HOST:PORT/DB ajan-sqlMySQL example:
DATABASE_DIALECT=mysql \
DATABASE_URL=mysql://USER:PASSWORD@HOST:PORT/DB ajan-sqlSQLite example:
DATABASE_DIALECT=sqlite \
DATABASE_URL=file:/absolute/path/to/database.sqlite ajan-sqlDATABASE_DIALECT defaults to postgres. Supported values today are postgres, mysql, and sqlite.
Optional readonly guard env vars:
AJAN_SQL_DEFAULT_LIMITAJAN_SQL_MAX_LIMITAJAN_SQL_TIMEOUT_MSAJAN_SQL_MAX_RESULT_BYTES
These can only tighten the defaults. They cannot exceed the built-in hard caps of LIMIT 100, 5000ms, and 1000000 bytes.
Local Development
Start the server with a PostgreSQL, MySQL, or SQLite connection target:
DATABASE_DIALECT=postgres \
DATABASE_URL=postgres://USER:PASSWORD@HOST:PORT/DB npm run devOr build and run the compiled server:
npm run build
DATABASE_DIALECT=postgres \
DATABASE_URL=postgres://USER:PASSWORD@HOST:PORT/DB npm startSQLite development example:
DATABASE_DIALECT=sqlite \
DATABASE_URL=file:/absolute/path/to/database.sqlite npm run devClient Configuration
For MCP clients that launch globally installed stdio servers:
{
"mcpServers": {
"ajan-sql": {
"command": "ajan-sql",
"env": {
"DATABASE_DIALECT": "postgres",
"DATABASE_URL": "postgres://USER:PASSWORD@HOST:PORT/DB"
}
}
}
}For repository-local development builds, point the command to the built CLI and provide DATABASE_URL:
{
"mcpServers": {
"ajan-sql": {
"command": "node",
"args": ["/absolute/path/to/ajan-sql/dist/index.js"],
"env": {
"DATABASE_DIALECT": "postgres",
"DATABASE_URL": "postgres://USER:PASSWORD@HOST:PORT/DB"
}
}
}
}Integration Testing
The repository supports local integration testing during development, but any Docker compose files or seeded local test databases can remain untracked and machine-local.
Project Docs
Development Principles
- Keep functions small and composable
- Avoid side effects
- Route all DB logic through
db/ - Route all query execution through
query-runner - Route all validation through
guard - Prefer simple working code over abstraction
- Prioritize correctness, safety, and clarity
CLI Behavior
The CLI will:
- Start the MCP server over stdio
- Read
DATABASE_URLfrom the environment - Fail fast if
DATABASE_URLis missing
Status
Early development. The CLI now supports PostgreSQL, MySQL, and SQLite through a shared dialect-based architecture, and the current package version is 0.1.9.
Support
If ajan-sql saves you time, helps you ship faster, or keeps a few risky queries out of trouble, you can support the project on GitHub Sponsors: @borakilicoglu
License
MIT
