mcp-controller 0.4.0 → 0.4.1
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/README.md +42 -26
- package/bin/mcp-controller +56 -0
- package/bin/mcp-controller.cmd +50 -0
- package/package.json +13 -45
- package/postinstall.mjs +142 -0
- package/preinstall.mjs +39 -0
- package/bun.lock +0 -987
- package/mcp-controller +0 -0
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ A Model Context Protocol (MCP) server that acts as a proxy between MCP clients a
|
|
|
5
5
|
## Key Features
|
|
6
6
|
|
|
7
7
|
- **🔧 Tool Filtering**: Selectively enable or disable specific tools from target MCP servers
|
|
8
|
-
- **🔍 Transparent Proxying**: Forwards all other MCP protocol messages without modification
|
|
8
|
+
- **🔍 Transparent Proxying**: Forwards all other MCP protocol messages without modification
|
|
9
9
|
- **⚡ Zero Configuration**: Works with any existing MCP server without changes
|
|
10
10
|
- **🛡️ Access Control**: Control which tools clients can access for security and usability
|
|
11
11
|
- **📦 Command Line Interface**: Start any MCP server through command arguments
|
|
@@ -15,8 +15,13 @@ A Model Context Protocol (MCP) server that acts as a proxy between MCP clients a
|
|
|
15
15
|
## Installation
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
curl -fsSL https://raw.githubusercontent.com/eli0shin/mcp-controller/main/install.sh | bash
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or install via npm:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install -g mcp-controller
|
|
20
25
|
```
|
|
21
26
|
|
|
22
27
|
## Usage
|
|
@@ -25,16 +30,16 @@ bun run build
|
|
|
25
30
|
|
|
26
31
|
```bash
|
|
27
32
|
# Proxy to a local MCP server
|
|
28
|
-
|
|
33
|
+
mcp-controller bun run my-server.ts
|
|
29
34
|
|
|
30
35
|
# Proxy to an npm-distributed MCP server
|
|
31
|
-
|
|
36
|
+
mcp-controller @modelcontextprotocol/server-sequential-thinking
|
|
32
37
|
|
|
33
38
|
# Proxy to a Python MCP server
|
|
34
|
-
|
|
39
|
+
mcp-controller python -m my_mcp_server
|
|
35
40
|
|
|
36
41
|
# Proxy to any executable MCP server
|
|
37
|
-
|
|
42
|
+
mcp-controller node server.js --port 3000
|
|
38
43
|
```
|
|
39
44
|
|
|
40
45
|
### Tool Filtering
|
|
@@ -43,13 +48,13 @@ Control which tools from the target server are exposed to clients:
|
|
|
43
48
|
|
|
44
49
|
```bash
|
|
45
50
|
# Only allow specific tools (whitelist mode)
|
|
46
|
-
|
|
51
|
+
mcp-controller --enabled-tools file-read,file-write,search bun run my-server.ts
|
|
47
52
|
|
|
48
|
-
# Block specific tools (blacklist mode)
|
|
49
|
-
|
|
53
|
+
# Block specific tools (blacklist mode)
|
|
54
|
+
mcp-controller --disabled-tools dangerous-tool,admin-commands python -m my_server
|
|
50
55
|
|
|
51
56
|
# Multiple tools (comma-separated, no spaces around commas)
|
|
52
|
-
|
|
57
|
+
mcp-controller --enabled-tools tool1,tool2,tool3 node server.js
|
|
53
58
|
```
|
|
54
59
|
|
|
55
60
|
### Filtering Rules
|
|
@@ -63,30 +68,33 @@ Control which tools from the target server are exposed to clients:
|
|
|
63
68
|
## Use Cases
|
|
64
69
|
|
|
65
70
|
### Security & Access Control
|
|
71
|
+
|
|
66
72
|
```bash
|
|
67
73
|
# Production environment - only allow safe read-only tools
|
|
68
|
-
|
|
74
|
+
mcp-controller --enabled-tools read-file,search,list-files my-server
|
|
69
75
|
|
|
70
76
|
# Development environment - block dangerous operations
|
|
71
|
-
|
|
77
|
+
mcp-controller --disabled-tools delete-file,format-disk,restart-system my-server
|
|
72
78
|
```
|
|
73
79
|
|
|
74
80
|
### Client-Specific Customization
|
|
81
|
+
|
|
75
82
|
```bash
|
|
76
83
|
# For a documentation client - only text processing tools
|
|
77
|
-
|
|
84
|
+
mcp-controller --enabled-tools text-search,summarize,translate content-server
|
|
78
85
|
|
|
79
|
-
# For an admin interface - block user-facing tools
|
|
80
|
-
|
|
86
|
+
# For an admin interface - block user-facing tools
|
|
87
|
+
mcp-controller --disabled-tools user-chat,send-email,post-social admin-server
|
|
81
88
|
```
|
|
82
89
|
|
|
83
90
|
### Testing & Development
|
|
91
|
+
|
|
84
92
|
```bash
|
|
85
93
|
# Test specific functionality by isolating tools
|
|
86
|
-
|
|
94
|
+
mcp-controller --enabled-tools database-query,cache-get test-server
|
|
87
95
|
|
|
88
96
|
# Debug by excluding problematic tools
|
|
89
|
-
|
|
97
|
+
mcp-controller --disabled-tools flaky-api,slow-process debug-server
|
|
90
98
|
```
|
|
91
99
|
|
|
92
100
|
## How it Works
|
|
@@ -107,7 +115,7 @@ MCP Client ↔ MCP Controller ↔ Target MCP Server
|
|
|
107
115
|
### Message Flow
|
|
108
116
|
|
|
109
117
|
1. **Client → Controller → Target**: All requests forwarded transparently
|
|
110
|
-
2. **Target → Controller → Client**:
|
|
118
|
+
2. **Target → Controller → Client**:
|
|
111
119
|
- `tools/list` responses are filtered based on configuration
|
|
112
120
|
- All other responses pass through unchanged
|
|
113
121
|
|
|
@@ -115,7 +123,7 @@ MCP Client ↔ MCP Controller ↔ Target MCP Server
|
|
|
115
123
|
|
|
116
124
|
- ✅ **`tools/list` responses** - Tool arrays are filtered according to your settings
|
|
117
125
|
- ❌ **Tool calls** - Individual tool invocations pass through (filtered tools simply won't be available)
|
|
118
|
-
- ❌ **Resources** - Resource lists and access remain unchanged
|
|
126
|
+
- ❌ **Resources** - Resource lists and access remain unchanged
|
|
119
127
|
- ❌ **Prompts** - Prompt functionality unaffected
|
|
120
128
|
- ❌ **Other messages** - Initialization, capabilities, etc. pass through
|
|
121
129
|
|
|
@@ -124,6 +132,8 @@ MCP Client ↔ MCP Controller ↔ Target MCP Server
|
|
|
124
132
|
```bash
|
|
125
133
|
Usage: mcp-controller [--enabled-tools <tool1,tool2,...>] [--disabled-tools <tool1,tool2,...>] <command> [args...]
|
|
126
134
|
|
|
135
|
+
mcp-controller update
|
|
136
|
+
|
|
127
137
|
Options:
|
|
128
138
|
--enabled-tools <tools> Comma-separated list of tools to allow (whitelist mode)
|
|
129
139
|
--disabled-tools <tools> Comma-separated list of tools to block (blacklist mode)
|
|
@@ -140,15 +150,15 @@ The controller validates arguments at startup and will exit with helpful error m
|
|
|
140
150
|
|
|
141
151
|
```bash
|
|
142
152
|
# Missing command
|
|
143
|
-
$
|
|
153
|
+
$ mcp-controller --enabled-tools read
|
|
144
154
|
Error: No target command specified
|
|
145
155
|
|
|
146
156
|
# Both filtering modes
|
|
147
|
-
$
|
|
157
|
+
$ mcp-controller --enabled-tools read --disabled-tools write bun server.ts
|
|
148
158
|
Error: --enabled-tools and --disabled-tools are mutually exclusive
|
|
149
159
|
|
|
150
160
|
# Missing tool list
|
|
151
|
-
$
|
|
161
|
+
$ mcp-controller --enabled-tools bun server.ts
|
|
152
162
|
Error: --enabled-tools requires a value
|
|
153
163
|
```
|
|
154
164
|
|
|
@@ -158,15 +168,21 @@ Error: --enabled-tools requires a value
|
|
|
158
168
|
# Install dependencies
|
|
159
169
|
bun install
|
|
160
170
|
|
|
161
|
-
# Build
|
|
171
|
+
# Build release binaries
|
|
162
172
|
bun run build
|
|
163
173
|
|
|
164
|
-
# Run
|
|
174
|
+
# Run via wrapper against the local release build
|
|
175
|
+
./bin/mcp-controller bun run tests/fixtures/mcp-server.ts
|
|
176
|
+
|
|
177
|
+
# Run in development mode
|
|
165
178
|
bun run dev <target-command>
|
|
166
179
|
|
|
167
180
|
# Run tests (includes tool filtering tests)
|
|
168
181
|
bun test
|
|
169
182
|
|
|
183
|
+
# Update installed binary from GitHub Releases
|
|
184
|
+
mcp-controller update
|
|
185
|
+
|
|
170
186
|
# Lint and format
|
|
171
187
|
bun run lint
|
|
172
188
|
bun run format
|
|
@@ -177,4 +193,4 @@ bun run typecheck
|
|
|
177
193
|
|
|
178
194
|
## License
|
|
179
195
|
|
|
180
|
-
MIT
|
|
196
|
+
MIT
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
if [ -n "$MCP_CONTROLLER_BIN_PATH" ]; then
|
|
5
|
+
resolved="$MCP_CONTROLLER_BIN_PATH"
|
|
6
|
+
else
|
|
7
|
+
script_path="$0"
|
|
8
|
+
while [ -L "$script_path" ]; do
|
|
9
|
+
link_target="$(readlink "$script_path")"
|
|
10
|
+
case "$link_target" in
|
|
11
|
+
/*) script_path="$link_target" ;;
|
|
12
|
+
*) script_path="$(dirname "$script_path")/$link_target" ;;
|
|
13
|
+
esac
|
|
14
|
+
done
|
|
15
|
+
script_dir="$(dirname "$script_path")"
|
|
16
|
+
script_dir="$(cd "$script_dir" && pwd)"
|
|
17
|
+
|
|
18
|
+
case "$(uname -s)" in
|
|
19
|
+
Darwin) platform="darwin" ;;
|
|
20
|
+
Linux) platform="linux" ;;
|
|
21
|
+
*) platform="$(uname -s | tr '[:upper:]' '[:lower:]')" ;;
|
|
22
|
+
esac
|
|
23
|
+
|
|
24
|
+
case "$(uname -m)" in
|
|
25
|
+
x86_64|amd64) arch="x64" ;;
|
|
26
|
+
aarch64|arm64) arch="arm64" ;;
|
|
27
|
+
*) arch="$(uname -m)" ;;
|
|
28
|
+
esac
|
|
29
|
+
|
|
30
|
+
resolved=""
|
|
31
|
+
|
|
32
|
+
candidate="$script_dir/mcp-controller-downloaded"
|
|
33
|
+
if [ -f "$candidate" ]; then
|
|
34
|
+
resolved="$candidate"
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
if [ -z "$resolved" ]; then
|
|
38
|
+
name="mcp-controller-${platform}-${arch}"
|
|
39
|
+
current_dir="$script_dir"
|
|
40
|
+
while [ "$current_dir" != "/" ]; do
|
|
41
|
+
candidate="$current_dir/dist/$name/bin/mcp-controller"
|
|
42
|
+
if [ -f "$candidate" ]; then
|
|
43
|
+
resolved="$candidate"
|
|
44
|
+
break
|
|
45
|
+
fi
|
|
46
|
+
current_dir="$(dirname "$current_dir")"
|
|
47
|
+
done
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
if [ -z "$resolved" ]; then
|
|
51
|
+
printf "Failed to find mcp-controller binary for your platform\n" >&2
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
exec "$resolved" "$@"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
setlocal enabledelayedexpansion
|
|
3
|
+
|
|
4
|
+
if defined MCP_CONTROLLER_BIN_PATH (
|
|
5
|
+
set "resolved=%MCP_CONTROLLER_BIN_PATH%"
|
|
6
|
+
goto :execute
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
set "script_dir=%~dp0"
|
|
10
|
+
set "script_dir=%script_dir:~0,-1%"
|
|
11
|
+
|
|
12
|
+
set "resolved="
|
|
13
|
+
set "candidate=%script_dir%\mcp-controller-downloaded.exe"
|
|
14
|
+
if exist "%candidate%" (
|
|
15
|
+
set "resolved=%candidate%"
|
|
16
|
+
goto :execute
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
if "%PROCESSOR_ARCHITECTURE%"=="AMD64" (
|
|
20
|
+
set "arch=x64"
|
|
21
|
+
) else if "%PROCESSOR_ARCHITECTURE%"=="ARM64" (
|
|
22
|
+
set "arch=arm64"
|
|
23
|
+
) else (
|
|
24
|
+
set "arch=x64"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
set "name=mcp-controller-windows-!arch!"
|
|
28
|
+
set "current_dir=%script_dir%"
|
|
29
|
+
|
|
30
|
+
:search_loop
|
|
31
|
+
set "candidate=%current_dir%\dist\%name%\bin\mcp-controller.exe"
|
|
32
|
+
if exist "%candidate%" (
|
|
33
|
+
set "resolved=%candidate%"
|
|
34
|
+
goto :execute
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
for %%i in ("%current_dir%") do set "parent_dir=%%~dpi"
|
|
38
|
+
set "parent_dir=%parent_dir:~0,-1%"
|
|
39
|
+
|
|
40
|
+
if "%current_dir%"=="%parent_dir%" goto :not_found
|
|
41
|
+
set "current_dir=%parent_dir%"
|
|
42
|
+
goto :search_loop
|
|
43
|
+
|
|
44
|
+
:not_found
|
|
45
|
+
echo Failed to find mcp-controller binary for your platform >&2
|
|
46
|
+
exit /b 1
|
|
47
|
+
|
|
48
|
+
:execute
|
|
49
|
+
start /b /wait "" "%resolved%" %*
|
|
50
|
+
exit /b %ERRORLEVEL%
|
package/package.json
CHANGED
|
@@ -1,53 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-controller",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "MCP server proxy that enables controlling availability of tools.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"bin": {
|
|
7
|
-
"mcp-controller": "mcp-controller"
|
|
8
|
-
},
|
|
9
|
-
"files": [
|
|
10
|
-
"README.md",
|
|
11
|
-
"package.json",
|
|
12
|
-
"bun.lock",
|
|
13
|
-
"mcp-controller"
|
|
14
|
-
],
|
|
15
|
-
"scripts": {
|
|
16
|
-
"build": "bun build src/cli.ts --compile --outfile mcp-controller",
|
|
17
|
-
"dev": "bun run src/cli.ts",
|
|
18
|
-
"typecheck": "bun tsc --noEmit",
|
|
19
|
-
"lint": "eslint .",
|
|
20
|
-
"lint:fix": "eslint . --fix",
|
|
21
|
-
"format": "prettier --check .",
|
|
22
|
-
"format:fix": "prettier --write .",
|
|
23
|
-
"test": "bun test",
|
|
24
|
-
"test:watch": "bun test tests/ --watch",
|
|
25
|
-
"prepublish": "bun test && bun run build"
|
|
26
|
-
},
|
|
27
|
-
"devDependencies": {
|
|
28
|
-
"@changesets/changelog-github": "^0.5.2",
|
|
29
|
-
"@changesets/cli": "^2.29.8",
|
|
30
|
-
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
31
|
-
"@total-typescript/ts-reset": "^0.6.1",
|
|
32
|
-
"@types/node": "^22.9.0",
|
|
33
|
-
"bun-types": "^1.1.34",
|
|
34
|
-
"eslint": "^9.15.0",
|
|
35
|
-
"eslint-for-ai": "^1.0.8",
|
|
36
|
-
"prettier": "^3.3.3",
|
|
37
|
-
"typescript": "^5.6.3",
|
|
38
|
-
"zod": "^3.23.8"
|
|
39
|
-
},
|
|
40
|
-
"keywords": [
|
|
41
|
-
"mcp",
|
|
42
|
-
"model-context-protocol",
|
|
43
|
-
"proxy",
|
|
44
|
-
"json-rpc",
|
|
45
|
-
"cli"
|
|
46
|
-
],
|
|
47
|
-
"author": "@eli0shin",
|
|
48
|
-
"license": "MIT",
|
|
49
5
|
"repository": {
|
|
50
6
|
"type": "git",
|
|
51
7
|
"url": "https://github.com/eli0shin/mcp-controller"
|
|
8
|
+
},
|
|
9
|
+
"bugs": {
|
|
10
|
+
"url": "https://github.com/eli0shin/mcp-controller/issues"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/eli0shin/mcp-controller#readme",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"bin": {
|
|
15
|
+
"mcp-controller": "./bin/mcp-controller"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"preinstall": "node ./preinstall.mjs",
|
|
19
|
+
"postinstall": "node ./postinstall.mjs"
|
|
52
20
|
}
|
|
53
21
|
}
|
package/postinstall.mjs
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import os from 'os';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { createRequire } from 'module';
|
|
8
|
+
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
const REPO = 'eli0shin/mcp-controller';
|
|
12
|
+
|
|
13
|
+
function shouldSkipPostinstall() {
|
|
14
|
+
const packageRoot = path.join(__dirname, '..');
|
|
15
|
+
const srcDir = path.join(packageRoot, 'src');
|
|
16
|
+
if (fs.existsSync(srcDir)) {
|
|
17
|
+
console.log('Skipping postinstall (running from source)');
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function detectPlatformAndArch() {
|
|
24
|
+
let platform;
|
|
25
|
+
switch (os.platform()) {
|
|
26
|
+
case 'darwin':
|
|
27
|
+
platform = 'darwin';
|
|
28
|
+
break;
|
|
29
|
+
case 'linux':
|
|
30
|
+
platform = 'linux';
|
|
31
|
+
break;
|
|
32
|
+
case 'win32':
|
|
33
|
+
platform = 'windows';
|
|
34
|
+
break;
|
|
35
|
+
default:
|
|
36
|
+
platform = os.platform();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let arch;
|
|
40
|
+
switch (os.arch()) {
|
|
41
|
+
case 'x64':
|
|
42
|
+
arch = 'x64';
|
|
43
|
+
break;
|
|
44
|
+
case 'arm64':
|
|
45
|
+
arch = 'arm64';
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
arch = os.arch();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { platform, arch };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function getDownloadedBinaryPath() {
|
|
55
|
+
const { platform } = detectPlatformAndArch();
|
|
56
|
+
const binary =
|
|
57
|
+
platform === 'windows'
|
|
58
|
+
? 'mcp-controller-downloaded.exe'
|
|
59
|
+
: 'mcp-controller-downloaded';
|
|
60
|
+
return path.join(__dirname, '..', 'bin', binary);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function downloadLatestBinary() {
|
|
64
|
+
const { platform, arch } = detectPlatformAndArch();
|
|
65
|
+
const asset =
|
|
66
|
+
platform === 'windows'
|
|
67
|
+
? `mcp-controller-${platform}-${arch}.exe`
|
|
68
|
+
: `mcp-controller-${platform}-${arch}`;
|
|
69
|
+
const url = `https://github.com/${REPO}/releases/latest/download/${asset}`;
|
|
70
|
+
const response = await fetch(url, {
|
|
71
|
+
headers: {
|
|
72
|
+
'User-Agent': 'mcp-controller',
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
throw new Error(`Failed to download ${url}: ${response.status}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const targetPath = getDownloadedBinaryPath();
|
|
81
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
82
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
83
|
+
fs.writeFileSync(targetPath, Buffer.from(arrayBuffer));
|
|
84
|
+
|
|
85
|
+
if (platform !== 'windows') {
|
|
86
|
+
fs.chmodSync(targetPath, 0o755);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
console.log(`Downloaded binary: ${targetPath}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function regenerateWindowsCmdWrappers() {
|
|
93
|
+
console.log('Windows + npm: Rebuilding bin links');
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
const { execSync } = require('child_process');
|
|
97
|
+
const pkgPath = path.join(__dirname, '..');
|
|
98
|
+
|
|
99
|
+
const isGlobal =
|
|
100
|
+
process.env.npm_config_global === 'true' ||
|
|
101
|
+
pkgPath.includes(path.join('npm', 'node_modules'));
|
|
102
|
+
|
|
103
|
+
const cmd = `npm rebuild mcp-controller --ignore-scripts${isGlobal ? ' -g' : ''}`;
|
|
104
|
+
const opts = {
|
|
105
|
+
stdio: 'inherit',
|
|
106
|
+
shell: true,
|
|
107
|
+
...(isGlobal ? {} : { cwd: path.join(pkgPath, '..', '..') }),
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
execSync(cmd, opts);
|
|
111
|
+
console.log('Successfully rebuilt npm bin links');
|
|
112
|
+
} catch (error) {
|
|
113
|
+
console.error('Error rebuilding npm links:', error.message);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function main() {
|
|
118
|
+
if (shouldSkipPostinstall()) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
await downloadLatestBinary();
|
|
124
|
+
|
|
125
|
+
if (
|
|
126
|
+
os.platform() === 'win32' &&
|
|
127
|
+
process.env.npm_config_user_agent?.startsWith('npm')
|
|
128
|
+
) {
|
|
129
|
+
await regenerateWindowsCmdWrappers();
|
|
130
|
+
}
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.error('Failed to install release binary:', error.message);
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
await main();
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.error('Postinstall error:', error.message);
|
|
141
|
+
process.exit(0);
|
|
142
|
+
}
|
package/preinstall.mjs
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import os from 'os';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
10
|
+
function main() {
|
|
11
|
+
if (os.platform() !== 'win32') {
|
|
12
|
+
console.log('Non-Windows platform, skipping preinstall');
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
console.log('Windows: Modifying package.json bin entry');
|
|
17
|
+
|
|
18
|
+
const packageJsonPath = path.join(__dirname, '..', 'package.json');
|
|
19
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
20
|
+
|
|
21
|
+
packageJson.bin = {
|
|
22
|
+
'mcp-controller': './bin/mcp-controller.cmd',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
26
|
+
console.log('Updated package.json bin to use mcp-controller.cmd');
|
|
27
|
+
|
|
28
|
+
const unixScript = path.join(__dirname, '..', 'bin', 'mcp-controller');
|
|
29
|
+
if (fs.existsSync(unixScript)) {
|
|
30
|
+
fs.unlinkSync(unixScript);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
main();
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.error('Preinstall error:', error.message);
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|