@onyxsecurity/mcp-gateway 1.0.6 → 1.0.7
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/dist/bin/mcp-gateway.d.ts +2 -5
- package/dist/bin/mcp-gateway.js +21 -19
- package/dist/bin/mcp-gateway.js.map +1 -1
- package/dist/index.d.ts +104 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-gateway-C0vm3vT0.d.ts +5 -0
- package/dist/{stdio-7bVg-CUZ.js → stdio-BzbVKxqR.js} +11 -11
- package/dist/stdio-BzbVKxqR.js.map +1 -0
- package/package.json +1 -1
- package/dist/stdio-7bVg-CUZ.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ProxyType } from "./mcp-gateway-C0vm3vT0.js";
|
|
1
2
|
import http from "node:http";
|
|
2
3
|
import { EventStore } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
3
4
|
import { JSONRPCMessage, ServerCapabilities } from "@modelcontextprotocol/sdk/types.js";
|
|
@@ -8,7 +9,6 @@ import { StreamableHTTPClientTransportOptions } from "@modelcontextprotocol/sdk/
|
|
|
8
9
|
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
9
10
|
|
|
10
11
|
//#region src/InMemoryEventStore.d.ts
|
|
11
|
-
|
|
12
12
|
/**
|
|
13
13
|
* Simple in-memory implementation of the EventStore interface for resumability
|
|
14
14
|
* This is primarily intended for examples and testing, not for production use
|
|
@@ -40,12 +40,115 @@ declare class InMemoryEventStore implements EventStore {
|
|
|
40
40
|
private getStreamIdFromEventId;
|
|
41
41
|
}
|
|
42
42
|
//#endregion
|
|
43
|
+
//#region src/utils/getUserData.d.ts
|
|
44
|
+
interface RemoteSessionCliArgs extends SessionCliArgs {
|
|
45
|
+
proxyType: "remote";
|
|
46
|
+
url: string;
|
|
47
|
+
}
|
|
48
|
+
interface SessionCliArgs {
|
|
49
|
+
proxyType: ProxyType;
|
|
50
|
+
}
|
|
51
|
+
interface SessionData {
|
|
52
|
+
clientAppName?: string;
|
|
53
|
+
deviceName?: string;
|
|
54
|
+
email?: string;
|
|
55
|
+
parentProcessId?: number;
|
|
56
|
+
parentProcessName?: string;
|
|
57
|
+
processId?: number;
|
|
58
|
+
proxyType: ProxyType;
|
|
59
|
+
remoteCliArgs?: RemoteSessionCliArgs;
|
|
60
|
+
stdioCliArgs?: StdioSessionCliArgs;
|
|
61
|
+
}
|
|
62
|
+
interface StdioSessionCliArgs extends SessionCliArgs {
|
|
63
|
+
args: string[];
|
|
64
|
+
command: string;
|
|
65
|
+
proxyType: "stdio";
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Retrieve user data including email from ~/.claude.json and device name
|
|
69
|
+
*/
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/accessControl/client.d.ts
|
|
72
|
+
interface AccessControlClientConfig {
|
|
73
|
+
apiKey: string;
|
|
74
|
+
headers: Record<string, string>;
|
|
75
|
+
sessionData: SessionData;
|
|
76
|
+
timeoutMs: number;
|
|
77
|
+
url: string;
|
|
78
|
+
}
|
|
79
|
+
interface AccessControlResponse {
|
|
80
|
+
action: "allow" | "block";
|
|
81
|
+
reason?: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Client for checking MCP server access control with backend API.
|
|
85
|
+
* Always fails open (allows) when backend is unreachable.
|
|
86
|
+
*/
|
|
87
|
+
declare class AccessControlClient {
|
|
88
|
+
private clientInfoBase64;
|
|
89
|
+
private config;
|
|
90
|
+
constructor(config: AccessControlClientConfig);
|
|
91
|
+
/**
|
|
92
|
+
* Authorize by querying the backend with full client info.
|
|
93
|
+
* Always fails open (allows) on any error.
|
|
94
|
+
*
|
|
95
|
+
* @returns Access control response
|
|
96
|
+
*/
|
|
97
|
+
authorize(): Promise<AccessControlResponse>;
|
|
98
|
+
/**
|
|
99
|
+
* Compress and base64-encode client info for URL.
|
|
100
|
+
* Matches scanner pattern.
|
|
101
|
+
*/
|
|
102
|
+
private getClientInfoBase64;
|
|
103
|
+
/**
|
|
104
|
+
* Send authorization request to backend with compressed client info in URL.
|
|
105
|
+
* Matches scanner URL pattern: ${url}/${apiKey}/mcp/${clientInfoBase64}
|
|
106
|
+
*
|
|
107
|
+
* @returns Access control response
|
|
108
|
+
* @throws Error if request fails
|
|
109
|
+
*/
|
|
110
|
+
private sendAuthorizeRequest;
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region src/accessControl/authorizer.d.ts
|
|
114
|
+
interface AccessControlConfig {
|
|
115
|
+
client?: AccessControlClient;
|
|
116
|
+
enabled: boolean;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Authorizes MCP servers based on access control configuration.
|
|
120
|
+
* Queries backend with full client info for authorization decisions.
|
|
121
|
+
*/
|
|
122
|
+
declare class AccessControlAuthorizer {
|
|
123
|
+
private client?;
|
|
124
|
+
private enabled;
|
|
125
|
+
private lastBlockReason?;
|
|
126
|
+
constructor(config: AccessControlConfig);
|
|
127
|
+
/**
|
|
128
|
+
* Get human-readable reason for why a server was blocked.
|
|
129
|
+
* Returns the reason from the last authorization check, or a default message.
|
|
130
|
+
*
|
|
131
|
+
* @returns Reason message
|
|
132
|
+
*/
|
|
133
|
+
getBlockReason(): string;
|
|
134
|
+
/**
|
|
135
|
+
* Check if access is allowed by querying the backend.
|
|
136
|
+
* Always fails open (allows) if backend is unavailable or not configured.
|
|
137
|
+
* Stores the block reason from the backend for later retrieval.
|
|
138
|
+
*
|
|
139
|
+
* @returns Promise resolving to true if allowed, false if blocked
|
|
140
|
+
*/
|
|
141
|
+
isAllowed(): Promise<boolean>;
|
|
142
|
+
}
|
|
143
|
+
//#endregion
|
|
43
144
|
//#region src/proxyServer.d.ts
|
|
44
145
|
declare const proxyServer: ({
|
|
146
|
+
authorizer,
|
|
45
147
|
client,
|
|
46
148
|
server,
|
|
47
149
|
serverCapabilities
|
|
48
150
|
}: {
|
|
151
|
+
authorizer?: AccessControlAuthorizer;
|
|
49
152
|
client: Client;
|
|
50
153
|
server: Server;
|
|
51
154
|
serverCapabilities: ServerCapabilities;
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Client as e,InMemoryEventStore as t,SSEClientTransport as n,Server as r,StdioServerTransport as i,StreamableHTTPClientTransport as a,config as o,proxyServer as s,startHTTPServer as c}from"./stdio-
|
|
1
|
+
import{Client as e,InMemoryEventStore as t,SSEClientTransport as n,Server as r,StdioServerTransport as i,StreamableHTTPClientTransport as a,config as o,proxyServer as s,startHTTPServer as c}from"./stdio-BzbVKxqR.js";let l=function(e){return e.HTTPStream=`HTTPStream`,e.SSE=`SSE`,e}({});const u=async({initStdioServer:t,initStreamClient:c,serverType:u,transportOptions:d={},url:f})=>{let p;switch(u){case l.SSE:p=new n(new URL(f),d);break;default:p=new a(new URL(f),d)}let m=c?await c():new e({name:`mcp-gateway`,version:o.appVersion},{capabilities:{}});await m.connect(p);let h=m.getServerVersion(),g=m.getServerCapabilities(),_=t?await t():new r(h,{capabilities:g}),v=new i;return await _.connect(v),await s({authorizer:void 0,client:m,server:_,serverCapabilities:g}),_},d=(e,t)=>{let n=e.close.bind(e),r=e.onclose?.bind(e),i=e.onerror?.bind(e),a=e.onmessage?.bind(e),o=e.send.bind(e),s=e.start.bind(e);return e.close=async()=>(t({type:`close`}),n?.()),e.onclose=async()=>(t({type:`onclose`}),r?.()),e.onerror=async e=>(t({error:e,type:`onerror`}),i?.(e)),e.onmessage=async e=>(t({message:e,type:`onmessage`}),a?.(e)),e.send=async e=>(t({message:e,type:`send`}),o?.(e)),e.start=async()=>(t({type:`start`}),s?.()),e};export{t as InMemoryEventStore,l as ServerType,s as proxyServer,c as startHTTPServer,u as startStdioServer,d as tapTransport};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["transport: SSEClientTransport | StreamableHTTPClientTransport"],"sources":["../src/startStdioServer.ts","../src/tapTransport.ts"],"sourcesContent":["import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport {\n\tSSEClientTransport,\n\ttype SSEClientTransportOptions,\n} from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport {\n\tStreamableHTTPClientTransport,\n\ttype StreamableHTTPClientTransportOptions,\n} from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\n\nimport { config } from \"./config/env.js\";\nimport { proxyServer } from \"./proxyServer.js\";\n\nexport enum ServerType {\n\tHTTPStream = \"HTTPStream\",\n\tSSE = \"SSE\",\n}\n\nexport const startStdioServer = async ({\n\tinitStdioServer,\n\tinitStreamClient,\n\tserverType,\n\ttransportOptions = {},\n\turl,\n}: {\n\tinitStdioServer?: () => Promise<Server>;\n\tinitStreamClient?: () => Promise<Client>;\n\tserverType: ServerType;\n\ttransportOptions?:\n\t\t| SSEClientTransportOptions\n\t\t| StreamableHTTPClientTransportOptions;\n\turl: string;\n}): Promise<Server> => {\n\tlet transport: SSEClientTransport | StreamableHTTPClientTransport;\n\tswitch (serverType) {\n\t\tcase ServerType.SSE:\n\t\t\ttransport = new SSEClientTransport(new URL(url), transportOptions);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\ttransport = new StreamableHTTPClientTransport(\n\t\t\t\tnew URL(url),\n\t\t\t\ttransportOptions,\n\t\t\t);\n\t}\n\tconst streamClient = initStreamClient\n\t\t? await initStreamClient()\n\t\t: new Client(\n\t\t\t\t{\n\t\t\t\t\tname: \"mcp-gateway\",\n\t\t\t\t\tversion: config.appVersion,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tcapabilities: {},\n\t\t\t\t},\n\t\t\t);\n\n\tawait streamClient.connect(transport);\n\n\tconst serverVersion = streamClient.getServerVersion() as {\n\t\tname: string;\n\t\tversion: string;\n\t};\n\n\tconst serverCapabilities = streamClient.getServerCapabilities() as {\n\t\tcapabilities: Record<string, unknown>;\n\t};\n\n\tconst stdioServer = initStdioServer\n\t\t? await initStdioServer()\n\t\t: new Server(serverVersion, {\n\t\t\t\tcapabilities: serverCapabilities,\n\t\t\t});\n\n\tconst stdioTransport = new StdioServerTransport();\n\n\tawait stdioServer.connect(stdioTransport);\n\n\tawait proxyServer({\n\t\tclient: streamClient,\n\t\tserver: stdioServer,\n\t\tserverCapabilities,\n\t});\n\n\treturn stdioServer;\n};\n","import { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\n\ntype TransportEvent =\n | {\n error: Error;\n type: \"onerror\";\n }\n | {\n message: JSONRPCMessage;\n type: \"onmessage\";\n }\n | {\n message: JSONRPCMessage;\n type: \"send\";\n }\n | {\n type: \"close\";\n }\n | {\n type: \"onclose\";\n }\n | {\n type: \"start\";\n };\n\nexport const tapTransport = (\n transport: Transport,\n eventHandler: (event: TransportEvent) => void,\n): Transport => {\n const originalClose = transport.close.bind(transport);\n const originalOnClose = transport.onclose?.bind(transport);\n const originalOnError = transport.onerror?.bind(transport);\n const originalOnMessage = transport.onmessage?.bind(transport);\n const originalSend = transport.send.bind(transport);\n const originalStart = transport.start.bind(transport);\n\n transport.close = async () => {\n eventHandler({\n type: \"close\",\n });\n\n return originalClose?.();\n };\n\n transport.onclose = async () => {\n eventHandler({\n type: \"onclose\",\n });\n\n return originalOnClose?.();\n };\n\n transport.onerror = async (error: Error) => {\n eventHandler({\n error,\n type: \"onerror\",\n });\n\n return originalOnError?.(error);\n };\n\n transport.onmessage = async (message: JSONRPCMessage) => {\n eventHandler({\n message,\n type: \"onmessage\",\n });\n\n return originalOnMessage?.(message);\n };\n\n transport.send = async (message: JSONRPCMessage) => {\n eventHandler({\n message,\n type: \"send\",\n });\n\n return originalSend?.(message);\n };\n\n transport.start = async () => {\n eventHandler({\n type: \"start\",\n });\n\n return originalStart?.();\n };\n\n return transport;\n};\n"],"mappings":"wNAeA,IAAY,EAAA,SAAA,EAAL,OACN,GAAA,WAAA,aACA,EAAA,IAAA,aAGD,MAAa,EAAmB,MAAO,CACtC,kBACA,mBACA,aACA,mBAAmB,EAAE,CACrB,SASsB,CACtB,IAAIA,EACJ,OAAQ,EAAR,CACC,KAAK,EAAW,IACf,EAAY,IAAI,EAAmB,IAAI,IAAI,EAAI,CAAE,EAAiB,CAClE,MACD,QACC,EAAY,IAAI,EACf,IAAI,IAAI,EAAI,CACZ,EACA,CAEH,IAAM,EAAe,EAClB,MAAM,GAAkB,CACxB,IAAI,EACJ,CACC,KAAM,cACN,QAAS,EAAO,WAChB,CACD,CACC,aAAc,EAAE,CAChB,CACD,CAEH,MAAM,EAAa,QAAQ,EAAU,CAErC,IAAM,EAAgB,EAAa,kBAAkB,CAK/C,EAAqB,EAAa,uBAAuB,CAIzD,EAAc,EACjB,MAAM,GAAiB,CACvB,IAAI,EAAO,EAAe,CAC1B,aAAc,EACd,CAAC,CAEE,EAAiB,IAAI,
|
|
1
|
+
{"version":3,"file":"index.js","names":["transport: SSEClientTransport | StreamableHTTPClientTransport"],"sources":["../src/startStdioServer.ts","../src/tapTransport.ts"],"sourcesContent":["import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport {\n\tSSEClientTransport,\n\ttype SSEClientTransportOptions,\n} from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport {\n\tStreamableHTTPClientTransport,\n\ttype StreamableHTTPClientTransportOptions,\n} from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\n\nimport { config } from \"./config/env.js\";\nimport { proxyServer } from \"./proxyServer.js\";\n\nexport enum ServerType {\n\tHTTPStream = \"HTTPStream\",\n\tSSE = \"SSE\",\n}\n\nexport const startStdioServer = async ({\n\tinitStdioServer,\n\tinitStreamClient,\n\tserverType,\n\ttransportOptions = {},\n\turl,\n}: {\n\tinitStdioServer?: () => Promise<Server>;\n\tinitStreamClient?: () => Promise<Client>;\n\tserverType: ServerType;\n\ttransportOptions?:\n\t\t| SSEClientTransportOptions\n\t\t| StreamableHTTPClientTransportOptions;\n\turl: string;\n}): Promise<Server> => {\n\tlet transport: SSEClientTransport | StreamableHTTPClientTransport;\n\tswitch (serverType) {\n\t\tcase ServerType.SSE:\n\t\t\ttransport = new SSEClientTransport(new URL(url), transportOptions);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\ttransport = new StreamableHTTPClientTransport(\n\t\t\t\tnew URL(url),\n\t\t\t\ttransportOptions,\n\t\t\t);\n\t}\n\tconst streamClient = initStreamClient\n\t\t? await initStreamClient()\n\t\t: new Client(\n\t\t\t\t{\n\t\t\t\t\tname: \"mcp-gateway\",\n\t\t\t\t\tversion: config.appVersion,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tcapabilities: {},\n\t\t\t\t},\n\t\t\t);\n\n\tawait streamClient.connect(transport);\n\n\tconst serverVersion = streamClient.getServerVersion() as {\n\t\tname: string;\n\t\tversion: string;\n\t};\n\n\tconst serverCapabilities = streamClient.getServerCapabilities() as {\n\t\tcapabilities: Record<string, unknown>;\n\t};\n\n\tconst stdioServer = initStdioServer\n\t\t? await initStdioServer()\n\t\t: new Server(serverVersion, {\n\t\t\t\tcapabilities: serverCapabilities,\n\t\t\t});\n\n\tconst stdioTransport = new StdioServerTransport();\n\n\tawait stdioServer.connect(stdioTransport);\n\n\tawait proxyServer({\n\t\tauthorizer: undefined,\n\t\tclient: streamClient,\n\t\tserver: stdioServer,\n\t\tserverCapabilities,\n\t});\n\n\treturn stdioServer;\n};\n","import { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\n\ntype TransportEvent =\n | {\n error: Error;\n type: \"onerror\";\n }\n | {\n message: JSONRPCMessage;\n type: \"onmessage\";\n }\n | {\n message: JSONRPCMessage;\n type: \"send\";\n }\n | {\n type: \"close\";\n }\n | {\n type: \"onclose\";\n }\n | {\n type: \"start\";\n };\n\nexport const tapTransport = (\n transport: Transport,\n eventHandler: (event: TransportEvent) => void,\n): Transport => {\n const originalClose = transport.close.bind(transport);\n const originalOnClose = transport.onclose?.bind(transport);\n const originalOnError = transport.onerror?.bind(transport);\n const originalOnMessage = transport.onmessage?.bind(transport);\n const originalSend = transport.send.bind(transport);\n const originalStart = transport.start.bind(transport);\n\n transport.close = async () => {\n eventHandler({\n type: \"close\",\n });\n\n return originalClose?.();\n };\n\n transport.onclose = async () => {\n eventHandler({\n type: \"onclose\",\n });\n\n return originalOnClose?.();\n };\n\n transport.onerror = async (error: Error) => {\n eventHandler({\n error,\n type: \"onerror\",\n });\n\n return originalOnError?.(error);\n };\n\n transport.onmessage = async (message: JSONRPCMessage) => {\n eventHandler({\n message,\n type: \"onmessage\",\n });\n\n return originalOnMessage?.(message);\n };\n\n transport.send = async (message: JSONRPCMessage) => {\n eventHandler({\n message,\n type: \"send\",\n });\n\n return originalSend?.(message);\n };\n\n transport.start = async () => {\n eventHandler({\n type: \"start\",\n });\n\n return originalStart?.();\n };\n\n return transport;\n};\n"],"mappings":"wNAeA,IAAY,EAAA,SAAA,EAAL,OACN,GAAA,WAAA,aACA,EAAA,IAAA,aAGD,MAAa,EAAmB,MAAO,CACtC,kBACA,mBACA,aACA,mBAAmB,EAAE,CACrB,SASsB,CACtB,IAAIA,EACJ,OAAQ,EAAR,CACC,KAAK,EAAW,IACf,EAAY,IAAI,EAAmB,IAAI,IAAI,EAAI,CAAE,EAAiB,CAClE,MACD,QACC,EAAY,IAAI,EACf,IAAI,IAAI,EAAI,CACZ,EACA,CAEH,IAAM,EAAe,EAClB,MAAM,GAAkB,CACxB,IAAI,EACJ,CACC,KAAM,cACN,QAAS,EAAO,WAChB,CACD,CACC,aAAc,EAAE,CAChB,CACD,CAEH,MAAM,EAAa,QAAQ,EAAU,CAErC,IAAM,EAAgB,EAAa,kBAAkB,CAK/C,EAAqB,EAAa,uBAAuB,CAIzD,EAAc,EACjB,MAAM,GAAiB,CACvB,IAAI,EAAO,EAAe,CAC1B,aAAc,EACd,CAAC,CAEE,EAAiB,IAAI,EAW3B,OATA,MAAM,EAAY,QAAQ,EAAe,CAEzC,MAAM,EAAY,CACjB,WAAY,IAAA,GACZ,OAAQ,EACR,OAAQ,EACR,qBACA,CAAC,CAEK,GC5DK,GACX,EACA,IACc,CACd,IAAM,EAAgB,EAAU,MAAM,KAAK,EAAU,CAC/C,EAAkB,EAAU,SAAS,KAAK,EAAU,CACpD,EAAkB,EAAU,SAAS,KAAK,EAAU,CACpD,EAAoB,EAAU,WAAW,KAAK,EAAU,CACxD,EAAe,EAAU,KAAK,KAAK,EAAU,CAC7C,EAAgB,EAAU,MAAM,KAAK,EAAU,CAqDrD,MAnDA,GAAU,MAAQ,UAChB,EAAa,CACX,KAAM,QACP,CAAC,CAEK,KAAiB,EAG1B,EAAU,QAAU,UAClB,EAAa,CACX,KAAM,UACP,CAAC,CAEK,KAAmB,EAG5B,EAAU,QAAU,KAAO,KACzB,EAAa,CACX,QACA,KAAM,UACP,CAAC,CAEK,IAAkB,EAAM,EAGjC,EAAU,UAAY,KAAO,KAC3B,EAAa,CACX,UACA,KAAM,YACP,CAAC,CAEK,IAAoB,EAAQ,EAGrC,EAAU,KAAO,KAAO,KACtB,EAAa,CACX,UACA,KAAM,OACP,CAAC,CAEK,IAAe,EAAQ,EAGhC,EAAU,MAAQ,UAChB,EAAa,CACX,KAAM,QACP,CAAC,CAEK,KAAiB,EAGnB"}
|