mcp-gov 1.0.0 → 1.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.
- package/bin/mcp-gov.js +175 -0
- package/package.json +4 -2
package/bin/mcp-gov.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* mcp-gov - Interactive CLI for MCP Governance System
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import inquirer from 'inquirer';
|
|
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.0.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
|
+
console.log(`\nMCP Governance System v${version}\n`);
|
|
26
|
+
|
|
27
|
+
async function main() {
|
|
28
|
+
// Step 1: Select action
|
|
29
|
+
const { action } = await inquirer.prompt([
|
|
30
|
+
{
|
|
31
|
+
type: 'list',
|
|
32
|
+
name: 'action',
|
|
33
|
+
message: 'Select action:',
|
|
34
|
+
choices: [
|
|
35
|
+
{ name: 'Wrap MCP servers', value: 'wrap' },
|
|
36
|
+
{ name: 'Unwrap MCP servers', value: 'unwrap' },
|
|
37
|
+
{ name: 'View audit logs', value: 'logs' },
|
|
38
|
+
{ name: 'Edit rules', value: 'rules' }
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
// Handle each action
|
|
44
|
+
switch (action) {
|
|
45
|
+
case 'wrap':
|
|
46
|
+
await handleWrap();
|
|
47
|
+
break;
|
|
48
|
+
case 'unwrap':
|
|
49
|
+
await handleUnwrap();
|
|
50
|
+
break;
|
|
51
|
+
case 'logs':
|
|
52
|
+
await handleLogs();
|
|
53
|
+
break;
|
|
54
|
+
case 'rules':
|
|
55
|
+
await handleRules();
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function handleWrap() {
|
|
61
|
+
const { configPath } = await inquirer.prompt([
|
|
62
|
+
{
|
|
63
|
+
type: 'input',
|
|
64
|
+
name: 'configPath',
|
|
65
|
+
message: 'Enter config path:',
|
|
66
|
+
default: join(homedir(), '.config', 'claude', 'config.json')
|
|
67
|
+
}
|
|
68
|
+
]);
|
|
69
|
+
|
|
70
|
+
if (!existsSync(configPath)) {
|
|
71
|
+
console.error(`\nError: Config file not found: ${configPath}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
console.log(`\nWrapping servers...\n`);
|
|
76
|
+
|
|
77
|
+
const child = spawn('node', [join(__dirname, 'mcp-gov-wrap.js'), '--config', configPath], {
|
|
78
|
+
stdio: 'inherit'
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
child.on('close', (code) => {
|
|
82
|
+
process.exit(code);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function handleUnwrap() {
|
|
87
|
+
const { configPath } = await inquirer.prompt([
|
|
88
|
+
{
|
|
89
|
+
type: 'input',
|
|
90
|
+
name: 'configPath',
|
|
91
|
+
message: 'Enter config path:',
|
|
92
|
+
default: join(homedir(), '.config', 'claude', 'config.json')
|
|
93
|
+
}
|
|
94
|
+
]);
|
|
95
|
+
|
|
96
|
+
if (!existsSync(configPath)) {
|
|
97
|
+
console.error(`\nError: Config file not found: ${configPath}`);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
console.log(`\nUnwrapping servers...\n`);
|
|
102
|
+
|
|
103
|
+
const child = spawn('node', [join(__dirname, 'mcp-gov-unwrap.js'), '--config', configPath], {
|
|
104
|
+
stdio: 'inherit'
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
child.on('close', (code) => {
|
|
108
|
+
process.exit(code);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function handleLogs() {
|
|
113
|
+
const logsDir = join(homedir(), '.mcp-gov', 'logs');
|
|
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
|
+
const { logFile } = await inquirer.prompt([
|
|
129
|
+
{
|
|
130
|
+
type: 'list',
|
|
131
|
+
name: 'logFile',
|
|
132
|
+
message: 'Select log file:',
|
|
133
|
+
choices: logFiles
|
|
134
|
+
}
|
|
135
|
+
]);
|
|
136
|
+
|
|
137
|
+
const logPath = join(logsDir, logFile);
|
|
138
|
+
const content = readFileSync(logPath, 'utf8');
|
|
139
|
+
const lines = content.trim().split('\n');
|
|
140
|
+
const lastLines = lines.slice(-50); // Show last 50 lines
|
|
141
|
+
|
|
142
|
+
console.log(`\n--- ${logFile} (last ${lastLines.length} entries) ---\n`);
|
|
143
|
+
console.log(lastLines.join('\n'));
|
|
144
|
+
console.log(`\n--- End of log ---\n`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async function handleRules() {
|
|
148
|
+
const rulesPath = join(homedir(), '.mcp-gov', 'rules.json');
|
|
149
|
+
|
|
150
|
+
if (!existsSync(rulesPath)) {
|
|
151
|
+
console.log(`\nRules file not found: ${rulesPath}`);
|
|
152
|
+
console.log('Run "Wrap MCP servers" first to generate default rules.');
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const editor = process.env.EDITOR || process.env.VISUAL || 'nano';
|
|
157
|
+
|
|
158
|
+
console.log(`\nOpening ${rulesPath} in ${editor}...\n`);
|
|
159
|
+
|
|
160
|
+
const child = spawn(editor, [rulesPath], {
|
|
161
|
+
stdio: 'inherit'
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
child.on('close', (code) => {
|
|
165
|
+
if (code === 0) {
|
|
166
|
+
console.log('\nRules saved.');
|
|
167
|
+
}
|
|
168
|
+
process.exit(code);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
main().catch((err) => {
|
|
173
|
+
console.error('Error:', err.message);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
});
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-gov",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.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"
|
|
@@ -45,7 +46,8 @@
|
|
|
45
46
|
"dependencies": {
|
|
46
47
|
"@modelcontextprotocol/sdk": "^0.5.0",
|
|
47
48
|
"axios": "^1.6.0",
|
|
48
|
-
"dotenv": "^16.0.0"
|
|
49
|
+
"dotenv": "^16.0.0",
|
|
50
|
+
"inquirer": "^13.2.1"
|
|
49
51
|
},
|
|
50
52
|
"devDependencies": {
|
|
51
53
|
"@types/node": "^25.0.10"
|