mcp-remote 0.1.7 → 0.1.8
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 +32 -1
- package/dist/{chunk-ETC3CC4Y.js → chunk-WTVTTD74.js} +41 -6
- package/dist/client.js +7 -5
- package/dist/proxy.js +7 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -152,6 +152,37 @@ npx mcp-remote https://example.remote/server --transport sse-only
|
|
|
152
152
|
- `http-only`: Only uses HTTP transport, fails if the server doesn't support it
|
|
153
153
|
- `sse-only`: Only uses SSE transport, fails if the server doesn't support it
|
|
154
154
|
|
|
155
|
+
### Static OAuth Client Metadata
|
|
156
|
+
|
|
157
|
+
MCP Remote supports providing static OAuth client metadata instead of using the mcp-remote defaults.
|
|
158
|
+
This is useful when connecting to OAuth servers that expect specific client/software IDs or scopes.
|
|
159
|
+
|
|
160
|
+
Provide the client metadata as a JSON string or as a `@` prefixed filepath with the `--static-oauth-client-metadata` flag:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
npx mcp-remote https://example.remote/server --static-oauth-client-metadata '{ "scope": "space separated scopes" }'
|
|
164
|
+
# uses node readfile, so you probably want to use absolute paths if you're not sure what the cwd is
|
|
165
|
+
npx mcp-remote https://example.remote/server --static-oauth-client-metadata '@/Users/username/Library/Application Support/Claude/oauth_client_metadata.json'
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Static OAuth Client Information
|
|
169
|
+
|
|
170
|
+
Per the [spec](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization#2-4-dynamic-client-registration),
|
|
171
|
+
servers are encouraged but not required to support [OAuth dynamic client registration](https://datatracker.ietf.org/doc/html/rfc7591).
|
|
172
|
+
|
|
173
|
+
For these servers, MCP Remote supports providing static OAuth client information instead.
|
|
174
|
+
This is useful when connecting to OAuth servers that require pre-registered clients.
|
|
175
|
+
|
|
176
|
+
Provide the client metadata as a JSON string or as a `@` prefixed filepath with the `--static-oauth-client-info` flag:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
export MCP_REMOTE_CLIENT_ID=xxx
|
|
180
|
+
export MCP_REMOTE_CLIENT_SECRET=yyy
|
|
181
|
+
npx mcp-remote https://example.remote/server --static-oauth-client-info "{ \"client_id\": \"$MCP_REMOTE_CLIENT_ID\", \"client_secret\": \"$MCP_REMOTE_CLIENT_SECRET\" }"
|
|
182
|
+
# uses node readfile, so you probably want to use absolute paths if you're not sure what the cwd is
|
|
183
|
+
npx mcp-remote https://example.remote/server --static-oauth-client-info '@/Users/username/Library/Application Support/Claude/oauth_client_info.json'
|
|
184
|
+
```
|
|
185
|
+
|
|
155
186
|
### Claude Desktop
|
|
156
187
|
|
|
157
188
|
[Official Docs](https://modelcontextprotocol.io/quickstart/user)
|
|
@@ -208,7 +239,7 @@ Then restarting your MCP client.
|
|
|
208
239
|
|
|
209
240
|
### Check your Node version
|
|
210
241
|
|
|
211
|
-
Make sure that the version of Node you have installed is [18 or
|
|
242
|
+
Make sure that the version of Node you have installed is [18 or
|
|
212
243
|
higher](https://modelcontextprotocol.io/quickstart/server). Claude
|
|
213
244
|
Desktop will use your system version of Node, even if you have a newer
|
|
214
245
|
version installed elsewhere.
|
|
@@ -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.1.
|
|
17
|
+
version: "0.1.8",
|
|
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",
|
|
@@ -6733,7 +6733,7 @@ async function writeTextFile(serverUrlHash, filename, text) {
|
|
|
6733
6733
|
import express from "express";
|
|
6734
6734
|
import net from "net";
|
|
6735
6735
|
import crypto2 from "crypto";
|
|
6736
|
-
import fs2 from "fs/promises";
|
|
6736
|
+
import fs2, { readFile } from "fs/promises";
|
|
6737
6737
|
import path2 from "path";
|
|
6738
6738
|
import os2 from "os";
|
|
6739
6739
|
var REASON_AUTH_NEEDED = "authentication-needed";
|
|
@@ -7005,8 +7005,8 @@ function setupOAuthCallbackServerWithLongPoll(options) {
|
|
|
7005
7005
|
Authorization successful!
|
|
7006
7006
|
You may close this window and return to the CLI.
|
|
7007
7007
|
<script>
|
|
7008
|
-
// If this is a non-interactive session (no manual approval step was required) then
|
|
7009
|
-
// this should automatically close the window. If not, this will have no effect and
|
|
7008
|
+
// If this is a non-interactive session (no manual approval step was required) then
|
|
7009
|
+
// this should automatically close the window. If not, this will have no effect and
|
|
7010
7010
|
// the user will see the message above.
|
|
7011
7011
|
window.close();
|
|
7012
7012
|
</script>
|
|
@@ -7105,6 +7105,32 @@ async function parseCommandLineArgs(args, usage) {
|
|
|
7105
7105
|
host = args[hostIndex + 1];
|
|
7106
7106
|
log(`Using callback hostname: ${host}`);
|
|
7107
7107
|
}
|
|
7108
|
+
let staticOAuthClientMetadata = null;
|
|
7109
|
+
const staticOAuthClientMetadataIndex = args.indexOf("--static-oauth-client-metadata");
|
|
7110
|
+
if (staticOAuthClientMetadataIndex !== -1 && staticOAuthClientMetadataIndex < args.length - 1) {
|
|
7111
|
+
const staticOAuthClientMetadataArg = args[staticOAuthClientMetadataIndex + 1];
|
|
7112
|
+
if (staticOAuthClientMetadataArg.startsWith("@")) {
|
|
7113
|
+
const filePath = staticOAuthClientMetadataArg.slice(1);
|
|
7114
|
+
staticOAuthClientMetadata = JSON.parse(await readFile(filePath, "utf8"));
|
|
7115
|
+
log(`Using static OAuth client metadata from file: ${filePath}`);
|
|
7116
|
+
} else {
|
|
7117
|
+
staticOAuthClientMetadata = JSON.parse(staticOAuthClientMetadataArg);
|
|
7118
|
+
log(`Using static OAuth client metadata from string`);
|
|
7119
|
+
}
|
|
7120
|
+
}
|
|
7121
|
+
let staticOAuthClientInfo = null;
|
|
7122
|
+
const staticOAuthClientInfoIndex = args.indexOf("--static-oauth-client-info");
|
|
7123
|
+
if (staticOAuthClientInfoIndex !== -1 && staticOAuthClientInfoIndex < args.length - 1) {
|
|
7124
|
+
const staticOAuthClientInfoArg = args[staticOAuthClientInfoIndex + 1];
|
|
7125
|
+
if (staticOAuthClientInfoArg.startsWith("@")) {
|
|
7126
|
+
const filePath = staticOAuthClientInfoArg.slice(1);
|
|
7127
|
+
staticOAuthClientInfo = JSON.parse(await readFile(filePath, "utf8"));
|
|
7128
|
+
log(`Using static OAuth client information from file: ${filePath}`);
|
|
7129
|
+
} else {
|
|
7130
|
+
staticOAuthClientInfo = JSON.parse(staticOAuthClientInfoArg);
|
|
7131
|
+
log(`Using static OAuth client information from string`);
|
|
7132
|
+
}
|
|
7133
|
+
}
|
|
7108
7134
|
if (!serverUrl) {
|
|
7109
7135
|
log(usage);
|
|
7110
7136
|
process.exit(1);
|
|
@@ -7156,7 +7182,7 @@ async function parseCommandLineArgs(args, usage) {
|
|
|
7156
7182
|
}
|
|
7157
7183
|
});
|
|
7158
7184
|
}
|
|
7159
|
-
return { serverUrl, callbackPort, headers, transportStrategy, host, debug };
|
|
7185
|
+
return { serverUrl, callbackPort, headers, transportStrategy, host, debug, staticOAuthClientMetadata, staticOAuthClientInfo };
|
|
7160
7186
|
}
|
|
7161
7187
|
function setupSignalHandlers(cleanup) {
|
|
7162
7188
|
process.on("SIGINT", async () => {
|
|
@@ -7190,6 +7216,8 @@ var NodeOAuthClientProvider = class {
|
|
|
7190
7216
|
this.clientUri = options.clientUri || "https://github.com/modelcontextprotocol/mcp-cli";
|
|
7191
7217
|
this.softwareId = options.softwareId || "2e6dc280-f3c3-4e01-99a7-8181dbd1d23d";
|
|
7192
7218
|
this.softwareVersion = options.softwareVersion || MCP_REMOTE_VERSION;
|
|
7219
|
+
this.staticOAuthClientMetadata = options.staticOAuthClientMetadata;
|
|
7220
|
+
this.staticOAuthClientInfo = options.staticOAuthClientInfo;
|
|
7193
7221
|
}
|
|
7194
7222
|
serverUrlHash;
|
|
7195
7223
|
callbackPath;
|
|
@@ -7197,6 +7225,8 @@ var NodeOAuthClientProvider = class {
|
|
|
7197
7225
|
clientUri;
|
|
7198
7226
|
softwareId;
|
|
7199
7227
|
softwareVersion;
|
|
7228
|
+
staticOAuthClientMetadata;
|
|
7229
|
+
staticOAuthClientInfo;
|
|
7200
7230
|
get redirectUrl() {
|
|
7201
7231
|
return `http://${this.options.host}:${this.options.callbackPort}${this.callbackPath}`;
|
|
7202
7232
|
}
|
|
@@ -7209,7 +7239,8 @@ var NodeOAuthClientProvider = class {
|
|
|
7209
7239
|
client_name: this.clientName,
|
|
7210
7240
|
client_uri: this.clientUri,
|
|
7211
7241
|
software_id: this.softwareId,
|
|
7212
|
-
software_version: this.softwareVersion
|
|
7242
|
+
software_version: this.softwareVersion,
|
|
7243
|
+
...this.staticOAuthClientMetadata
|
|
7213
7244
|
};
|
|
7214
7245
|
}
|
|
7215
7246
|
/**
|
|
@@ -7218,6 +7249,10 @@ var NodeOAuthClientProvider = class {
|
|
|
7218
7249
|
*/
|
|
7219
7250
|
async clientInformation() {
|
|
7220
7251
|
if (DEBUG) await debugLog(this.serverUrlHash, "Reading client info");
|
|
7252
|
+
if (this.staticOAuthClientInfo) {
|
|
7253
|
+
if (DEBUG) await debugLog(this.serverUrlHash, "Returning static client info");
|
|
7254
|
+
return this.staticOAuthClientInfo;
|
|
7255
|
+
}
|
|
7221
7256
|
const clientInfo = await readJsonFile(this.serverUrlHash, "client_info.json", OAuthClientInformationFullSchema);
|
|
7222
7257
|
if (DEBUG) await debugLog(this.serverUrlHash, "Client info result:", clientInfo ? "Found" : "Not found");
|
|
7223
7258
|
return clientInfo;
|
package/dist/client.js
CHANGED
|
@@ -11,11 +11,11 @@ import {
|
|
|
11
11
|
log,
|
|
12
12
|
parseCommandLineArgs,
|
|
13
13
|
setupSignalHandlers
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-WTVTTD74.js";
|
|
15
15
|
|
|
16
16
|
// src/client.ts
|
|
17
17
|
import { EventEmitter } from "events";
|
|
18
|
-
async function runClient(serverUrl, callbackPort, headers, transportStrategy = "http-first", host) {
|
|
18
|
+
async function runClient(serverUrl, callbackPort, headers, transportStrategy = "http-first", host, staticOAuthClientMetadata, staticOAuthClientInfo) {
|
|
19
19
|
const events = new EventEmitter();
|
|
20
20
|
const serverUrlHash = getServerUrlHash(serverUrl);
|
|
21
21
|
const authCoordinator = createLazyAuthCoordinator(serverUrlHash, callbackPort, events);
|
|
@@ -23,7 +23,9 @@ async function runClient(serverUrl, callbackPort, headers, transportStrategy = "
|
|
|
23
23
|
serverUrl,
|
|
24
24
|
callbackPort,
|
|
25
25
|
host,
|
|
26
|
-
clientName: "MCP CLI Client"
|
|
26
|
+
clientName: "MCP CLI Client",
|
|
27
|
+
staticOAuthClientMetadata,
|
|
28
|
+
staticOAuthClientInfo
|
|
27
29
|
});
|
|
28
30
|
const client = new Client(
|
|
29
31
|
{
|
|
@@ -95,8 +97,8 @@ async function runClient(serverUrl, callbackPort, headers, transportStrategy = "
|
|
|
95
97
|
process.exit(1);
|
|
96
98
|
}
|
|
97
99
|
}
|
|
98
|
-
parseCommandLineArgs(process.argv.slice(2), "Usage: npx tsx client.ts <https://server-url> [callback-port] [--debug]").then(({ serverUrl, callbackPort, headers, transportStrategy, host,
|
|
99
|
-
return runClient(serverUrl, callbackPort, headers, transportStrategy, host);
|
|
100
|
+
parseCommandLineArgs(process.argv.slice(2), "Usage: npx tsx client.ts <https://server-url> [callback-port] [--debug]").then(({ serverUrl, callbackPort, headers, transportStrategy, host, staticOAuthClientMetadata, staticOAuthClientInfo }) => {
|
|
101
|
+
return runClient(serverUrl, callbackPort, headers, transportStrategy, host, staticOAuthClientMetadata, staticOAuthClientInfo);
|
|
100
102
|
}).catch((error) => {
|
|
101
103
|
console.error("Fatal error:", error);
|
|
102
104
|
process.exit(1);
|
package/dist/proxy.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
mcpProxy,
|
|
10
10
|
parseCommandLineArgs,
|
|
11
11
|
setupSignalHandlers
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-WTVTTD74.js";
|
|
13
13
|
|
|
14
14
|
// src/proxy.ts
|
|
15
15
|
import { EventEmitter } from "events";
|
|
@@ -110,7 +110,7 @@ var StdioServerTransport = class {
|
|
|
110
110
|
};
|
|
111
111
|
|
|
112
112
|
// src/proxy.ts
|
|
113
|
-
async function runProxy(serverUrl, callbackPort, headers, transportStrategy = "http-first", host) {
|
|
113
|
+
async function runProxy(serverUrl, callbackPort, headers, transportStrategy = "http-first", host, staticOAuthClientMetadata, staticOAuthClientInfo) {
|
|
114
114
|
const events = new EventEmitter();
|
|
115
115
|
const serverUrlHash = getServerUrlHash(serverUrl);
|
|
116
116
|
const authCoordinator = createLazyAuthCoordinator(serverUrlHash, callbackPort, events);
|
|
@@ -118,7 +118,9 @@ async function runProxy(serverUrl, callbackPort, headers, transportStrategy = "h
|
|
|
118
118
|
serverUrl,
|
|
119
119
|
callbackPort,
|
|
120
120
|
host,
|
|
121
|
-
clientName: "MCP CLI Proxy"
|
|
121
|
+
clientName: "MCP CLI Proxy",
|
|
122
|
+
staticOAuthClientMetadata,
|
|
123
|
+
staticOAuthClientInfo
|
|
122
124
|
});
|
|
123
125
|
const localTransport = new StdioServerTransport();
|
|
124
126
|
let server = null;
|
|
@@ -182,8 +184,8 @@ to the CA certificate file. If using claude_desktop_config.json, this might look
|
|
|
182
184
|
process.exit(1);
|
|
183
185
|
}
|
|
184
186
|
}
|
|
185
|
-
parseCommandLineArgs(process.argv.slice(2), "Usage: npx tsx proxy.ts <https://server-url> [callback-port] [--debug]").then(({ serverUrl, callbackPort, headers, transportStrategy, host, debug }) => {
|
|
186
|
-
return runProxy(serverUrl, callbackPort, headers, transportStrategy, host);
|
|
187
|
+
parseCommandLineArgs(process.argv.slice(2), "Usage: npx tsx proxy.ts <https://server-url> [callback-port] [--debug]").then(({ serverUrl, callbackPort, headers, transportStrategy, host, debug, staticOAuthClientMetadata, staticOAuthClientInfo }) => {
|
|
188
|
+
return runProxy(serverUrl, callbackPort, headers, transportStrategy, host, staticOAuthClientMetadata, staticOAuthClientInfo);
|
|
187
189
|
}).catch((error) => {
|
|
188
190
|
log("Fatal error:", error);
|
|
189
191
|
process.exit(1);
|