mcp-gov 1.0.0 → 1.2.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 (2) hide show
  1. package/bin/mcp-gov.js +171 -0
  2. package/package.json +2 -1
package/bin/mcp-gov.js ADDED
@@ -0,0 +1,171 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * mcp-gov - Interactive CLI for MCP Governance System
4
+ */
5
+
6
+ import * as readline from 'node:readline';
7
+ import { spawn } from 'node:child_process';
8
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
9
+ import { join, dirname } from 'node:path';
10
+ import { fileURLToPath } from 'node:url';
11
+ import { homedir } from 'node:os';
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = dirname(__filename);
15
+
16
+ // Get version from package.json
17
+ let version = '1.1.0';
18
+ try {
19
+ const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
20
+ version = pkg.version;
21
+ } catch (e) {
22
+ // ignore
23
+ }
24
+
25
+ const rl = readline.createInterface({
26
+ input: process.stdin,
27
+ output: process.stdout
28
+ });
29
+
30
+ function ask(question) {
31
+ return new Promise((resolve) => {
32
+ rl.question(question, resolve);
33
+ });
34
+ }
35
+
36
+ async function main() {
37
+ console.log(`\nMCP Governance System v${version}\n`);
38
+ console.log('Select action:');
39
+ console.log(' 1) Wrap MCP servers');
40
+ console.log(' 2) Unwrap MCP servers');
41
+ console.log(' 3) View audit logs');
42
+ console.log(' 4) Edit rules');
43
+ console.log('');
44
+
45
+ const choice = await ask('Enter choice [1-4]: ');
46
+
47
+ switch (choice.trim()) {
48
+ case '1':
49
+ await handleWrap();
50
+ break;
51
+ case '2':
52
+ await handleUnwrap();
53
+ break;
54
+ case '3':
55
+ await handleLogs();
56
+ break;
57
+ case '4':
58
+ await handleRules();
59
+ break;
60
+ default:
61
+ console.log('Invalid choice');
62
+ rl.close();
63
+ process.exit(1);
64
+ }
65
+ }
66
+
67
+ async function handleWrap() {
68
+ const defaultPath = join(homedir(), '.config', 'claude', 'config.json');
69
+ const configPath = await ask(`Enter config path [${defaultPath}]: `);
70
+ const path = configPath.trim() || defaultPath;
71
+ rl.close();
72
+
73
+ if (!existsSync(path)) {
74
+ console.error(`\nError: Config file not found: ${path}`);
75
+ process.exit(1);
76
+ }
77
+
78
+ console.log(`\nWrapping servers...\n`);
79
+
80
+ const child = spawn('node', [join(__dirname, 'mcp-gov-wrap.js'), '--config', path], {
81
+ stdio: 'inherit'
82
+ });
83
+
84
+ child.on('close', (code) => {
85
+ process.exit(code);
86
+ });
87
+ }
88
+
89
+ async function handleUnwrap() {
90
+ const defaultPath = join(homedir(), '.config', 'claude', 'config.json');
91
+ const configPath = await ask(`Enter config path [${defaultPath}]: `);
92
+ const path = configPath.trim() || defaultPath;
93
+ rl.close();
94
+
95
+ if (!existsSync(path)) {
96
+ console.error(`\nError: Config file not found: ${path}`);
97
+ process.exit(1);
98
+ }
99
+
100
+ console.log(`\nUnwrapping servers...\n`);
101
+
102
+ const child = spawn('node', [join(__dirname, 'mcp-gov-unwrap.js'), '--config', path], {
103
+ stdio: 'inherit'
104
+ });
105
+
106
+ child.on('close', (code) => {
107
+ process.exit(code);
108
+ });
109
+ }
110
+
111
+ async function handleLogs() {
112
+ const logsDir = join(homedir(), '.mcp-gov', 'logs');
113
+ rl.close();
114
+
115
+ if (!existsSync(logsDir)) {
116
+ console.log('\nNo audit logs found yet.');
117
+ console.log(`Logs will appear in: ${logsDir}`);
118
+ return;
119
+ }
120
+
121
+ const logFiles = readdirSync(logsDir).filter(f => f.endsWith('.log'));
122
+
123
+ if (logFiles.length === 0) {
124
+ console.log('\nNo audit logs found yet.');
125
+ return;
126
+ }
127
+
128
+ // Show all log files
129
+ for (const logFile of logFiles) {
130
+ const logPath = join(logsDir, logFile);
131
+ const content = readFileSync(logPath, 'utf8');
132
+ const lines = content.trim().split('\n');
133
+ const lastLines = lines.slice(-20);
134
+
135
+ console.log(`\n--- ${logFile} (last ${lastLines.length} entries) ---\n`);
136
+ console.log(lastLines.join('\n'));
137
+ }
138
+ console.log(`\n--- End of logs ---\n`);
139
+ }
140
+
141
+ async function handleRules() {
142
+ const rulesPath = join(homedir(), '.mcp-gov', 'rules.json');
143
+ rl.close();
144
+
145
+ if (!existsSync(rulesPath)) {
146
+ console.log(`\nRules file not found: ${rulesPath}`);
147
+ console.log('Run "Wrap MCP servers" first to generate default rules.');
148
+ return;
149
+ }
150
+
151
+ const editor = process.env.EDITOR || process.env.VISUAL || 'nano';
152
+
153
+ console.log(`\nOpening ${rulesPath} in ${editor}...\n`);
154
+
155
+ const child = spawn(editor, [rulesPath], {
156
+ stdio: 'inherit'
157
+ });
158
+
159
+ child.on('close', (code) => {
160
+ if (code === 0) {
161
+ console.log('\nRules saved.');
162
+ }
163
+ process.exit(code);
164
+ });
165
+ }
166
+
167
+ main().catch((err) => {
168
+ rl.close();
169
+ console.error('Error:', err.message);
170
+ process.exit(1);
171
+ });
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "mcp-gov",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "MCP Governance System - Permission control and audit logging for Model Context Protocol servers",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
7
7
  "bin": {
8
+ "mcp-gov": "bin/mcp-gov.js",
8
9
  "mcp-gov-proxy": "bin/mcp-gov-proxy.js",
9
10
  "mcp-gov-wrap": "bin/mcp-gov-wrap.js",
10
11
  "mcp-gov-unwrap": "bin/mcp-gov-unwrap.js"