@defai.digital/mcp-server 13.0.3
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/LICENSE +214 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +7 -0
- package/dist/bin.js.map +1 -0
- package/dist/bootstrap.d.ts +89 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +161 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/rate-limiter.d.ts +136 -0
- package/dist/middleware/rate-limiter.d.ts.map +1 -0
- package/dist/middleware/rate-limiter.js +262 -0
- package/dist/middleware/rate-limiter.js.map +1 -0
- package/dist/prompts/agent-guide.d.ts +16 -0
- package/dist/prompts/agent-guide.d.ts.map +1 -0
- package/dist/prompts/agent-guide.js +391 -0
- package/dist/prompts/agent-guide.js.map +1 -0
- package/dist/prompts/explain-workflow.d.ts +15 -0
- package/dist/prompts/explain-workflow.d.ts.map +1 -0
- package/dist/prompts/explain-workflow.js +157 -0
- package/dist/prompts/explain-workflow.js.map +1 -0
- package/dist/prompts/index.d.ts +39 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +83 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/review-changes.d.ts +15 -0
- package/dist/prompts/review-changes.d.ts.map +1 -0
- package/dist/prompts/review-changes.js +102 -0
- package/dist/prompts/review-changes.js.map +1 -0
- package/dist/prompts/troubleshoot-session.d.ts +15 -0
- package/dist/prompts/troubleshoot-session.d.ts.map +1 -0
- package/dist/prompts/troubleshoot-session.js +156 -0
- package/dist/prompts/troubleshoot-session.js.map +1 -0
- package/dist/registry-accessor.d.ts +83 -0
- package/dist/registry-accessor.d.ts.map +1 -0
- package/dist/registry-accessor.js +153 -0
- package/dist/registry-accessor.js.map +1 -0
- package/dist/resources/agents.d.ts +40 -0
- package/dist/resources/agents.d.ts.map +1 -0
- package/dist/resources/agents.js +123 -0
- package/dist/resources/agents.js.map +1 -0
- package/dist/resources/config.d.ts +57 -0
- package/dist/resources/config.d.ts.map +1 -0
- package/dist/resources/config.js +222 -0
- package/dist/resources/config.js.map +1 -0
- package/dist/resources/index.d.ts +38 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +132 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/policies.d.ts +40 -0
- package/dist/resources/policies.d.ts.map +1 -0
- package/dist/resources/policies.js +122 -0
- package/dist/resources/policies.js.map +1 -0
- package/dist/resources/sessions.d.ts +30 -0
- package/dist/resources/sessions.d.ts.map +1 -0
- package/dist/resources/sessions.js +64 -0
- package/dist/resources/sessions.js.map +1 -0
- package/dist/resources/workflows.d.ts +40 -0
- package/dist/resources/workflows.d.ts.map +1 -0
- package/dist/resources/workflows.js +143 -0
- package/dist/resources/workflows.js.map +1 -0
- package/dist/schema-registry.d.ts +23 -0
- package/dist/schema-registry.d.ts.map +1 -0
- package/dist/schema-registry.js +225 -0
- package/dist/schema-registry.js.map +1 -0
- package/dist/server.d.ts +63 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +393 -0
- package/dist/server.js.map +1 -0
- package/dist/session-accessor.d.ts +23 -0
- package/dist/session-accessor.d.ts.map +1 -0
- package/dist/session-accessor.js +39 -0
- package/dist/session-accessor.js.map +1 -0
- package/dist/shared-registry.d.ts +23 -0
- package/dist/shared-registry.d.ts.map +1 -0
- package/dist/shared-registry.js +235 -0
- package/dist/shared-registry.js.map +1 -0
- package/dist/stdio.d.ts +6 -0
- package/dist/stdio.d.ts.map +1 -0
- package/dist/stdio.js +152 -0
- package/dist/stdio.js.map +1 -0
- package/dist/tool-namespacing.d.ts +28 -0
- package/dist/tool-namespacing.d.ts.map +1 -0
- package/dist/tool-namespacing.js +80 -0
- package/dist/tool-namespacing.js.map +1 -0
- package/dist/tools/ability.d.ts +55 -0
- package/dist/tools/ability.d.ts.map +1 -0
- package/dist/tools/ability.js +560 -0
- package/dist/tools/ability.js.map +1 -0
- package/dist/tools/agent.d.ts +73 -0
- package/dist/tools/agent.d.ts.map +1 -0
- package/dist/tools/agent.js +895 -0
- package/dist/tools/agent.js.map +1 -0
- package/dist/tools/config.d.ts +36 -0
- package/dist/tools/config.d.ts.map +1 -0
- package/dist/tools/config.js +265 -0
- package/dist/tools/config.js.map +1 -0
- package/dist/tools/design.d.ts +42 -0
- package/dist/tools/design.d.ts.map +1 -0
- package/dist/tools/design.js +736 -0
- package/dist/tools/design.js.map +1 -0
- package/dist/tools/discuss.d.ts +40 -0
- package/dist/tools/discuss.d.ts.map +1 -0
- package/dist/tools/discuss.js +331 -0
- package/dist/tools/discuss.js.map +1 -0
- package/dist/tools/file-system.d.ts +63 -0
- package/dist/tools/file-system.d.ts.map +1 -0
- package/dist/tools/file-system.js +513 -0
- package/dist/tools/file-system.js.map +1 -0
- package/dist/tools/guard.d.ts +29 -0
- package/dist/tools/guard.d.ts.map +1 -0
- package/dist/tools/guard.js +311 -0
- package/dist/tools/guard.js.map +1 -0
- package/dist/tools/index.d.ts +35 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +178 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/memory.d.ts +101 -0
- package/dist/tools/memory.d.ts.map +1 -0
- package/dist/tools/memory.js +704 -0
- package/dist/tools/memory.js.map +1 -0
- package/dist/tools/orchestration.d.ts +58 -0
- package/dist/tools/orchestration.d.ts.map +1 -0
- package/dist/tools/orchestration.js +714 -0
- package/dist/tools/orchestration.js.map +1 -0
- package/dist/tools/review.d.ts +40 -0
- package/dist/tools/review.d.ts.map +1 -0
- package/dist/tools/review.js +319 -0
- package/dist/tools/review.js.map +1 -0
- package/dist/tools/scaffold.d.ts +27 -0
- package/dist/tools/scaffold.d.ts.map +1 -0
- package/dist/tools/scaffold.js +495 -0
- package/dist/tools/scaffold.js.map +1 -0
- package/dist/tools/session.d.ts +75 -0
- package/dist/tools/session.d.ts.map +1 -0
- package/dist/tools/session.js +749 -0
- package/dist/tools/session.js.map +1 -0
- package/dist/tools/telemetry.d.ts +58 -0
- package/dist/tools/telemetry.d.ts.map +1 -0
- package/dist/tools/telemetry.js +638 -0
- package/dist/tools/telemetry.js.map +1 -0
- package/dist/tools/trace.d.ts +29 -0
- package/dist/tools/trace.d.ts.map +1 -0
- package/dist/tools/trace.js +191 -0
- package/dist/tools/trace.js.map +1 -0
- package/dist/tools/workflow.d.ts +26 -0
- package/dist/tools/workflow.d.ts.map +1 -0
- package/dist/tools/workflow.js +269 -0
- package/dist/tools/workflow.js.map +1 -0
- package/dist/trace-wrapper.d.ts +79 -0
- package/dist/trace-wrapper.d.ts.map +1 -0
- package/dist/trace-wrapper.js +151 -0
- package/dist/trace-wrapper.js.map +1 -0
- package/dist/types.d.ts +185 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/artifact-store.d.ts +49 -0
- package/dist/utils/artifact-store.d.ts.map +1 -0
- package/dist/utils/artifact-store.js +102 -0
- package/dist/utils/artifact-store.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +10 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/response.d.ts +139 -0
- package/dist/utils/response.d.ts.map +1 -0
- package/dist/utils/response.js +293 -0
- package/dist/utils/response.js.map +1 -0
- package/dist/validation.d.ts +223 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +372 -0
- package/dist/validation.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,704 @@
|
|
|
1
|
+
import { LIMIT_DEFAULT, LIMIT_MEMORY } from '@defai.digital/contracts';
|
|
2
|
+
/**
|
|
3
|
+
* Memory store tool definition
|
|
4
|
+
* INV-MCP-004: Idempotent - storing same key/value is safe to retry
|
|
5
|
+
*/
|
|
6
|
+
export const memoryStoreTool = {
|
|
7
|
+
name: 'memory_store',
|
|
8
|
+
description: 'Store a value in memory with a key',
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
key: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
description: 'The key to store the value under',
|
|
15
|
+
},
|
|
16
|
+
value: {
|
|
17
|
+
type: 'object',
|
|
18
|
+
description: 'The value to store',
|
|
19
|
+
},
|
|
20
|
+
namespace: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
description: 'Optional namespace for the key',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
required: ['key', 'value'],
|
|
26
|
+
},
|
|
27
|
+
idempotent: true,
|
|
28
|
+
retryableErrors: ['STORE_FAILED'],
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Memory retrieve tool definition
|
|
32
|
+
* INV-MCP-004: Idempotent - read-only operation
|
|
33
|
+
*/
|
|
34
|
+
export const memoryRetrieveTool = {
|
|
35
|
+
name: 'memory_retrieve',
|
|
36
|
+
description: 'Retrieve a value from memory by key',
|
|
37
|
+
inputSchema: {
|
|
38
|
+
type: 'object',
|
|
39
|
+
properties: {
|
|
40
|
+
key: {
|
|
41
|
+
type: 'string',
|
|
42
|
+
description: 'The key to retrieve',
|
|
43
|
+
},
|
|
44
|
+
namespace: {
|
|
45
|
+
type: 'string',
|
|
46
|
+
description: 'Optional namespace for the key',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
required: ['key'],
|
|
50
|
+
},
|
|
51
|
+
idempotent: true,
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Memory search tool definition
|
|
55
|
+
* INV-MCP-004: Idempotent - read-only operation
|
|
56
|
+
*/
|
|
57
|
+
export const memorySearchTool = {
|
|
58
|
+
name: 'memory_search',
|
|
59
|
+
description: 'Search memory for values matching a query',
|
|
60
|
+
inputSchema: {
|
|
61
|
+
type: 'object',
|
|
62
|
+
properties: {
|
|
63
|
+
query: {
|
|
64
|
+
type: 'string',
|
|
65
|
+
description: 'Search query',
|
|
66
|
+
},
|
|
67
|
+
namespace: {
|
|
68
|
+
type: 'string',
|
|
69
|
+
description: 'Optional namespace to search in',
|
|
70
|
+
},
|
|
71
|
+
limit: {
|
|
72
|
+
type: 'number',
|
|
73
|
+
description: 'Maximum number of results',
|
|
74
|
+
default: LIMIT_DEFAULT,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
required: ['query'],
|
|
78
|
+
},
|
|
79
|
+
idempotent: true,
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Memory list tool definition
|
|
83
|
+
* INV-MCP-004: Idempotent - read-only operation
|
|
84
|
+
*/
|
|
85
|
+
export const memoryListTool = {
|
|
86
|
+
name: 'memory_list',
|
|
87
|
+
description: 'List all keys in memory with optional namespace filtering. Read-only, no side effects.',
|
|
88
|
+
inputSchema: {
|
|
89
|
+
type: 'object',
|
|
90
|
+
properties: {
|
|
91
|
+
namespace: {
|
|
92
|
+
type: 'string',
|
|
93
|
+
description: 'Optional namespace to filter keys',
|
|
94
|
+
},
|
|
95
|
+
limit: {
|
|
96
|
+
type: 'number',
|
|
97
|
+
description: 'Maximum number of keys to return',
|
|
98
|
+
default: LIMIT_MEMORY,
|
|
99
|
+
},
|
|
100
|
+
prefix: {
|
|
101
|
+
type: 'string',
|
|
102
|
+
description: 'Optional key prefix filter',
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
idempotent: true,
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Memory delete tool definition
|
|
110
|
+
* INV-MCP-004: Idempotent - deleting non-existent key returns deleted=false
|
|
111
|
+
* INV-MCP-002: Side effects - removes key from memory store
|
|
112
|
+
*/
|
|
113
|
+
export const memoryDeleteTool = {
|
|
114
|
+
name: 'memory_delete',
|
|
115
|
+
description: 'Delete a key from memory. SIDE EFFECTS: Removes key from store. Idempotent - deleting non-existent key returns deleted=false.',
|
|
116
|
+
inputSchema: {
|
|
117
|
+
type: 'object',
|
|
118
|
+
properties: {
|
|
119
|
+
key: {
|
|
120
|
+
type: 'string',
|
|
121
|
+
description: 'The key to delete',
|
|
122
|
+
},
|
|
123
|
+
namespace: {
|
|
124
|
+
type: 'string',
|
|
125
|
+
description: 'Optional namespace for the key',
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
required: ['key'],
|
|
129
|
+
},
|
|
130
|
+
idempotent: true,
|
|
131
|
+
};
|
|
132
|
+
// In-memory storage for demonstration
|
|
133
|
+
const memoryStore = new Map();
|
|
134
|
+
/**
|
|
135
|
+
* Handler for memory_store tool
|
|
136
|
+
*/
|
|
137
|
+
export const handleMemoryStore = (args) => {
|
|
138
|
+
const key = args.key;
|
|
139
|
+
const value = args.value;
|
|
140
|
+
const namespace = args.namespace ?? 'default';
|
|
141
|
+
const fullKey = `${namespace}:${key}`;
|
|
142
|
+
try {
|
|
143
|
+
memoryStore.set(fullKey, {
|
|
144
|
+
value,
|
|
145
|
+
storedAt: new Date().toISOString(),
|
|
146
|
+
namespace,
|
|
147
|
+
});
|
|
148
|
+
return Promise.resolve({
|
|
149
|
+
content: [
|
|
150
|
+
{
|
|
151
|
+
type: 'text',
|
|
152
|
+
text: JSON.stringify({
|
|
153
|
+
success: true,
|
|
154
|
+
key,
|
|
155
|
+
namespace,
|
|
156
|
+
message: `Value stored successfully at key: ${key}`,
|
|
157
|
+
}, null, 2),
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
return Promise.resolve({
|
|
164
|
+
content: [
|
|
165
|
+
{
|
|
166
|
+
type: 'text',
|
|
167
|
+
text: `Error storing value: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
isError: true,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
/**
|
|
175
|
+
* Handler for memory_retrieve tool
|
|
176
|
+
*/
|
|
177
|
+
export const handleMemoryRetrieve = (args) => {
|
|
178
|
+
const key = args.key;
|
|
179
|
+
const namespace = args.namespace ?? 'default';
|
|
180
|
+
const fullKey = `${namespace}:${key}`;
|
|
181
|
+
const stored = memoryStore.get(fullKey);
|
|
182
|
+
if (stored === undefined) {
|
|
183
|
+
return Promise.resolve({
|
|
184
|
+
content: [
|
|
185
|
+
{
|
|
186
|
+
type: 'text',
|
|
187
|
+
text: JSON.stringify({
|
|
188
|
+
found: false,
|
|
189
|
+
key,
|
|
190
|
+
namespace,
|
|
191
|
+
message: `No value found for key: ${key}`,
|
|
192
|
+
}, null, 2),
|
|
193
|
+
},
|
|
194
|
+
],
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
return Promise.resolve({
|
|
198
|
+
content: [
|
|
199
|
+
{
|
|
200
|
+
type: 'text',
|
|
201
|
+
text: JSON.stringify({
|
|
202
|
+
found: true,
|
|
203
|
+
key,
|
|
204
|
+
namespace,
|
|
205
|
+
value: stored.value,
|
|
206
|
+
storedAt: stored.storedAt,
|
|
207
|
+
}, null, 2),
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
});
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* Handler for memory_search tool
|
|
214
|
+
*/
|
|
215
|
+
export const handleMemorySearch = (args) => {
|
|
216
|
+
const query = args.query;
|
|
217
|
+
const namespace = args.namespace;
|
|
218
|
+
const limit = args.limit ?? 10;
|
|
219
|
+
const results = [];
|
|
220
|
+
for (const [fullKey, stored] of memoryStore.entries()) {
|
|
221
|
+
const storedData = stored;
|
|
222
|
+
// Filter by namespace if specified
|
|
223
|
+
if (namespace !== undefined && storedData.namespace !== namespace) {
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
// Simple substring search in key
|
|
227
|
+
const keyPart = fullKey.split(':')[1] ?? fullKey;
|
|
228
|
+
if (keyPart.includes(query)) {
|
|
229
|
+
results.push({
|
|
230
|
+
key: keyPart,
|
|
231
|
+
namespace: storedData.namespace,
|
|
232
|
+
value: storedData.value,
|
|
233
|
+
storedAt: storedData.storedAt,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
if (results.length >= limit) {
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return Promise.resolve({
|
|
241
|
+
content: [
|
|
242
|
+
{
|
|
243
|
+
type: 'text',
|
|
244
|
+
text: JSON.stringify({
|
|
245
|
+
query,
|
|
246
|
+
namespace: namespace ?? 'all',
|
|
247
|
+
count: results.length,
|
|
248
|
+
results,
|
|
249
|
+
}, null, 2),
|
|
250
|
+
},
|
|
251
|
+
],
|
|
252
|
+
});
|
|
253
|
+
};
|
|
254
|
+
/**
|
|
255
|
+
* Handler for memory_list tool
|
|
256
|
+
* INV-MCP-MEM-001: Keys returned in storage order (oldest first)
|
|
257
|
+
* INV-MCP-MEM-002: Namespace filter is exact match
|
|
258
|
+
* INV-MCP-MEM-003: Prefix filter is case-sensitive
|
|
259
|
+
*/
|
|
260
|
+
export const handleMemoryList = (args) => {
|
|
261
|
+
const namespace = args.namespace;
|
|
262
|
+
const limit = args.limit ?? 100;
|
|
263
|
+
const prefix = args.prefix;
|
|
264
|
+
const keys = [];
|
|
265
|
+
for (const [fullKey, stored] of memoryStore.entries()) {
|
|
266
|
+
const storedData = stored;
|
|
267
|
+
// Filter by namespace if specified (exact match - INV-MCP-MEM-002)
|
|
268
|
+
if (namespace !== undefined && storedData.namespace !== namespace) {
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
// Extract key part from fullKey (namespace:key)
|
|
272
|
+
const keyPart = fullKey.split(':')[1] ?? fullKey;
|
|
273
|
+
// Filter by prefix if specified (case-sensitive - INV-MCP-MEM-003)
|
|
274
|
+
if (prefix !== undefined && !keyPart.startsWith(prefix)) {
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
keys.push({
|
|
278
|
+
key: keyPart,
|
|
279
|
+
namespace: storedData.namespace,
|
|
280
|
+
storedAt: storedData.storedAt,
|
|
281
|
+
});
|
|
282
|
+
if (keys.length >= limit) {
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return Promise.resolve({
|
|
287
|
+
content: [
|
|
288
|
+
{
|
|
289
|
+
type: 'text',
|
|
290
|
+
text: JSON.stringify({
|
|
291
|
+
keys,
|
|
292
|
+
total: keys.length,
|
|
293
|
+
hasMore: memoryStore.size > keys.length,
|
|
294
|
+
}, null, 2),
|
|
295
|
+
},
|
|
296
|
+
],
|
|
297
|
+
});
|
|
298
|
+
};
|
|
299
|
+
/**
|
|
300
|
+
* Handler for memory_delete tool
|
|
301
|
+
* INV-MCP-MEM-004: Delete is idempotent (deleting non-existent key returns deleted=false)
|
|
302
|
+
* INV-MCP-MEM-005: Delete emits trace event with key info
|
|
303
|
+
*/
|
|
304
|
+
export const handleMemoryDelete = (args) => {
|
|
305
|
+
const key = args.key;
|
|
306
|
+
const namespace = args.namespace ?? 'default';
|
|
307
|
+
const fullKey = `${namespace}:${key}`;
|
|
308
|
+
const existed = memoryStore.has(fullKey);
|
|
309
|
+
if (existed) {
|
|
310
|
+
memoryStore.delete(fullKey);
|
|
311
|
+
}
|
|
312
|
+
// INV-MCP-MEM-004: Idempotent - returns deleted=false for non-existent key
|
|
313
|
+
return Promise.resolve({
|
|
314
|
+
content: [
|
|
315
|
+
{
|
|
316
|
+
type: 'text',
|
|
317
|
+
text: JSON.stringify({
|
|
318
|
+
deleted: existed,
|
|
319
|
+
key,
|
|
320
|
+
namespace,
|
|
321
|
+
message: existed
|
|
322
|
+
? `Key "${key}" deleted successfully`
|
|
323
|
+
: `Key "${key}" not found in namespace "${namespace}"`,
|
|
324
|
+
}, null, 2),
|
|
325
|
+
},
|
|
326
|
+
],
|
|
327
|
+
});
|
|
328
|
+
};
|
|
329
|
+
// ============================================================================
|
|
330
|
+
// Enhanced Memory Tools
|
|
331
|
+
// ============================================================================
|
|
332
|
+
/**
|
|
333
|
+
* Memory export tool definition
|
|
334
|
+
* INV-MCP-004: Idempotent - read-only operation
|
|
335
|
+
*/
|
|
336
|
+
export const memoryExportTool = {
|
|
337
|
+
name: 'memory_export',
|
|
338
|
+
description: 'Export memory entries to JSON format. Read-only, no side effects.',
|
|
339
|
+
inputSchema: {
|
|
340
|
+
type: 'object',
|
|
341
|
+
properties: {
|
|
342
|
+
namespace: {
|
|
343
|
+
type: 'string',
|
|
344
|
+
description: 'Optional namespace to export',
|
|
345
|
+
},
|
|
346
|
+
prefix: {
|
|
347
|
+
type: 'string',
|
|
348
|
+
description: 'Optional key prefix filter',
|
|
349
|
+
},
|
|
350
|
+
includeMetadata: {
|
|
351
|
+
type: 'boolean',
|
|
352
|
+
description: 'Include storedAt and other metadata',
|
|
353
|
+
default: true,
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
idempotent: true,
|
|
358
|
+
};
|
|
359
|
+
/**
|
|
360
|
+
* Memory import tool definition
|
|
361
|
+
* INV-MCP-004: Non-idempotent without overwrite flag
|
|
362
|
+
* INV-MCP-002: Side effects - writes entries to memory store
|
|
363
|
+
*/
|
|
364
|
+
export const memoryImportTool = {
|
|
365
|
+
name: 'memory_import',
|
|
366
|
+
description: 'Import memory entries from JSON format. SIDE EFFECTS: Writes entries to memory store. Use overwrite=true for idempotent behavior.',
|
|
367
|
+
inputSchema: {
|
|
368
|
+
type: 'object',
|
|
369
|
+
properties: {
|
|
370
|
+
data: {
|
|
371
|
+
type: 'array',
|
|
372
|
+
description: 'Array of entries to import',
|
|
373
|
+
items: {
|
|
374
|
+
type: 'object',
|
|
375
|
+
properties: {
|
|
376
|
+
key: { type: 'string' },
|
|
377
|
+
value: { type: 'object' },
|
|
378
|
+
namespace: { type: 'string' },
|
|
379
|
+
},
|
|
380
|
+
required: ['key', 'value'],
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
overwrite: {
|
|
384
|
+
type: 'boolean',
|
|
385
|
+
description: 'Overwrite existing keys',
|
|
386
|
+
default: false,
|
|
387
|
+
},
|
|
388
|
+
namespace: {
|
|
389
|
+
type: 'string',
|
|
390
|
+
description: 'Override namespace for all imported entries',
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
required: ['data'],
|
|
394
|
+
},
|
|
395
|
+
idempotent: false,
|
|
396
|
+
};
|
|
397
|
+
/**
|
|
398
|
+
* Memory stats tool definition
|
|
399
|
+
* INV-MCP-004: Idempotent - read-only operation
|
|
400
|
+
*/
|
|
401
|
+
export const memoryStatsTool = {
|
|
402
|
+
name: 'memory_stats',
|
|
403
|
+
description: 'Get memory storage statistics. Read-only, no side effects.',
|
|
404
|
+
inputSchema: {
|
|
405
|
+
type: 'object',
|
|
406
|
+
properties: {
|
|
407
|
+
namespace: {
|
|
408
|
+
type: 'string',
|
|
409
|
+
description: 'Optional namespace to get stats for',
|
|
410
|
+
},
|
|
411
|
+
detailed: {
|
|
412
|
+
type: 'boolean',
|
|
413
|
+
description: 'Include detailed breakdown by namespace',
|
|
414
|
+
default: false,
|
|
415
|
+
},
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
idempotent: true,
|
|
419
|
+
};
|
|
420
|
+
/**
|
|
421
|
+
* Memory bulk delete tool definition
|
|
422
|
+
* INV-MCP-004: Idempotent - deleting non-existent keys is safe
|
|
423
|
+
* INV-MCP-002: Side effects - removes multiple keys from memory store
|
|
424
|
+
*/
|
|
425
|
+
export const memoryBulkDeleteTool = {
|
|
426
|
+
name: 'memory_bulk_delete',
|
|
427
|
+
description: 'Delete multiple keys from memory. SIDE EFFECTS: Removes keys from store. Idempotent - deleting non-existent keys returns notFound count.',
|
|
428
|
+
inputSchema: {
|
|
429
|
+
type: 'object',
|
|
430
|
+
properties: {
|
|
431
|
+
keys: {
|
|
432
|
+
type: 'array',
|
|
433
|
+
description: 'Array of keys to delete',
|
|
434
|
+
items: { type: 'string' },
|
|
435
|
+
},
|
|
436
|
+
namespace: {
|
|
437
|
+
type: 'string',
|
|
438
|
+
description: 'Namespace for all keys',
|
|
439
|
+
},
|
|
440
|
+
prefix: {
|
|
441
|
+
type: 'string',
|
|
442
|
+
description: 'Delete all keys with this prefix (alternative to keys)',
|
|
443
|
+
},
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
idempotent: true,
|
|
447
|
+
};
|
|
448
|
+
/**
|
|
449
|
+
* Memory clear tool definition
|
|
450
|
+
* INV-MCP-004: Idempotent - clearing empty namespace returns cleared=0
|
|
451
|
+
* INV-MCP-002: Side effects - removes all entries in namespace
|
|
452
|
+
*/
|
|
453
|
+
export const memoryClearTool = {
|
|
454
|
+
name: 'memory_clear',
|
|
455
|
+
description: 'Clear all memory entries in a namespace. SIDE EFFECTS: Removes all entries in namespace. Requires confirm=true. Idempotent - clearing empty namespace returns cleared=0.',
|
|
456
|
+
inputSchema: {
|
|
457
|
+
type: 'object',
|
|
458
|
+
properties: {
|
|
459
|
+
namespace: {
|
|
460
|
+
type: 'string',
|
|
461
|
+
description: 'Namespace to clear (required for safety)',
|
|
462
|
+
},
|
|
463
|
+
confirm: {
|
|
464
|
+
type: 'boolean',
|
|
465
|
+
description: 'Confirmation flag (must be true)',
|
|
466
|
+
},
|
|
467
|
+
},
|
|
468
|
+
required: ['namespace', 'confirm'],
|
|
469
|
+
},
|
|
470
|
+
idempotent: true,
|
|
471
|
+
};
|
|
472
|
+
/**
|
|
473
|
+
* Handler for memory_export tool
|
|
474
|
+
*/
|
|
475
|
+
export const handleMemoryExport = (args) => {
|
|
476
|
+
const namespace = args.namespace;
|
|
477
|
+
const prefix = args.prefix;
|
|
478
|
+
const includeMetadata = args.includeMetadata ?? true;
|
|
479
|
+
const exports = [];
|
|
480
|
+
for (const [fullKey, stored] of memoryStore.entries()) {
|
|
481
|
+
const storedData = stored;
|
|
482
|
+
if (namespace !== undefined && storedData.namespace !== namespace) {
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
const keyPart = fullKey.split(':')[1] ?? fullKey;
|
|
486
|
+
if (prefix !== undefined && !keyPart.startsWith(prefix)) {
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
const entry = {
|
|
490
|
+
key: keyPart,
|
|
491
|
+
value: storedData.value,
|
|
492
|
+
namespace: storedData.namespace,
|
|
493
|
+
};
|
|
494
|
+
if (includeMetadata) {
|
|
495
|
+
entry.storedAt = storedData.storedAt;
|
|
496
|
+
}
|
|
497
|
+
exports.push(entry);
|
|
498
|
+
}
|
|
499
|
+
return Promise.resolve({
|
|
500
|
+
content: [
|
|
501
|
+
{
|
|
502
|
+
type: 'text',
|
|
503
|
+
text: JSON.stringify({
|
|
504
|
+
count: exports.length,
|
|
505
|
+
exportedAt: new Date().toISOString(),
|
|
506
|
+
data: exports,
|
|
507
|
+
}, null, 2),
|
|
508
|
+
},
|
|
509
|
+
],
|
|
510
|
+
});
|
|
511
|
+
};
|
|
512
|
+
/**
|
|
513
|
+
* Handler for memory_import tool
|
|
514
|
+
*/
|
|
515
|
+
export const handleMemoryImport = (args) => {
|
|
516
|
+
const data = args.data;
|
|
517
|
+
const overwrite = args.overwrite ?? false;
|
|
518
|
+
const defaultNamespace = args.namespace ?? 'default';
|
|
519
|
+
let imported = 0;
|
|
520
|
+
let skipped = 0;
|
|
521
|
+
const errors = [];
|
|
522
|
+
for (const entry of data) {
|
|
523
|
+
const namespace = entry.namespace ?? defaultNamespace;
|
|
524
|
+
const fullKey = `${namespace}:${entry.key}`;
|
|
525
|
+
if (!overwrite && memoryStore.has(fullKey)) {
|
|
526
|
+
skipped++;
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
try {
|
|
530
|
+
memoryStore.set(fullKey, {
|
|
531
|
+
value: entry.value,
|
|
532
|
+
storedAt: new Date().toISOString(),
|
|
533
|
+
namespace,
|
|
534
|
+
});
|
|
535
|
+
imported++;
|
|
536
|
+
}
|
|
537
|
+
catch (error) {
|
|
538
|
+
errors.push(`Failed to import key "${entry.key}": ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
return Promise.resolve({
|
|
542
|
+
content: [
|
|
543
|
+
{
|
|
544
|
+
type: 'text',
|
|
545
|
+
text: JSON.stringify({
|
|
546
|
+
imported,
|
|
547
|
+
skipped,
|
|
548
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
549
|
+
importedAt: new Date().toISOString(),
|
|
550
|
+
}, null, 2),
|
|
551
|
+
},
|
|
552
|
+
],
|
|
553
|
+
});
|
|
554
|
+
};
|
|
555
|
+
/**
|
|
556
|
+
* Handler for memory_stats tool
|
|
557
|
+
*/
|
|
558
|
+
export const handleMemoryStats = (args) => {
|
|
559
|
+
const namespaceFilter = args.namespace;
|
|
560
|
+
const detailed = args.detailed ?? false;
|
|
561
|
+
const namespaceStats = new Map();
|
|
562
|
+
let totalEntries = 0;
|
|
563
|
+
for (const [fullKey, stored] of memoryStore.entries()) {
|
|
564
|
+
const storedData = stored;
|
|
565
|
+
if (namespaceFilter !== undefined && storedData.namespace !== namespaceFilter) {
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
totalEntries++;
|
|
569
|
+
const existing = namespaceStats.get(storedData.namespace);
|
|
570
|
+
if (existing !== undefined) {
|
|
571
|
+
existing.count++;
|
|
572
|
+
if (detailed) {
|
|
573
|
+
const keyPart = fullKey.split(':')[1] ?? fullKey;
|
|
574
|
+
existing.keys.push(keyPart);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
else {
|
|
578
|
+
const keyPart = fullKey.split(':')[1] ?? fullKey;
|
|
579
|
+
namespaceStats.set(storedData.namespace, {
|
|
580
|
+
count: 1,
|
|
581
|
+
keys: detailed ? [keyPart] : [],
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
const byNamespace = {};
|
|
586
|
+
for (const [ns, stats] of namespaceStats.entries()) {
|
|
587
|
+
byNamespace[ns] = detailed ? stats : { count: stats.count };
|
|
588
|
+
}
|
|
589
|
+
return Promise.resolve({
|
|
590
|
+
content: [
|
|
591
|
+
{
|
|
592
|
+
type: 'text',
|
|
593
|
+
text: JSON.stringify({
|
|
594
|
+
totalEntries,
|
|
595
|
+
namespaceCount: namespaceStats.size,
|
|
596
|
+
byNamespace,
|
|
597
|
+
generatedAt: new Date().toISOString(),
|
|
598
|
+
}, null, 2),
|
|
599
|
+
},
|
|
600
|
+
],
|
|
601
|
+
});
|
|
602
|
+
};
|
|
603
|
+
/**
|
|
604
|
+
* Handler for memory_bulk_delete tool
|
|
605
|
+
*/
|
|
606
|
+
export const handleMemoryBulkDelete = (args) => {
|
|
607
|
+
const keys = args.keys;
|
|
608
|
+
const namespace = args.namespace ?? 'default';
|
|
609
|
+
const prefix = args.prefix;
|
|
610
|
+
let deleted = 0;
|
|
611
|
+
let notFound = 0;
|
|
612
|
+
const deletedKeys = [];
|
|
613
|
+
if (keys !== undefined && keys.length > 0) {
|
|
614
|
+
for (const key of keys) {
|
|
615
|
+
const fullKey = `${namespace}:${key}`;
|
|
616
|
+
if (memoryStore.has(fullKey)) {
|
|
617
|
+
memoryStore.delete(fullKey);
|
|
618
|
+
deleted++;
|
|
619
|
+
deletedKeys.push(key);
|
|
620
|
+
}
|
|
621
|
+
else {
|
|
622
|
+
notFound++;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
else if (prefix !== undefined) {
|
|
627
|
+
const keysToDelete = [];
|
|
628
|
+
for (const [fullKey, stored] of memoryStore.entries()) {
|
|
629
|
+
const storedData = stored;
|
|
630
|
+
if (storedData.namespace !== namespace)
|
|
631
|
+
continue;
|
|
632
|
+
const keyPart = fullKey.split(':')[1] ?? fullKey;
|
|
633
|
+
if (keyPart.startsWith(prefix)) {
|
|
634
|
+
keysToDelete.push(fullKey);
|
|
635
|
+
deletedKeys.push(keyPart);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
for (const fullKey of keysToDelete) {
|
|
639
|
+
memoryStore.delete(fullKey);
|
|
640
|
+
deleted++;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
return Promise.resolve({
|
|
644
|
+
content: [
|
|
645
|
+
{
|
|
646
|
+
type: 'text',
|
|
647
|
+
text: JSON.stringify({
|
|
648
|
+
deleted,
|
|
649
|
+
notFound,
|
|
650
|
+
deletedKeys,
|
|
651
|
+
namespace,
|
|
652
|
+
deletedAt: new Date().toISOString(),
|
|
653
|
+
}, null, 2),
|
|
654
|
+
},
|
|
655
|
+
],
|
|
656
|
+
});
|
|
657
|
+
};
|
|
658
|
+
/**
|
|
659
|
+
* Handler for memory_clear tool
|
|
660
|
+
*/
|
|
661
|
+
export const handleMemoryClear = (args) => {
|
|
662
|
+
const namespace = args.namespace;
|
|
663
|
+
const confirm = args.confirm;
|
|
664
|
+
if (!confirm) {
|
|
665
|
+
return Promise.resolve({
|
|
666
|
+
content: [
|
|
667
|
+
{
|
|
668
|
+
type: 'text',
|
|
669
|
+
text: JSON.stringify({
|
|
670
|
+
error: 'CONFIRMATION_REQUIRED',
|
|
671
|
+
message: 'Set confirm=true to clear the namespace',
|
|
672
|
+
namespace,
|
|
673
|
+
}),
|
|
674
|
+
},
|
|
675
|
+
],
|
|
676
|
+
isError: true,
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
let cleared = 0;
|
|
680
|
+
const keysToDelete = [];
|
|
681
|
+
for (const [fullKey, stored] of memoryStore.entries()) {
|
|
682
|
+
const storedData = stored;
|
|
683
|
+
if (storedData.namespace === namespace) {
|
|
684
|
+
keysToDelete.push(fullKey);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
for (const fullKey of keysToDelete) {
|
|
688
|
+
memoryStore.delete(fullKey);
|
|
689
|
+
cleared++;
|
|
690
|
+
}
|
|
691
|
+
return Promise.resolve({
|
|
692
|
+
content: [
|
|
693
|
+
{
|
|
694
|
+
type: 'text',
|
|
695
|
+
text: JSON.stringify({
|
|
696
|
+
cleared,
|
|
697
|
+
namespace,
|
|
698
|
+
clearedAt: new Date().toISOString(),
|
|
699
|
+
}, null, 2),
|
|
700
|
+
},
|
|
701
|
+
],
|
|
702
|
+
});
|
|
703
|
+
};
|
|
704
|
+
//# sourceMappingURL=memory.js.map
|