zapql-mcp 0.1.1
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/README.md +146 -0
- package/dist/cache/index.d.ts +6 -0
- package/dist/cache/index.js +14 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/query-cache.d.ts +158 -0
- package/dist/cache/query-cache.js +624 -0
- package/dist/cache/query-cache.js.map +1 -0
- package/dist/config/database.d.ts +13 -0
- package/dist/config/database.js +77 -0
- package/dist/config/database.js.map +1 -0
- package/dist/config/environment.d.ts +15 -0
- package/dist/config/environment.js +78 -0
- package/dist/config/environment.js.map +1 -0
- package/dist/config/optimization-history.d.ts +2 -0
- package/dist/config/optimization-history.js +144 -0
- package/dist/config/optimization-history.js.map +1 -0
- package/dist/database/sql-server-driver.d.ts +78 -0
- package/dist/database/sql-server-driver.js +305 -0
- package/dist/database/sql-server-driver.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/connections.d.ts +83 -0
- package/dist/resources/connections.js +228 -0
- package/dist/resources/connections.js.map +1 -0
- package/dist/resources/optimization.d.ts +74 -0
- package/dist/resources/optimization.js +290 -0
- package/dist/resources/optimization.js.map +1 -0
- package/dist/resources/queries.d.ts +56 -0
- package/dist/resources/queries.js +235 -0
- package/dist/resources/queries.js.map +1 -0
- package/dist/resources.d.ts +54 -0
- package/dist/resources.js +336 -0
- package/dist/resources.js.map +1 -0
- package/dist/server.d.ts +132 -0
- package/dist/server.js +168 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/analyze-query.d.ts +219 -0
- package/dist/tools/analyze-query.js +1356 -0
- package/dist/tools/analyze-query.js.map +1 -0
- package/dist/tools/connect-database.d.ts +68 -0
- package/dist/tools/connect-database.js +304 -0
- package/dist/tools/connect-database.js.map +1 -0
- package/dist/tools/optimize-query.d.ts +246 -0
- package/dist/tools/optimize-query.js +2396 -0
- package/dist/tools/optimize-query.js.map +1 -0
- package/dist/tools.d.ts +123 -0
- package/dist/tools.js +376 -0
- package/dist/tools.js.map +1 -0
- package/dist/types/database.d.ts +334 -0
- package/dist/types/database.js +20 -0
- package/dist/types/database.js.map +1 -0
- package/dist/types/environment.d.ts +18 -0
- package/dist/types/environment.js +3 -0
- package/dist/types/environment.js.map +1 -0
- package/dist/types/index.d.ts +32 -0
- package/dist/types/index.js +31 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/mcp.d.ts +193 -0
- package/dist/types/mcp.js +27 -0
- package/dist/types/mcp.js.map +1 -0
- package/dist/types/optimization.d.ts +348 -0
- package/dist/types/optimization.js +57 -0
- package/dist/types/optimization.js.map +1 -0
- package/dist/utils/errors.d.ts +254 -0
- package/dist/utils/errors.js +363 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +155 -0
- package/dist/utils/logger.js +378 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# ZapQL MCP Server
|
|
2
|
+
|
|
3
|
+
Autonomous SQL Server query optimizer via the [Model Context Protocol](https://modelcontextprotocol.io). Connect Claude (or any MCP-compatible agent) directly to your SQL Server and get instant query analysis and AI-powered optimization suggestions.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
### 1. Install dependencies
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install
|
|
11
|
+
npm run build
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### 2. Configure environment
|
|
15
|
+
|
|
16
|
+
Create `~/.zapql/.env`:
|
|
17
|
+
|
|
18
|
+
```env
|
|
19
|
+
# Required
|
|
20
|
+
SQL_CONNECTION_STRING=Server=your-server,1433;Database=your-db;User Id=your-user;Password=your-password;Encrypt=false
|
|
21
|
+
ZAPQL_API_KEY=any-string-you-choose
|
|
22
|
+
|
|
23
|
+
# Optional — enables AI optimization suggestions
|
|
24
|
+
LITELLM_API_KEY=your-openai-or-litellm-key
|
|
25
|
+
LITELLM_MODEL=gpt-4 # default: gpt-4
|
|
26
|
+
ZAPQL_TOP_N=20 # number of optimization suggestions
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 3. Add to Claude Desktop
|
|
30
|
+
|
|
31
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"mcpServers": {
|
|
36
|
+
"zapql": {
|
|
37
|
+
"command": "node",
|
|
38
|
+
"args": ["/path/to/mcp-server/dist/index.js"]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Restart Claude Desktop. ZapQL tools will appear in the tool panel.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Tools
|
|
49
|
+
|
|
50
|
+
### `connect_database`
|
|
51
|
+
Establish a connection to a SQL Server instance.
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
Input: connectionString (string)
|
|
55
|
+
Output: connection status, server info, database name
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### `analyze_query`
|
|
59
|
+
Analyze a SQL query for performance issues without executing it.
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
Input: connectionString (string), queryText (string)
|
|
63
|
+
Output: issues list, complexity score, execution plan, suggestions
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Detects: SELECT *, missing WHERE clause, leading wildcards, N+1 patterns, NOT IN subqueries, excessive OR conditions, implicit conversions.
|
|
67
|
+
|
|
68
|
+
### `optimize_query`
|
|
69
|
+
Get AI-powered optimization suggestions for a slow query.
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
Input: connectionString (string), originalQuery (string), context? (string)
|
|
73
|
+
Output: optimizedQuery, explanation, performance comparison, cost improvement estimate
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Requires `LITELLM_API_KEY`. Results are cached in SQLite at `~/.zapql/cache.db`.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## MCP Resources
|
|
81
|
+
|
|
82
|
+
| Resource | Description |
|
|
83
|
+
|----------|-------------|
|
|
84
|
+
| `zapql:///connections` | List of active database connections |
|
|
85
|
+
| `zapql:///queries/{connection}` | Recent queries for a connection |
|
|
86
|
+
| `zapql:///optimization/{queryId}` | Cached optimization result |
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Architecture
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
Claude Desktop
|
|
94
|
+
│ MCP Protocol (stdio)
|
|
95
|
+
▼
|
|
96
|
+
ZapQL MCP Server (Node.js)
|
|
97
|
+
├── Tools: connect_database, analyze_query, optimize_query
|
|
98
|
+
├── Resources: connections, queries, optimization results
|
|
99
|
+
├── SQLServerDriver (mssql) ──→ Your SQL Server
|
|
100
|
+
├── QueryCache (in-memory + SQLite persistence)
|
|
101
|
+
└── LiteLLM ──→ OpenAI / any LLM provider
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Development
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npm run build # Compile TypeScript
|
|
110
|
+
npm test # Run unit tests (node:test)
|
|
111
|
+
npm run dev # Run with tsx (no compile step)
|
|
112
|
+
npm run lint # Type-check without emit
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Tests run against `dist/` (compiled output). No SQL Server connection required for unit tests — the SQL driver is mocked.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Environment Variables
|
|
120
|
+
|
|
121
|
+
| Variable | Required | Default | Description |
|
|
122
|
+
|----------|----------|---------|-------------|
|
|
123
|
+
| `SQL_CONNECTION_STRING` | ✅ | — | mssql connection string |
|
|
124
|
+
| `ZAPQL_API_KEY` | ✅ | — | Internal API key (any string) |
|
|
125
|
+
| `LITELLM_API_KEY` | — | — | Enables optimize_query |
|
|
126
|
+
| `LITELLM_MODEL` | — | `gpt-4` | LLM model for optimization |
|
|
127
|
+
| `ZAPQL_TOP_N` | — | `20` | Max optimization suggestions |
|
|
128
|
+
|
|
129
|
+
Config file: `~/.zapql/.env` (loaded automatically on startup)
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Logs
|
|
134
|
+
|
|
135
|
+
Log files at `~/.zapql/logs/zapql-YYYY-MM-DD.log`. Structured JSON. Rotates daily, keeps 7 days.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Status
|
|
140
|
+
|
|
141
|
+
- ✅ MCP tools: connect_database, analyze_query, optimize_query
|
|
142
|
+
- ✅ MCP resources: connections, queries, optimization
|
|
143
|
+
- ✅ SQLite state persistence
|
|
144
|
+
- ✅ In-memory query cache with TTL
|
|
145
|
+
- ✅ Comprehensive error handling
|
|
146
|
+
- ⏳ Integration tests (US-016)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cache module exports
|
|
4
|
+
*
|
|
5
|
+
* Provides comprehensive caching functionality for ZapQL MCP server
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.resetQueryCache = exports.getQueryCache = exports.CacheType = exports.QueryCache = void 0;
|
|
9
|
+
var query_cache_1 = require("./query-cache");
|
|
10
|
+
Object.defineProperty(exports, "QueryCache", { enumerable: true, get: function () { return query_cache_1.QueryCache; } });
|
|
11
|
+
Object.defineProperty(exports, "CacheType", { enumerable: true, get: function () { return query_cache_1.CacheType; } });
|
|
12
|
+
Object.defineProperty(exports, "getQueryCache", { enumerable: true, get: function () { return query_cache_1.getQueryCache; } });
|
|
13
|
+
Object.defineProperty(exports, "resetQueryCache", { enumerable: true, get: function () { return query_cache_1.resetQueryCache; } });
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,6CAOuB;AANrB,yGAAA,UAAU,OAAA;AACV,wGAAA,SAAS,OAAA;AACT,4GAAA,aAAa,OAAA;AACb,8GAAA,eAAe,OAAA"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query Cache System for ZapQL MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Provides comprehensive caching for database queries and API calls with:
|
|
5
|
+
* - Configurable TTL (Time To Live) caching
|
|
6
|
+
* - LRU eviction with memory size limits
|
|
7
|
+
* - Different cache policies for different data types
|
|
8
|
+
* - Cache hit/miss metrics and logging
|
|
9
|
+
* - SQLite persistence for optimization results
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Cache types with different TTL policies
|
|
13
|
+
*/
|
|
14
|
+
export declare enum CacheType {
|
|
15
|
+
EXECUTION_PLAN = "execution_plan",// 5 minutes TTL
|
|
16
|
+
DMV_QUERIES = "dmv_queries",// 1 minute TTL
|
|
17
|
+
OPTIMIZATION = "optimization",// Permanent (stored in SQLite)
|
|
18
|
+
GENERAL = "general"
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Cache statistics for monitoring
|
|
22
|
+
*/
|
|
23
|
+
export interface CacheStats {
|
|
24
|
+
totalEntries: number;
|
|
25
|
+
totalSize: number;
|
|
26
|
+
hitCount: number;
|
|
27
|
+
missCount: number;
|
|
28
|
+
evictionCount: number;
|
|
29
|
+
hitRate: number;
|
|
30
|
+
averageEntrySize: number;
|
|
31
|
+
oldestEntry?: Date;
|
|
32
|
+
newestEntry?: Date;
|
|
33
|
+
entriesByType: Record<CacheType, number>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Cache configuration options
|
|
37
|
+
*/
|
|
38
|
+
export interface CacheConfig {
|
|
39
|
+
maxSizeBytes: number;
|
|
40
|
+
defaultTtlMs: number;
|
|
41
|
+
cleanupIntervalMs: number;
|
|
42
|
+
enableMetrics: boolean;
|
|
43
|
+
sqlitePath?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Comprehensive query cache system with LRU eviction and persistent storage
|
|
47
|
+
*/
|
|
48
|
+
export declare class QueryCache {
|
|
49
|
+
private cache;
|
|
50
|
+
private config;
|
|
51
|
+
private logger;
|
|
52
|
+
private db;
|
|
53
|
+
private cleanupTimer;
|
|
54
|
+
private hitCount;
|
|
55
|
+
private missCount;
|
|
56
|
+
private evictionCount;
|
|
57
|
+
constructor(config?: Partial<CacheConfig>);
|
|
58
|
+
/**
|
|
59
|
+
* Generate cache key from connection string and query content
|
|
60
|
+
*/
|
|
61
|
+
static generateCacheKey(connectionString: string, queryContent: string, type: CacheType): string;
|
|
62
|
+
/**
|
|
63
|
+
* Set cache entry with appropriate TTL based on type
|
|
64
|
+
*/
|
|
65
|
+
set<T>(key: string, value: T, type?: CacheType, customTtlMs?: number): void;
|
|
66
|
+
/**
|
|
67
|
+
* Get cache entry if not expired
|
|
68
|
+
*/
|
|
69
|
+
get<T>(key: string, type?: CacheType): T | null;
|
|
70
|
+
/**
|
|
71
|
+
* Check if key exists and is not expired
|
|
72
|
+
*/
|
|
73
|
+
has(key: string, type?: CacheType): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Delete cache entry
|
|
76
|
+
*/
|
|
77
|
+
delete(key: string, type?: CacheType): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Clear all cache entries or entries of specific type
|
|
80
|
+
*/
|
|
81
|
+
clear(type?: CacheType): void;
|
|
82
|
+
/**
|
|
83
|
+
* Get comprehensive cache statistics
|
|
84
|
+
*/
|
|
85
|
+
getStats(): CacheStats;
|
|
86
|
+
/**
|
|
87
|
+
* Clean up expired entries
|
|
88
|
+
*/
|
|
89
|
+
cleanup(): void;
|
|
90
|
+
/**
|
|
91
|
+
* Close cache and cleanup resources
|
|
92
|
+
*/
|
|
93
|
+
close(): void;
|
|
94
|
+
/**
|
|
95
|
+
* Initialize SQLite database for persistent optimization results
|
|
96
|
+
*/
|
|
97
|
+
private initializeSQLiteDatabase;
|
|
98
|
+
/**
|
|
99
|
+
* Store optimization result permanently in SQLite
|
|
100
|
+
*/
|
|
101
|
+
private setPermanentOptimization;
|
|
102
|
+
/**
|
|
103
|
+
* Get optimization result from SQLite
|
|
104
|
+
*/
|
|
105
|
+
private getPermanentOptimization;
|
|
106
|
+
/**
|
|
107
|
+
* Check if permanent optimization exists
|
|
108
|
+
*/
|
|
109
|
+
private hasPermanentOptimization;
|
|
110
|
+
/**
|
|
111
|
+
* Delete permanent optimization
|
|
112
|
+
*/
|
|
113
|
+
private deletePermanentOptimization;
|
|
114
|
+
/**
|
|
115
|
+
* Clear all permanent optimizations
|
|
116
|
+
*/
|
|
117
|
+
private clearPermanentOptimizations;
|
|
118
|
+
/**
|
|
119
|
+
* Get count of permanent optimization entries
|
|
120
|
+
*/
|
|
121
|
+
private getOptimizationCount;
|
|
122
|
+
/**
|
|
123
|
+
* Ensure cache doesn't exceed size limit using LRU eviction
|
|
124
|
+
*/
|
|
125
|
+
private ensureCapacity;
|
|
126
|
+
/**
|
|
127
|
+
* Evict least recently used entries to free up space
|
|
128
|
+
*/
|
|
129
|
+
private evictLRU;
|
|
130
|
+
/**
|
|
131
|
+
* Estimate memory size of value in bytes
|
|
132
|
+
*/
|
|
133
|
+
private estimateSize;
|
|
134
|
+
/**
|
|
135
|
+
* Get total size of all cache entries
|
|
136
|
+
*/
|
|
137
|
+
private getTotalSize;
|
|
138
|
+
/**
|
|
139
|
+
* Record cache hit for metrics
|
|
140
|
+
*/
|
|
141
|
+
private recordHit;
|
|
142
|
+
/**
|
|
143
|
+
* Record cache miss for metrics
|
|
144
|
+
*/
|
|
145
|
+
private recordMiss;
|
|
146
|
+
/**
|
|
147
|
+
* Start periodic cleanup timer
|
|
148
|
+
*/
|
|
149
|
+
private startCleanupTimer;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get or create singleton cache instance
|
|
153
|
+
*/
|
|
154
|
+
export declare function getQueryCache(config?: Partial<CacheConfig>): QueryCache;
|
|
155
|
+
/**
|
|
156
|
+
* Reset singleton cache instance (primarily for testing)
|
|
157
|
+
*/
|
|
158
|
+
export declare function resetQueryCache(): void;
|