@weave_protocol/mund 0.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.
Files changed (98) hide show
  1. package/dist/analyzers/code-analyzer.d.ts +24 -0
  2. package/dist/analyzers/code-analyzer.d.ts.map +1 -0
  3. package/dist/analyzers/code-analyzer.js +73 -0
  4. package/dist/analyzers/code-analyzer.js.map +1 -0
  5. package/dist/analyzers/exfiltration-detector.d.ts +40 -0
  6. package/dist/analyzers/exfiltration-detector.d.ts.map +1 -0
  7. package/dist/analyzers/exfiltration-detector.js +220 -0
  8. package/dist/analyzers/exfiltration-detector.js.map +1 -0
  9. package/dist/analyzers/index.d.ts +26 -0
  10. package/dist/analyzers/index.d.ts.map +1 -0
  11. package/dist/analyzers/index.js +61 -0
  12. package/dist/analyzers/index.js.map +1 -0
  13. package/dist/analyzers/injection-detector.d.ts +36 -0
  14. package/dist/analyzers/injection-detector.d.ts.map +1 -0
  15. package/dist/analyzers/injection-detector.js +165 -0
  16. package/dist/analyzers/injection-detector.js.map +1 -0
  17. package/dist/analyzers/pii-detector.d.ts +44 -0
  18. package/dist/analyzers/pii-detector.d.ts.map +1 -0
  19. package/dist/analyzers/pii-detector.js +190 -0
  20. package/dist/analyzers/pii-detector.js.map +1 -0
  21. package/dist/analyzers/secret-scanner.d.ts +32 -0
  22. package/dist/analyzers/secret-scanner.d.ts.map +1 -0
  23. package/dist/analyzers/secret-scanner.js +119 -0
  24. package/dist/analyzers/secret-scanner.js.map +1 -0
  25. package/dist/constants.d.ts +18 -0
  26. package/dist/constants.d.ts.map +1 -0
  27. package/dist/constants.js +580 -0
  28. package/dist/constants.js.map +1 -0
  29. package/dist/index.d.ts +9 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +242 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/notifications/email.d.ts +18 -0
  34. package/dist/notifications/email.d.ts.map +1 -0
  35. package/dist/notifications/email.js +192 -0
  36. package/dist/notifications/email.js.map +1 -0
  37. package/dist/notifications/index.d.ts +51 -0
  38. package/dist/notifications/index.d.ts.map +1 -0
  39. package/dist/notifications/index.js +107 -0
  40. package/dist/notifications/index.js.map +1 -0
  41. package/dist/notifications/slack.d.ts +17 -0
  42. package/dist/notifications/slack.d.ts.map +1 -0
  43. package/dist/notifications/slack.js +128 -0
  44. package/dist/notifications/slack.js.map +1 -0
  45. package/dist/notifications/teams.d.ts +17 -0
  46. package/dist/notifications/teams.d.ts.map +1 -0
  47. package/dist/notifications/teams.js +136 -0
  48. package/dist/notifications/teams.js.map +1 -0
  49. package/dist/notifications/webhook.d.ts +15 -0
  50. package/dist/notifications/webhook.d.ts.map +1 -0
  51. package/dist/notifications/webhook.js +67 -0
  52. package/dist/notifications/webhook.js.map +1 -0
  53. package/dist/storage/index.d.ts +11 -0
  54. package/dist/storage/index.d.ts.map +1 -0
  55. package/dist/storage/index.js +26 -0
  56. package/dist/storage/index.js.map +1 -0
  57. package/dist/storage/memory.d.ts +35 -0
  58. package/dist/storage/memory.d.ts.map +1 -0
  59. package/dist/storage/memory.js +144 -0
  60. package/dist/storage/memory.js.map +1 -0
  61. package/dist/tools/configuration.d.ts +8 -0
  62. package/dist/tools/configuration.d.ts.map +1 -0
  63. package/dist/tools/configuration.js +399 -0
  64. package/dist/tools/configuration.js.map +1 -0
  65. package/dist/tools/index.d.ts +15 -0
  66. package/dist/tools/index.d.ts.map +1 -0
  67. package/dist/tools/index.js +16 -0
  68. package/dist/tools/index.js.map +1 -0
  69. package/dist/tools/monitoring.d.ts +10 -0
  70. package/dist/tools/monitoring.d.ts.map +1 -0
  71. package/dist/tools/monitoring.js +476 -0
  72. package/dist/tools/monitoring.js.map +1 -0
  73. package/dist/types.d.ts +207 -0
  74. package/dist/types.d.ts.map +1 -0
  75. package/dist/types.js +6 -0
  76. package/dist/types.js.map +1 -0
  77. package/package.json +62 -0
  78. package/rules/default.yaml +189 -0
  79. package/src/analyzers/code-analyzer.ts +88 -0
  80. package/src/analyzers/exfiltration-detector.ts +257 -0
  81. package/src/analyzers/index.ts +74 -0
  82. package/src/analyzers/injection-detector.ts +191 -0
  83. package/src/analyzers/pii-detector.ts +220 -0
  84. package/src/analyzers/secret-scanner.ts +142 -0
  85. package/src/constants.ts +603 -0
  86. package/src/index.ts +285 -0
  87. package/src/notifications/email.ts +211 -0
  88. package/src/notifications/index.ts +136 -0
  89. package/src/notifications/slack.ts +170 -0
  90. package/src/notifications/teams.ts +200 -0
  91. package/src/notifications/webhook.ts +80 -0
  92. package/src/storage/index.ts +29 -0
  93. package/src/storage/memory.ts +181 -0
  94. package/src/tools/configuration.ts +478 -0
  95. package/src/tools/index.ts +29 -0
  96. package/src/tools/monitoring.ts +559 -0
  97. package/src/types.ts +300 -0
  98. package/tsconfig.json +24 -0
