regen-koi-mcp 1.0.6 → 1.1.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/README.md CHANGED
@@ -12,6 +12,8 @@ curl -fsSL https://raw.githubusercontent.com/gaiaaiagent/regen-koi-mcp/main/inst
12
12
 
13
13
  This automatically configures Claude Desktop and Claude Code CLI. Just restart and you're done! 🎉
14
14
 
15
+ **Quick Test:** After restarting, open Claude and ask: _"What repositories are indexed in KOI?"_ to verify the tools are working.
16
+
15
17
  ---
16
18
 
17
19
  ### Option 1: NPM (Recommended - Auto-Updates)
@@ -45,6 +47,8 @@ Config file locations:
45
47
 
46
48
  Then restart Claude Desktop and you're done! 🎉
47
49
 
50
+ **Quick Test:** Ask Claude: _"What repositories are indexed in KOI?"_ to verify the tools are working.
51
+
48
52
  **For existing git users**: See the migration section below for a simple one-line script to switch to npx.
49
53
 
50
54
  ---
@@ -112,6 +116,66 @@ This MCP server gives AI assistants access to Regen Network's comprehensive know
112
116
 
113
117
  **Note:** This MCP server connects to our hosted KOI API at `https://regen.gaiaai.xyz/api/koi` (behind HTTPS via Nginx), so you don't need to run any infrastructure locally.
114
118
 
119
+ ## 🎓 Quick Start: Example Queries
120
+
121
+ Once you've installed the MCP server, try these queries in Claude to explore what's available:
122
+
123
+ ### 🔍 Discovery: What's Indexed?
124
+
125
+ ```
126
+ "What repositories are indexed in the KOI knowledge base?"
127
+ "What types of code entities exist?"
128
+ "Show me statistics about what's in the knowledge base"
129
+ ```
130
+
131
+ **What you'll get:** The system has indexed 5 repositories (regen-ledger, regen-web, koi-sensors, and more) with 26,768 code entities including Methods, Functions, Structs, and Interfaces.
132
+
133
+ ### 💻 Code Exploration: Find Specific Code
134
+
135
+ ```
136
+ "Search for functions containing 'keeper' in regen-ledger"
137
+ "Find all code related to MsgCreateBatch"
138
+ "What Structs exist in the ecocredit module?"
139
+ "Show me all Interface types in regen-ledger"
140
+ "Search for retirement-related code"
141
+ ```
142
+
143
+ **What you'll get:** Direct links to code entities with file paths and signatures. The graph contains Methods, Functions, Structs, and Interfaces extracted via tree-sitter AST parsing.
144
+
145
+ ### 📚 Documentation: Understanding the System
146
+
147
+ ```
148
+ "Explain the ecocredit module architecture"
149
+ "What's the tech stack for regen-web?"
150
+ "Search GitHub docs for information about credit classes"
151
+ "Get an overview of the regen-ledger repository"
152
+ ```
153
+
154
+ **What you'll get:** Architectural explanations, technology choices, and relevant documentation from GitHub repositories.
155
+
156
+ ### 🔬 Advanced: Graph Traversal
157
+
158
+ ```
159
+ "What functions call CreateBatch?"
160
+ "What does the NewKeeper function call?"
161
+ "Find orphaned code that's never called"
162
+ "Show me the call graph for MsgRetire"
163
+ ```
164
+
165
+ **What you'll get:** Call graph traversal showing function relationships (CALLS edges), orphan detection, and code dependency analysis.
166
+
167
+ ### 📊 Knowledge Base: Recent Activity
168
+
169
+ ```
170
+ "Generate a weekly digest of Regen Network discussions"
171
+ "Search for recent discussions about carbon credits from the past week"
172
+ "Find documentation about basket creation from 2024"
173
+ ```
174
+
175
+ **What you'll get:** Summaries of community discussions, forum posts, and activity with source citations.
176
+
177
+ ---
178
+
115
179
  ## 📦 Available Tools
116
180
 
117
181
  ### Knowledge Base Search
@@ -134,6 +198,87 @@ This MCP server gives AI assistants access to Regen Network's comprehensive know
134
198
  | `get_repo_overview` | Get structured overview of a Regen repository | `repository` (enum: regen-ledger, regen-web, regen-data-standards, regenie-corpus) |
135
199
  | `get_tech_stack` | Get technical stack information for Regen repositories | `repository` (optional, omit to show all repos) |
136
200
 
