mcp-remote 0.0.16 → 0.0.17
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 +23 -0
- package/dist/{chunk-NCBLL6DH.js → chunk-XGBHOQQX.js} +34 -6
- package/dist/client.js +5 -5
- package/dist/proxy.js +5 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -32,6 +32,29 @@ All the most popular MCP clients (Claude Desktop, Cursor & Windsurf) use the fol
|
|
|
32
32
|
}
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
### Custom Headers
|
|
36
|
+
|
|
37
|
+
To bypass authentication, or to emit custom headers on all requests to your remote server, pass `--header` CLI arguments:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"mcpServers": {
|
|
42
|
+
"remote-example": {
|
|
43
|
+
"command": "npx",
|
|
44
|
+
"args": [
|
|
45
|
+
"mcp-remote",
|
|
46
|
+
"https://remote.mcp.server/sse",
|
|
47
|
+
"--header",
|
|
48
|
+
"Authorization: Bearer ${AUTH_TOKEN}"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"env": {
|
|
52
|
+
"AUTH_TOKEN": "..."
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
35
58
|
### Flags
|
|
36
59
|
|
|
37
60
|
* If `npx` is producing errors, consider adding `-y` as the first argument to auto-accept the installation of the `mcp-remote` package.
|
|
@@ -14,7 +14,7 @@ var require_package = __commonJS({
|
|
|
14
14
|
"package.json"(exports, module) {
|
|
15
15
|
module.exports = {
|
|
16
16
|
name: "mcp-remote",
|
|
17
|
-
version: "0.0.
|
|
17
|
+
version: "0.0.17",
|
|
18
18
|
description: "Remote proxy for Model Context Protocol, allowing local-only clients to connect to remote servers using oAuth",
|
|
19
19
|
keywords: [
|
|
20
20
|
"mcp",
|
|
@@ -37,8 +37,8 @@ var require_package = __commonJS({
|
|
|
37
37
|
"mcp-remote-client": "dist/client.js"
|
|
38
38
|
},
|
|
39
39
|
scripts: {
|
|
40
|
-
dev: "tsup --watch",
|
|
41
40
|
build: "tsup",
|
|
41
|
+
"build:watch": "tsup --watch",
|
|
42
42
|
check: "prettier --check . && tsc"
|
|
43
43
|
},
|
|
44
44
|
dependencies: {
|
|
@@ -120,10 +120,10 @@ function mcpProxy({ transportToClient, transportToServer }) {
|
|
|
120
120
|
log("Error from remote server:", error);
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
|
-
async function connectToRemoteServer(serverUrl, authProvider, waitForAuthCode, skipBrowserAuth = false) {
|
|
123
|
+
async function connectToRemoteServer(serverUrl, authProvider, headers, waitForAuthCode, skipBrowserAuth = false) {
|
|
124
124
|
log(`[${pid}] Connecting to remote server: ${serverUrl}`);
|
|
125
125
|
const url = new URL(serverUrl);
|
|
126
|
-
const transport = new SSEClientTransport(url, { authProvider });
|
|
126
|
+
const transport = new SSEClientTransport(url, { authProvider, requestInit: { headers } });
|
|
127
127
|
try {
|
|
128
128
|
await transport.start();
|
|
129
129
|
log("Connected to remote server");
|
|
@@ -139,7 +139,7 @@ async function connectToRemoteServer(serverUrl, authProvider, waitForAuthCode, s
|
|
|
139
139
|
try {
|
|
140
140
|
log("Completing authorization...");
|
|
141
141
|
await transport.finishAuth(code);
|
|
142
|
-
const newTransport = new SSEClientTransport(url, { authProvider });
|
|
142
|
+
const newTransport = new SSEClientTransport(url, { authProvider, requestInit: { headers } });
|
|
143
143
|
await newTransport.start();
|
|
144
144
|
log("Connected to remote server after authentication");
|
|
145
145
|
return newTransport;
|
|
@@ -242,6 +242,19 @@ async function parseCommandLineArgs(args, defaultPort, usage) {
|
|
|
242
242
|
if (clean) {
|
|
243
243
|
args.splice(cleanIndex, 1);
|
|
244
244
|
}
|
|
245
|
+
const headers = {};
|
|
246
|
+
args.forEach((arg, i) => {
|
|
247
|
+
if (arg === "--header" && i < args.length - 1) {
|
|
248
|
+
const value = args[i + 1];
|
|
249
|
+
const match = value.match(/^([A-Za-z0-9_-]+):(.*)$/);
|
|
250
|
+
if (match) {
|
|
251
|
+
headers[match[1]] = match[2];
|
|
252
|
+
} else {
|
|
253
|
+
log(`Warning: ignoring invalid header argument: ${value}`);
|
|
254
|
+
}
|
|
255
|
+
args.splice(i, 2);
|
|
256
|
+
}
|
|
257
|
+
});
|
|
245
258
|
const serverUrl = args[0];
|
|
246
259
|
const specifiedPort = args[1] ? parseInt(args[1]) : void 0;
|
|
247
260
|
if (!serverUrl) {
|
|
@@ -263,7 +276,22 @@ async function parseCommandLineArgs(args, defaultPort, usage) {
|
|
|
263
276
|
if (clean) {
|
|
264
277
|
log("Clean mode enabled: config files will be reset before reading");
|
|
265
278
|
}
|
|
266
|
-
|
|
279
|
+
if (Object.keys(headers).length > 0) {
|
|
280
|
+
log(`Using custom headers: ${JSON.stringify(headers)}`);
|
|
281
|
+
}
|
|
282
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
283
|
+
headers[key] = value.replace(/\$\{([^}]+)}/g, (match, envVarName) => {
|
|
284
|
+
const envVarValue = process.env[envVarName];
|
|
285
|
+
if (envVarValue !== void 0) {
|
|
286
|
+
log(`Replacing ${match} with environment value in header '${key}'`);
|
|
287
|
+
return envVarValue;
|
|
288
|
+
} else {
|
|
289
|
+
log(`Warning: Environment variable '${envVarName}' not found for header '${key}'.`);
|
|
290
|
+
return "";
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
return { serverUrl, callbackPort, clean, headers };
|
|
267
295
|
}
|
|
268
296
|
function setupSignalHandlers(cleanup) {
|
|
269
297
|
process.on("SIGINT", async () => {
|
package/dist/client.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
log,
|
|
8
8
|
parseCommandLineArgs,
|
|
9
9
|
setupSignalHandlers
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-XGBHOQQX.js";
|
|
11
11
|
|
|
12
12
|
// src/client.ts
|
|
13
13
|
import { EventEmitter } from "events";
|
|
@@ -15,7 +15,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
|
15
15
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
16
16
|
import { ListResourcesResultSchema, ListToolsResultSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
17
17
|
import { UnauthorizedError } from "@modelcontextprotocol/sdk/client/auth.js";
|
|
18
|
-
async function runClient(serverUrl, callbackPort, clean = false) {
|
|
18
|
+
async function runClient(serverUrl, callbackPort, headers, clean = false) {
|
|
19
19
|
const events = new EventEmitter();
|
|
20
20
|
const serverUrlHash = getServerUrlHash(serverUrl);
|
|
21
21
|
const { server, waitForAuthCode, skipBrowserAuth } = await coordinateAuth(serverUrlHash, callbackPort, events);
|
|
@@ -40,7 +40,7 @@ async function runClient(serverUrl, callbackPort, clean = false) {
|
|
|
40
40
|
);
|
|
41
41
|
const url = new URL(serverUrl);
|
|
42
42
|
function initTransport() {
|
|
43
|
-
const transport2 = new SSEClientTransport(url, { authProvider });
|
|
43
|
+
const transport2 = new SSEClientTransport(url, { authProvider, requestInit: { headers } });
|
|
44
44
|
transport2.onmessage = (message) => {
|
|
45
45
|
log("Received message:", JSON.stringify(message, null, 2));
|
|
46
46
|
};
|
|
@@ -108,8 +108,8 @@ async function runClient(serverUrl, callbackPort, clean = false) {
|
|
|
108
108
|
}
|
|
109
109
|
log("Listening for messages. Press Ctrl+C to exit.");
|
|
110
110
|
}
|
|
111
|
-
parseCommandLineArgs(process.argv.slice(2), 3333, "Usage: npx tsx client.ts [--clean] <https://server-url> [callback-port]").then(({ serverUrl, callbackPort, clean }) => {
|
|
112
|
-
return runClient(serverUrl, callbackPort, clean);
|
|
111
|
+
parseCommandLineArgs(process.argv.slice(2), 3333, "Usage: npx tsx client.ts [--clean] <https://server-url> [callback-port]").then(({ serverUrl, callbackPort, clean, headers }) => {
|
|
112
|
+
return runClient(serverUrl, callbackPort, headers, clean);
|
|
113
113
|
}).catch((error) => {
|
|
114
114
|
console.error("Fatal error:", error);
|
|
115
115
|
process.exit(1);
|
package/dist/proxy.js
CHANGED
|
@@ -8,12 +8,12 @@ import {
|
|
|
8
8
|
mcpProxy,
|
|
9
9
|
parseCommandLineArgs,
|
|
10
10
|
setupSignalHandlers
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-XGBHOQQX.js";
|
|
12
12
|
|
|
13
13
|
// src/proxy.ts
|
|
14
14
|
import { EventEmitter } from "events";
|
|
15
15
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
16
|
-
async function runProxy(serverUrl, callbackPort, clean = false) {
|
|
16
|
+
async function runProxy(serverUrl, callbackPort, headers, clean = false) {
|
|
17
17
|
const events = new EventEmitter();
|
|
18
18
|
const serverUrlHash = getServerUrlHash(serverUrl);
|
|
19
19
|
const { server, waitForAuthCode, skipBrowserAuth } = await coordinateAuth(serverUrlHash, callbackPort, events);
|
|
@@ -29,7 +29,7 @@ async function runProxy(serverUrl, callbackPort, clean = false) {
|
|
|
29
29
|
}
|
|
30
30
|
const localTransport = new StdioServerTransport();
|
|
31
31
|
try {
|
|
32
|
-
const remoteTransport = await connectToRemoteServer(serverUrl, authProvider, waitForAuthCode, skipBrowserAuth);
|
|
32
|
+
const remoteTransport = await connectToRemoteServer(serverUrl, authProvider, headers, waitForAuthCode, skipBrowserAuth);
|
|
33
33
|
mcpProxy({
|
|
34
34
|
transportToClient: localTransport,
|
|
35
35
|
transportToServer: remoteTransport
|
|
@@ -72,8 +72,8 @@ to the CA certificate file. If using claude_desktop_config.json, this might look
|
|
|
72
72
|
process.exit(1);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
-
parseCommandLineArgs(process.argv.slice(2), 3334, "Usage: npx tsx proxy.ts [--clean] <https://server-url> [callback-port]").then(({ serverUrl, callbackPort, clean }) => {
|
|
76
|
-
return runProxy(serverUrl, callbackPort, clean);
|
|
75
|
+
parseCommandLineArgs(process.argv.slice(2), 3334, "Usage: npx tsx proxy.ts [--clean] <https://server-url> [callback-port]").then(({ serverUrl, callbackPort, clean, headers }) => {
|
|
76
|
+
return runProxy(serverUrl, callbackPort, headers, clean);
|
|
77
77
|
}).catch((error) => {
|
|
78
78
|
log("Fatal error:", error);
|
|
79
79
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-remote",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"description": "Remote proxy for Model Context Protocol, allowing local-only clients to connect to remote servers using oAuth",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"mcp-remote-client": "dist/client.js"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
|
-
"dev": "tsup --watch",
|
|
27
26
|
"build": "tsup",
|
|
27
|
+
"build:watch": "tsup --watch",
|
|
28
28
|
"check": "prettier --check . && tsc"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|