@@ -0,0 +1,478 @@
1
+ /**
2
+ * Mund - The Guardian Protocol
3
+ * Configuration & Response Tools - MCP tools for configuration and incident response
4
+ */
5
+
6
+ import { z } from 'zod';
7
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
8
+ import type {
9
+ IStorage,
10
+ DetectionRule,
11
+ DetectorType,
12
+ Severity,
13
+ ActionType
14
+ } from '../types.js';
15
+
16
+ // ============================================================================
17
+ // Input Schemas
18
+ // ============================================================================
19
+
20
+ const AddRuleInputSchema = z.object({
21
+ id: z.string()
22
+ .min(1, 'Rule ID is required')
23
+ .max(100, 'Rule ID too long')
24
+ .regex(/^[a-z0-9_]+$/, 'Rule ID must be lowercase alphanumeric with underscores')
25
+ .describe('Unique identifier for the rule'),
26
+ name: z.string()
27
+ .min(1, 'Rule name is required')
28
+ .max(200, 'Rule name too long')
29
+ .describe('Human-readable name for the rule'),
30
+ description: z.string().max(1000).optional()
31
+ .describe('Description of what this rule detects'),
32
+ type: z.enum(['secret', 'pii', 'code_pattern', 'injection', 'exfiltration'])
33
+ .describe('Type of detection'),
34
+ pattern: z.string()
35
+ .min(1, 'Pattern is required')
36
+ .describe('Regular expression pattern to match'),
37
+ severity: z.enum(['critical', 'high', 'medium', 'low', 'info'])
38
+ .describe('Severity level when this rule matches'),
39
+ action: z.enum(['alert', 'block', 'log', 'quarantine'])
40
+ .default('alert')
41
+ .describe('Action to take when rule matches')
42
+ }).strict();
43
+
44
+ const RemoveRuleInputSchema = z.object({
45
+ id: z.string()
46
+ .min(1, 'Rule ID is required')
47
+ .describe('ID of the rule to remove')
48
+ }).strict();
49
+
50
+ const ListRulesInputSchema = z.object({
51
+ type: z.enum(['secret', 'pii', 'code_pattern', 'injection', 'exfiltration', 'behavioral']).optional()
52
+ .describe('Filter rules by type'),
53
+ enabled_only: z.boolean().default(false)
54
+ .describe('Only show enabled rules')
55
+ }).strict();
56
+
57
+ const AcknowledgeAlertInputSchema = z.object({
58
+ event_id: z.string()
59
+ .min(1, 'Event ID is required')
60
+ .describe('ID of the event to acknowledge'),
61
+ acknowledged_by: z.string().optional()
62
+ .describe('Name or ID of person acknowledging')
63
+ }).strict();
64
+
65
+ const BlockPatternInputSchema = z.object({
66
+ pattern: z.string()
67
+ .min(1, 'Pattern is required')
68
+ .describe('Pattern to add to blocklist'),
69
+ type: z.enum(['secret', 'pii', 'code_pattern', 'injection', 'exfiltration'])
70
+ .describe('Type of pattern')
71
+ }).strict();
72
+
73
+ const AllowlistPatternInputSchema = z.object({
74
+ pattern: z.string()
75
+ .min(1, 'Pattern is required')
76
+ .describe('Pattern to add to allowlist'),
77
+ type: z.enum(['secret', 'pii', 'code_pattern', 'injection', 'exfiltration'])
78
+ .describe('Type of pattern')
79
+ }).strict();
80
+
81
+ const ConfigureNotificationInputSchema = z.object({
82
+ type: z.enum(['slack', 'teams', 'email', 'webhook'])
83
+ .describe('Type of notification channel'),
84
+ webhook_url: z.string().url().optional()
85
+ .describe('Webhook URL for Slack/Teams/generic webhook'),
86
+ min_severity: z.enum(['critical', 'high', 'medium', 'low', 'info']).optional()
87
+ .describe('Minimum severity to send notifications')
88
+ }).strict();
89
+
90
+ // ============================================================================
91
+ // Tool Registration
92
+ // ============================================================================
93
+
94
+ export function registerConfigurationTools(
95
+ server: McpServer,
96
+ storage: IStorage,
97
+ rules: DetectionRule[]
98
+ ): void {
99
+
100
+ // ============================================================================
101
+ // mund_add_rule - Add custom detection rule
102
+ // ============================================================================
103
+ server.registerTool(
104
+ 'mund_add_rule',
105
+ {
106
+ title: 'Add Detection Rule',
107
+ description: `Add a custom security detection rule.
108
+
109
+ Create custom rules to detect specific patterns in content. Rules use regular expressions
110
+ for pattern matching and can be configured with different severity levels and actions.
111
+
112
+ Args:
113
+ - id (string): Unique rule identifier (lowercase, alphanumeric, underscores)
114
+ - name (string): Human-readable rule name
115
+ - description (string): Optional description
116
+ - type: Detection type (secret, pii, code_pattern, injection, exfiltration)
117
+ - pattern (string): Regular expression to match
118
+ - severity: Severity level (critical, high, medium, low, info)
119
+ - action: Action to take (alert, block, log, quarantine)
120
+
121
+ Returns:
122
+ Confirmation of rule addition with rule details`,
123
+ inputSchema: AddRuleInputSchema,
124
+ annotations: {
125
+ readOnlyHint: false,
126
+ destructiveHint: false,
127
+ idempotentHint: true,
128
+ openWorldHint: false
129
+ }
130
+ },
131
+ async (params) => {
132
+ // Validate the regex pattern
133
+ try {
134
+ new RegExp(params.pattern);
135
+ } catch {
136
+ return {
137
+ content: [{ type: 'text', text: JSON.stringify({
138
+ success: false,
139
+ error: 'Invalid regular expression pattern'
140
+ }, null, 2) }]
141
+ };
142
+ }
143
+
144
+ // Check for duplicate ID
145
+ const existing = rules.find(r => r.id === params.id);
146
+ if (existing) {
147
+ return {
148
+ content: [{ type: 'text', text: JSON.stringify({
149
+ success: false,
150
+ error: `Rule with ID '${params.id}' already exists`
151
+ }, null, 2) }]
152
+ };
153
+ }
154
+
155
+ // Create the rule
156
+ const newRule: DetectionRule = {
157
+ id: params.id,
158
+ name: params.name,
159
+ description: params.description,
160
+ type: params.type as DetectorType,
161
+ pattern: params.pattern,
162
+ severity: params.severity as Severity,
163
+ action: params.action as ActionType,
164
+ enabled: true
165
+ };
166
+
167
+ // Add to rules array and storage
168
+ rules.push(newRule);
169
+ await storage.saveRule(newRule);
170
+
171
+ const response = {
172
+ success: true,
173
+ message: `Rule '${params.id}' added successfully`,
174
+ rule: newRule
175
+ };
176
+
177
+ return {
178
+ content: [{ type: 'text', text: JSON.stringify(response, null, 2) }],
179
+ structuredContent: response
180
+ };
181
+ }
182
+ );
183
+
184
+ // ============================================================================
185
+ // mund_remove_rule - Remove a detection rule
186
+ // ============================================================================
187
+ server.registerTool(
188
+ 'mund_remove_rule',
189
+ {
190
+ title: 'Remove Detection Rule',
191
+ description: `Remove a custom detection rule by ID.
192
+
193
+ Note: Built-in rules cannot be removed, only disabled.
194
+
195
+ Args:
196
+ - id (string): ID of the rule to remove
197
+
198
+ Returns:
199
+ Confirmation of rule removal`,
200
+ inputSchema: RemoveRuleInputSchema,
201
+ annotations: {
202
+ readOnlyHint: false,
203
+ destructiveHint: true,
204
+ idempotentHint: true,
205
+ openWorldHint: false
206
+ }
207
+ },
208
+ async (params) => {
209
+ const index = rules.findIndex(r => r.id === params.id);
210
+
211
+ if (index === -1) {
212
+ return {
213
+ content: [{ type: 'text', text: JSON.stringify({
214
+ success: false,
215
+ error: `Rule '${params.id}' not found`
216
+ }, null, 2) }]
217
+ };
218
+ }
219
+
220
+ // Remove from array and storage
221
+ rules.splice(index, 1);
222
+ await storage.deleteRule(params.id);
223
+
224
+ const response = {
225
+ success: true,
226
+ message: `Rule '${params.id}' removed successfully`
227
+ };
228
+
229
+ return {
230
+ content: [{ type: 'text', text: JSON.stringify(response, null, 2) }],
231
+ structuredContent: response
232
+ };
233
+ }
234
+ );
235
+
236
+ // ============================================================================
237
+ // mund_list_rules - List all active rules
238
+ // ============================================================================
239
+ server.registerTool(
240
+ 'mund_list_rules',
241
+ {
242
+ title: 'List Detection Rules',
243
+ description: `List all configured detection rules.
244
+
245
+ Args:
246
+ - type: Optional filter by detection type
247
+ - enabled_only: Only show enabled rules (default: false)
248
+
249
+ Returns:
250
+ Array of rule configurations`,
251
+ inputSchema: ListRulesInputSchema,
252
+ annotations: {
253
+ readOnlyHint: true,
254
+ destructiveHint: false,
255
+ idempotentHint: true,
256
+ openWorldHint: false
257
+ }
258
+ },
259
+ async (params) => {
260
+ let filteredRules = [...rules];
261
+
262
+ if (params.type) {
263
+ filteredRules = filteredRules.filter(r => r.type === params.type);
264
+ }
265
+
266
+ if (params.enabled_only) {
267
+ filteredRules = filteredRules.filter(r => r.enabled);
268
+ }
269
+
270
+ // Group by type
271
+ const grouped = filteredRules.reduce((acc, rule) => {
272
+ if (!acc[rule.type]) acc[rule.type] = [];
273
+ acc[rule.type].push({
274
+ id: rule.id,
275
+ name: rule.name,
276
+ severity: rule.severity,
277
+ action: rule.action,
278
+ enabled: rule.enabled
279
+ });
280
+ return acc;
281
+ }, {} as Record<string, Array<{ id: string; name: string; severity: Severity; action: ActionType; enabled: boolean }>>);
282
+
283
+ const response = {
284
+ total: filteredRules.length,
285
+ rules_by_type: grouped
286
+ };
287
+
288
+ return {
289
+ content: [{ type: 'text', text: JSON.stringify(response, null, 2) }],
290
+ structuredContent: response
291
+ };
292
+ }
293
+ );
294
+
295
+ // ============================================================================
296
+ // mund_acknowledge_alert - Mark alert as reviewed
297
+ // ============================================================================
298
+ server.registerTool(
299
+ 'mund_acknowledge_alert',
300
+ {
301
+ title: 'Acknowledge Security Alert',
302
+ description: `Mark a security event/alert as acknowledged.
303
+
304
+ Args:
305
+ - event_id (string): ID of the event to acknowledge
306
+ - acknowledged_by (string): Optional name/ID of acknowledger
307
+
308
+ Returns:
309
+ Confirmation of acknowledgment`,
310
+ inputSchema: AcknowledgeAlertInputSchema,
311
+ annotations: {
312
+ readOnlyHint: false,
313
+ destructiveHint: false,
314
+ idempotentHint: true,
315
+ openWorldHint: false
316
+ }
317
+ },
318
+ async (params) => {
319
+ const event = await storage.getEvent(params.event_id);
320
+
321
+ if (!event) {
322
+ return {
323
+ content: [{ type: 'text', text: JSON.stringify({
324
+ success: false,
325
+ error: `Event '${params.event_id}' not found`
326
+ }, null, 2) }]
327
+ };
328
+ }
329
+
330
+ await storage.acknowledgeEvent(params.event_id, params.acknowledged_by);
331
+
332
+ const response = {
333
+ success: true,
334
+ message: `Event '${params.event_id}' acknowledged`,
335
+ acknowledged_by: params.acknowledged_by,
336
+ acknowledged_at: new Date().toISOString()
337
+ };
338
+
339
+ return {
340
+ content: [{ type: 'text', text: JSON.stringify(response, null, 2) }],
341
+ structuredContent: response
342
+ };
343
+ }
344
+ );
345
+
346
+ // ============================================================================
347
+ // mund_block_pattern - Add pattern to blocklist
348
+ // ============================================================================
349
+ server.registerTool(
350
+ 'mund_block_pattern',
351
+ {
352
+ title: 'Block Pattern',
353
+ description: `Add a pattern to the blocklist.
354
+
355
+ Blocked patterns will always be flagged regardless of other rules.
356
+
357
+ Args:
358
+ - pattern (string): Pattern to block
359
+ - type: Type of pattern (secret, pii, code_pattern, injection, exfiltration)
360
+
361
+ Returns:
362
+ Confirmation of blocklist addition`,
363
+ inputSchema: BlockPatternInputSchema,
364
+ annotations: {
365
+ readOnlyHint: false,
366
+ destructiveHint: false,
367
+ idempotentHint: true,
368
+ openWorldHint: false
369
+ }
370
+ },
371
+ async (params) => {
372
+ await storage.addToBlocklist(params.pattern, params.type as DetectorType);
373
+
374
+ const response = {
375
+ success: true,
376
+ message: `Pattern added to blocklist`,
377
+ pattern: params.pattern,
378
+ type: params.type
379
+ };
380
+
381
+ return {
382
+ content: [{ type: 'text', text: JSON.stringify(response, null, 2) }],
383
+ structuredContent: response
384
+ };
385
+ }
386
+ );
387
+
388
+ // ============================================================================
389
+ // mund_allowlist_pattern - Add pattern to allowlist
390
+ // ============================================================================
391
+ server.registerTool(
392
+ 'mund_allowlist_pattern',
393
+ {
394
+ title: 'Allowlist Pattern',
395
+ description: `Add a pattern to the allowlist.
396
+
397
+ Allowlisted patterns will be ignored by detection rules.
398
+
399
+ Args:
400
+ - pattern (string): Pattern to allowlist
401
+ - type: Type of pattern
402
+
403
+ Returns:
404
+ Confirmation of allowlist addition`,
405
+ inputSchema: AllowlistPatternInputSchema,
406
+ annotations: {
407
+ readOnlyHint: false,
408
+ destructiveHint: false,
409
+ idempotentHint: true,
410
+ openWorldHint: false
411
+ }
412
+ },
413
+ async (params) => {
414
+ await storage.addToAllowlist(params.pattern, params.type as DetectorType);
415
+
416
+ const response = {
417
+ success: true,
418
+ message: `Pattern added to allowlist`,
419
+ pattern: params.pattern,
420
+ type: params.type
421
+ };
422
+
423
+ return {
424
+ content: [{ type: 'text', text: JSON.stringify(response, null, 2) }],
425
+ structuredContent: response
426
+ };
427
+ }
428
+ );
429
+
430
+ // ============================================================================
431
+ // mund_configure_notification - Set up notification channel
432
+ // ============================================================================
433
+ server.registerTool(
434
+ 'mund_configure_notification',
435
+ {
436
+ title: 'Configure Notification Channel',
437
+ description: `Configure a notification channel for security alerts.
438
+
439
+ Note: Full configuration requires environment variables. This tool can update
440
+ webhook URLs and minimum severity settings at runtime.
441
+
442
+ Args:
443
+ - type: Channel type (slack, teams, email, webhook)
444
+ - webhook_url: Webhook URL (for slack, teams, webhook)
445
+ - min_severity: Minimum severity to notify
446
+
447
+ Returns:
448
+ Confirmation of configuration`,
449
+ inputSchema: ConfigureNotificationInputSchema,
450
+ annotations: {
451
+ readOnlyHint: false,
452
+ destructiveHint: false,
453
+ idempotentHint: true,
454
+ openWorldHint: false
455
+ }
456
+ },
457
+ async (params) => {
458
+ // In a full implementation, this would update the NotificationHub
459
+ // For now, we'll return a message indicating the configuration was received
460
+
461
+ const response = {
462
+ success: true,
463
+ message: `Notification channel '${params.type}' configuration received`,
464
+ note: 'Full configuration requires setting environment variables and restarting the server',
465
+ config: {
466
+ type: params.type,
467
+ webhook_url: params.webhook_url ? '***configured***' : undefined,
468
+ min_severity: params.min_severity
469
+ }
470
+ };
471
+
472
+ return {
473
+ content: [{ type: 'text', text: JSON.stringify(response, null, 2) }],
474
+ structuredContent: response
475
+ };
476
+ }
477
+ );
478
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Mund - The Guardian Protocol
3
+ * Tools Index - Exports all MCP tools
4
+ */
5
+
6
+ export { registerMonitoringTools } from './monitoring.js';
7
+ export { registerConfigurationTools } from './configuration.js';
8
+
9
+ import { registerMonitoringTools } from './monitoring.js';
10
+ import { registerConfigurationTools } from './configuration.js';
11
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
12
+ import type { IStorage, DetectionRule } from '../types.js';
13
+ import { AnalyzerEngine } from '../analyzers/index.js';
14
+ import { NotificationHub } from '../notifications/index.js';
15
+
16
+ /**
17
+ * Register all Mund MCP tools
18
+ */
19
+ export function registerAllTools(
20
+ server: McpServer,
21
+ storage: IStorage,
22
+ rules: DetectionRule[],
23
+ analyzer: AnalyzerEngine,
24
+ notificationHub: NotificationHub,
25
+ blockMode: boolean
26
+ ): void {
27
+ registerMonitoringTools(server, storage, rules, analyzer, notificationHub, blockMode);
28
+ registerConfigurationTools(server, storage, rules);
29
+ }