@weave_protocol/mund 0.4.0 → 0.4.2

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/src/index.ts CHANGED
@@ -1,394 +1,22 @@
1
- #!/usr/bin/env node
2
1
  /**
3
- * Mund - The Guardian Protocol
4
- * Main Entry Point
2
+ * @weave_protocol/mund: library entry point.
3
+ * The MCP server lives in server.ts (bin).
5
4
  */
6
5
 
7
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
8
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
9
- import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
10
- import express from 'express';
11
-
12
- import type { MundConfig, DetectionRule } from './types.js';
13
- import { DEFAULT_CONFIG, DEFAULT_RULES } from './constants.js';
14
- import { createStorage } from './storage/index.js';
15
- import { AnalyzerEngine } from './analyzers/index.js';
16
- import { NotificationHub } from './notifications/index.js';
17
- import { registerAllTools } from './tools/index.js';
18
- import { runScanCli } from './cli/scan.js';
19
- import { runAgentAuditCli, runCheckSkillCli } from './cli/agent.js';
20
- import { getVersion } from './version.js';
21
- import { loadCanariesFromEnv } from './canary.js';
22
-
23
- // Threat Intelligence imports
24
- import { threatIntel } from './threat-intel-manager.js';
25
- import {
26
- threatIntelTools,
27
- createThreatIntelToolHandlers,
28
- UpdateThreatIntelSchema,
29
- ListIntelSourcesSchema,
30
- IntelStatusSchema,
31
- AddIntelSourceSchema,
32
- RemoveIntelSourceSchema,
33
- ThreatScanSchema,
34
- ListPatternsSchema,
35
- TogglePatternSchema,
36
- } from './threat-intel-tools.js';
37
-
38
- // ============================================================================
39
- // Configuration Loading
40
- // ============================================================================
41
-
42
- function loadConfig(): MundConfig {
43
- const config: MundConfig = {
44
- ...DEFAULT_CONFIG,
45
-
46
- // Server settings from environment
47
- port: parseInt(process.env.MUND_PORT || '3000'),
48
- host: process.env.MUND_HOST || '127.0.0.1',
49
- transport: (process.env.MUND_TRANSPORT as 'stdio' | 'http') || 'stdio',
50
-
51
- // Logging
52
- log_level: (process.env.MUND_LOG_LEVEL as MundConfig['log_level']) || 'info',
53
-
54
- // Storage
55
- storage_type: (process.env.MUND_STORAGE as MundConfig['storage_type']) || 'memory',
56
- database_url: process.env.MUND_DATABASE_URL,
57
-
58
- // Security
59
- block_mode: process.env.MUND_BLOCK_MODE === 'block',
60
- api_key: process.env.MUND_API_KEY,
61
-
62
- // Notifications
63
- notifications: {
64
- slack: process.env.MUND_SLACK_WEBHOOK ? {
65
- webhook_url: process.env.MUND_SLACK_WEBHOOK,
66
- channel: process.env.MUND_SLACK_CHANNEL,
67
- username: process.env.MUND_SLACK_USERNAME || 'Mund Guardian',
68
- icon_emoji: process.env.MUND_SLACK_EMOJI || ':eye:',
69
- min_severity: (process.env.MUND_SLACK_MIN_SEVERITY as any) || 'high'
70
- } : undefined,
71
-
72
- teams: process.env.MUND_TEAMS_WEBHOOK ? {
73
- webhook_url: process.env.MUND_TEAMS_WEBHOOK,
74
- min_severity: (process.env.MUND_TEAMS_MIN_SEVERITY as any) || 'high'
75
- } : undefined,
76
-
77
- email: process.env.MUND_EMAIL_SMTP_HOST ? {
78
- smtp_host: process.env.MUND_EMAIL_SMTP_HOST,
79
- smtp_port: parseInt(process.env.MUND_EMAIL_SMTP_PORT || '587'),
80
- smtp_secure: process.env.MUND_EMAIL_SMTP_SECURE === 'true',
81
- smtp_user: process.env.MUND_EMAIL_SMTP_USER,
82
- smtp_pass: process.env.MUND_EMAIL_SMTP_PASS,
83
- from_address: process.env.MUND_EMAIL_FROM || 'mund@localhost',
84
- to_addresses: (process.env.MUND_EMAIL_TO || '').split(',').filter(Boolean),
85
- min_severity: (process.env.MUND_EMAIL_MIN_SEVERITY as any) || 'high'
86
- } : undefined,
87
-
88
- webhooks: process.env.MUND_WEBHOOK_URL ? [{
89
- url: process.env.MUND_WEBHOOK_URL,
90
- method: 'POST' as const,
91
- headers: process.env.MUND_WEBHOOK_HEADERS ? JSON.parse(process.env.MUND_WEBHOOK_HEADERS) : undefined,
92
- min_severity: (process.env.MUND_WEBHOOK_MIN_SEVERITY as 'critical' | 'high' | 'medium' | 'low' | 'info') || 'high'
93
- }] : undefined
94
- }
95
- };
96
-
97
- return config;
98
- }
99
-
100
- // ============================================================================
101
- // Threat Intelligence Tool Registration
102
- // ============================================================================
103
-
104
- function registerThreatIntelTools(server: McpServer): void {
105
- const handlers = createThreatIntelToolHandlers(threatIntel);
106
-
107
- // Map tool names to schemas
108
- const schemaMap: Record<string, Record<string, any>> = {
109
- 'mund_update_threat_intel': UpdateThreatIntelSchema,
110
- 'mund_list_intel_sources': ListIntelSourcesSchema,
111
- 'mund_intel_status': IntelStatusSchema,
112
- 'mund_add_intel_source': AddIntelSourceSchema,
113
- 'mund_remove_intel_source': RemoveIntelSourceSchema,
114
- 'mund_threat_scan': ThreatScanSchema,
115
- 'mund_list_patterns': ListPatternsSchema,
116
- 'mund_toggle_pattern': TogglePatternSchema,
117
- };
118
-
119
- // Register each threat intel tool with Zod schema
120
- for (const tool of threatIntelTools) {
121
- const schema = schemaMap[tool.name];
122
- if (!schema) continue;
123
-
124
- server.tool(
125
- tool.name,
126
- tool.description,
127
- schema,
128
- async (args: any) => {
129
- const handler = handlers[tool.name as keyof typeof handlers];
130
- if (!handler) {
131
- return {
132
- content: [{ type: 'text' as const, text: JSON.stringify({ error: `Unknown tool: ${tool.name}` }) }]
133
- };
134
- }
135
-
136
- try {
137
- const result = await handler(args);
138
- return {
139
- content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }]
140
- };
141
- } catch (error) {
142
- return {
143
- content: [{ type: 'text' as const, text: JSON.stringify({
144
- error: error instanceof Error ? error.message : String(error)
145
- }) }]
146
- };
147
- }
148
- }
149
- );
150
- }
151
- }
152
-
153
- // ============================================================================
154
- // Server Initialization
155
- // ============================================================================
156
-
157
- async function createMundServer(config: MundConfig): Promise<McpServer> {
158
- // Create MCP server
159
- const server = new McpServer({
160
- name: 'mund-mcp-server',
161
- version: getVersion()
162
- });
163
-
164
- // Initialize storage
165
- const storage = createStorage(config);
166
-
167
- // Initialize analyzer engine
168
- const analyzer = new AnalyzerEngine();
169
-
170
- // Initialize notification hub
171
- const notificationHub = new NotificationHub(config);
172
-
173
- // Load rules (start with defaults, could be extended from file)
174
- const rules: DetectionRule[] = [...DEFAULT_RULES];
175
-
176
- // Load any saved custom rules from storage
177
- const savedRules = await storage.getRules();
178
- for (const rule of savedRules) {
179
- if (!rules.find(r => r.id === rule.id)) {
180
- rules.push(rule);
181
- }
182
- }
183
-
184
- // Register all core tools
185
- loadCanariesFromEnv();
186
- registerAllTools(server, storage, rules, analyzer, notificationHub, config.block_mode);
187
-
188
- // Register threat intelligence tools
189
- registerThreatIntelTools(server);
190
-
191
- // Get threat intel status for logging
192
- const intelStatus = threatIntel.getStatus();
193
-
194
- // Log startup info
195
- console.error(`Mund Guardian Protocol v0.2.0`);
196
- console.error(`- Transport: ${config.transport}`);
197
- console.error(`- Storage: ${config.storage_type}`);
198
- console.error(`- Block Mode: ${config.block_mode ? 'enabled' : 'disabled'}`);
199
- console.error(`- Rules Loaded: ${rules.filter(r => r.enabled).length}`);
200
- console.error(`- Threat Intel: ${intelStatus.patterns.total} patterns from ${intelStatus.sources.enabled} sources`);
201
- console.error(`- Notifiers: ${notificationHub.getNotifierNames().join(', ') || 'none'}`);
202
-
203
- return server;
204
- }
205
-
206
- // ============================================================================
207
- // Transport Handlers
208
- // ============================================================================
209
-
210
- async function runStdio(config: MundConfig): Promise<void> {
211
- const server = await createMundServer(config);
212
- const transport = new StdioServerTransport();
213
-
214
- await server.connect(transport);
215
- console.error('Mund MCP server running on stdio');
216
- }
217
-
218
- async function runHTTP(config: MundConfig): Promise<void> {
219
- const server = await createMundServer(config);
220
- const app = express();
221
-
222
- app.use(express.json({ limit: '10mb' }));
223
-
224
- // Health check endpoint
225
- app.get('/health', (_req, res) => {
226
- res.json({ status: 'ok', version: getVersion() });
227
- });
228
-
229
- // Threat intel status endpoint
230
- app.get('/intel/status', (_req, res) => {
231
- res.json(threatIntel.getStatus());
232
- });
233
-
234
- // MCP endpoint
235
- app.post('/mcp', async (req, res) => {
236
- const transport = new StreamableHTTPServerTransport({
237
- sessionIdGenerator: undefined,
238
- enableJsonResponse: true
239
- });
240
-
241
- res.on('close', () => transport.close());
242
-
243
- await server.connect(transport);
244
- await transport.handleRequest(req, res, req.body);
245
- });
246
-
247
- // Start server
248
- app.listen(config.port, config.host, () => {
249
- console.error(`Mund MCP server running on http://${config.host}:${config.port}/mcp`);
250
- });
251
- }
252
-
253
- // ============================================================================
254
- // CLI and Main
255
- // ============================================================================
256
-
257
- function printHelp(): void {
258
- console.log(`
259
- Mund - The Guardian Protocol
260
- MCP-based security monitoring for agentic AI systems
261
-
262
- Usage: mund-mcp [options] Run the MCP server
263
- mund-mcp scan [paths...] Scan files (see: mund-mcp scan --help)
264
- mund-mcp agent-audit Audit installed skills + MCP servers
265
- mund-mcp check-skill <path> Scan a skill before installing it
266
-
267
- Options:
268
- --help, -h Show this help message
269
- --version, -v Show version number
270
- --transport <type> Transport type: stdio (default) or http
271
- --port <port> HTTP port (default: 3000)
272
- --host <host> HTTP host (default: 127.0.0.1)
273
- --block Enable block mode (block dangerous content)
274
-
275
- Environment Variables:
276
- MUND_PORT HTTP server port
277
- MUND_HOST HTTP server host
278
- MUND_TRANSPORT Transport type (stdio or http)
279
- MUND_LOG_LEVEL Log level (debug, info, warn, error)
280
- MUND_STORAGE Storage type (memory, sqlite, postgres)
281
- MUND_DATABASE_URL Database connection URL
282
- MUND_BLOCK_MODE Set to 'block' to enable blocking
283
- MUND_API_KEY API key for authentication
284
-
285
- MUND_SLACK_WEBHOOK Slack webhook URL
286
- MUND_SLACK_CHANNEL Slack channel override
287
- MUND_SLACK_MIN_SEVERITY Minimum severity for Slack alerts
288
-
289
- MUND_TEAMS_WEBHOOK Microsoft Teams webhook URL
290
- MUND_TEAMS_MIN_SEVERITY Minimum severity for Teams alerts
291
-
292
- MUND_EMAIL_SMTP_HOST SMTP server host
293
- MUND_EMAIL_SMTP_PORT SMTP server port
294
- MUND_EMAIL_FROM From address for emails
295
- MUND_EMAIL_TO Comma-separated recipient addresses
296
-
297
- MUND_WEBHOOK_URL Generic webhook URL
298
- MUND_WEBHOOK_HEADERS JSON string of webhook headers
299
-
300
- Threat Intelligence:
301
- Built-in threat patterns with MITRE ATT&CK mapping.
302
- Use mund_intel_status to check coverage.
303
- Use mund_update_threat_intel to pull latest patterns.
304
-
305
- Examples:
306
- # Run as stdio server (for MCP clients)
307
- mund-mcp
308
-
309
- # Run as HTTP server
310
- mund-mcp --transport http --port 3000
311
-
312
- # Run with Slack notifications
313
- MUND_SLACK_WEBHOOK=https://hooks.slack.com/... mund-mcp
314
-
315
- # Run in block mode
316
- mund-mcp --block
317
-
318
- For more information, visit: https://github.com/Tyox-all/Weave_Protocol
319
- `);
320
- }
321
-
322
- async function main(): Promise<void> {
323
- const args = process.argv.slice(2);
324
-
325
- if (args[0] === 'scan') {
326
- process.exit(await runScanCli(args.slice(1)));
327
- }
328
- if (args[0] === 'agent-audit') {
329
- process.exit(await runAgentAuditCli(args.slice(1)));
330
- }
331
- if (args[0] === 'check-skill') {
332
- process.exit(await runCheckSkillCli(args.slice(1)));
333
- }
334
-
335
- // Parse CLI arguments
336
- if (args.includes('--help') || args.includes('-h')) {
337
- printHelp();
338
- process.exit(0);
339
- }
340
-
341
- if (args.includes('--version') || args.includes('-v')) {
342
- console.log(getVersion());
343
- process.exit(0);
344
- }
345
-
346
- // Load config
347
- const config = loadConfig();
348
-
349
- // Override from CLI
350
- const transportIndex = args.indexOf('--transport');
351
- if (transportIndex !== -1 && args[transportIndex + 1]) {
352
- config.transport = args[transportIndex + 1] as 'stdio' | 'http';
353
- }
354
-
355
- const portIndex = args.indexOf('--port');
356
- if (portIndex !== -1 && args[portIndex + 1]) {
357
- config.port = parseInt(args[portIndex + 1]);
358
- }
359
-
360
- const hostIndex = args.indexOf('--host');
361
- if (hostIndex !== -1 && args[hostIndex + 1]) {
362
- config.host = args[hostIndex + 1];
363
- }
6
+ export { ThreatIntelManager, threatIntel } from './threat-intel-manager.js';
7
+ export { threatIntelTools, createThreatIntelToolHandlers } from './threat-intel-tools.js';
8
+ export * from './threat-intel-types.js';
364
9
 
365
- if (args.includes('--block')) {
366
- config.block_mode = true;
367
- }
10
+ // Importing this module has no side effects. Run directly (`node dist/index.js`,
11
+ // as older MCP configs do), it still starts the server; the bin points at server.js.
12
+ import { realpathSync } from 'node:fs';
13
+ import { fileURLToPath } from 'node:url';
368
14
 
369
- // Run appropriate transport
15
+ const invokedDirectly = (() => {
370
16
  try {
371
- if (config.transport === 'http') {
372
- await runHTTP(config);
373
- } else {
374
- await runStdio(config);
375
- }
376
- } catch (error) {
377
- console.error('Failed to start Mund server:', error);
378
- process.exit(1);
17
+ return !!process.argv[1] && realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));
18
+ } catch {
19
+ return false;
379
20
  }
380
- }
381
-
382
- // Run
383
- main().catch(error => {
384
- console.error('Fatal error:', error);
385
- process.exit(1);
386
- });
387
-
388
- // ============================================================================
389
- // Exports for programmatic use
390
- // ============================================================================
391
-
392
- export { ThreatIntelManager, threatIntel } from './threat-intel-manager.js';
393
- export { threatIntelTools, createThreatIntelToolHandlers } from './threat-intel-tools.js';
394
- export * from './threat-intel-types.js';
21
+ })();
22
+ if (invokedDirectly) void import('./server.js');