201
+ ---
202
+
203
+ ## 🤔 What Can I Ask? User Guide
204
+
205
+ This table helps you understand which tool to use for different tasks. Just ask Claude in natural language - it will automatically use the right tool.
206
+
207
+ | **When You Want To...** | **Ask Claude** | **Tool Used** |
208
+ |----------------------------------------------------------|----------------------------------------------------------|--------------------------|
209
+ | **Discover what's indexed** | | |
210
+ | See what repositories are available | "What repositories are indexed?" | `list_repos` |
211
+ | See what types of code entities exist | "What entity types are available?" | `list_entity_types` |
212
+ | Get comprehensive statistics | "Show me statistics about the knowledge base" | `get_entity_stats` |
213
+ | **Find specific code** | | |
214
+ | Find all entities of a type | "Show me all Keepers in regen-ledger" | `find_by_type` |
215
+ | Search for entities by name | "Find entities related to MsgCreateBatch" | `search_entities` |
216
+ | Find related code entities | "What's related to the ecocredit Keeper?" | `related_entities` |
217
+ | **Understand relationships** | | |
218
+ | Find which Keeper handles a Message | "Which Keeper handles MsgCreateBatch?" | `keeper_for_msg` |
219
+ | Find what Messages a Keeper handles | "What messages does the ecocredit Keeper handle?" | `msgs_for_keeper` |
220
+ | Find what documentation mentions an entity | "What docs mention MsgRetire?" | `docs_mentioning` |
221
+ | Find entities in a file | "What entities are in keeper.go?" | `entities_in_doc` |
222
+ | **Navigate by modules** | | |
223
+ | List all modules | "What modules exist in regen-ledger?" | `list_modules` |
224
+ | Get details about a module | "Tell me about the ecocredit module" | `get_module` |
225
+ | Search for modules | "Find modules related to baskets" | `search_modules` |
226
+ | Find entities in a module | "What entities are in the ecocredit module?" | `module_entities` |
227
+ | **Search documentation** | | |
228
+ | Search GitHub docs | "Search for documentation about credit classes" | `search_github_docs` |
229
+ | Get repository overview | "Give me an overview of regen-web" | `get_repo_overview` |
230
+ | Understand tech stack | "What's the tech stack for regen-ledger?" | `get_tech_stack` |
231
+ | **Search everything (hybrid)** | | |
232
+ | Semantic search across code and docs | "How does credit retirement work?" | `hybrid_search` |
233
+ | Advanced filtering by date | "Find discussions about tokens from last week" | `search_knowledge` |
234
+ | **Get activity summaries** | | |
235
+ | Generate weekly digest | "Create a weekly digest of Regen activity" | `generate_weekly_digest` |
236
+
237
+ ### Query Type Reference
238
+
239
+ The `query_code_graph` tool supports these query types:
240
+
241
+ #### Discovery
242
+ - **`list_repos`** - Show all indexed repositories with entity counts
243
+ - **`list_entity_types`** - Show all entity types (Function, Class, Keeper, Message, etc.) with counts
244
+ - **`get_entity_stats`** - Comprehensive statistics: entities by type, language, repository
245
+ - **`list_modules`** - Show all modules across repositories
246
+
247
+ #### Entity Queries
248
+ - **`find_by_type`** - Find all entities of a specific type (requires `entity_type` parameter)
249
+ - **`search_entities`** - Search entities by name pattern (requires `entity_name` parameter)
250
+ - **`related_entities`** - Find entities related to a given entity (requires `entity_name` parameter)
251
+
252
+ #### Relationship Queries
253
+ - **`keeper_for_msg`** - Find which Keeper handles a Message (requires `entity_name` parameter)
254
+ - **`msgs_for_keeper`** - Find what Messages a Keeper handles (requires `entity_name` parameter)
255
+ - **`docs_mentioning`** - Find documentation mentioning an entity (requires `entity_name` parameter)
256
+ - **`entities_in_doc`** - Find entities defined in a document (requires `doc_path` parameter)
257
+
258
+ #### Module Queries
259
+ - **`get_module`** - Get details about a specific module (requires `module_name` parameter)
260
+ - **`search_modules`** - Search modules by keyword (requires `entity_name` parameter)
261
+ - **`module_entities`** - Get entities in a module (requires `module_name` parameter)
262
+ - **`module_for_entity`** - Find which module contains an entity (requires `entity_name` parameter)
263
+
264
+ ### What's Currently Indexed
265
+
266
+ **Repositories:** 5 total
267
+ - `regen-ledger`: 18,619 entities (Go, Cosmos SDK modules)
268
+ - `regen-web`: 3,164 entities (TypeScript/React frontend)
269
+ - `koi-sensors`: 1,250 entities (Python data collection)
270
+ - `regen-koi-mcp`: 688 entities (TypeScript MCP server)
271
+ - `regen-data-standards`: 6 entities (JSON schemas)
272
+
273
+ **Entity Types:** 10 types
274
+ - Function, Class, Interface, Method, Type
275
+ - Keeper, Message, Query, Event (Cosmos SDK specific)
276
+ - Module, Repository
277
+
278
+ **Total:** 23,728 code entities
279
+
280
+ ---
281
+
137
282
  ## 🏗️ Architecture
