@jessejoris/mcp-mysql-via-api 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/PRD.md ADDED
@@ -0,0 +1,364 @@
1
+ # Product Requirement Document (PRD)
2
+ # MySQL Model Context Protocol (MCP) Server via API (`mcp_mysql_via_api`)
3
+
4
+ **Document Version:** 1.1.0
5
+ **Status:** Approved & Verified
6
+ **Author:** Antigravity Engineering
7
+ **Target Systems:** Hermes AI, OpenClaw, Claude Desktop, Cursor, Windsurf, Cline, Codex, CLI & Local IDEs
8
+
9
+ ---
10
+
11
+ ## 1. Executive Summary & Problem Statement
12
+
13
+ ### 1.1 Context & Background
14
+ The legacy `mcp_mysql` solution establishes direct TCP socket connections (via the `mysql2` driver on port 3306) to MySQL database instances. While effective for local or flat networks, this architectural pattern encounters severe limitations in real-world enterprise, cloud, and distributed environments:
15
+ - **Firewall & Security Boundaries:** Production databases rarely expose port 3306 directly to external networks or AI developer workstations.
16
+ - **Microservices & Multi-Cloud Architecture:** Databases are shielded inside private VPCs / subnets behind API Gateways, ingress controllers, or dedicated internal REST services.
17
+ - **Audit & Governance:** Direct SQL socket connections bypass application-level telemetry, token-based rate limiting, role-based access control (RBAC), and centralized API auditing.
18
+
19
+ ### 1.2 The Solution: `mcp_mysql_via_api`
20
+ `mcp_mysql_via_api` decouples the AI Agent interface from the physical database wire protocol. Instead of direct database socket connections:
21
+ 1. The **AI Agent** communicates via standard **Model Context Protocol (MCP)** (`stdio` / stream transport) with the `mcp_mysql_via_api` client.
22
+ 2. The MCP client translates tool invocations into authenticated HTTP/REST requests against a remote **MySQL API Server Endpoint** hosted in the database's secure environment.
23
+ 3. The server exposes structured endpoints for every table, schema discovery, point lookups, execution of guarded queries, and metadata extraction.
24
+ 4. Strict access controls (including presets like `only-read`, `read-write`, `admin` and granular permissions) protect against unauthorized mutations.
25
+ 5. All tool outputs are **strictly valid JSON**—guaranteed 100% parseable with zero plaintext, HTML, or unstructured error strings.
26
+ 6. Multi-record operations feature **default pagination** with an explicit **bypass option** for AI agents requiring complete data extracts.
27
+
28
+ ---
29
+
30
+ ## 2. Core Personas & Target Agents
31
+
32
+ | Persona / Agent | Typical Environment | Primary Needs & Constraints |
33
+ |-----------------|---------------------|-----------------------------|
34
+ | **Hermes AI** | Autonomous Agent / Sandbox | High-reliability JSON schema, determinism, zero non-JSON output, RAG context window optimization, self-describing metadata |
35
+ | **OpenClaw** | Multi-agent Orchestrator | Strict token management via default pagination, schema RAG context, cross-table text search, permission guards |
36
+ | **Cursor / Windsurf / Cline** | IDE Integration | Instant response times, tabular and record browsing, connection health checks, direct single-record access |
37
+ | **Claude Desktop / Codex** | Desktop / CLI Agent | Stdio transport compliance, transparent error codes, ERD and relationship mapping |
38
+
39
+ ---
40
+
41
+ ## 3. Key Design Principles & Requirements
42
+
43
+ ### 3.1 Strict JSON Output Guarantee
44
+ - **Mandate:** All outputs returned through the MCP tool interface MUST be strictly valid, well-formed JSON strings (`application/json`).
45
+ - **Forbidden:** No raw markdown backticks, no emoji error prefixes (e.g., `❌ Error`), no unstructured text, and no HTML error pages (even on HTTP 404/500).
46
+ - **Envelope Standard:**
47
+ ```json
48
+ // Success Response Envelope
49
+ {
50
+ "success": true,
51
+ "data": { ... },
52
+ "meta": {
53
+ "pagination": {
54
+ "page": 1,
55
+ "limit": 50,
56
+ "total": 120,
57
+ "totalPages": 3,
58
+ "hasMore": true
59
+ },
60
+ "timestamp": "2026-09-03T15:25:00.000Z"
61
+ }
62
+ }
63
+
64
+ // Error Response Envelope
65
+ {
66
+ "success": false,
67
+ "error": {
68
+ "code": "PERMISSION_DENIED",
69
+ "message": "Operation 'create_record' is blocked by active permission policy 'only-read'.",
70
+ "details": {
71
+ "requiredPermission": "create",
72
+ "activePermissions": ["list", "read", "utility"]
73
+ },
74
+ "timestamp": "2026-09-03T15:25:00.000Z"
75
+ }
76
+ }
77
+ ```
78
+
79
+ ### 3.2 Dual-Layer Permission System & Defense-in-Depth
80
+ To satisfy safety requirements and prevent unauthorized schema alteration or data destruction:
81
+ 1. **Permission Presets:**
82
+ - `only-read` (aliases `readonly`, `read-only`, `only_read`, `read_only`, `view-only`): Allows `list`, `read`, `utility`. Strictly forbids `create`, `update`, `delete`, `execute`, `ddl`.
83
+ - `read-write` (alias `read_write`): Allows `list`, `read`, `create`, `update`, `utility`. Blocks `delete`, `execute`, `ddl`.
84
+ - `admin` (aliases `all`, `*`): Allows all operations (`list`, `read`, `create`, `update`, `delete`, `execute`, `ddl`, `utility`, `transaction`).
85
+ - `custom`: Explicit comma-separated permissions (e.g. `list,read,create`).
86
+ 2. **Granular Categories:**
87
+ - `list`: Database discovery, table listing, schema inspection, ERD generation, RAG context generation.
88
+ - `read`: Querying records, search data across tables, column statistics, point record lookups, running select queries.
89
+ - `create`: Single record insertion, bulk insert.
90
+ - `update`: Single record update, bulk update.
91
+ - `delete`: Single record deletion, bulk delete.
92
+ - `execute`: Custom SQL query execution via API.
93
+ - `ddl`: Schema alterations (`create_table`, `alter_table`, `drop_table`, `execute_ddl`).
94
+ - `utility`: Connection testing, metadata health checks, CSV exports.
95
+ 3. **Dual-Layer Defense Architecture:**
96
+ - **MCP Client Layer:** Pre-execution permission check; blocks requests locally before network calls if unauthorized.
97
+ - **API Server Layer:** HTTP endpoint authorization check via `API_PERMISSIONS` / `MCP_PERMISSIONS`; rejects unauthorized mutation verbs with HTTP 403 Forbidden envelopes.
98
+ - **SQL Keyword Inspection:** Dangerous keywords (`INTO OUTFILE`, `LOAD DATA`, `GRANT`, `REVOKE`) and covert DDL inside `execute_write_query` are intercepted and blocked before execution.
99
+
100
+ ### 3.3 Default Pagination & Explicit Bypass System
101
+ To balance LLM context window safety with full data access:
102
+ - **Default Behavior:**
103
+ - Multi-record operations (`read_records`, `run_select_query`, `search_data_across_tables`) paginate results by default.
104
+ - Default: `page = 1`, `limit = 50` (configurable via `DEFAULT_PAGE_SIZE`, default max page size 500).
105
+ - Metadata provides `total`, `page`, `limit`, `totalPages`, `hasMore`.
106
+ - **Bypass Mode:**
107
+ - Agents can specify `bypass_pagination: true` (or `all: true` / `limit: 0`).
108
+ - When active, the server fetches the complete dataset without slicing.
109
+ - Safety guard: A safety ceiling (`MAX_BYPASS_LIMIT`, default 10,000 rows) prevents memory exhaustion (OOM), returning an explicit warning if the table exceeds the ceiling.
110
+
111
+ ---
112
+
113
+ ## 4. System Architecture & Components
114
+
115
+ ```
116
+ ┌────────────────────────────────────────────────────────┐
117
+ │ AI Agent (Host) │
118
+ │ Hermes / OpenClaw / Cursor / Claude Code │
119
+ └──────────────────────────┬─────────────────────────────┘
120
+ │ MCP Protocol (stdio / JSON-RPC 2.0)
121
+ ┌──────────────────────────▼─────────────────────────────┐
122
+ │ mcp_mysql_via_api (MCP Client) │
123
+ │ ┌────────────────────┐ ┌──────────────────────┐ │
124
+ │ │ Permission Engine │ │ Strict JSON Engine │ │
125
+ │ │ (only-read, etc.) │ │ (Guaranteed Parse) │ │
126
+ │ └────────────────────┘ └──────────────────────┘ │
127
+ │ ┌────────────────────┐ ┌──────────────────────┐ │
128
+ │ │ Pagination Handler │ │ Resilient API Client │ │
129
+ │ │ (Default + Bypass) │ │ (Retries & Auth) │ │
130
+ │ └────────────────────┘ └──────────────────────┘ │
131
+ └──────────────────────────┬─────────────────────────────┘
132
+ │ Authenticated HTTP/REST (JSON)
133
+ │ Bearer Token / API Key
134
+ ┌──────────────────────────▼─────────────────────────────┐
135
+ │ Remote MySQL API Server (Target Host) │
136
+ │ ┌──────────────────────────────────────────────────┐ │
137
+ │ │ REST Router (/api/tables, /api/schema, etc.) │ │
138
+ │ ├──────────────────────────────────────────────────┤ │
139
+ │ │ Dual-Layer Auth & RBAC Middleware (HTTP 403) │ │
140
+ │ ├──────────────────────────────────────────────────┤ │
141
+ │ │ MySQL Connection Pool & Query Sanitizer │ │
142
+ │ └──────────────────────────┬───────────────────────┘ │
143
+ └─────────────────────────────┼──────────────────────────┘
144
+ │ TCP (Internal Network)
145
+ ┌─────────────────────────────▼──────────────────────────┐
146
+ │ MySQL Database │
147
+ └────────────────────────────────────────────────────────┘
148
+ ```
149
+
150
+ ---
151
+
152
+ ## 5. Tool Catalog (31 Tools Specification)
153
+
154
+ ### 5.1 Database & Schema Discovery
155
+ 1. `list_databases`
156
+ - **Permission:** `list`
157
+ - **Description:** Lists all accessible databases on the remote MySQL server.
158
+ - **Input:** `{}`
159
+ 2. `list_tables`
160
+ - **Permission:** `list`
161
+ - **Description:** Lists all tables in the specified or default database.
162
+ - **Input:** `{ database?: string }`
163
+ 3. `read_table_schema`
164
+ - **Permission:** `list`
165
+ - **Description:** Inspects column definitions, data types, primary keys, foreign keys, and indexes for a specific table.
166
+ - **Input:** `{ table_name: string, database?: string }`
167
+ 4. `get_database_summary`
168
+ - **Permission:** `list`
169
+ - **Description:** High-level summary of database structure, table count, column details, and approximate row counts.
170
+ - **Input:** `{ database?: string, max_tables?: number, include_relationships?: boolean }`
171
+ 5. `get_schema_erd`
172
+ - **Permission:** `list`
173
+ - **Description:** Generates a visual Mermaid.js Entity-Relationship diagram representing the database foreign keys.
174
+ - **Input:** `{ database?: string }`
175
+ 6. `get_schema_rag_context` *(New AI-Optimized)*
176
+ - **Permission:** `list`
177
+ - **Description:** 🎯 AI-OPTIMIZED: Returns ultra-compact schema information designed specifically for LLM context windows (Hermes AI, OpenClaw, IDEs). Use keyword_filter for concept-focused schema discovery.
178
+ - **Input:** `{ database?: string, max_tables?: number, max_columns?: number, keyword_filter?: string }`
179
+ 7. `get_all_tables_relationships`
180
+ - **Permission:** `list`
181
+ - **Description:** Analyzes foreign key relationships across all tables.
182
+ - **Input:** `{ database?: string }`
183
+ 8. `search_schema`
184
+ - **Permission:** `list`
185
+ - **Description:** Searches for keywords across table names, column names, and comments.
186
+ - **Input:** `{ query: string, database?: string }`
187
+ 9. `find_tables_by_keyword`
188
+ - **Permission:** `list`
189
+ - **Description:** Fast ranked keyword search for tables matching specific entities (e.g. "users", "orders").
190
+ - **Input:** `{ keyword: string, database?: string, limit?: number }`
191
+ 10. `search_data_across_tables` *(New AI-Optimized)*
192
+ - **Permission:** `read`
193
+ - **Description:** 🔍 Guarded read-only keyword scan across text-like column values across tables. Discovers which table contains specific values or IDs when table structure is unknown.
194
+ - **Input:** `{ keyword: string, tables?: string[], database?: string, max_tables?: number, limit_per_table?: number }`
195
+
196
+ ### 5.2 CRUD & Data Operations
197
+ 11. `read_records`
198
+ - **Permission:** `read`
199
+ - **Description:** Retrieves records from any table with filtering, sorting, column selection, and pagination. Supports legacy operator aliases (`eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `like`, `in`, `is null`, `between`) and `conditions` alias.
200
+ - **Input:** `{ table_name: string, columns?: string[], filters?: any[], conditions?: any[], sorting?: object, pagination?: object, bypass_pagination?: boolean, all?: boolean, database?: string }`
201
+ 12. `read_record` *(New Direct Point Lookup)*
202
+ - **Permission:** `read`
203
+ - **Description:** Fetches a single record by primary key or ID from a table via API. Fast direct point lookup.
204
+ - **Input:** `{ table_name: string, id: string | number, key_column?: string, database?: string }`
205
+ 13. `count_records`
206
+ - **Permission:** `read`
207
+ - **Description:** Returns total count of records matching optional filters/conditions.
208
+ - **Input:** `{ table_name: string, filters?: any[], conditions?: any[], database?: string }`
209
+ 14. `create_record`
210
+ - **Permission:** `create`
211
+ - **Description:** Inserts a single record into a table.
212
+ - **Input:** `{ table_name: string, data: Record<string, any>, database?: string }`
213
+ 15. `bulk_insert`
214
+ - **Permission:** `create`
215
+ - **Description:** Batch inserts multiple records into a table.
216
+ - **Input:** `{ table_name: string, records: Array<Record<string, any>>, database?: string }`
217
+ 16. `update_record`
218
+ - **Permission:** `update`
219
+ - **Description:** Updates records matching specified filter conditions. Accepts `filters` or `conditions`.
220
+ - **Input:** `{ table_name: string, data: Record<string, any>, filters?: any[], conditions?: any[], database?: string }`
221
+ 17. `bulk_update`
222
+ - **Permission:** `update`
223
+ - **Description:** Batch updates records by primary key.
224
+ - **Input:** `{ table_name: string, records: Array<Record<string, any>>, key_column: string, database?: string }`
225
+ 18. `delete_record`
226
+ - **Permission:** `delete`
227
+ - **Description:** Deletes records matching specified filter conditions. Accepts `filters` or `conditions`.
228
+ - **Input:** `{ table_name: string, filters?: any[], conditions?: any[], database?: string }`
229
+ 19. `bulk_delete`
230
+ - **Permission:** `delete`
231
+ - **Description:** Batch deletes records by matching primary key array.
232
+ - **Input:** `{ table_name: string, key_column: string, keys: Array<string | number>, database?: string }`
233
+
234
+ ### 5.3 Data Profiling & Analysis
235
+ 20. `get_column_statistics` *(New AI-Optimized)*
236
+ - **Permission:** `read`
237
+ - **Description:** Returns detailed statistical analysis for a specific column: total rows, non-null count, null percentage, distinct count, min/max values, and top frequent values.
238
+ - **Input:** `{ table_name: string, column_name: string, database?: string }`
239
+
240
+ ### 5.4 Query Management
241
+ 21. `run_select_query`
242
+ - **Permission:** `read`
243
+ - **Description:** Executes read-only SQL queries via API with optional pagination or bypass. Semicolon-safe and supports `all: true`.
244
+ - **Input:** `{ query: string, params?: any[], page?: number, limit?: number, bypass_pagination?: boolean, all?: boolean, database?: string }`
245
+ 22. `execute_write_query`
246
+ - **Permission:** `execute` (requires `delete` for DELETE statements, `ddl` for DDL statements; blocks dangerous keywords)
247
+ - **Description:** Executes INSERT, UPDATE, or guarded mutation queries via API.
248
+ - **Input:** `{ query: string, params?: any[], database?: string }`
249
+
250
+ ### 5.5 Schema Management (DDL)
251
+ 23. `create_table`
252
+ - **Permission:** `ddl`
253
+ - **Description:** Creates a new table via API.
254
+ - **Input:** `{ table_name: string, columns: any[], primary_key?: string | string[], database?: string }`
255
+ 24. `alter_table`
256
+ - **Permission:** `ddl`
257
+ - **Description:** Adds, modifies, or drops columns via API.
258
+ - **Input:** `{ table_name: string, action: string, column_definition: any, database?: string }`
259
+ 25. `drop_table`
260
+ - **Permission:** `ddl`
261
+ - **Description:** Drops a table via API.
262
+ - **Input:** `{ table_name: string, if_exists?: boolean, database?: string }`
263
+ 26. `execute_ddl`
264
+ - **Permission:** `ddl`
265
+ - **Description:** Executes raw DDL statements via API with dangerous keyword checks.
266
+ - **Input:** `{ query: string, database?: string }`
267
+
268
+ ### 5.6 Utilities & Diagnostics
269
+ 27. `test_connection`
270
+ - **Permission:** `utility`
271
+ - **Description:** Pings remote API endpoint, verifies credentials, database connectivity, and latency in milliseconds.
272
+ - **Input:** `{}`
273
+ 28. `describe_connection`
274
+ - **Permission:** `utility`
275
+ - **Description:** Reports active API endpoint, server status, permissions profile, and pagination configuration.
276
+ - **Input:** `{}`
277
+ 29. `list_all_tools`
278
+ - **Permission:** `utility`
279
+ - **Description:** Returns a dynamic catalog of all 31 MCP tools with active permission status and agent recommendations.
280
+ - **Input:** `{}`
281
+ 30. `export_table_to_csv`
282
+ - **Permission:** `utility`
283
+ - **Description:** Exports table data as CSV string via API.
284
+ - **Input:** `{ table_name: string, limit?: number, database?: string }`
285
+ 31. `export_query_to_csv`
286
+ - **Permission:** `utility`
287
+ - **Description:** Exports SELECT query results as CSV string via API (guarded to read-only queries).
288
+ - **Input:** `{ query: string, limit?: number, database?: string }`
289
+
290
+ ---
291
+
292
+ ## 6. API Server Endpoint Specifications (Companion Server)
293
+
294
+ The standalone companion Express API server (`src/server/apiServer.ts`) provides full REST access for all tables:
295
+
296
+ | Method | Endpoint | Description | Auth Required | Permission Checked |
297
+ |--------|----------|-------------|---------------|--------------------|
298
+ | `GET` | `/health` | Server & DB health check + latency measurement | No | Public |
299
+ | `GET` | `/api/info` | Server metadata, version & permission policy | Yes | Utility |
300
+ | `GET` | `/api/databases` | List all databases | Yes | `list` |
301
+ | `GET` | `/api/tables` | List tables in database | Yes | `list` |
302
+ | `GET` | `/api/tables/find` | Find tables by keyword | Yes | `list` |
303
+ | `GET` | `/api/tables/search-data` | Search text data across tables | Yes | `read` |
304
+ | `GET` | `/api/tables/:table/schema` | Get column metadata & indexes | Yes | `list` |
305
+ | `GET` | `/api/tables/:table/records` | Read records with query params (`page`, `limit`, `bypass`, `sort`, `filters`) | Yes | `read` |
306
+ | `GET` | `/api/tables/:table/records/:id` | Point lookup single record by ID | Yes | `read` |
307
+ | `POST` | `/api/tables/:table/records` | Insert single record | Yes | `create` |
308
+ | `POST` | `/api/tables/:table/records/bulk` | Bulk insert records | Yes | `create` |
309
+ | `PUT` | `/api/tables/:table/records/:id` | Update single record by ID | Yes | `update` |
310
+ | `PUT` | `/api/tables/:table/records` | Update records matching condition | Yes | `update` |
311
+ | `PUT` | `/api/tables/:table/records/bulk` | Bulk update records | Yes | `update` |
312
+ | `DELETE` | `/api/tables/:table/records/:id` | Delete single record by ID | Yes | `delete` |
313
+ | `DELETE` | `/api/tables/:table/records` | Delete records matching condition | Yes | `delete` |
314
+ | `POST` | `/api/tables/:table/records/bulk-delete` | Bulk delete records by IDs | Yes | `delete` |
315
+ | `GET` | `/api/tables/:table/count` | Count records matching filter | Yes | `read` |
316
+ | `GET` | `/api/tables/:table/columns/:column/stats` | Statistical profile of column | Yes | `read` |
317
+ | `POST` | `/api/query/select` | Execute SELECT query | Yes | `read` |
318
+ | `POST` | `/api/query/write` | Execute INSERT/UPDATE query | Yes | `execute` |
319
+ | `POST` | `/api/tables` | Create new table | Yes | `ddl` |
320
+ | `PUT` | `/api/tables/:table` | Alter existing table | Yes | `ddl` |
321
+ | `DELETE` | `/api/tables/:table` | Drop existing table | Yes | `ddl` |
322
+ | `POST` | `/api/ddl` | Execute DDL statements | Yes | `ddl` |
323
+ | `GET` | `/api/schema/summary` | Get database summary | Yes | `list` |
324
+ | `GET` | `/api/schema/rag-context` | Generate ultra-compact RAG schema | Yes | `list` |
325
+ | `GET` | `/api/schema/erd` | Generate ER diagram data | Yes | `list` |
326
+ | `GET` | `/api/schema/relationships` | Get foreign key relationships | Yes | `list` |
327
+ | `GET` | `/api/schema/search` | Search schema metadata | Yes | `list` |
328
+ | `GET` | `/api/tables/:table/export` | Export table to CSV | Yes | `utility` |
329
+ | `POST` | `/api/query/export` | Export SELECT query to CSV | Yes | `utility` |
330
+ | `ALL` | `*` (Catch-all) | 404 Handler guaranteeing strict JSON error | Yes | None |
331
+
332
+ ---
333
+
334
+ ## 7. Configuration & Environment Variables
335
+
336
+ | Variable | Default | Description |
337
+ |----------|---------|-------------|
338
+ | `MYSQL_API_ENDPOINT` | `http://localhost:3300` | Remote MySQL API server URL |
339
+ | `MYSQL_API_KEY` | `""` | API Key or Bearer token for authentication |
340
+ | `MCP_PERMISSIONS` | `all` | Permission preset (`only-read`, `read-write`, `admin`, or comma-separated list) |
341
+ | `API_PERMISSIONS` | `all` | Server-level permission preset enforced on HTTP endpoints |
342
+ | `DEFAULT_PAGE_SIZE` | `50` | Default records per page |
343
+ | `MAX_PAGE_SIZE` | `500` | Maximum allowed records per page |
344
+ | `MAX_BYPASS_LIMIT` | `10000` | Maximum allowed records during pagination bypass |
345
+ | `API_TIMEOUT_MS` | `30000` | Network timeout for API requests in milliseconds |
346
+ | `PORT` | `3300` | HTTP port for the companion API server |
347
+
348
+ ---
349
+
350
+ ## 8. Verification & Testing Strategy
351
+
352
+ 1. **Unit Testing:**
353
+ - Permissions engine: verify `only-read` blocks all mutating tools; verify custom lists; verify queryContext inspection.
354
+ - Strict JSON formatter: guarantee that every response envelope parses via `JSON.parse()`.
355
+ - Pagination engine: verify default limit applied; verify bypass mode logic.
356
+ 2. **Integration Testing:**
357
+ - In-memory mock API server simulating remote endpoints.
358
+ - Full MCP tool invocation cycles over simulated stdio transport.
359
+ - Security tests: operator normalization, SQL injection rejection, dangerous SQL keyword blocking.
360
+ - Dual-layer tests: API server blocking mutations with HTTP 403 under `only-read`.
361
+ - Strict JSON 404/500 tests: verify zero HTML output.
362
+ 3. **Build & Type Safety:**
363
+ - Zero TypeScript compile errors (`tsc`).
364
+ - Clean Jest test execution (100% passing across 6 test suites and 61 tests).
package/README.md ADDED
@@ -0,0 +1,202 @@
1
+ # MySQL MCP via API (`mcp-mysql-via-api`)
2
+
3
+ A production-grade **Model Context Protocol (MCP)** server for interacting with MySQL databases **via HTTP/REST API endpoints** on a remote server. Specially optimized for autonomous AI agents like **Hermes AI** and **OpenClaw**, as well as IDEs (Cursor, Windsurf, Cline) and desktop/CLI environments.
4
+
5
+ ---
6
+
7
+ ## 🌟 Key Features
8
+
9
+ - **Decoupled Architecture:** Access MySQL securely without exposing port 3306 or direct database socket connections across corporate firewalls or VPCs. Connects via an authenticated HTTP/REST API endpoint.
10
+ - **Strict Valid JSON Output Guarantee:** 100% of all tool responses (both success results and error envelopes) are strictly formatted as valid JSON (`application/json`). Never plain text, no raw markdown backticks, no emoji error prefixes, and never HTML error pages (even on HTTP 404/500).
11
+ - **Default Pagination + Instant Bypass:**
12
+ - Multi-row operations (`read_records`, `run_select_query`, `search_data_across_tables`) paginate by default (`page=1`, `limit=50`).
13
+ - Supports instant bypass (`bypass_pagination: true` or `all: true`) for full dataset extraction with memory safety guards (`MAX_BYPASS_LIMIT`).
14
+ - **Dual-Layer Defense Permission System:**
15
+ - **MCP Client Level:** Pre-execution verification preventing unauthorized tool dispatch.
16
+ - **API Server Level:** HTTP endpoint authorization via `API_PERMISSIONS` returning HTTP 403 Forbidden envelopes.
17
+ - Presets: `only-read` (read-only), `read-write`, `admin` (all operations).
18
+ - Granular permissions: `list`, `read`, `create`, `update`, `delete`, `execute`, `ddl`, `utility`.
19
+ - **AI Agent Context Window Optimization (Hermes & OpenClaw):**
20
+ - `get_schema_rag_context`: Ultra-compact schema representation designed to preserve LLM token context windows.
21
+ - `search_data_across_tables`: Cross-table text search when schema storage location is unknown.
22
+ - `get_column_statistics`: Statistical data profiling (null percentage, distinct values, min/max, distribution).
23
+ - `read_record`: Direct point lookup by primary key or ID.
24
+ - **Direct Table REST Endpoints:** Every table exposes standard REST endpoints (`/api/tables/:table/records`, `/api/tables/:table/records/:id`, `/api/tables/:table/count`, etc.).
25
+ - **Companion MySQL REST API Server Included:** Comes with a standalone Express/Node.js API server (`npm run start:server`) that can be deployed directly to the remote database machine.
26
+
27
+ ---
28
+
29
+ ## 🚀 Quick Start
30
+
31
+ ### 1. Installation
32
+
33
+ ```bash
34
+ cd C:\DEKSTOP\MCP\mcp_mysql_via_api
35
+ npm install
36
+ npm run build
37
+ ```
38
+
39
+ ### 2. Configure Environment
40
+
41
+ Copy `.env.example` to `.env`:
42
+
43
+ ```env
44
+ MYSQL_API_ENDPOINT=http://remote-mysql-server:3300
45
+ MYSQL_API_KEY=your-secure-api-token
46
+ MCP_PERMISSIONS=only-read
47
+ API_PERMISSIONS=only-read
48
+ DEFAULT_PAGE_SIZE=50
49
+ ```
50
+
51
+ ### 3. Start the MCP Server
52
+
53
+ ```bash
54
+ npm start
55
+ ```
56
+
57
+ Or run directly via Node/CLI:
58
+
59
+ ```bash
60
+ node dist/mcp-server.js http://remote-server:3300 only-read your-api-key
61
+ ```
62
+
63
+ ---
64
+
65
+ ## 🤖 AI Agent Integration
66
+
67
+ ### Hermes AI / OpenClaw Configuration
68
+
69
+ Add to your agent's MCP servers config (`mcp_config.json` or agent YAML):
70
+
71
+ ```json
72
+ {
73
+ "mcpServers": {
74
+ "mysql_via_api": {
75
+ "command": "npx",
76
+ "args": [
77
+ "-y",
78
+ "@jessejoris/mcp-mysql-via-api",
79
+ "http://your-remote-api-server:3300",
80
+ "only-read",
81
+ "your-api-key"
82
+ ],
83
+ "env": {
84
+ "MYSQL_API_ENDPOINT": "http://your-remote-api-server:3300",
85
+ "MYSQL_API_KEY": "your-api-key",
86
+ "MCP_PERMISSIONS": "only-read",
87
+ "DEFAULT_PAGE_SIZE": "50"
88
+ }
89
+ }
90
+ }
91
+ }
92
+ ```
93
+
94
+ ### Cursor / Windsurf / Claude Desktop (`claude_desktop_config.json`)
95
+
96
+ ```json
97
+ {
98
+ "mcpServers": {
99
+ "mysql_api": {
100
+ "command": "npx",
101
+ "args": [
102
+ "-y",
103
+ "@jessejoris/mcp-mysql-via-api"
104
+ ],
105
+ "env": {
106
+ "MYSQL_API_ENDPOINT": "https://api.internal.example.com",
107
+ "MYSQL_API_KEY": "secret-bearer-token",
108
+ "MCP_PERMISSIONS": "only-read"
109
+ }
110
+ }
111
+ }
112
+ }
113
+ ```
114
+
115
+ ---
116
+
117
+ ## 🔒 Permission Profiles
118
+
119
+ Set via `MCP_PERMISSIONS` and `API_PERMISSIONS` environment variables or CLI arguments:
120
+
121
+ | Preset | Allowed Categories | Mutating Actions Blocked? |
122
+ |--------|-------------------|--------------------------|
123
+ | `only-read` / `readonly` | `list`, `read`, `utility` | ✅ Blocks `create`, `update`, `delete`, `execute`, `ddl` |
124
+ | `read-write` | `list`, `read`, `create`, `update`, `utility` | ✅ Blocks `delete`, `execute`, `ddl` |
125
+ | `admin` / `all` | All permissions | None blocked |
126
+ | Custom (e.g. `list,read`) | Explicit list | Blocks anything omitted |
127
+
128
+ ---
129
+
130
+ ## 🧰 Available Tools (31 Tools Catalog)
131
+
132
+ ### Discovery & Schema
133
+ 1. `list_databases`: Lists all accessible databases.
134
+ 2. `list_tables`: Lists tables in database.
135
+ 3. `read_table_schema`: Full column and index definitions.
136
+ 4. `get_database_summary`: Structural overview of tables and rows.
137
+ 5. `get_schema_erd`: Generates Mermaid.js ER diagram.
138
+ 6. `get_schema_rag_context`: Ultra-compact schema for LLM context windows.
139
+ 7. `get_all_tables_relationships`: Analyzes foreign key relationships.
140
+ 8. `search_schema`: Searches table and column metadata.
141
+ 9. `find_tables_by_keyword`: Ranked keyword search for candidate tables.
142
+ 10. `search_data_across_tables`: Scans text data across tables for keywords.
143
+
144
+ ### CRUD & Data
145
+ 11. `read_records`: Reads rows with pagination, sorting, and filter conditions.
146
+ 12. `read_record`: Direct point lookup by primary key or ID.
147
+ 13. `count_records`: Counts matching rows.
148
+ 14. `create_record`: Inserts single record.
149
+ 15. `bulk_insert`: Batch inserts multiple records.
150
+ 16. `update_record`: Updates records matching filter conditions.
151
+ 17. `bulk_update`: Batch updates records by primary key.
152
+ 18. `delete_record`: Deletes records matching filter conditions.
153
+ 19. `bulk_delete`: Batch deletes records by primary keys.
154
+
155
+ ### Data Profiling
156
+ 20. `get_column_statistics`: Statistical data profiling of column values.
157
+
158
+ ### Query Execution
159
+ 21. `run_select_query`: Runs read-only SELECT queries with pagination/bypass.
160
+ 22. `execute_write_query`: Executes guarded mutation queries with DDL/dangerous keyword checks.
161
+
162
+ ### Schema Management (DDL)
163
+ 23. `create_table`: Creates table.
164
+ 24. `alter_table`: Alters table columns.
165
+ 25. `drop_table`: Drops table.
166
+ 26. `execute_ddl`: Executes raw DDL statements.
167
+
168
+ ### Diagnostics & Utilities
169
+ 27. `test_connection`: Pings remote API, checks DB connection and latency.
170
+ 28. `describe_connection`: Returns endpoint, status, and active permission policies.
171
+ 29. `list_all_tools`: Live catalog of all 31 tools with active permission status.
172
+ 30. `export_table_to_csv`: Exports table data to CSV.
173
+ 31. `export_query_to_csv`: Exports SELECT query results to CSV.
174
+
175
+ ---
176
+
177
+ ## 🖥️ Companion MySQL API Server
178
+
179
+ Deploy `src/server/` on your remote server running MySQL:
180
+
181
+ ```bash
182
+ # On remote server
183
+ export DB_HOST=localhost
184
+ export DB_USER=root
185
+ export DB_PASSWORD=my-password
186
+ export DB_NAME=production_db
187
+ export MYSQL_API_KEY=my-secret-key
188
+ export API_PERMISSIONS=only-read # Optional server-level guard
189
+ export PORT=3300
190
+
191
+ npm run start:server
192
+ ```
193
+
194
+ ---
195
+
196
+ ## 🧪 Testing
197
+
198
+ ```bash
199
+ npm test
200
+ ```
201
+
202
+ Runs all 6 test suites covering 61 unit and integration tests.
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+
3
+ const path = require("path");
4
+ require(path.join(__dirname, "../dist/mcp-server.js"));
@@ -0,0 +1,46 @@
1
+ import { ReadRecordsParams, ReadRecordParams, CreateRecordParams, BulkInsertParams, UpdateRecordParams, BulkUpdateParams, DeleteRecordParams, BulkDeleteParams, CountRecordsParams, SelectQueryParams, WriteQueryParams, DdlQueryParams, CreateTableParams, DropTableParams, RagContextParams, SearchDataParams, ColumnStatsParams, ServerConfig } from "../types/index.js";
2
+ export declare class MysqlApiClient {
3
+ private endpoint;
4
+ private apiKey;
5
+ private timeoutMs;
6
+ private defaultPageSize;
7
+ private maxPageSize;
8
+ private maxBypassLimit;
9
+ constructor(config: ServerConfig);
10
+ private getHeaders;
11
+ private request;
12
+ testConnection(): Promise<any>;
13
+ getInfo(): Promise<any>;
14
+ listDatabases(): Promise<any>;
15
+ listTables(database?: string): Promise<any>;
16
+ readTableSchema(tableName: string, database?: string): Promise<any>;
17
+ getDatabaseSummary(options?: {
18
+ database?: string;
19
+ maxTables?: number;
20
+ includeRelationships?: boolean;
21
+ }): Promise<any>;
22
+ getSchemaRagContext(options?: RagContextParams): Promise<any>;
23
+ getSchemaErd(database?: string): Promise<any>;
24
+ getAllTablesRelationships(database?: string): Promise<any>;
25
+ searchSchema(query: string, database?: string): Promise<any>;
26
+ findTablesByKeyword(keyword: string, database?: string, limit?: number): Promise<any>;
27
+ searchDataAcrossTables(options: SearchDataParams): Promise<any>;
28
+ readRecords(params: ReadRecordsParams): Promise<any>;
29
+ readRecord(params: ReadRecordParams): Promise<any>;
30
+ countRecords(params: CountRecordsParams): Promise<any>;
31
+ getColumnStatistics(params: ColumnStatsParams): Promise<any>;
32
+ createRecord(params: CreateRecordParams): Promise<any>;
33
+ bulkInsert(params: BulkInsertParams): Promise<any>;
34
+ updateRecord(params: UpdateRecordParams): Promise<any>;
35
+ bulkUpdate(params: BulkUpdateParams): Promise<any>;
36
+ deleteRecord(params: DeleteRecordParams): Promise<any>;
37
+ bulkDelete(params: BulkDeleteParams): Promise<any>;
38
+ runSelectQuery(params: SelectQueryParams): Promise<any>;
39
+ executeWriteQuery(params: WriteQueryParams): Promise<any>;
40
+ createTable(params: CreateTableParams): Promise<any>;
41
+ alterTable(tableName: string, action: string, columnDefinition: any, database?: string): Promise<any>;
42
+ dropTable(params: DropTableParams): Promise<any>;
43
+ executeDdl(params: DdlQueryParams): Promise<any>;
44
+ exportTableToCsv(tableName: string, limit?: number, database?: string): Promise<any>;
45
+ exportQueryToCsv(query: string, limit?: number, database?: string): Promise<any>;
46
+ }