mcp-remote 0.1.21 → 0.1.22

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 CHANGED
@@ -135,6 +135,24 @@ To bypass authentication, or to emit custom headers on all requests to your remo
135
135
  ]
136
136
  ```
137
137
 
138
+ * To ignore specific tools from the remote server, add the `--ignore-tool` flag. This will filter out tools matching the specified patterns from both `tools/list` responses and block `tools/call` requests. Supports wildcard patterns with `*`.
139
+
140
+ ```json
141
+ "args": [
142
+ "mcp-remote",
143
+ "https://remote.mcp.server/sse",
144
+ "--ignore-tool",
145
+ "delete*",
146
+ "--ignore-tool",
147
+ "remove*"
148
+ ]
149
+ ```
150
+
151
+ You can specify multiple `--ignore-tool` flags to ignore different patterns. Examples:
152
+ - `delete*` - ignores all tools starting with "delete" (e.g., `deleteTask`, `deleteUser`)
153
+ - `*account` - ignores all tools ending with "account" (e.g., `getAccount`, `updateAccount`)
154
+ - `exactTool` - ignores only the tool named exactly "exactTool"
155
+
138
156
  ### Transport Strategies
139
157
 
140
158
  MCP Remote supports different transport strategies when connecting to an MCP server. This allows you to control whether it uses Server-Sent Events (SSE) or HTTP transport, and in what order it tries them.
@@ -11872,7 +11872,7 @@ var Client = class extends Protocol {
11872
11872
  };
11873
11873
 
11874
11874
  // package.json
11875
- var version = "0.1.21";
11875
+ var version = "0.1.22";
11876
11876
 
11877
11877
  // node_modules/.pnpm/pkce-challenge@5.0.0/node_modules/pkce-challenge/dist/index.node.js
11878
11878
  var crypto;
@@ -13679,11 +13679,75 @@ function log(str, ...rest) {
13679
13679
  debugLog(str, ...rest);
13680
13680
  }
13681
13681
  }
13682
- function mcpProxy({ transportToClient, transportToServer }) {
13682
+ var MESSAGE_BLOCKED = Symbol("MessageBlocked");
13683
+ var isMessageBlocked = (value) => value === MESSAGE_BLOCKED;
13684
+ function createMessageTransformer({
13685
+ transformRequestFunction,
13686
+ transformResponseFunction
13687
+ } = {}) {
13688
+ const pendingRequests = /* @__PURE__ */ new Map();
13689
+ const interceptRequest = (message) => {
13690
+ const messageId = message.id;
13691
+ if (!messageId) return message;
13692
+ pendingRequests.set(messageId, message);
13693
+ return transformRequestFunction?.(message) ?? message;
13694
+ };
13695
+ const interceptResponse = (message) => {
13696
+ const messageId = message.id;
13697
+ if (!messageId) return message;
13698
+ const originalRequest = pendingRequests.get(messageId);
13699
+ pendingRequests.delete(messageId);
13700
+ return transformResponseFunction?.(originalRequest, message) ?? message;
13701
+ };
13702
+ return {
13703
+ interceptRequest,
13704
+ interceptResponse
13705
+ };
13706
+ }
13707
+ function mcpProxy({
13708
+ transportToClient,
13709
+ transportToServer,
13710
+ ignoredTools = []
13711
+ }) {
13683
13712
  let transportToClientClosed = false;
13684
13713
  let transportToServerClosed = false;
13714
+ const messageTransformer = createMessageTransformer({
13715
+ transformRequestFunction: (request) => {
13716
+ if (request.method === "tools/call" && request.params?.name) {
13717
+ const toolName = request.params.name;
13718
+ if (!shouldIncludeTool(ignoredTools, toolName)) {
13719
+ const errorResponse = {
13720
+ jsonrpc: "2.0",
13721
+ id: request.id,
13722
+ error: {
13723
+ code: -32603,
13724
+ message: `Tool "${toolName}" is not available`
13725
+ }
13726
+ };
13727
+ transportToClient.send(errorResponse).catch(onClientError);
13728
+ return MESSAGE_BLOCKED;
13729
+ }
13730
+ }
13731
+ return request;
13732
+ },
13733
+ transformResponseFunction: (req, res) => {
13734
+ if (req.method === "tools/list") {
13735
+ return {
13736
+ ...res,
13737
+ result: {
13738
+ ...res.result,
13739
+ tools: res.result.tools.filter((tool) => shouldIncludeTool(ignoredTools, tool.name))
13740
+ }
13741
+ };
13742
+ }
13743
+ return res;
13744
+ }
13745
+ });
13685
13746
  transportToClient.onmessage = (_message) => {
13686
- const message = _message;
13747
+ const message = messageTransformer.interceptRequest(_message);
13748
+ if (isMessageBlocked(message)) {
13749
+ return;
13750
+ }
13687
13751
  log("[Local\u2192Remote]", message.method || message.id);
13688
13752
  if (DEBUG) {
13689
13753
  debugLog("Local \u2192 Remote message", {
@@ -13703,7 +13767,7 @@ function mcpProxy({ transportToClient, transportToServer }) {
13703
13767
  transportToServer.send(message).catch(onServerError);
13704
13768
  };
13705
13769
  transportToServer.onmessage = (_message) => {
13706
- const message = _message;
13770
+ const message = messageTransformer.interceptResponse(_message);
13707
13771
  log("[Remote\u2192Local]", message.method || message.id);
13708
13772
  if (DEBUG) {
13709
13773
  debugLog("Remote \u2192 Local message", {
@@ -14045,6 +14109,18 @@ async function parseCommandLineArgs(args, usage) {
14045
14109
  authorizeResource = args[resourceIndex + 1];
14046
14110
  log(`Using authorize resource: ${authorizeResource}`);
14047
14111
  }
14112
+ const ignoredTools = [];
14113
+ let j = 0;
14114
+ while (j < args.length) {
14115
+ if (args[j] === "--ignore-tool" && j < args.length - 1) {
14116
+ const toolName = args[j + 1];
14117
+ ignoredTools.push(toolName);
14118
+ log(`Ignoring tool: ${toolName}`);
14119
+ args.splice(j, 2);
14120
+ continue;
14121
+ }
14122
+ j++;
14123
+ }
14048
14124
  if (!serverUrl) {
14049
14125
  log(usage);
14050
14126
  process.exit(1);
@@ -14104,7 +14180,8 @@ async function parseCommandLineArgs(args, usage) {
14104
14180
  debug,
14105
14181
  staticOAuthClientMetadata,
14106
14182
  staticOAuthClientInfo,
14107
- authorizeResource
14183
+ authorizeResource,
14184
+ ignoredTools
14108
14185
  };
14109
14186
  }
14110
14187
  function setupSignalHandlers(cleanup) {
@@ -14123,6 +14200,24 @@ function setupSignalHandlers(cleanup) {
14123
14200
  function getServerUrlHash(serverUrl) {
14124
14201
  return crypto2.createHash("md5").update(serverUrl).digest("hex");
14125
14202
  }
14203
+ function patternToRegex(pattern) {
14204
+ const parts = pattern.split("*");
14205
+ const escapedParts = parts.map((part) => part.replace(/\W/g, "\\$&"));
14206
+ const regexPattern = escapedParts.join(".*");
14207
+ return new RegExp(`^${regexPattern}$`, "i");
14208
+ }
14209
+ function shouldIncludeTool(ignorePatterns, toolName) {
14210
+ if (!ignorePatterns || ignorePatterns.length === 0) {
14211
+ return true;
14212
+ }
14213
+ for (const pattern of ignorePatterns) {
14214
+ const regex = patternToRegex(pattern);
14215
+ if (regex.test(toolName)) {
14216
+ return false;
14217
+ }
14218
+ }
14219
+ return true;
14220
+ }
14126
14221
 
14127
14222
  // src/lib/node-oauth-client-provider.ts
14128
14223
  import open from "open";
package/dist/client.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  parseCommandLineArgs,
12
12
  setupSignalHandlers,
13
13
  version
14
- } from "./chunk-BCWNEBAL.js";
14
+ } from "./chunk-AVTRP4BV.js";
15
15
 
16
16
  // src/client.ts
17
17
  import { EventEmitter } from "events";
package/dist/proxy.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  mcpProxy,
10
10
  parseCommandLineArgs,
11
11
  setupSignalHandlers
12
- } from "./chunk-BCWNEBAL.js";
12
+ } from "./chunk-AVTRP4BV.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, staticOAuthClientMetadata, staticOAuthClientInfo, authorizeResource) {
113
+ async function runProxy(serverUrl, callbackPort, headers, transportStrategy = "http-first", host, staticOAuthClientMetadata, staticOAuthClientInfo, authorizeResource, ignoredTools) {
114
114
  const events = new EventEmitter();
115
115
  const serverUrlHash = getServerUrlHash(serverUrl);
116
116
  const authCoordinator = createLazyAuthCoordinator(serverUrlHash, callbackPort, events);
@@ -141,7 +141,8 @@ async function runProxy(serverUrl, callbackPort, headers, transportStrategy = "h
141
141
  const remoteTransport = await connectToRemoteServer(null, serverUrl, authProvider, headers, authInitializer, transportStrategy);
142
142
  mcpProxy({
143
143
  transportToClient: localTransport,
144
- transportToServer: remoteTransport
144
+ transportToServer: remoteTransport,
145
+ ignoredTools
145
146
  });
146
147
  await localTransport.start();
147
148
  log("Local STDIO server running");
@@ -195,7 +196,8 @@ parseCommandLineArgs(process.argv.slice(2), "Usage: npx tsx proxy.ts <https://se
195
196
  debug,
196
197
  staticOAuthClientMetadata,
197
198
  staticOAuthClientInfo,
198
- authorizeResource
199
+ authorizeResource,
200
+ ignoredTools
199
201
  }) => {
200
202
  return runProxy(
201
203
  serverUrl,
@@ -205,7 +207,8 @@ parseCommandLineArgs(process.argv.slice(2), "Usage: npx tsx proxy.ts <https://se
205
207
  host,
206
208
  staticOAuthClientMetadata,
207
209
  staticOAuthClientInfo,
208
- authorizeResource
210
+ authorizeResource,
211
+ ignoredTools
209
212
  );
210
213
  }
211
214
  ).catch((error) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-remote",
3
- "version": "0.1.21",
3
+ "version": "0.1.22",
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",