138
283
 
139
284
  This repo contains everything you need to run a complete KOI MCP setup:
@@ -184,16 +329,35 @@ Or manually add to config (`~/Library/Application Support/Claude/claude_desktop_
184
329
 
185
330
  ### Claude Code CLI
186
331
 
187
- **One-line install:**
332
+ **Option 1: Use the automated installer (recommended)**
188
333
  ```bash
189
- claude mcp add regen-koi npx -y regen-koi-mcp@latest
334
+ curl -fsSL https://raw.githubusercontent.com/gaiaaiagent/regen-koi-mcp/main/install.sh | bash
190
335
  ```
336
+ This configures both Claude Desktop and Claude Code CLI with the correct environment variables.
191
337
 
192
- Then set environment variable:
338
+ **Option 2: Manual installation**
339
+ 1. Add the MCP server:
193
340
  ```bash
194
- export KOI_API_ENDPOINT=https://regen.gaiaai.xyz/api/koi
341
+ claude mcp add regen-koi npx -y regen-koi-mcp@latest
342
+ ```
343
+
344
+ 2. Configure the environment variable in your Claude Code settings file (`~/.claude/settings.json` or similar):
345
+ ```json
346
+ {
347
+ "mcpServers": {
348
+ "regen-koi": {
349
+ "command": "npx",
350
+ "args": ["-y", "regen-koi-mcp@latest"],
351
+ "env": {
352
+ "KOI_API_ENDPOINT": "https://regen.gaiaai.xyz/api/koi"
353
+ }
354
+ }
355
+ }
356
+ }
195
357
  ```
196
358
 
359
+ **Verification:** After installation, restart Claude Code and ask: "What repositories are indexed?" to verify the tools are working.
360
+
197
361
  ---
198
362
 
199
363
  ### VS Code / VS Code Insiders
@@ -545,6 +709,27 @@ The setup connects to our hosted KOI API at `https://regen.gaiaai.xyz/api/koi`.
545
709
  ### "Command not found"
546
710
  Make sure Node.js is installed and in your PATH. The setup script uses `node` command.
547
711
 
712
+ ### "Connection error: localhost:8301" or "localhost:8910"
713
+
714
+ **Cause:** Claude caches MCP configurations in `~/.claude.json`. If you previously ran a local dev server, it may have cached `localhost` URLs that override your current config.
715
+
716
+ **Fix:**
717
+ ```bash
718
+ # 1. Check for cached localhost configs
719
+ grep -i "localhost.*8301\|localhost.*8910" ~/.claude.json
720
+
721
+ # 2. Backup your config
722
+ cp ~/.claude.json ~/.claude.json.backup
723
+
724
+ # 3. Replace localhost with public API
725
+ sed -i '' 's|http://localhost:8301/api/koi|https://regen.gaiaai.xyz/api/koi|g' ~/.claude.json
726
+ sed -i '' 's|http://localhost:8910/api/koi|https://regen.gaiaai.xyz/api/koi|g' ~/.claude.json
727
+
728
+ # 4. Restart Claude Code/Desktop
729
+ ```
730
+
731
+ **Prevention:** Always use `https://regen.gaiaai.xyz/api/koi` in MCP configs unless you're actively developing the API server locally.
732
+
548
733
  ## 📚 Example Usage
549
734
 
550
735
  Once configured, you can ask Claude:
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Cache Module - LRU Caching for Query Results
3
+ *
4
+ * Provides in-memory caching with TTL for query results to reduce
5
+ * database load and improve response times.
6
+ */
7
+ /**
8
+ * Query Cache class
9
+ */
10
+ declare class QueryCache {
11
+ private caches;
12
+ constructor();
13
+ /**
14
+ * Get cache for a specific category
15
+ */
16
+ private getCache;
17
+ /**
18
+ * Get the category for a query type
19
+ */
20
+ private getCategory;
21
+ /**
22
+ * Get a cached result
23
+ */
24
+ get<T>(tool: string, queryType: string, params: Record<string, any>): T | undefined;
25
+ /**
26
+ * Set a cached result
27
+ */
28
+ set<T>(tool: string, queryType: string, params: Record<string, any>, value: T): void;
29
+ /**
30
+ * Check if a key exists in cache
31
+ */
32
+ has(tool: string, queryType: string, params: Record<string, any>): boolean;
33
+ /**
34
+ * Delete a specific cached result
35
+ */
36
+ delete(tool: string, queryType: string, params: Record<string, any>): void;
37
+ /**
38
+ * Clear all caches
39
+ */
40
+ clear(): void;
41
+ /**
42
+ * Clear a specific category's cache
43
+ */
44
+ clearCategory(category: string): void;
45
+ /**
46
+ * Get cache statistics
47
+ */
48
+ getStats(): {
49
+ totalSize: number;
50
+ byCategory: Record<string, {
51
+ size: number;
52
+ maxSize: number;
53
+ }>;
54
+ };
55
+ }
56
+ export declare const queryCache: QueryCache;
57
+ /**
58
+ * Wrapper function to cache async query results
59
+ */
60
+ export declare function cachedQuery<T>(tool: string, queryType: string, params: Record<string, any>, fetchFn: () => Promise<T>): Promise<T>;
61
+ /**
62
+ * Check if a query type should be cached
63
+ */
64
+ export declare function shouldCache(queryType: string): boolean;
65
+ /**
66
+ * Get TTL for a query type
67
+ */
68
+ export declare function getTTL(queryType: string): number;
69
+ export default queryCache;
70
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAgGH;;GAEG;AACH,cAAM,UAAU;IACd,OAAO,CAAC,MAAM,CAAiD;;IAc/D;;OAEG;IACH,OAAO,CAAC,QAAQ;IAShB;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS;IAkBnF;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAUpF;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO;IAO1E;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQ1E;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAOrC;;OAEG;IACH,QAAQ,IAAI;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC/D;CAeF;AAGD,eAAO,MAAM,UAAU,YAAmB,CAAC;AAE3C;;GAEG;AACH,wBAAsB,WAAW,CAAC,CAAC,EACjC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACxB,OAAO,CAAC,CAAC,CAAC,CAcZ;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAGtD;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED,eAAe,UAAU,CAAC"}
package/dist/cache.js ADDED
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Cache Module - LRU Caching for Query Results
3
+ *
4
+ * Provides in-memory caching with TTL for query results to reduce
5
+ * database load and improve response times.
6
+ */
7
+ import { LRUCache } from 'lru-cache';
8
+ import crypto from 'crypto';
9
+ import { logCacheOp } from './logger.js';
10
+ import { recordCacheHit, recordCacheMiss } from './metrics.js';
11
+ /**
12
+ * Default cache configurations by category
13
+ */
14
+ const CACHE_CONFIGS = {
15
+ // Static data - cache for 1 hour
16
+ static: {
17
+ ttlMs: 60 * 60 * 1000, // 1 hour
18
+ maxSize: 100
19
+ },
20
+ // Semi-static data - cache for 10 minutes
21
+ semi_static: {
22
+ ttlMs: 10 * 60 * 1000, // 10 minutes
23
+ maxSize: 200
24
+ },
25
+ // Dynamic queries - cache for 5 minutes
26
+ dynamic: {
27
+ ttlMs: 5 * 60 * 1000, // 5 minutes
28
+ maxSize: 500
29
+ },
30
+ // Frequently changing - cache for 1 minute
31
+ volatile: {
32
+ ttlMs: 60 * 1000, // 1 minute
33
+ maxSize: 100
34
+ }
35
+ };
36
+ /**
37
+ * Map query types to cache categories
38
+ */
39
+ const QUERY_TYPE_TO_CATEGORY = {
40
+ // Static (changes rarely)
41
+ 'list_repos': 'static',
42
+ 'list_entity_types': 'static',
43
+ 'get_entity_stats': 'static',
44
+ 'get_tech_stack': 'static',
45
+ 'get_repo_overview': 'static',
46
+ 'list_modules': 'static',
47
+ // Semi-static (changes occasionally)
48
+ 'find_by_type': 'semi_static',
49
+ 'get_module': 'semi_static',
50
+ 'search_modules': 'semi_static',
51
+ 'module_entities': 'semi_static',
52
+ 'module_for_entity': 'semi_static',
53
+ // Dynamic (user queries)
54
+ 'search_entities': 'dynamic',
55
+ 'search_knowledge': 'dynamic',
56
+ 'search_github_docs': 'dynamic',
57
+ 'hybrid_search': 'dynamic',
58
+ 'keeper_for_msg': 'dynamic',
59
+ 'msgs_for_keeper': 'dynamic',
60
+ 'docs_mentioning': 'dynamic',
61
+ 'entities_in_doc': 'dynamic',
62
+ 'related_entities': 'dynamic',
63
+ // Volatile (changes frequently)
64
+ 'get_stats': 'volatile',
65
+ 'generate_weekly_digest': 'volatile'
66
+ };
67
+ /**
68
+ * Generate a cache key from query parameters
69
+ */
70
+ function generateCacheKey(tool, queryType, params) {
71
+ // Create a deterministic string from params
72
+ const sortedParams = Object.keys(params)
73
+ .filter(k => params[k] !== undefined && params[k] !== null)
74
+ .sort()
75
+ .map(k => `${k}=${JSON.stringify(params[k])}`)
76
+ .join('|');
77
+ const keyString = `${tool}:${queryType}:${sortedParams}`;
78
+ // Hash for consistent key length
79
+ const hash = crypto.createHash('sha256').update(keyString).digest('hex').substring(0, 16);
80
+ return `${tool}:${queryType}:${hash}`;
81
+ }
82
+ /**
83
+ * Query Cache class
84
+ */
85
+ class QueryCache {
86
+ caches = new Map();
87
+ constructor() {
88
+ // Initialize caches for each category
89
+ for (const [category, config] of Object.entries(CACHE_CONFIGS)) {
90
+ this.caches.set(category, new LRUCache({
91
+ max: config.maxSize,
92
+ ttl: config.ttlMs,
93
+ updateAgeOnGet: false, // Don't refresh TTL on read
94
+ updateAgeOnHas: false
95
+ }));
96
+ }
97
+ }
98
+ /**
99
+ * Get cache for a specific category
100
+ */
101
+ getCache(category) {
102
+ const cache = this.caches.get(category);
103
+ if (!cache) {
104
+ // Fall back to dynamic cache
105
+ return this.caches.get('dynamic');
106
+ }
107
+ return cache;
108
+ }
109
+ /**
110
+ * Get the category for a query type
111
+ */
112
+ getCategory(queryType) {
113
+ return QUERY_TYPE_TO_CATEGORY[queryType] || 'dynamic';
114
+ }
115
+ /**
116
+ * Get a cached result
117
+ */
118
+ get(tool, queryType, params) {
119
+ const category = this.getCategory(queryType);
120
+ const cache = this.getCache(category);
121
+ const key = generateCacheKey(tool, queryType, params);
122
+ const cached = cache.get(key);
123
+ if (cached !== undefined) {
124
+ logCacheOp({ operation: 'hit', key });
125
+ recordCacheHit();
126
+ return cached;
127
+ }
128
+ else {
129
+ logCacheOp({ operation: 'miss', key });
130
+ recordCacheMiss();
131
+ return undefined;
132
+ }
133
+ }
134
+ /**
135
+ * Set a cached result
136
+ */
137
+ set(tool, queryType, params, value) {
138
+ const category = this.getCategory(queryType);
139
+ const cache = this.getCache(category);
140
+ const key = generateCacheKey(tool, queryType, params);
141
+ const config = CACHE_CONFIGS[category] || CACHE_CONFIGS.dynamic;
142
+ cache.set(key, value);
143
+ logCacheOp({ operation: 'set', key, ttl_ms: config.ttlMs });
144
+ }
145
+ /**
146
+ * Check if a key exists in cache
147
+ */
148
+ has(tool, queryType, params) {
149
+ const category = this.getCategory(queryType);
150
+ const cache = this.getCache(category);
151
+ const key = generateCacheKey(tool, queryType, params);
152
+ return cache.has(key);
153
+ }
154
+ /**
155
+ * Delete a specific cached result
156
+ */
157
+ delete(tool, queryType, params) {
158
+ const category = this.getCategory(queryType);
159
+ const cache = this.getCache(category);
160
+ const key = generateCacheKey(tool, queryType, params);
161
+ cache.delete(key);
162
+ logCacheOp({ operation: 'evict', key });
163
+ }
164
+ /**
165
+ * Clear all caches
166
+ */
167
+ clear() {
168
+ for (const cache of this.caches.values()) {
169
+ cache.clear();
170
+ }
171
+ }
172
+ /**
173
+ * Clear a specific category's cache
174
+ */
175
+ clearCategory(category) {
176
+ const cache = this.caches.get(category);
177
+ if (cache) {
178
+ cache.clear();
179
+ }
180
+ }
181
+ /**
182
+ * Get cache statistics
183
+ */
184
+ getStats() {
185
+ let totalSize = 0;
186
+ const byCategory = {};
187
+ for (const [category, cache] of this.caches) {
188
+ const size = cache.size;
189
+ totalSize += size;
190
+ byCategory[category] = {
191
+ size,
192
+ maxSize: CACHE_CONFIGS[category]?.maxSize || 0
193
+ };
194
+ }
195
+ return { totalSize, byCategory };
196
+ }
197
+ }
198
+ // Singleton instance
199
+ export const queryCache = new QueryCache();
200
+ /**
201
+ * Wrapper function to cache async query results
202
+ */
203
+ export async function cachedQuery(tool, queryType, params, fetchFn) {
204
+ // Check cache first
205
+ const cached = queryCache.get(tool, queryType, params);
206
+ if (cached !== undefined) {
207
+ return cached;
208
+ }
209
+ // Execute query
210
+ const result = await fetchFn();
211
+ // Cache result
212
+ queryCache.set(tool, queryType, params, result);
213
+ return result;
214
+ }
215
+ /**
216
+ * Check if a query type should be cached
217
+ */
218
+ export function shouldCache(queryType) {
219
+ // Don't cache volatile queries
220
+ return QUERY_TYPE_TO_CATEGORY[queryType] !== 'volatile';
221
+ }
222
+ /**
223
+ * Get TTL for a query type
224
+ */
225
+ export function getTTL(queryType) {
226
+ const category = QUERY_TYPE_TO_CATEGORY[queryType] || 'dynamic';
227
+ return CACHE_CONFIGS[category]?.ttlMs || CACHE_CONFIGS.dynamic.ttlMs;
228
+ }
229
+ export default queryCache;
230
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
@@ -7,11 +7,19 @@
7
7
  * Supports two modes:
8
8
  * 1. API mode: When KOI_API_ENDPOINT is set, uses HTTP API at /api/koi/graph
9
9
  * 2. Direct mode: Connects directly to PostgreSQL (only works on server)
10
+ *
11
+ * Production Features (Phase 7):
12
+ * - Structured logging with pino
13
+ * - Metrics collection for performance monitoring
14
+ * - Retry logic with exponential backoff
15
+ * - Circuit breaker for preventing cascading failures
16
+ * - LRU caching for query results
17
+ * - Input validation with zod schemas
10
18
  */
11
19
  import { Tool } from '@modelcontextprotocol/sdk/types.js';
12
20
  export declare const GRAPH_TOOL: Tool;
13
21
  /**
14
- * Execute the query_code_graph tool
22
+ * Execute the query_code_graph tool with production hardening
15
23
  */
16
24
  export declare function executeGraphTool(args: any): Promise<{
17
25
  content: {
@@ -34,6 +42,9 @@ declare const _default: {
34
42
  } | undefined;
35
43
  required?: string[] | undefined;
36
44
  };
45
+ _meta?: {
46
+ [x: string]: unknown;
47
+ } | undefined;
37
48
  title?: string | undefined;
38
49
  description?: string | undefined;
39
50
  outputSchema?: {
@@ -52,9 +63,6 @@ declare const _default: {
52
63
  idempotentHint?: boolean | undefined;
53
64
  openWorldHint?: boolean | undefined;
54
65
  } | undefined;
55
- _meta?: {
56
- [x: string]: unknown;
57
- } | undefined;
58
66
  icons?: {
59
67
  [x: string]: unknown;
60
68
  src: string;
@@ -1 +1 @@
1
- {"version":3,"file":"graph_tool.d.ts","sourceRoot":"","sources":["../src/graph_tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAoB1D,eAAO,MAAM,UAAU,EAAE,IAuCxB,CAAC;AAqCF;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,GAAG;;;;;GA2f/C;AAgID;;GAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACH,wBAGE"}
1
+ {"version":3,"file":"graph_tool.d.ts","sourceRoot":"","sources":["../src/graph_tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAyB1D,eAAO,MAAM,UAAU,EAAE,IAyCxB,CAAC;AAiIF;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,GAAG;;;;;GA6qB/C;AAgID;;GAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACH,wBAGE"}