sqlew 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/ARCHITECTURE.md +636 -0
- package/CHANGELOG.md +107 -0
- package/LICENSE +21 -0
- package/README.md +359 -0
- package/assets/schema.sql +320 -0
- package/assets/sqlew-logo.png +0 -0
- package/dist/constants.d.ts +146 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +230 -0
- package/dist/constants.js.map +1 -0
- package/dist/database.d.ts +94 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +214 -0
- package/dist/database.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +771 -0
- package/dist/index.js.map +1 -0
- package/dist/schema.d.ts +50 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +161 -0
- package/dist/schema.js.map +1 -0
- package/dist/tools/constraints.d.ts +29 -0
- package/dist/tools/constraints.d.ts.map +1 -0
- package/dist/tools/constraints.js +192 -0
- package/dist/tools/constraints.js.map +1 -0
- package/dist/tools/context.d.ts +56 -0
- package/dist/tools/context.d.ts.map +1 -0
- package/dist/tools/context.js +442 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/files.d.ts +30 -0
- package/dist/tools/files.d.ts.map +1 -0
- package/dist/tools/files.js +201 -0
- package/dist/tools/files.js.map +1 -0
- package/dist/tools/messaging.d.ts +50 -0
- package/dist/tools/messaging.d.ts.map +1 -0
- package/dist/tools/messaging.js +151 -0
- package/dist/tools/messaging.js.map +1 -0
- package/dist/tools/utils.d.ts +29 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +131 -0
- package/dist/tools/utils.js.map +1 -0
- package/dist/types.d.ts +388 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +50 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,771 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MCP Shared Context Server - Entry Point
|
|
4
|
+
* Provides context management tools via Model Context Protocol
|
|
5
|
+
*/
|
|
6
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
7
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
8
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
9
|
+
import { initializeDatabase, closeDatabase } from './database.js';
|
|
10
|
+
import { setDecision, getContext, getDecision, searchByTags, getVersions, searchByLayer } from './tools/context.js';
|
|
11
|
+
import { sendMessage, getMessages, markRead } from './tools/messaging.js';
|
|
12
|
+
import { recordFileChange, getFileChanges, checkFileLock } from './tools/files.js';
|
|
13
|
+
import { addConstraint, getConstraints, deactivateConstraint } from './tools/constraints.js';
|
|
14
|
+
import { getLayerSummary, clearOldData, getStats } from './tools/utils.js';
|
|
15
|
+
// Parse command-line arguments for database path
|
|
16
|
+
const args = process.argv.slice(2);
|
|
17
|
+
const dbPath = args.length > 0 ? args[0] : undefined;
|
|
18
|
+
// Initialize database
|
|
19
|
+
let db;
|
|
20
|
+
try {
|
|
21
|
+
db = initializeDatabase(dbPath);
|
|
22
|
+
console.error('✓ MCP Shared Context Server initialized');
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
console.error('✗ Failed to initialize database:', error);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
// Create MCP server
|
|
29
|
+
const server = new Server({
|
|
30
|
+
name: 'mcp-sklew',
|
|
31
|
+
version: '1.0.0',
|
|
32
|
+
}, {
|
|
33
|
+
capabilities: {
|
|
34
|
+
tools: {},
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
// Handle tool listing
|
|
38
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
39
|
+
return {
|
|
40
|
+
tools: [
|
|
41
|
+
{
|
|
42
|
+
name: 'set_decision',
|
|
43
|
+
description: 'Set or update a decision in the shared context. Auto-detects numeric vs string values. Supports tags, layers, scopes, and version tracking.',
|
|
44
|
+
inputSchema: {
|
|
45
|
+
type: 'object',
|
|
46
|
+
properties: {
|
|
47
|
+
key: {
|
|
48
|
+
type: 'string',
|
|
49
|
+
description: 'Unique key for the decision (e.g., "auth_method", "max_connections")',
|
|
50
|
+
},
|
|
51
|
+
value: {
|
|
52
|
+
type: ['string', 'number'],
|
|
53
|
+
description: 'Decision value (string or numeric). Numeric values are stored in optimized table.',
|
|
54
|
+
},
|
|
55
|
+
agent: {
|
|
56
|
+
type: 'string',
|
|
57
|
+
description: 'Name of the agent making the decision (defaults to "system")',
|
|
58
|
+
},
|
|
59
|
+
layer: {
|
|
60
|
+
type: 'string',
|
|
61
|
+
description: 'Architecture layer (presentation, business, data, infrastructure, cross-cutting)',
|
|
62
|
+
enum: ['presentation', 'business', 'data', 'infrastructure', 'cross-cutting'],
|
|
63
|
+
},
|
|
64
|
+
version: {
|
|
65
|
+
type: 'string',
|
|
66
|
+
description: 'Version identifier (defaults to "1.0.0"). Used for change tracking.',
|
|
67
|
+
},
|
|
68
|
+
status: {
|
|
69
|
+
type: 'string',
|
|
70
|
+
description: 'Decision status (defaults to "active")',
|
|
71
|
+
enum: ['active', 'deprecated', 'draft'],
|
|
72
|
+
},
|
|
73
|
+
tags: {
|
|
74
|
+
type: 'array',
|
|
75
|
+
items: { type: 'string' },
|
|
76
|
+
description: 'Tags for categorization (e.g., ["authentication", "security"])',
|
|
77
|
+
},
|
|
78
|
+
scopes: {
|
|
79
|
+
type: 'array',
|
|
80
|
+
items: { type: 'string' },
|
|
81
|
+
description: 'Module or component scopes (e.g., ["user-service", "api"])',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
required: ['key', 'value'],
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: 'get_context',
|
|
89
|
+
description: 'Retrieve decisions with advanced filtering. Returns token-efficient view with all metadata. Supports filtering by status, layer, tags, and scope.',
|
|
90
|
+
inputSchema: {
|
|
91
|
+
type: 'object',
|
|
92
|
+
properties: {
|
|
93
|
+
status: {
|
|
94
|
+
type: 'string',
|
|
95
|
+
description: 'Filter by decision status',
|
|
96
|
+
enum: ['active', 'deprecated', 'draft'],
|
|
97
|
+
},
|
|
98
|
+
layer: {
|
|
99
|
+
type: 'string',
|
|
100
|
+
description: 'Filter by architecture layer',
|
|
101
|
+
enum: ['presentation', 'business', 'data', 'infrastructure', 'cross-cutting'],
|
|
102
|
+
},
|
|
103
|
+
tags: {
|
|
104
|
+
type: 'array',
|
|
105
|
+
items: { type: 'string' },
|
|
106
|
+
description: 'Filter by tags (use tag_match to control AND/OR logic)',
|
|
107
|
+
},
|
|
108
|
+
scope: {
|
|
109
|
+
type: 'string',
|
|
110
|
+
description: 'Filter by specific scope/module',
|
|
111
|
+
},
|
|
112
|
+
tag_match: {
|
|
113
|
+
type: 'string',
|
|
114
|
+
description: 'Tag matching mode: "AND" (all tags required) or "OR" (any tag)',
|
|
115
|
+
enum: ['AND', 'OR'],
|
|
116
|
+
default: 'OR',
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: 'get_decision',
|
|
123
|
+
description: 'Get a specific decision by key. Returns full metadata including tags, layer, scopes, version, and timestamp.',
|
|
124
|
+
inputSchema: {
|
|
125
|
+
type: 'object',
|
|
126
|
+
properties: {
|
|
127
|
+
key: {
|
|
128
|
+
type: 'string',
|
|
129
|
+
description: 'Decision key to retrieve',
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
required: ['key'],
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: 'search_by_tags',
|
|
137
|
+
description: 'Search for decisions by tags with AND/OR logic. Supports flexible tag-based filtering with optional status and layer filters.',
|
|
138
|
+
inputSchema: {
|
|
139
|
+
type: 'object',
|
|
140
|
+
properties: {
|
|
141
|
+
tags: {
|
|
142
|
+
type: 'array',
|
|
143
|
+
items: { type: 'string' },
|
|
144
|
+
description: 'Array of tags to search for (at least one required)',
|
|
145
|
+
},
|
|
146
|
+
match_mode: {
|
|
147
|
+
type: 'string',
|
|
148
|
+
description: 'Tag matching mode: "AND" (all tags required) or "OR" (any tag)',
|
|
149
|
+
enum: ['AND', 'OR'],
|
|
150
|
+
default: 'OR',
|
|
151
|
+
},
|
|
152
|
+
status: {
|
|
153
|
+
type: 'string',
|
|
154
|
+
description: 'Optional filter by decision status',
|
|
155
|
+
enum: ['active', 'deprecated', 'draft'],
|
|
156
|
+
},
|
|
157
|
+
layer: {
|
|
158
|
+
type: 'string',
|
|
159
|
+
description: 'Optional filter by architecture layer',
|
|
160
|
+
enum: ['presentation', 'business', 'data', 'infrastructure', 'cross-cutting'],
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
required: ['tags'],
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: 'get_versions',
|
|
168
|
+
description: 'Get version history for a specific decision key. Returns all historical versions ordered by timestamp (newest first).',
|
|
169
|
+
inputSchema: {
|
|
170
|
+
type: 'object',
|
|
171
|
+
properties: {
|
|
172
|
+
key: {
|
|
173
|
+
type: 'string',
|
|
174
|
+
description: 'Decision key to get version history for',
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
required: ['key'],
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: 'search_by_layer',
|
|
182
|
+
description: 'Search for decisions within a specific architecture layer. Supports status filtering and optional tag inclusion.',
|
|
183
|
+
inputSchema: {
|
|
184
|
+
type: 'object',
|
|
185
|
+
properties: {
|
|
186
|
+
layer: {
|
|
187
|
+
type: 'string',
|
|
188
|
+
description: 'Architecture layer to search in',
|
|
189
|
+
enum: ['presentation', 'business', 'data', 'infrastructure', 'cross-cutting'],
|
|
190
|
+
},
|
|
191
|
+
status: {
|
|
192
|
+
type: 'string',
|
|
193
|
+
description: 'Filter by decision status (defaults to "active")',
|
|
194
|
+
enum: ['active', 'deprecated', 'draft'],
|
|
195
|
+
default: 'active',
|
|
196
|
+
},
|
|
197
|
+
include_tags: {
|
|
198
|
+
type: 'boolean',
|
|
199
|
+
description: 'Include tag information in results (defaults to true)',
|
|
200
|
+
default: true,
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
required: ['layer'],
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
name: 'send_message',
|
|
208
|
+
description: 'Send a message from one agent to another (or broadcast to all). Supports priority levels and optional JSON payload.',
|
|
209
|
+
inputSchema: {
|
|
210
|
+
type: 'object',
|
|
211
|
+
properties: {
|
|
212
|
+
from_agent: {
|
|
213
|
+
type: 'string',
|
|
214
|
+
description: 'Name of the sending agent',
|
|
215
|
+
},
|
|
216
|
+
to_agent: {
|
|
217
|
+
type: ['string', 'null'],
|
|
218
|
+
description: 'Name of the receiving agent (null or omit for broadcast)',
|
|
219
|
+
},
|
|
220
|
+
msg_type: {
|
|
221
|
+
type: 'string',
|
|
222
|
+
description: 'Type of message',
|
|
223
|
+
enum: ['decision', 'warning', 'request', 'info'],
|
|
224
|
+
},
|
|
225
|
+
message: {
|
|
226
|
+
type: 'string',
|
|
227
|
+
description: 'The message content',
|
|
228
|
+
},
|
|
229
|
+
priority: {
|
|
230
|
+
type: 'string',
|
|
231
|
+
description: 'Message priority level (defaults to "medium")',
|
|
232
|
+
enum: ['low', 'medium', 'high', 'critical'],
|
|
233
|
+
default: 'medium',
|
|
234
|
+
},
|
|
235
|
+
payload: {
|
|
236
|
+
type: 'object',
|
|
237
|
+
description: 'Optional JSON payload with additional data',
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
required: ['from_agent', 'msg_type', 'message'],
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
name: 'get_messages',
|
|
245
|
+
description: 'Retrieve messages for an agent. Returns messages addressed to the agent or broadcast messages. Supports filtering by read status, priority, and message type.',
|
|
246
|
+
inputSchema: {
|
|
247
|
+
type: 'object',
|
|
248
|
+
properties: {
|
|
249
|
+
agent_name: {
|
|
250
|
+
type: 'string',
|
|
251
|
+
description: 'Name of the agent to retrieve messages for',
|
|
252
|
+
},
|
|
253
|
+
unread_only: {
|
|
254
|
+
type: 'boolean',
|
|
255
|
+
description: 'Only return unread messages (defaults to false)',
|
|
256
|
+
default: false,
|
|
257
|
+
},
|
|
258
|
+
priority_filter: {
|
|
259
|
+
type: 'string',
|
|
260
|
+
description: 'Filter by specific priority level',
|
|
261
|
+
enum: ['low', 'medium', 'high', 'critical'],
|
|
262
|
+
},
|
|
263
|
+
msg_type_filter: {
|
|
264
|
+
type: 'string',
|
|
265
|
+
description: 'Filter by message type',
|
|
266
|
+
enum: ['decision', 'warning', 'request', 'info'],
|
|
267
|
+
},
|
|
268
|
+
limit: {
|
|
269
|
+
type: 'number',
|
|
270
|
+
description: 'Maximum number of messages to return (defaults to 50)',
|
|
271
|
+
default: 50,
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
required: ['agent_name'],
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
name: 'mark_read',
|
|
279
|
+
description: 'Mark messages as read. Only marks messages addressed to the specified agent (security check). Idempotent operation.',
|
|
280
|
+
inputSchema: {
|
|
281
|
+
type: 'object',
|
|
282
|
+
properties: {
|
|
283
|
+
message_ids: {
|
|
284
|
+
type: 'array',
|
|
285
|
+
items: { type: 'number' },
|
|
286
|
+
description: 'Array of message IDs to mark as read',
|
|
287
|
+
},
|
|
288
|
+
agent_name: {
|
|
289
|
+
type: 'string',
|
|
290
|
+
description: 'Name of the agent marking messages as read',
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
required: ['message_ids', 'agent_name'],
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
name: 'record_file_change',
|
|
298
|
+
description: 'Record a file change with optional layer assignment and description. Auto-registers the file and agent. Useful for tracking file modifications across agents.',
|
|
299
|
+
inputSchema: {
|
|
300
|
+
type: 'object',
|
|
301
|
+
properties: {
|
|
302
|
+
file_path: {
|
|
303
|
+
type: 'string',
|
|
304
|
+
description: 'The file path (absolute or relative)',
|
|
305
|
+
},
|
|
306
|
+
agent_name: {
|
|
307
|
+
type: 'string',
|
|
308
|
+
description: 'Name of the agent making the change',
|
|
309
|
+
},
|
|
310
|
+
change_type: {
|
|
311
|
+
type: 'string',
|
|
312
|
+
description: 'Type of change made to the file',
|
|
313
|
+
enum: ['created', 'modified', 'deleted'],
|
|
314
|
+
},
|
|
315
|
+
layer: {
|
|
316
|
+
type: 'string',
|
|
317
|
+
description: 'Optional architecture layer assignment',
|
|
318
|
+
enum: ['presentation', 'business', 'data', 'infrastructure', 'cross-cutting'],
|
|
319
|
+
},
|
|
320
|
+
description: {
|
|
321
|
+
type: 'string',
|
|
322
|
+
description: 'Optional description of the change',
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
required: ['file_path', 'agent_name', 'change_type'],
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
name: 'get_file_changes',
|
|
330
|
+
description: 'Retrieve file changes with advanced filtering. Supports filtering by file, agent, layer, change type, and time range. Returns token-efficient view when no filters applied.',
|
|
331
|
+
inputSchema: {
|
|
332
|
+
type: 'object',
|
|
333
|
+
properties: {
|
|
334
|
+
file_path: {
|
|
335
|
+
type: 'string',
|
|
336
|
+
description: 'Filter by specific file path',
|
|
337
|
+
},
|
|
338
|
+
agent_name: {
|
|
339
|
+
type: 'string',
|
|
340
|
+
description: 'Filter by agent who made the change',
|
|
341
|
+
},
|
|
342
|
+
layer: {
|
|
343
|
+
type: 'string',
|
|
344
|
+
description: 'Filter by architecture layer',
|
|
345
|
+
enum: ['presentation', 'business', 'data', 'infrastructure', 'cross-cutting'],
|
|
346
|
+
},
|
|
347
|
+
change_type: {
|
|
348
|
+
type: 'string',
|
|
349
|
+
description: 'Filter by type of change',
|
|
350
|
+
enum: ['created', 'modified', 'deleted'],
|
|
351
|
+
},
|
|
352
|
+
since: {
|
|
353
|
+
type: 'string',
|
|
354
|
+
description: 'ISO 8601 timestamp - return changes since this time',
|
|
355
|
+
},
|
|
356
|
+
limit: {
|
|
357
|
+
type: 'number',
|
|
358
|
+
description: 'Maximum number of changes to return (default: 100)',
|
|
359
|
+
default: 100,
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
name: 'check_file_lock',
|
|
366
|
+
description: 'Check if a file is "locked" (recently modified). Useful to prevent concurrent edits by multiple agents. Returns lock status with details of last change.',
|
|
367
|
+
inputSchema: {
|
|
368
|
+
type: 'object',
|
|
369
|
+
properties: {
|
|
370
|
+
file_path: {
|
|
371
|
+
type: 'string',
|
|
372
|
+
description: 'The file path to check',
|
|
373
|
+
},
|
|
374
|
+
lock_duration: {
|
|
375
|
+
type: 'number',
|
|
376
|
+
description: 'Time window in seconds to consider "locked" (default: 300 = 5 minutes)',
|
|
377
|
+
default: 300,
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
required: ['file_path'],
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
name: 'add_constraint',
|
|
385
|
+
description: 'Add a constraint with priority level, optional layer assignment, and tags. Categories: performance, architecture, security. Auto-registers category and agent.',
|
|
386
|
+
inputSchema: {
|
|
387
|
+
type: 'object',
|
|
388
|
+
properties: {
|
|
389
|
+
category: {
|
|
390
|
+
type: 'string',
|
|
391
|
+
description: 'Constraint category',
|
|
392
|
+
enum: ['performance', 'architecture', 'security'],
|
|
393
|
+
},
|
|
394
|
+
constraint_text: {
|
|
395
|
+
type: 'string',
|
|
396
|
+
description: 'The constraint description/requirement',
|
|
397
|
+
},
|
|
398
|
+
priority: {
|
|
399
|
+
type: 'string',
|
|
400
|
+
description: 'Priority level (defaults to "medium")',
|
|
401
|
+
enum: ['low', 'medium', 'high', 'critical'],
|
|
402
|
+
default: 'medium',
|
|
403
|
+
},
|
|
404
|
+
layer: {
|
|
405
|
+
type: 'string',
|
|
406
|
+
description: 'Optional architecture layer assignment',
|
|
407
|
+
enum: ['presentation', 'business', 'data', 'infrastructure', 'cross-cutting'],
|
|
408
|
+
},
|
|
409
|
+
tags: {
|
|
410
|
+
type: 'array',
|
|
411
|
+
items: { type: 'string' },
|
|
412
|
+
description: 'Optional tags for categorization (e.g., ["api", "security"])',
|
|
413
|
+
},
|
|
414
|
+
created_by: {
|
|
415
|
+
type: 'string',
|
|
416
|
+
description: 'Agent creating the constraint (defaults to "system")',
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
required: ['category', 'constraint_text'],
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
name: 'get_constraints',
|
|
424
|
+
description: 'Retrieve constraints with advanced filtering. Supports filtering by category, layer, priority, tags, and active status. Uses token-efficient view with all metadata.',
|
|
425
|
+
inputSchema: {
|
|
426
|
+
type: 'object',
|
|
427
|
+
properties: {
|
|
428
|
+
category: {
|
|
429
|
+
type: 'string',
|
|
430
|
+
description: 'Filter by constraint category',
|
|
431
|
+
enum: ['performance', 'architecture', 'security'],
|
|
432
|
+
},
|
|
433
|
+
layer: {
|
|
434
|
+
type: 'string',
|
|
435
|
+
description: 'Filter by architecture layer',
|
|
436
|
+
enum: ['presentation', 'business', 'data', 'infrastructure', 'cross-cutting'],
|
|
437
|
+
},
|
|
438
|
+
priority: {
|
|
439
|
+
type: 'string',
|
|
440
|
+
description: 'Filter by priority level',
|
|
441
|
+
enum: ['low', 'medium', 'high', 'critical'],
|
|
442
|
+
},
|
|
443
|
+
tags: {
|
|
444
|
+
type: 'array',
|
|
445
|
+
items: { type: 'string' },
|
|
446
|
+
description: 'Filter by tags (OR logic - matches ANY tag)',
|
|
447
|
+
},
|
|
448
|
+
active_only: {
|
|
449
|
+
type: 'boolean',
|
|
450
|
+
description: 'Only return active constraints (defaults to true)',
|
|
451
|
+
default: true,
|
|
452
|
+
},
|
|
453
|
+
limit: {
|
|
454
|
+
type: 'number',
|
|
455
|
+
description: 'Maximum number of constraints to return (default: 50)',
|
|
456
|
+
default: 50,
|
|
457
|
+
},
|
|
458
|
+
},
|
|
459
|
+
},
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
name: 'deactivate_constraint',
|
|
463
|
+
description: 'Deactivate a constraint (soft delete). Idempotent - deactivating already-inactive constraint is safe. Constraints are never removed from database.',
|
|
464
|
+
inputSchema: {
|
|
465
|
+
type: 'object',
|
|
466
|
+
properties: {
|
|
467
|
+
constraint_id: {
|
|
468
|
+
type: 'number',
|
|
469
|
+
description: 'The constraint ID to deactivate',
|
|
470
|
+
},
|
|
471
|
+
},
|
|
472
|
+
required: ['constraint_id'],
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
name: 'get_layer_summary',
|
|
477
|
+
description: 'Get summary statistics for all architecture layers. Returns decision counts, recent file changes (last 1 hour), and active constraints per layer.',
|
|
478
|
+
inputSchema: {
|
|
479
|
+
type: 'object',
|
|
480
|
+
properties: {},
|
|
481
|
+
},
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
name: 'clear_old_data',
|
|
485
|
+
description: 'Manually clear old data from the database. Deletes messages older than specified hours and file changes older than specified days. Transaction-safe operation that returns counts of deleted records.',
|
|
486
|
+
inputSchema: {
|
|
487
|
+
type: 'object',
|
|
488
|
+
properties: {
|
|
489
|
+
messages_older_than_hours: {
|
|
490
|
+
type: 'number',
|
|
491
|
+
description: 'Delete messages older than this many hours (default: 24)',
|
|
492
|
+
default: 24,
|
|
493
|
+
},
|
|
494
|
+
file_changes_older_than_days: {
|
|
495
|
+
type: 'number',
|
|
496
|
+
description: 'Delete file changes older than this many days (default: 7)',
|
|
497
|
+
default: 7,
|
|
498
|
+
},
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
name: 'get_stats',
|
|
504
|
+
description: 'Get comprehensive database statistics including counts for all major tables, active vs total records for decisions and constraints, and overall database health metrics.',
|
|
505
|
+
inputSchema: {
|
|
506
|
+
type: 'object',
|
|
507
|
+
properties: {},
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
],
|
|
511
|
+
};
|
|
512
|
+
});
|
|
513
|
+
// Handle tool execution
|
|
514
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
515
|
+
const { name, arguments: args } = request.params;
|
|
516
|
+
try {
|
|
517
|
+
switch (name) {
|
|
518
|
+
case 'set_decision': {
|
|
519
|
+
const params = args;
|
|
520
|
+
const result = setDecision(params);
|
|
521
|
+
return {
|
|
522
|
+
content: [
|
|
523
|
+
{
|
|
524
|
+
type: 'text',
|
|
525
|
+
text: JSON.stringify(result, null, 2),
|
|
526
|
+
},
|
|
527
|
+
],
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
case 'get_context': {
|
|
531
|
+
const params = args;
|
|
532
|
+
const result = getContext(params);
|
|
533
|
+
return {
|
|
534
|
+
content: [
|
|
535
|
+
{
|
|
536
|
+
type: 'text',
|
|
537
|
+
text: JSON.stringify(result, null, 2),
|
|
538
|
+
},
|
|
539
|
+
],
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
case 'get_decision': {
|
|
543
|
+
const params = args;
|
|
544
|
+
const result = getDecision(params);
|
|
545
|
+
return {
|
|
546
|
+
content: [
|
|
547
|
+
{
|
|
548
|
+
type: 'text',
|
|
549
|
+
text: JSON.stringify(result, null, 2),
|
|
550
|
+
},
|
|
551
|
+
],
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
case 'search_by_tags': {
|
|
555
|
+
const params = args;
|
|
556
|
+
const result = searchByTags(params);
|
|
557
|
+
return {
|
|
558
|
+
content: [
|
|
559
|
+
{
|
|
560
|
+
type: 'text',
|
|
561
|
+
text: JSON.stringify(result, null, 2),
|
|
562
|
+
},
|
|
563
|
+
],
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
case 'get_versions': {
|
|
567
|
+
const params = args;
|
|
568
|
+
const result = getVersions(params);
|
|
569
|
+
return {
|
|
570
|
+
content: [
|
|
571
|
+
{
|
|
572
|
+
type: 'text',
|
|
573
|
+
text: JSON.stringify(result, null, 2),
|
|
574
|
+
},
|
|
575
|
+
],
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
case 'search_by_layer': {
|
|
579
|
+
const params = args;
|
|
580
|
+
const result = searchByLayer(params);
|
|
581
|
+
return {
|
|
582
|
+
content: [
|
|
583
|
+
{
|
|
584
|
+
type: 'text',
|
|
585
|
+
text: JSON.stringify(result, null, 2),
|
|
586
|
+
},
|
|
587
|
+
],
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
case 'send_message': {
|
|
591
|
+
const params = args;
|
|
592
|
+
const result = sendMessage(params);
|
|
593
|
+
return {
|
|
594
|
+
content: [
|
|
595
|
+
{
|
|
596
|
+
type: 'text',
|
|
597
|
+
text: JSON.stringify(result, null, 2),
|
|
598
|
+
},
|
|
599
|
+
],
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
case 'get_messages': {
|
|
603
|
+
const params = args;
|
|
604
|
+
const result = getMessages(params);
|
|
605
|
+
return {
|
|
606
|
+
content: [
|
|
607
|
+
{
|
|
608
|
+
type: 'text',
|
|
609
|
+
text: JSON.stringify(result, null, 2),
|
|
610
|
+
},
|
|
611
|
+
],
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
case 'mark_read': {
|
|
615
|
+
const params = args;
|
|
616
|
+
const result = markRead(params);
|
|
617
|
+
return {
|
|
618
|
+
content: [
|
|
619
|
+
{
|
|
620
|
+
type: 'text',
|
|
621
|
+
text: JSON.stringify(result, null, 2),
|
|
622
|
+
},
|
|
623
|
+
],
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
case 'record_file_change': {
|
|
627
|
+
const params = args;
|
|
628
|
+
const result = recordFileChange(params);
|
|
629
|
+
return {
|
|
630
|
+
content: [
|
|
631
|
+
{
|
|
632
|
+
type: 'text',
|
|
633
|
+
text: JSON.stringify(result, null, 2),
|
|
634
|
+
},
|
|
635
|
+
],
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
case 'get_file_changes': {
|
|
639
|
+
const params = args;
|
|
640
|
+
const result = getFileChanges(params);
|
|
641
|
+
return {
|
|
642
|
+
content: [
|
|
643
|
+
{
|
|
644
|
+
type: 'text',
|
|
645
|
+
text: JSON.stringify(result, null, 2),
|
|
646
|
+
},
|
|
647
|
+
],
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
case 'check_file_lock': {
|
|
651
|
+
const params = args;
|
|
652
|
+
const result = checkFileLock(params);
|
|
653
|
+
return {
|
|
654
|
+
content: [
|
|
655
|
+
{
|
|
656
|
+
type: 'text',
|
|
657
|
+
text: JSON.stringify(result, null, 2),
|
|
658
|
+
},
|
|
659
|
+
],
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
case 'add_constraint': {
|
|
663
|
+
const params = args;
|
|
664
|
+
const result = addConstraint(params);
|
|
665
|
+
return {
|
|
666
|
+
content: [
|
|
667
|
+
{
|
|
668
|
+
type: 'text',
|
|
669
|
+
text: JSON.stringify(result, null, 2),
|
|
670
|
+
},
|
|
671
|
+
],
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
case 'get_constraints': {
|
|
675
|
+
const params = args;
|
|
676
|
+
const result = getConstraints(params);
|
|
677
|
+
return {
|
|
678
|
+
content: [
|
|
679
|
+
{
|
|
680
|
+
type: 'text',
|
|
681
|
+
text: JSON.stringify(result, null, 2),
|
|
682
|
+
},
|
|
683
|
+
],
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
case 'deactivate_constraint': {
|
|
687
|
+
const params = args;
|
|
688
|
+
const result = deactivateConstraint(params);
|
|
689
|
+
return {
|
|
690
|
+
content: [
|
|
691
|
+
{
|
|
692
|
+
type: 'text',
|
|
693
|
+
text: JSON.stringify(result, null, 2),
|
|
694
|
+
},
|
|
695
|
+
],
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
case 'get_layer_summary': {
|
|
699
|
+
const result = getLayerSummary();
|
|
700
|
+
return {
|
|
701
|
+
content: [
|
|
702
|
+
{
|
|
703
|
+
type: 'text',
|
|
704
|
+
text: JSON.stringify(result, null, 2),
|
|
705
|
+
},
|
|
706
|
+
],
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
case 'clear_old_data': {
|
|
710
|
+
const params = args;
|
|
711
|
+
const result = clearOldData(params);
|
|
712
|
+
return {
|
|
713
|
+
content: [
|
|
714
|
+
{
|
|
715
|
+
type: 'text',
|
|
716
|
+
text: JSON.stringify(result, null, 2),
|
|
717
|
+
},
|
|
718
|
+
],
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
case 'get_stats': {
|
|
722
|
+
const result = getStats();
|
|
723
|
+
return {
|
|
724
|
+
content: [
|
|
725
|
+
{
|
|
726
|
+
type: 'text',
|
|
727
|
+
text: JSON.stringify(result, null, 2),
|
|
728
|
+
},
|
|
729
|
+
],
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
default:
|
|
733
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
catch (error) {
|
|
737
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
738
|
+
return {
|
|
739
|
+
content: [
|
|
740
|
+
{
|
|
741
|
+
type: 'text',
|
|
742
|
+
text: JSON.stringify({ error: message }, null, 2),
|
|
743
|
+
},
|
|
744
|
+
],
|
|
745
|
+
isError: true,
|
|
746
|
+
};
|
|
747
|
+
}
|
|
748
|
+
});
|
|
749
|
+
// Handle graceful shutdown
|
|
750
|
+
process.on('SIGINT', () => {
|
|
751
|
+
console.error('\n✓ Shutting down MCP server...');
|
|
752
|
+
closeDatabase();
|
|
753
|
+
process.exit(0);
|
|
754
|
+
});
|
|
755
|
+
process.on('SIGTERM', () => {
|
|
756
|
+
console.error('\n✓ Shutting down MCP server...');
|
|
757
|
+
closeDatabase();
|
|
758
|
+
process.exit(0);
|
|
759
|
+
});
|
|
760
|
+
// Start server with stdio transport
|
|
761
|
+
async function main() {
|
|
762
|
+
const transport = new StdioServerTransport();
|
|
763
|
+
await server.connect(transport);
|
|
764
|
+
console.error('✓ MCP Shared Context Server running on stdio');
|
|
765
|
+
}
|
|
766
|
+
main().catch((error) => {
|
|
767
|
+
console.error('✗ Fatal error:', error);
|
|
768
|
+
closeDatabase();
|
|
769
|
+
process.exit(1);
|
|
770
|
+
});
|
|
771
|
+
//# sourceMappingURL=index.js.map
|