chatgpt-local-mcp 1.0.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/README.md +299 -0
- package/bin/cli.js +162 -0
- package/package.json +39 -0
- package/scripts/start.cmd +7 -0
- package/scripts/start.js +677 -0
- package/src/server.js +2416 -0
package/README.md
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# chatgpt-local-mcp
|
|
2
|
+
|
|
3
|
+
Give ChatGPT (or any MCP client) full control of your local machine — read and write files, run shell commands, use Git, manage processes, make HTTP requests, and more — through a secure cloudflared tunnel.
|
|
4
|
+
|
|
5
|
+
**53 tools · Folder-scoped by default · Auto-tunnel · Zero config · One command**
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## How it works
|
|
10
|
+
|
|
11
|
+
1. Run `chatgpt-local-mcp` (or `npm start`) in any folder
|
|
12
|
+
2. It starts an MCP server and opens a free public tunnel via cloudflared
|
|
13
|
+
3. Paste the tunnel URL into ChatGPT as a connector
|
|
14
|
+
4. ChatGPT now has agentic access to your machine through all 53 tools
|
|
15
|
+
|
|
16
|
+
By default the AI can **only access the folder you ran the command in**. Use `--bypass` to allow full filesystem access.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Requirements
|
|
21
|
+
|
|
22
|
+
| | Minimum |
|
|
23
|
+
|---|---|
|
|
24
|
+
| Node.js | 18 LTS or newer (22 recommended) |
|
|
25
|
+
| OS | Windows 10/11, macOS, or Linux |
|
|
26
|
+
| Internet | Required for cloudflared tunnel |
|
|
27
|
+
| ChatGPT | Plus, Team, or Enterprise (for custom connectors) |
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
### Global install (recommended)
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install -g chatgpt-local-mcp
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Then run from any project folder:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
cd my-project
|
|
43
|
+
chatgpt-local-mcp
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### From source
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
git clone https://github.com/your-username/chatgpt-local-mcp
|
|
50
|
+
cd chatgpt-local-mcp
|
|
51
|
+
npm install
|
|
52
|
+
npm start
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Usage
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
chatgpt-local-mcp # AI sees only the current folder (safe default)
|
|
61
|
+
chatgpt-local-mcp --bypass # Full filesystem access (use with care)
|
|
62
|
+
chatgpt-local-mcp --log # Stream live tool-call logs
|
|
63
|
+
chatgpt-local-mcp --port 3002 # Custom port
|
|
64
|
+
chatgpt-local-mcp --no-tunnel # Local only — skip cloudflared
|
|
65
|
+
chatgpt-local-mcp --help
|
|
66
|
+
chatgpt-local-mcp --version
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Connect to ChatGPT
|
|
72
|
+
|
|
73
|
+
1. After startup, copy the MCP URL printed in the terminal — it looks like:
|
|
74
|
+
```
|
|
75
|
+
https://abc123.trycloudflare.com/mcp
|
|
76
|
+
```
|
|
77
|
+
2. Go to **ChatGPT → Settings → Connectors → Add connector**
|
|
78
|
+
3. Select **Model Context Protocol (MCP)**
|
|
79
|
+
4. Paste the URL, set **Authentication: No Auth**, and save
|
|
80
|
+
|
|
81
|
+
> The tunnel URL changes on every restart. Update the connector URL in ChatGPT after each restart.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Live logs
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
chatgpt-local-mcp --log
|
|
89
|
+
# or
|
|
90
|
+
npm run start:log
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Every request, tool call, and event is streamed to the terminal:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
14:22:01.043 [SRV] · ChatGPT Local MCP v1.0.0 — 53 tools
|
|
97
|
+
14:22:01.891 [TUN] ✓ Tunnel ready: https://abc123.trycloudflare.com
|
|
98
|
+
14:22:04.112 [SRV] · [MCP] tools/list → 53 tools
|
|
99
|
+
14:22:09.303 [SRV] · [TOOL] ▶ read_file {path=src/index.js}
|
|
100
|
+
14:22:09.315 [SRV] · [TOOL] ✓ read_file (12ms)
|
|
101
|
+
14:22:11.100 [SRV] · [TOOL] ▶ run_command {command=npm test}
|
|
102
|
+
14:22:14.890 [SRV] · [TOOL] ✓ run_command (3790ms)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Tools
|
|
108
|
+
|
|
109
|
+
### Filesystem — 14 tools
|
|
110
|
+
|
|
111
|
+
| Tool | What it does |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `list_directory` | List files with size, type, and timestamps |
|
|
114
|
+
| `directory_tree` | Recursive tree view with depth limit |
|
|
115
|
+
| `file_info` | Metadata for a file or directory |
|
|
116
|
+
| `read_file` | Read a file (up to 4 MB) |
|
|
117
|
+
| `read_file_lines` | Read a specific line range — great for large files |
|
|
118
|
+
| `write_file` | Write or overwrite a file |
|
|
119
|
+
| `append_file` | Append text to a file |
|
|
120
|
+
| `touch_file` | Create empty file or update timestamps |
|
|
121
|
+
| `create_directory` | Create a directory tree (mkdir -p) |
|
|
122
|
+
| `delete_path` | Delete a file or directory |
|
|
123
|
+
| `copy_path` | Copy a file or directory |
|
|
124
|
+
| `move_path` | Move or rename a file or directory |
|
|
125
|
+
| `make_executable` | Set execute bits (Unix chmod +x) |
|
|
126
|
+
| `search_files` | Find files by name, glob, or regex |
|
|
127
|
+
|
|
128
|
+
### File editing — 5 tools
|
|
129
|
+
|
|
130
|
+
| Tool | What it does |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `search_text` | Grep for text inside files |
|
|
133
|
+
| `replace_text` | Find-and-replace inside one file |
|
|
134
|
+
| `patch_file` | Apply multiple edits to a file in a single call |
|
|
135
|
+
| `find_replace_all` | Find-and-replace across an entire directory tree |
|
|
136
|
+
| `diff_files` | Compare two files and show a unified diff |
|
|
137
|
+
|
|
138
|
+
### Multi-file — 2 tools
|
|
139
|
+
|
|
140
|
+
| Tool | What it does |
|
|
141
|
+
|---|---|
|
|
142
|
+
| `read_many_files` | Read multiple files at once |
|
|
143
|
+
| `write_many_files` | Write multiple files at once — great for scaffolding |
|
|
144
|
+
|
|
145
|
+
### Terminal & processes — 7 tools
|
|
146
|
+
|
|
147
|
+
| Tool | What it does |
|
|
148
|
+
|---|---|
|
|
149
|
+
| `run_command` | Run any shell command, capture stdout/stderr |
|
|
150
|
+
| `run_script` | Run a code snippet inline (Node, Python, PowerShell, Bash) |
|
|
151
|
+
| `start_process` | Start a long-running background process |
|
|
152
|
+
| `read_process` | Poll stdout/stderr of a background process |
|
|
153
|
+
| `send_to_process` | Send input to a background process (REPL support) |
|
|
154
|
+
| `stop_process` | Stop a background process |
|
|
155
|
+
| `list_processes` | List all managed background processes |
|
|
156
|
+
|
|
157
|
+
### System — 5 tools
|
|
158
|
+
|
|
159
|
+
| Tool | What it does |
|
|
160
|
+
|---|---|
|
|
161
|
+
| `current_context` | Show connector config and session stats |
|
|
162
|
+
| `system_info` | OS, CPU, RAM, Node version |
|
|
163
|
+
| `disk_usage` | Drive space (df / PowerShell Get-PSDrive) |
|
|
164
|
+
| `list_system_processes` | OS process list (ps / tasklist) |
|
|
165
|
+
| `network_info` | Network interfaces with IPs and MACs |
|
|
166
|
+
|
|
167
|
+
### Environment — 3 tools
|
|
168
|
+
|
|
169
|
+
| Tool | What it does |
|
|
170
|
+
|---|---|
|
|
171
|
+
| `environment_list` | List env vars (secrets redacted by default) |
|
|
172
|
+
| `environment_get` | Get a single env var |
|
|
173
|
+
| `environment_set` | Set an env var for the session |
|
|
174
|
+
|
|
175
|
+
### Git — 5 tools
|
|
176
|
+
|
|
177
|
+
| Tool | What it does |
|
|
178
|
+
|---|---|
|
|
179
|
+
| `git_status` | Working tree status |
|
|
180
|
+
| `git_diff` | Show uncommitted changes or diff between commits |
|
|
181
|
+
| `git_log` | Recent commit history |
|
|
182
|
+
| `git_commit` | Stage files and create a commit |
|
|
183
|
+
| `git_branch` | List, create, switch, or delete branches |
|
|
184
|
+
|
|
185
|
+
### Network & web — 3 tools
|
|
186
|
+
|
|
187
|
+
| Tool | What it does |
|
|
188
|
+
|---|---|
|
|
189
|
+
| `http_request` | Make HTTP/HTTPS requests with custom headers and body |
|
|
190
|
+
| `port_check` | Check if a TCP port is open |
|
|
191
|
+
| `open_url` | Open a URL in the host browser |
|
|
192
|
+
|
|
193
|
+
### Data & utilities — 9 tools
|
|
194
|
+
|
|
195
|
+
| Tool | What it does |
|
|
196
|
+
|---|---|
|
|
197
|
+
| `count_lines` | Count lines, words, and characters in a file |
|
|
198
|
+
| `hash_file` | Compute file hash (SHA-256, SHA-1, MD5, SHA-512) |
|
|
199
|
+
| `json_query` | Extract a value from a JSON file with a dot-path query |
|
|
200
|
+
| `clipboard_read` | Read the system clipboard |
|
|
201
|
+
| `clipboard_write` | Write to the system clipboard |
|
|
202
|
+
| `archive_create` | Create a .zip or .tar.gz archive |
|
|
203
|
+
| `archive_extract` | Extract a zip or tar archive |
|
|
204
|
+
| `generate_token` | Generate a secure token, UUID, or random password |
|
|
205
|
+
| `list_installed_packages` | Read package manifests (npm, pip, Cargo) |
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## HTTP endpoints
|
|
210
|
+
|
|
211
|
+
| Endpoint | Method | What it does |
|
|
212
|
+
|---|---|---|
|
|
213
|
+
| `/` | GET | Dashboard with status and MCP URL |
|
|
214
|
+
| `/mcp` | POST | MCP JSON-RPC 2.0 endpoint (used by ChatGPT) |
|
|
215
|
+
| `/health` | GET | Health check — returns `{"status":"ok"}` |
|
|
216
|
+
| `/stats` | GET | Session stats: uptime, call counts, top tools |
|
|
217
|
+
| `/tools` | GET | Full JSON list of all tool schemas |
|
|
218
|
+
| `/logs/live` | GET | Live SSE log stream |
|
|
219
|
+
| `/execute` | POST | Direct tool call — body: `{"tool":"tool_name",...args}` |
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Environment variables
|
|
224
|
+
|
|
225
|
+
Set these in a `.env` file at the project root, or export before running.
|
|
226
|
+
|
|
227
|
+
| Variable | Default | Description |
|
|
228
|
+
|---|---|---|
|
|
229
|
+
| `AI_PC_MCP_PORT` | `3001` | HTTP port |
|
|
230
|
+
| `AI_PC_MCP_HOST` | `0.0.0.0` | Bind address |
|
|
231
|
+
| `AI_PC_MCP_ROOT` | Drive root | Filesystem access boundary — AI cannot read outside this |
|
|
232
|
+
| `AI_PC_MCP_DEFAULT_CWD` | Home directory | Default working directory for file and command tools |
|
|
233
|
+
| `AI_PC_MCP_COMMAND_TIMEOUT_MS` | `30000` | Default shell command timeout (ms) |
|
|
234
|
+
| `AI_PC_MCP_MAX_READ_BYTES` | `4194304` (4 MB) | Max bytes read by `read_file` |
|
|
235
|
+
| `AI_PC_MCP_NO_TUNNEL` | — | Set to `true` to skip cloudflared and serve locally only |
|
|
236
|
+
| `AI_PC_MCP_PUBLIC_URL` | *(auto from tunnel)* | Override the public URL shown to the AI |
|
|
237
|
+
| `AI_PC_MCP_PROTECTED_PATHS` | *(runtime paths)* | Extra paths to protect, separated by `\|` |
|
|
238
|
+
| `AI_PC_MCP_JSON_LIMIT` | `100mb` | Max request body size |
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Security model
|
|
243
|
+
|
|
244
|
+
| Feature | Detail |
|
|
245
|
+
|---|---|
|
|
246
|
+
| **Folder-scoped by default** | Without `--bypass`, the AI can only access the directory you ran the command in |
|
|
247
|
+
| **Protected runtime** | The connector's own files in `~/.chatgpt-local-mcp` cannot be read, edited, or deleted by MCP tools |
|
|
248
|
+
| **Blocked commands** | `sudo`, `kill`, `pkill`, `taskkill`, `shutdown`, `reboot`, and destructive ops on protected paths are always blocked |
|
|
249
|
+
| **Secret redaction** | `environment_list` / `environment_get` auto-redact names containing `TOKEN`, `SECRET`, `PASSWORD`, `KEY`, etc. |
|
|
250
|
+
| **Cloud metadata blocked** | `http_request` cannot reach `169.254.169.254` or similar metadata endpoints |
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Runtime layout
|
|
255
|
+
|
|
256
|
+
On first run, the launcher copies the server to a protected directory and installs dependencies there:
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
~/.chatgpt-local-mcp/ (Windows: %USERPROFILE%\.chatgpt-local-mcp)
|
|
260
|
+
├── .env ← runtime config (written by the launcher)
|
|
261
|
+
├── bin/
|
|
262
|
+
│ └── cloudflared(.exe) ← auto-downloaded on first run
|
|
263
|
+
├── logs/
|
|
264
|
+
│ ├── server.log
|
|
265
|
+
│ ├── watchdog.log
|
|
266
|
+
│ └── cloudflared.log
|
|
267
|
+
├── node_modules/
|
|
268
|
+
├── package.json
|
|
269
|
+
└── src/
|
|
270
|
+
└── server.js ← protected server copy
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
MCP tools cannot read or modify anything inside this directory.
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## npm scripts
|
|
278
|
+
|
|
279
|
+
| Script | What it does |
|
|
280
|
+
|---|---|
|
|
281
|
+
| `npm start` | Start server + tunnel (quiet mode) |
|
|
282
|
+
| `npm run start:log` | Start with live verbose logs |
|
|
283
|
+
| `npm run serve` | Run server only, no tunnel (for manual tunnel setup) |
|
|
284
|
+
| `npm run dev` | Dev mode — auto-restart on file changes |
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Windows tips
|
|
289
|
+
|
|
290
|
+
- **cloudflared** is auto-downloaded to `%USERPROFILE%\.chatgpt-local-mcp\bin\cloudflared.exe` on first run — no manual install needed
|
|
291
|
+
- The tunnel URL changes on every restart — update the ChatGPT connector URL after each restart
|
|
292
|
+
- To stop: press `Ctrl+C` in the terminal
|
|
293
|
+
- The `scripts\start.cmd` launcher can be double-clicked or pinned as a shortcut
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## License
|
|
298
|
+
|
|
299
|
+
MIT
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* chatgpt-local-mcp — CLI entry point
|
|
4
|
+
*
|
|
5
|
+
* Install globally: npm install -g chatgpt-local-mcp
|
|
6
|
+
*
|
|
7
|
+
* Usage (run inside any project folder):
|
|
8
|
+
* chatgpt-local-mcp # folder-scoped (AI sees only this folder)
|
|
9
|
+
* chatgpt-local-mcp --bypass # full filesystem access
|
|
10
|
+
* chatgpt-local-mcp --log # live tool-call logs in terminal
|
|
11
|
+
* chatgpt-local-mcp --port 3002 # custom port
|
|
12
|
+
* chatgpt-local-mcp --no-tunnel # local only (skip cloudflared)
|
|
13
|
+
* chatgpt-local-mcp --help
|
|
14
|
+
* chatgpt-local-mcp --version
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { fileURLToPath } from "url";
|
|
18
|
+
import { dirname, resolve } from "path";
|
|
19
|
+
import { spawn } from "child_process";
|
|
20
|
+
import { readFileSync } from "fs";
|
|
21
|
+
import os from "os";
|
|
22
|
+
|
|
23
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
24
|
+
const __dirname = dirname(__filename);
|
|
25
|
+
|
|
26
|
+
const pkg = JSON.parse(readFileSync(resolve(__dirname, "../package.json"), "utf8"));
|
|
27
|
+
const args = process.argv.slice(2);
|
|
28
|
+
|
|
29
|
+
// ── ANSI colours ──────────────────────────────────────────────────────────────
|
|
30
|
+
const bold = (s) => `\x1b[1m${s}\x1b[0m`;
|
|
31
|
+
const cyan = (s) => `\x1b[1;36m${s}\x1b[0m`;
|
|
32
|
+
const green = (s) => `\x1b[1;32m${s}\x1b[0m`;
|
|
33
|
+
const yellow = (s) => `\x1b[1;33m${s}\x1b[0m`;
|
|
34
|
+
const dim = (s) => `\x1b[2m${s}\x1b[0m`;
|
|
35
|
+
|
|
36
|
+
// ── --help ────────────────────────────────────────────────────────────────────
|
|
37
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
38
|
+
console.log(`
|
|
39
|
+
${cyan("chatgpt-local-mcp")} ${dim(`v${pkg.version}`)}
|
|
40
|
+
|
|
41
|
+
Give ChatGPT (or any MCP client) agentic access to your local project.
|
|
42
|
+
By default, the AI can ${bold("only")} access the folder you run this in.
|
|
43
|
+
|
|
44
|
+
${bold("Usage:")}
|
|
45
|
+
chatgpt-local-mcp [options]
|
|
46
|
+
|
|
47
|
+
${bold("Options:")}
|
|
48
|
+
${cyan("--bypass")} Allow access to the entire filesystem
|
|
49
|
+
${yellow("(removes folder restriction — use with care)")}
|
|
50
|
+
${cyan("--port")} ${dim("<n>")} HTTP port (default: 3001)
|
|
51
|
+
${cyan("--log")} Stream live tool-call logs in this terminal
|
|
52
|
+
${cyan("--no-tunnel")} Skip cloudflared — serve on localhost only
|
|
53
|
+
${cyan("--version")} Print version and exit
|
|
54
|
+
${cyan("--help")} Show this help
|
|
55
|
+
|
|
56
|
+
${bold("Examples:")}
|
|
57
|
+
${dim("# In your project — AI sees only this folder")}
|
|
58
|
+
cd my-project
|
|
59
|
+
chatgpt-local-mcp
|
|
60
|
+
|
|
61
|
+
${dim("# With live logs")}
|
|
62
|
+
chatgpt-local-mcp --log
|
|
63
|
+
|
|
64
|
+
${dim("# Full filesystem access")}
|
|
65
|
+
chatgpt-local-mcp --bypass --log
|
|
66
|
+
|
|
67
|
+
${dim("# Custom port")}
|
|
68
|
+
chatgpt-local-mcp --port 3002
|
|
69
|
+
|
|
70
|
+
${bold("After startup, paste the /mcp URL into:")}
|
|
71
|
+
ChatGPT → Settings → Connectors → Add connector → MCP
|
|
72
|
+
`);
|
|
73
|
+
process.exit(0);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ── --version ─────────────────────────────────────────────────────────────────
|
|
77
|
+
if (args.includes("--version") || args.includes("-v")) {
|
|
78
|
+
console.log(pkg.version);
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ── parse flags ───────────────────────────────────────────────────────────────
|
|
83
|
+
const bypass = args.includes("--bypass");
|
|
84
|
+
const logMode = args.includes("--log");
|
|
85
|
+
const noTunnel = args.includes("--no-tunnel");
|
|
86
|
+
|
|
87
|
+
const portIdx = args.findIndex((a) => a === "--port");
|
|
88
|
+
const port = portIdx !== -1 ? Number(args[portIdx + 1]) || 3001 : undefined;
|
|
89
|
+
|
|
90
|
+
// ── security scope ────────────────────────────────────────────────────────────
|
|
91
|
+
const cwd = process.cwd();
|
|
92
|
+
|
|
93
|
+
if (bypass) {
|
|
94
|
+
// Full filesystem access — remove any folder restriction
|
|
95
|
+
delete process.env.AI_PC_MCP_ROOT;
|
|
96
|
+
delete process.env.AI_PC_MCP_DEFAULT_CWD;
|
|
97
|
+
process.env.AI_PC_MCP_BYPASS = "true";
|
|
98
|
+
} else {
|
|
99
|
+
// Folder-scoped mode: AI can only access the current working directory
|
|
100
|
+
process.env.AI_PC_MCP_ROOT = cwd;
|
|
101
|
+
process.env.AI_PC_MCP_DEFAULT_CWD = cwd;
|
|
102
|
+
process.env.AI_PC_MCP_BYPASS = "false";
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (port) process.env.AI_PC_MCP_PORT = String(port);
|
|
106
|
+
if (noTunnel) process.env.AI_PC_MCP_NO_TUNNEL = "true";
|
|
107
|
+
|
|
108
|
+
// Signal to start.js that cli.js already printed a header
|
|
109
|
+
process.env.CHATGPT_LOCAL_MCP_CLI = "1";
|
|
110
|
+
|
|
111
|
+
// ── header banner ─────────────────────────────────────────────────────────────
|
|
112
|
+
// Strip ANSI codes to get the true visual length for centering.
|
|
113
|
+
const visLen = (s) => s.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
114
|
+
const BOX_W = 62; // inner width between ║ chars (total box = 64)
|
|
115
|
+
|
|
116
|
+
const titleRaw = `ChatGPT Local MCP v${pkg.version}`;
|
|
117
|
+
const titleStyled = `ChatGPT Local MCP ${dim(`v${pkg.version}`)}`;
|
|
118
|
+
const lp = Math.floor((BOX_W - titleRaw.length) / 2);
|
|
119
|
+
const rp = BOX_W - titleRaw.length - lp;
|
|
120
|
+
|
|
121
|
+
console.log();
|
|
122
|
+
console.log(cyan("╔" + "═".repeat(BOX_W) + "╗"));
|
|
123
|
+
console.log(cyan("║") + " ".repeat(lp) + titleStyled + " ".repeat(rp) + cyan("║"));
|
|
124
|
+
console.log(cyan("╚" + "═".repeat(BOX_W) + "╝"));
|
|
125
|
+
console.log();
|
|
126
|
+
|
|
127
|
+
if (bypass) {
|
|
128
|
+
const root = os.platform() === "win32"
|
|
129
|
+
? (process.env.SystemDrive || "C:") + "\\"
|
|
130
|
+
: "/";
|
|
131
|
+
console.log(yellow(" ⚠️ Bypass mode — full filesystem access"));
|
|
132
|
+
console.log(yellow(` Root: ${root}`));
|
|
133
|
+
console.log(yellow(" The AI can read and write anywhere on this machine."));
|
|
134
|
+
} else {
|
|
135
|
+
console.log(green(" 🔒 Folder-scoped mode"));
|
|
136
|
+
console.log(` AI access restricted to: ${bold(cwd)}`);
|
|
137
|
+
console.log(dim(" Use --bypass to allow full filesystem access."));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (noTunnel) {
|
|
141
|
+
const p = port || 3001;
|
|
142
|
+
console.log();
|
|
143
|
+
console.log(dim(` 🔌 Tunnel disabled — local only: http://localhost:${p}/mcp`));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
console.log();
|
|
147
|
+
|
|
148
|
+
// ── launch ────────────────────────────────────────────────────────────────────
|
|
149
|
+
const startScript = resolve(__dirname, "../scripts/start.js");
|
|
150
|
+
const nodeArgs = [startScript];
|
|
151
|
+
if (logMode) nodeArgs.push("--log");
|
|
152
|
+
|
|
153
|
+
const child = spawn(process.execPath, nodeArgs, {
|
|
154
|
+
stdio: "inherit",
|
|
155
|
+
env: process.env,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
159
|
+
|
|
160
|
+
process.on("SIGINT", () => { try { child.kill("SIGINT"); } catch {} });
|
|
161
|
+
process.on("SIGTERM", () => { try { child.kill("SIGTERM"); } catch {} });
|
|
162
|
+
process.on("SIGHUP", () => { try { child.kill("SIGHUP"); } catch {} });
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "chatgpt-local-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Give ChatGPT (or any MCP client) agentic access to your local project folder — filesystem, terminal, git, processes, clipboard, archives and more — over a secure cloudflared tunnel. Folder-scoped by default for security.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/server.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"chatgpt-local-mcp": "./bin/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node scripts/start.js",
|
|
12
|
+
"start:log": "node scripts/start.js --log",
|
|
13
|
+
"win:start": "node scripts/start.js",
|
|
14
|
+
"win:log": "node scripts/start.js --log",
|
|
15
|
+
"serve": "node src/server.js",
|
|
16
|
+
"dev": "node --watch src/server.js"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"bin",
|
|
20
|
+
"scripts",
|
|
21
|
+
"src"
|
|
22
|
+
],
|
|
23
|
+
"keywords": [
|
|
24
|
+
"mcp",
|
|
25
|
+
"chatgpt",
|
|
26
|
+
"ai",
|
|
27
|
+
"local",
|
|
28
|
+
"filesystem",
|
|
29
|
+
"model-context-protocol",
|
|
30
|
+
"claude",
|
|
31
|
+
"llm"
|
|
32
|
+
],
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=18.0.0"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"express": "^4.18.2"
|
|
38
|
+
}
|
|
39
|
+
}
|