OctoQuery
OctoQuery is an MCP server that converts databases into AI-accessible tools by exposing each configured database as a tool that accepts SQL queries and returns JSON results, enabling AI agents to query your data directly.
README
OctoQuery
Turn your databases into AI-ready tools. OctoQuery is a thin MCP (Model Context Protocol) server around your databases: every database you configure becomes one MCP tool that an AI agent — Claude, your IDE assistant, or any other MCP client — can call with plain SQL. See Supported databases for what it can connect to today.
Motivation
AI agents are great at writing SQL, but they need two things to be useful with your data:
- Access — a safe, standard way to run queries. OctoQuery provides that: each configured database is exposed as a single MCP tool (e.g.
sql_orders_prod,sql_analytics_dev) that accepts aquerystring and returns rows as JSON. Adding a database is one JSON entry — no code. - Understanding — knowledge of your schema, relations, and conventions. For that, you pair each database tool with an agent skill: a markdown file describing the tables, how they join, and what the gotchas are (money in cents, soft deletes, statuses to exclude, ...). With a skill, the agent reasons about your database efficiently instead of guessing at the schema query by query.

This repo ships working examples of both: three demo databases (demo/ — an e-commerce PostgreSQL, a blog MySQL, and a library MariaDB) with their matching skills (ecommerce-demo-db, blog-demo-db, library-demo-db), wired together through AGENTS.md. Use them as the template for your own databases.
Under the hood it's a NestJS service speaking MCP over Streamable HTTP at /mcp, protected by OAuth 2.0 (optional for local use). Connections are opened lazily on first query, so databases don't need to be reachable at startup.
Supported databases
| Database | Status |
|---|---|
| PostgreSQL | ✅ Supported |
| MySQL | ✅ Supported |
| MariaDB | ✅ Supported |
More engines may be added over time — contributions are welcome.
Quick start
From clone to asking your data questions in three steps: run the server (backed by seeded demo databases), connect your AI agent, and try the demo prompts.
Step 1 — Run the server with the demo databases
Three seeded demo databases run in Docker: an e-commerce PostgreSQL (users, products, orders, order items), a blog MySQL (authors, posts, comments), and a library MariaDB (books, members, loans).
- Clone the repository:
git clone https://github.com/benedya/octoquery.git && cd octoquery
- Install dependencies:
npm install
- Start the demo databases (PostgreSQL on
127.0.0.1:45432, MySQL on127.0.0.1:43306, MariaDB on127.0.0.1:43307, all seeded automatically):
docker compose -f demo/docker-compose.yml up -d
- Configure the service — set
MCP_AUTH_ENABLED=falsein.envfor a tokenless start;mcp-sql-tools.jsonalready points at all demo databases:
cp .env.example .env && cp mcp-sql-tools.example.json mcp-sql-tools.json
- Run it:
npm run start:dev
The MCP endpoint is now live at http://localhost:3000/mcp with three tools: sql_ecommerce_demo, sql_blog_demo, and sql_library_demo.
Step 2 — Connect your AI agent
The server speaks standard MCP over Streamable HTTP, so any MCP client works — Claude Code, Claude Desktop, VS Code, JetBrains IDEs, or anything else that understands MCP. With auth disabled (local dev) no token is needed; otherwise clients go through the OAuth flow described below.
Register the MCP server in your agent's MCP configuration (the exact file or settings screen depends on the client, but the shape is always the same):
{
"mcpServers": {
"octoquery": {
"type": "http",
"url": "http://localhost:3000/mcp"
}
}
}
Give the agent the skills. Point your agent at the skills in .agents/skills/ — most agents pick them up through the project's AGENTS.md, others discover a skills directory on their own. The skill is what turns a generic SQL tool into an agent that knows your schema.
Step 3 — Try the demo
Everything here works out of the box with this repository's stock configuration: the three seeded databases from step 1 and the tool entries shipped in mcp-sql-tools.example.json. Try these prompts — the agent picks the right tool and skill on its own:
| Example prompt | Tool (database) | Skill |
|---|---|---|
| "Who are our top 5 customers by total spend?" | sql_ecommerce_demo (PostgreSQL) |
ecommerce-demo-db |
| "Which blog post got the most comments?" | sql_blog_demo (MySQL) |
blog-demo-db |
| "Who has overdue library books, and which titles?" | sql_library_demo (MariaDB) |
library-demo-db |
Adding your own databases
Databases are defined entirely in mcp-sql-tools.json (gitignored — it holds credentials; mcp-sql-tools.example.json is the committed template):
[
{
"name": "sql_orders_prod",
"label": "prod orders",
"host": "prod-db.example.com",
"port": 5432,
"database": "orders_service",
"user": "orders_reader",
"password": "...",
"enableTLS": true
}
]
Each entry becomes one MCP tool and accepts the following fields:
| Field | Required | Default | Description |
|---|---|---|---|
name |
yes | — | Tool name shown to the agent (letters, digits, _, -; max 64 chars) |
host |
yes | — | Database host |
database |
yes | — | Database name |
user |
yes | — | Database user (prefer a read-only one) |
password |
yes | — | Database password |
type |
no | postgres |
Engine: postgres, mysql, or mariadb |
port |
no | engine standard (5432 postgres, 3306 mysql/mariadb) | Database port |
label |
no | the name value |
Human-friendly name used in the tool title and description |
description |
no | generated from label |
Full override of the tool description shown to the agent |
enableTLS |
no | true |
Connect over TLS |
maxRows |
no | MCP_MAX_ROWS (100) |
Row limit per query result for this tool |
Tool names are free-form, so any environment/database combination works (sql_orders_prod, sql_analytics_dev, ...) — one entry per tool. The file is validated at startup: duplicate names, malformed JSON, or a missing file stop the service with a clear error. Set MCP_SQL_TOOLS_FILE to load the file from a different path (e.g. a mounted secret in Kubernetes).
To give agents real understanding of a database, add a skill next to the demo one: create .agents/skills/<your-db>/SKILL.md describing the schema, relations, and conventions (use ecommerce-demo-db as the pattern), and list it in AGENTS.md.
Authentication
The service is an OAuth 2.0 resource server per the MCP authorization spec. It works with any OIDC provider (Auth0, Okta, ...) — configured via AUTH_ISSUER and AUTH_AUDIENCE:
- Unauthenticated requests to
/mcpget401with aWWW-Authenticate: Bearer resource_metadata="..."header. - The client fetches the RFC 9728 metadata (
GET /.well-known/oauth-protected-resource), which points at the provider (authorization_servers: [AUTH_ISSUER]). - The client obtains an access token from the provider (authorization code + PKCE for interactive clients, client credentials for machine-to-machine).
- The service validates the JWT against the provider's JWKS: signature (RS256),
iss,exp, and — ifAUTH_AUDIENCEis set —aud.
For local development set MCP_AUTH_ENABLED=false — all auth env vars become optional.
Tests
Integration tests run with Jest and Testcontainers — each suite starts a disposable PostgreSQL or MySQL container, so Docker must be running:
npm test
There is one full-stack suite per supported database (npm run test:postgres, npm run test:mysql): each boots the application against a real database container and drives the MCP endpoint over Streamable HTTP like a real client — covering tool discovery, query execution, read-only enforcement, multi-statement rejection, and row truncation.
Testing with MCP Inspector
The MCP Inspector is a web UI for exercising an MCP server by hand — the quickest way to verify your setup before involving an agent:
npx @modelcontextprotocol/inspector
In the Inspector: select transport Streamable HTTP, set the URL to http://localhost:3000/mcp, and connect (with auth enabled, paste a bearer token in the Authentication field; with MCP_AUTH_ENABLED=false just connect). Under Tools you'll see one tool per configured database — run sql_ecommerce_demo with a query like SELECT count(*) FROM orders and inspect the JSON rows that an agent would receive. Results are truncated to the tool's maxRows.
Operational notes
- Sessions are in-memory (map of
mcp-session-id→ transport). When running more than one replica, use sticky sessions at the ingress. BASE_URLmust be the public URL clients see (behind a proxy this differs fromlocalhost:<port>); it is used in the resource metadata andWWW-Authenticatechallenges.- Read-only by default. With
MCP_READ_ONLY=true(the default) every query runs as a single statement inside aREAD ONLYtransaction, so the database itself rejects writes and DDL. On MySQL and MariaDB — where DDL escapes read-only transactions via implicit commit — statements are additionally restricted to a read allowlist (SELECT,WITH,SHOW,DESCRIBE,EXPLAIN). SetMCP_READ_ONLY=falseto allow data modification. - With read-only mode disabled the SQL tools execute arbitrary SQL — the caller is fully trusted. Access control is entirely provider-side, so a token grant should be treated as a database access grant. Read-only database users are still the strongest guarantee.
License
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。