@mcp-use/client 2.0.0-beta.8 → 2.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 +18 -19
- package/dist/.tsbuildinfo +1 -1
- package/dist/auth/browser.d.ts +62 -6
- package/dist/auth/browser.d.ts.map +1 -1
- package/dist/auth/callback.d.ts.map +1 -1
- package/dist/auth/flow.d.ts.map +1 -1
- package/dist/auth/node.d.ts +115 -5
- package/dist/auth/node.d.ts.map +1 -1
- package/dist/auth/session-store.d.ts +7 -1
- package/dist/auth/session-store.d.ts.map +1 -1
- package/dist/auth/storage.d.ts +12 -3
- package/dist/auth/storage.d.ts.map +1 -1
- package/dist/code-mode/executor-e2b.d.ts.map +1 -1
- package/dist/core/base.d.ts +4 -8
- package/dist/core/base.d.ts.map +1 -1
- package/dist/core/browser.d.ts +14 -2
- package/dist/core/browser.d.ts.map +1 -1
- package/dist/core/config.d.ts +82 -20
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/node.d.ts +7 -10
- package/dist/core/node.d.ts.map +1 -1
- package/dist/core/session.d.ts +102 -25
- package/dist/core/session.d.ts.map +1 -1
- package/dist/index-browser.d.ts +1 -0
- package/dist/index-browser.d.ts.map +1 -1
- package/dist/index-browser.js +568 -163
- package/dist/index-browser.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +407 -92
- package/dist/index.js.map +1 -1
- package/dist/react/McpClientProvider.d.ts +22 -10
- package/dist/react/McpClientProvider.d.ts.map +1 -1
- package/dist/react/index.d.ts +5 -2
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +1104 -368
- package/dist/react/index.js.map +1 -1
- package/dist/react/rpc-logger.d.ts +5 -0
- package/dist/react/rpc-logger.d.ts.map +1 -1
- package/dist/react/storage.d.ts +57 -10
- package/dist/react/storage.d.ts.map +1 -1
- package/dist/react/token-expiry.d.ts +9 -0
- package/dist/react/token-expiry.d.ts.map +1 -0
- package/dist/react/types.d.ts +134 -22
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/useMcp-helpers.d.ts.map +1 -1
- package/dist/react/useMcp-operations.d.ts +24 -6
- package/dist/react/useMcp-operations.d.ts.map +1 -1
- package/dist/react/useMcp.d.ts.map +1 -1
- package/dist/react/useMcpServerQueues.d.ts +36 -9
- package/dist/react/useMcpServerQueues.d.ts.map +1 -1
- package/dist/react/view/ViewRenderer.d.ts +12 -4
- package/dist/react/view/ViewRenderer.d.ts.map +1 -1
- package/dist/react/view/ext-apps-bridge.d.ts +1 -1
- package/dist/react/view/ext-apps-bridge.d.ts.map +1 -1
- package/dist/react/view/inject-openai-file-apis.d.ts.map +1 -1
- package/dist/react/view/parse-custom-props.d.ts +8 -0
- package/dist/react/view/parse-custom-props.d.ts.map +1 -1
- package/dist/react/view/resolve-view-resource.d.ts +10 -0
- package/dist/react/view/resolve-view-resource.d.ts.map +1 -1
- package/dist/react/view/sandbox-blob-url.d.ts +2 -0
- package/dist/react/view/sandbox-blob-url.d.ts.map +1 -1
- package/dist/react/view/types.d.ts +111 -4
- package/dist/react/view/types.d.ts.map +1 -1
- package/dist/react/view/view-detection.d.ts +18 -0
- package/dist/react/view/view-detection.d.ts.map +1 -1
- package/dist/react/view/view-host-policy.d.ts +61 -0
- package/dist/react/view/view-host-policy.d.ts.map +1 -0
- package/dist/sandbox.d.ts +2 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +283 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/telemetry/events.d.ts.map +1 -1
- package/dist/telemetry/tel-fetch.d.ts.map +1 -1
- package/dist/telemetry/telemetry.d.ts +5 -1
- package/dist/telemetry/telemetry.d.ts.map +1 -1
- package/dist/transport/base.d.ts +169 -34
- package/dist/transport/base.d.ts.map +1 -1
- package/dist/transport/connection-manager.d.ts +5 -1
- package/dist/transport/connection-manager.d.ts.map +1 -1
- package/dist/transport/http.d.ts +51 -2
- package/dist/transport/http.d.ts.map +1 -1
- package/dist/transport/stdio.d.ts +29 -1
- package/dist/transport/stdio.d.ts.map +1 -1
- package/dist/utils/elicitation.d.ts +4 -2
- package/dist/utils/elicitation.d.ts.map +1 -1
- package/dist/utils/logging.d.ts +1 -0
- package/dist/utils/logging.d.ts.map +1 -1
- package/dist/utils/version.d.ts +6 -0
- package/dist/utils/version.d.ts.map +1 -1
- package/package.json +9 -3
package/dist/index.js
CHANGED
|
@@ -209,6 +209,11 @@ var init_base = __esm({
|
|
|
209
209
|
notificationHandlers = [];
|
|
210
210
|
rootsCache = [];
|
|
211
211
|
activeProgressHandlers = /* @__PURE__ */ new Set();
|
|
212
|
+
/**
|
|
213
|
+
* Creates a connector with shared SDK and callback options.
|
|
214
|
+
*
|
|
215
|
+
* @param opts - Connector initialization options.
|
|
216
|
+
*/
|
|
212
217
|
constructor(opts = {}) {
|
|
213
218
|
this.opts = opts;
|
|
214
219
|
if (opts.roots) {
|
|
@@ -391,7 +396,9 @@ var init_base = __esm({
|
|
|
391
396
|
}
|
|
392
397
|
}
|
|
393
398
|
/**
|
|
394
|
-
*
|
|
399
|
+
* Returns the roots currently advertised to the server.
|
|
400
|
+
*
|
|
401
|
+
* @returns A copy of the configured roots.
|
|
395
402
|
*/
|
|
396
403
|
getRoots() {
|
|
397
404
|
return [...this.rootsCache];
|
|
@@ -460,7 +467,11 @@ var init_base = __esm({
|
|
|
460
467
|
"setupElicitationHandler: Elicitation handler registered successfully"
|
|
461
468
|
);
|
|
462
469
|
}
|
|
463
|
-
/**
|
|
470
|
+
/**
|
|
471
|
+
* Disconnects the SDK client and releases transport resources.
|
|
472
|
+
*
|
|
473
|
+
* @returns A promise that resolves after cleanup completes.
|
|
474
|
+
*/
|
|
464
475
|
async disconnect() {
|
|
465
476
|
if (!this.connected) {
|
|
466
477
|
logger.debug("Not connected to MCP implementation");
|
|
@@ -471,7 +482,7 @@ var init_base = __esm({
|
|
|
471
482
|
this.connected = false;
|
|
472
483
|
logger.debug("Disconnected from MCP implementation");
|
|
473
484
|
}
|
|
474
|
-
/**
|
|
485
|
+
/** Whether an SDK client currently exists for this connector. */
|
|
475
486
|
get isClientConnected() {
|
|
476
487
|
return this.client != null;
|
|
477
488
|
}
|
|
@@ -481,6 +492,10 @@ var init_base = __esm({
|
|
|
481
492
|
* In the SDK, `Client.connect(transport)` automatically performs the
|
|
482
493
|
* protocol‑level `initialize` handshake, so we only need to cache the list of
|
|
483
494
|
* tools and expose some server info.
|
|
495
|
+
*
|
|
496
|
+
* @param defaultRequestOptions - Options used while fetching the initial tool list.
|
|
497
|
+
* @returns The capabilities advertised by the server.
|
|
498
|
+
* @throws When {@link BaseConnector.connect} has not completed.
|
|
484
499
|
*/
|
|
485
500
|
async initialize(defaultRequestOptions = this.opts.defaultRequestOptions ?? {}) {
|
|
486
501
|
if (!this.client) {
|
|
@@ -518,18 +533,22 @@ var init_base = __esm({
|
|
|
518
533
|
logger.debug("Server info:", serverInfo);
|
|
519
534
|
return capabilities;
|
|
520
535
|
}
|
|
521
|
-
/**
|
|
536
|
+
/**
|
|
537
|
+
* Returns the tool list cached during initialization.
|
|
538
|
+
*
|
|
539
|
+
* @throws When {@link BaseConnector.initialize} has not completed.
|
|
540
|
+
*/
|
|
522
541
|
get tools() {
|
|
523
542
|
if (!this.toolsCache) {
|
|
524
543
|
throw new Error("MCP client is not initialized; call initialize() first");
|
|
525
544
|
}
|
|
526
545
|
return this.toolsCache;
|
|
527
546
|
}
|
|
528
|
-
/**
|
|
547
|
+
/** Capabilities cached during initialization, or an empty object. */
|
|
529
548
|
get serverCapabilities() {
|
|
530
549
|
return this.capabilitiesCache || {};
|
|
531
550
|
}
|
|
532
|
-
/**
|
|
551
|
+
/** Server identity cached during initialization, or `null`. */
|
|
533
552
|
get serverInfo() {
|
|
534
553
|
return this.serverInfoCache;
|
|
535
554
|
}
|
|
@@ -550,7 +569,15 @@ var init_base = __esm({
|
|
|
550
569
|
get negotiatedProtocolVersion() {
|
|
551
570
|
return this.client?.getNegotiatedProtocolVersion?.();
|
|
552
571
|
}
|
|
553
|
-
/**
|
|
572
|
+
/**
|
|
573
|
+
* Calls a tool on the connected server.
|
|
574
|
+
*
|
|
575
|
+
* @param name - Tool name.
|
|
576
|
+
* @param args - Tool arguments.
|
|
577
|
+
* @param options - Per-request timeout, cancellation, and progress options.
|
|
578
|
+
* @returns The tool result returned by the server.
|
|
579
|
+
* @throws When the connector is not connected or the tool call fails.
|
|
580
|
+
*/
|
|
554
581
|
async callTool(name, args, options) {
|
|
555
582
|
if (!this.client) {
|
|
556
583
|
throw new Error("MCP client is not connected");
|
|
@@ -675,7 +702,13 @@ var init_base = __esm({
|
|
|
675
702
|
);
|
|
676
703
|
return result;
|
|
677
704
|
}
|
|
678
|
-
/**
|
|
705
|
+
/**
|
|
706
|
+
* Reads a resource by URI.
|
|
707
|
+
*
|
|
708
|
+
* @param uri - Resource URI to read.
|
|
709
|
+
* @param options - Per-request options.
|
|
710
|
+
* @returns The resource contents returned by the server.
|
|
711
|
+
*/
|
|
679
712
|
async readResource(uri, options) {
|
|
680
713
|
if (!this.client) {
|
|
681
714
|
throw new Error("MCP client is not connected");
|
|
@@ -710,6 +743,11 @@ var init_base = __esm({
|
|
|
710
743
|
logger.debug(`Unsubscribing from resource: ${uri}`);
|
|
711
744
|
return await this.client.unsubscribeResource({ uri }, options);
|
|
712
745
|
}
|
|
746
|
+
/**
|
|
747
|
+
* Lists prompts exposed by the server.
|
|
748
|
+
*
|
|
749
|
+
* @returns The prompt list, or an empty list when prompts are unsupported.
|
|
750
|
+
*/
|
|
713
751
|
async listPrompts() {
|
|
714
752
|
if (!this.client) {
|
|
715
753
|
throw new Error("MCP client is not connected");
|
|
@@ -730,6 +768,13 @@ var init_base = __esm({
|
|
|
730
768
|
throw err;
|
|
731
769
|
}
|
|
732
770
|
}
|
|
771
|
+
/**
|
|
772
|
+
* Gets a prompt with the supplied arguments.
|
|
773
|
+
*
|
|
774
|
+
* @param name - Prompt name.
|
|
775
|
+
* @param args - Prompt arguments.
|
|
776
|
+
* @returns The rendered prompt returned by the server.
|
|
777
|
+
*/
|
|
733
778
|
async getPrompt(name, args) {
|
|
734
779
|
if (!this.client) {
|
|
735
780
|
throw new Error("MCP client is not connected");
|
|
@@ -737,7 +782,14 @@ var init_base = __esm({
|
|
|
737
782
|
logger.debug(`Getting prompt ${name}`);
|
|
738
783
|
return await this.client.getPrompt({ name, arguments: args });
|
|
739
784
|
}
|
|
740
|
-
/**
|
|
785
|
+
/**
|
|
786
|
+
* Sends a raw, potentially non-standard request through the SDK client.
|
|
787
|
+
*
|
|
788
|
+
* @param method - JSON-RPC method name.
|
|
789
|
+
* @param params - Request parameters. Defaults to an empty object.
|
|
790
|
+
* @param options - Per-request options.
|
|
791
|
+
* @returns The unvalidated result returned by the server.
|
|
792
|
+
*/
|
|
741
793
|
async request(method, params = null, options) {
|
|
742
794
|
if (!this.client) {
|
|
743
795
|
throw new Error("MCP client is not connected");
|
|
@@ -802,6 +854,8 @@ var init_connection_manager = __esm({
|
|
|
802
854
|
_connection = null;
|
|
803
855
|
_task = null;
|
|
804
856
|
_abortController = null;
|
|
857
|
+
_startPromise = null;
|
|
858
|
+
_stopPromise = null;
|
|
805
859
|
constructor() {
|
|
806
860
|
this.reset();
|
|
807
861
|
}
|
|
@@ -811,10 +865,21 @@ var init_connection_manager = __esm({
|
|
|
811
865
|
* @returns The established connection.
|
|
812
866
|
* @throws If the connection cannot be established.
|
|
813
867
|
*/
|
|
814
|
-
|
|
868
|
+
start() {
|
|
869
|
+
if (this._stopPromise) {
|
|
870
|
+
return this._stopPromise.then(() => this.start());
|
|
871
|
+
}
|
|
872
|
+
if (this._startPromise) return this._startPromise;
|
|
815
873
|
this.reset();
|
|
816
874
|
logger.debug(`Starting ${this.constructor.name}`);
|
|
817
875
|
this._task = this.connectionTask();
|
|
876
|
+
this._startPromise = this.waitUntilReady().catch((error) => {
|
|
877
|
+
this._startPromise = null;
|
|
878
|
+
throw error;
|
|
879
|
+
});
|
|
880
|
+
return this._startPromise;
|
|
881
|
+
}
|
|
882
|
+
async waitUntilReady() {
|
|
818
883
|
await this._readyPromise;
|
|
819
884
|
if (this._exception) {
|
|
820
885
|
throw this._exception;
|
|
@@ -827,7 +892,18 @@ var init_connection_manager = __esm({
|
|
|
827
892
|
/**
|
|
828
893
|
* Stop the connection manager and close the connection.
|
|
829
894
|
*/
|
|
830
|
-
|
|
895
|
+
stop() {
|
|
896
|
+
if (this._stopPromise) return this._stopPromise;
|
|
897
|
+
if (!this._task) return Promise.resolve();
|
|
898
|
+
const trackedStop = this.stopTask().finally(() => {
|
|
899
|
+
if (this._stopPromise === trackedStop) {
|
|
900
|
+
this._stopPromise = null;
|
|
901
|
+
}
|
|
902
|
+
});
|
|
903
|
+
this._stopPromise = trackedStop;
|
|
904
|
+
return trackedStop;
|
|
905
|
+
}
|
|
906
|
+
async stopTask() {
|
|
831
907
|
if (this._task && this._abortController) {
|
|
832
908
|
logger.debug(`Cancelling ${this.constructor.name} task`);
|
|
833
909
|
this._abortController.abort();
|
|
@@ -842,6 +918,8 @@ var init_connection_manager = __esm({
|
|
|
842
918
|
}
|
|
843
919
|
}
|
|
844
920
|
await this._donePromise;
|
|
921
|
+
this._task = null;
|
|
922
|
+
this._startPromise = null;
|
|
845
923
|
logger.debug(`${this.constructor.name} task completed`);
|
|
846
924
|
}
|
|
847
925
|
/**
|
|
@@ -933,6 +1011,11 @@ var init_stdio = __esm({
|
|
|
933
1011
|
errlog;
|
|
934
1012
|
clientInfo;
|
|
935
1013
|
protocolNegotiation;
|
|
1014
|
+
/**
|
|
1015
|
+
* Creates a stdio connector.
|
|
1016
|
+
*
|
|
1017
|
+
* @param options - Process launch, client identity, and shared connector options.
|
|
1018
|
+
*/
|
|
936
1019
|
constructor({
|
|
937
1020
|
command = "npx",
|
|
938
1021
|
args = [],
|
|
@@ -952,7 +1035,11 @@ var init_stdio = __esm({
|
|
|
952
1035
|
this.cwd = rest.cwd;
|
|
953
1036
|
this.protocolNegotiation = rest.protocolNegotiation ?? "legacy";
|
|
954
1037
|
}
|
|
955
|
-
/**
|
|
1038
|
+
/**
|
|
1039
|
+
* Starts the child process and establishes an MCP connection.
|
|
1040
|
+
*
|
|
1041
|
+
* @returns A promise that resolves after protocol negotiation completes.
|
|
1042
|
+
*/
|
|
956
1043
|
async connect() {
|
|
957
1044
|
if (this.connected) {
|
|
958
1045
|
logger.debug("Already connected to MCP implementation");
|
|
@@ -1048,6 +1135,11 @@ var init_stdio = __esm({
|
|
|
1048
1135
|
throw err;
|
|
1049
1136
|
}
|
|
1050
1137
|
}
|
|
1138
|
+
/**
|
|
1139
|
+
* Returns fields identifying the launched command and arguments.
|
|
1140
|
+
*
|
|
1141
|
+
* @returns Stdio connector identity metadata.
|
|
1142
|
+
*/
|
|
1051
1143
|
get publicIdentifier() {
|
|
1052
1144
|
return {
|
|
1053
1145
|
type: "stdio",
|
|
@@ -1059,6 +1151,12 @@ var init_stdio = __esm({
|
|
|
1059
1151
|
serverParams;
|
|
1060
1152
|
errlog;
|
|
1061
1153
|
_transport = null;
|
|
1154
|
+
/**
|
|
1155
|
+
* Creates a connection manager for a local server process.
|
|
1156
|
+
*
|
|
1157
|
+
* @param serverParams - Process parameters passed to the SDK transport.
|
|
1158
|
+
* @param errlog - Destination for the child process's standard error stream.
|
|
1159
|
+
*/
|
|
1062
1160
|
constructor(serverParams, errlog = process2.stderr) {
|
|
1063
1161
|
super();
|
|
1064
1162
|
this.serverParams = serverParams;
|
|
@@ -1108,7 +1206,7 @@ init_connector_telemetry();
|
|
|
1108
1206
|
init_logging();
|
|
1109
1207
|
|
|
1110
1208
|
// src/utils/version.ts
|
|
1111
|
-
var VERSION = "2.0.0
|
|
1209
|
+
var VERSION = "2.0.0";
|
|
1112
1210
|
function getPackageVersion() {
|
|
1113
1211
|
return VERSION;
|
|
1114
1212
|
}
|
|
@@ -1128,16 +1226,13 @@ var MCPAgentExecutionEvent = class extends BaseTelemetryEvent {
|
|
|
1128
1226
|
return {
|
|
1129
1227
|
// Core execution info
|
|
1130
1228
|
execution_method: this.data.executionMethod,
|
|
1131
|
-
query: this.data.query,
|
|
1132
1229
|
query_length: this.data.query.length,
|
|
1133
1230
|
success: this.data.success,
|
|
1134
1231
|
// Agent configuration
|
|
1135
1232
|
model_provider: this.data.modelProvider,
|
|
1136
1233
|
model_name: this.data.modelName,
|
|
1137
1234
|
server_count: this.data.serverCount,
|
|
1138
|
-
server_identifiers: this.data.serverIdentifiers,
|
|
1139
1235
|
total_tools_available: this.data.totalToolsAvailable,
|
|
1140
|
-
tools_available_names: this.data.toolsAvailableNames,
|
|
1141
1236
|
max_steps_configured: this.data.maxStepsConfigured,
|
|
1142
1237
|
memory_enabled: this.data.memoryEnabled,
|
|
1143
1238
|
use_server_manager: this.data.useServerManager,
|
|
@@ -1148,8 +1243,6 @@ var MCPAgentExecutionEvent = class extends BaseTelemetryEvent {
|
|
|
1148
1243
|
// Execution results (always include, even if null)
|
|
1149
1244
|
steps_taken: this.data.stepsTaken ?? null,
|
|
1150
1245
|
tools_used_count: this.data.toolsUsedCount ?? null,
|
|
1151
|
-
tools_used_names: this.data.toolsUsedNames ?? null,
|
|
1152
|
-
response: this.data.response ?? null,
|
|
1153
1246
|
response_length: this.data.response ? this.data.response.length : null,
|
|
1154
1247
|
execution_time_ms: this.data.executionTimeMs ?? null,
|
|
1155
1248
|
error_type: this.data.errorType ?? null,
|
|
@@ -1245,21 +1338,72 @@ async function telFetch(url, init) {
|
|
|
1245
1338
|
}
|
|
1246
1339
|
var POSTHOG_HOST = "https://eu.i.posthog.com";
|
|
1247
1340
|
var POSTHOG_API_KEY = "phc_lyTtbYwvkdSbrcMQNPiKiiRWrrM1seyKIMjycSvItEI";
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1341
|
+
var CONTENT_PROPERTY = /(^|_)(arguments?|args|body|command|headers?|location|message|query|response|secret|subject|token|uri|url|user_agent)(_|$)/i;
|
|
1342
|
+
var IDENTIFYING_PROPERTY = /(^|_)(server_identifiers?|server_names?|servers|tool_names?|tools_(available|used)_names)(_|$)/i;
|
|
1343
|
+
var AGGREGATE_PROPERTY = /(_count|_length|_duration(?:_ms)?|_time_ms|(^|_)num_[a-z0-9_]+)$/i;
|
|
1344
|
+
function normalizePropertyKey(key) {
|
|
1345
|
+
return key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-z0-9_$]+/gi, "_").toLowerCase();
|
|
1346
|
+
}
|
|
1347
|
+
function sanitizeValue(value, seen) {
|
|
1348
|
+
if (Array.isArray(value)) {
|
|
1349
|
+
if (seen.has(value)) {
|
|
1350
|
+
throw new TypeError("Cyclic telemetry properties are not supported");
|
|
1351
|
+
}
|
|
1352
|
+
seen.add(value);
|
|
1353
|
+
const sanitized = value.map((item) => sanitizeValue(item, seen));
|
|
1354
|
+
seen.delete(value);
|
|
1355
|
+
return sanitized;
|
|
1356
|
+
}
|
|
1357
|
+
if (value !== null && typeof value === "object" && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) {
|
|
1358
|
+
if (seen.has(value)) {
|
|
1359
|
+
throw new TypeError("Cyclic telemetry properties are not supported");
|
|
1360
|
+
}
|
|
1361
|
+
seen.add(value);
|
|
1362
|
+
const sanitized = sanitizeProperties(
|
|
1363
|
+
value,
|
|
1364
|
+
seen
|
|
1365
|
+
);
|
|
1366
|
+
seen.delete(value);
|
|
1367
|
+
return sanitized;
|
|
1368
|
+
}
|
|
1369
|
+
return value;
|
|
1370
|
+
}
|
|
1371
|
+
function sanitizeProperties(properties, seen = /* @__PURE__ */ new WeakSet()) {
|
|
1372
|
+
const sanitized = {};
|
|
1373
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
1374
|
+
const normalizedKey = normalizePropertyKey(key);
|
|
1375
|
+
if (AGGREGATE_PROPERTY.test(normalizedKey)) {
|
|
1376
|
+
if (value === null || typeof value === "number") {
|
|
1377
|
+
sanitized[key] = value;
|
|
1378
|
+
}
|
|
1379
|
+
continue;
|
|
1380
|
+
}
|
|
1381
|
+
if (IDENTIFYING_PROPERTY.test(normalizedKey) || CONTENT_PROPERTY.test(normalizedKey)) {
|
|
1382
|
+
continue;
|
|
1383
|
+
}
|
|
1384
|
+
sanitized[key] = sanitizeValue(value, seen);
|
|
1385
|
+
}
|
|
1386
|
+
return sanitized;
|
|
1387
|
+
}
|
|
1388
|
+
async function capturePostHog(params) {
|
|
1389
|
+
try {
|
|
1390
|
+
const host = params.host ?? POSTHOG_HOST;
|
|
1391
|
+
const apiKey = params.apiKey ?? POSTHOG_API_KEY;
|
|
1392
|
+
const body = JSON.stringify({
|
|
1256
1393
|
api_key: apiKey,
|
|
1257
1394
|
event: params.event,
|
|
1258
1395
|
distinct_id: params.distinctId,
|
|
1259
|
-
properties: params.properties,
|
|
1396
|
+
properties: sanitizeProperties(params.properties),
|
|
1260
1397
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1261
|
-
})
|
|
1262
|
-
|
|
1398
|
+
});
|
|
1399
|
+
await telFetch(`${host}/i/v0/e/`, {
|
|
1400
|
+
method: "POST",
|
|
1401
|
+
headers: { "Content-Type": "application/json" },
|
|
1402
|
+
keepalive: true,
|
|
1403
|
+
body
|
|
1404
|
+
});
|
|
1405
|
+
} catch {
|
|
1406
|
+
}
|
|
1263
1407
|
}
|
|
1264
1408
|
|
|
1265
1409
|
// src/telemetry/telemetry.ts
|
|
@@ -1789,11 +1933,12 @@ async function completeOAuthFlow(provider, serverUrl, options = {}) {
|
|
|
1789
1933
|
throw new Error(`Unexpected OAuth auth() result: ${result}`);
|
|
1790
1934
|
}
|
|
1791
1935
|
}
|
|
1792
|
-
if (typeof flowProvider.getAuthorizationCode === "function") {
|
|
1793
|
-
const
|
|
1936
|
+
if (typeof flowProvider.getAuthorizationResponse === "function" || typeof flowProvider.getAuthorizationCode === "function") {
|
|
1937
|
+
const response = typeof flowProvider.getAuthorizationResponse === "function" ? await flowProvider.getAuthorizationResponse() : { code: await flowProvider.getAuthorizationCode() };
|
|
1794
1938
|
await auth(provider, {
|
|
1795
1939
|
serverUrl,
|
|
1796
|
-
authorizationCode: code,
|
|
1940
|
+
authorizationCode: response.code,
|
|
1941
|
+
...response.iss !== void 0 ? { iss: response.iss } : {},
|
|
1797
1942
|
fetchFn
|
|
1798
1943
|
});
|
|
1799
1944
|
return;
|
|
@@ -1807,6 +1952,8 @@ async function waitForBrowserAuthComplete(provider, timeoutMs) {
|
|
|
1807
1952
|
);
|
|
1808
1953
|
}
|
|
1809
1954
|
if (provider.useRedirectFlow) {
|
|
1955
|
+
await new Promise(() => {
|
|
1956
|
+
});
|
|
1810
1957
|
return;
|
|
1811
1958
|
}
|
|
1812
1959
|
const tokensKey = provider.getKey?.("tokens");
|
|
@@ -1823,25 +1970,29 @@ async function waitForBrowserAuthComplete(provider, timeoutMs) {
|
|
|
1823
1970
|
} catch {
|
|
1824
1971
|
}
|
|
1825
1972
|
}
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1973
|
+
try {
|
|
1974
|
+
const result = await runAuthPopup({
|
|
1975
|
+
popup: null,
|
|
1976
|
+
state,
|
|
1977
|
+
tokensKey,
|
|
1978
|
+
timeoutMs
|
|
1979
|
+
});
|
|
1980
|
+
switch (result.kind) {
|
|
1981
|
+
case "success":
|
|
1982
|
+
return;
|
|
1983
|
+
case "cancelled":
|
|
1984
|
+
throw new Error("OAuth authentication was cancelled.");
|
|
1985
|
+
case "timeout":
|
|
1986
|
+
throw new Error(
|
|
1987
|
+
`OAuth callback not received within ${timeoutMs}ms. Ensure /oauth/callback calls onMcpAuthorization().`
|
|
1988
|
+
);
|
|
1989
|
+
case "error":
|
|
1990
|
+
throw new Error(result.error);
|
|
1991
|
+
default:
|
|
1992
|
+
throw new Error("Unexpected OAuth popup result");
|
|
1993
|
+
}
|
|
1994
|
+
} finally {
|
|
1995
|
+
provider.markFlowComplete?.();
|
|
1845
1996
|
}
|
|
1846
1997
|
}
|
|
1847
1998
|
|
|
@@ -2054,29 +2205,39 @@ var OAuthSessionStore = class _OAuthSessionStore {
|
|
|
2054
2205
|
if (ctx) await this.store.set(this.credentialKey("tokens"), serialized);
|
|
2055
2206
|
await this.store.remove(this.getKey("code_verifier"));
|
|
2056
2207
|
await this.store.remove(this.getKey("last_auth_url"));
|
|
2208
|
+
await this.store.remove(this.getKey("last_auth_callback_url"));
|
|
2057
2209
|
}
|
|
2058
2210
|
async clientInformation(ctx) {
|
|
2211
|
+
if (!this.allowClientSecret) {
|
|
2212
|
+
const registeredRedirectUri = await this.store.get(
|
|
2213
|
+
this.getKey("client_info_redirect_uri")
|
|
2214
|
+
);
|
|
2215
|
+
if (registeredRedirectUri !== this.redirectUrl) {
|
|
2216
|
+
await this.invalidateCredentials("registration");
|
|
2217
|
+
console.info(
|
|
2218
|
+
`[${this.storageKeyPrefix}] Re-registering browser OAuth client after its Inspector callback changed or could not be verified.`
|
|
2219
|
+
);
|
|
2220
|
+
return void 0;
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2059
2223
|
const stored = await this.readCredential("client_info", ctx);
|
|
2060
2224
|
if (!stored) return void 0;
|
|
2061
2225
|
const { key, value: clientInfo } = stored;
|
|
2062
2226
|
try {
|
|
2063
2227
|
if (!this.allowClientSecret && clientInfo.client_secret) {
|
|
2064
|
-
await this.
|
|
2065
|
-
if (ctx) await this.store.remove(this.credentialKey("client_info"));
|
|
2228
|
+
await this.invalidateCredentials("registration");
|
|
2066
2229
|
console.warn(
|
|
2067
|
-
`[${this.storageKeyPrefix}]
|
|
2230
|
+
`[${this.storageKeyPrefix}] Recovered stale browser OAuth credentials containing a client_secret.`
|
|
2068
2231
|
);
|
|
2069
2232
|
return void 0;
|
|
2070
2233
|
}
|
|
2071
2234
|
const storedRedirectUris = Array.isArray(clientInfo.redirect_uris) ? clientInfo.redirect_uris : [];
|
|
2072
|
-
const hasMatchingRedirect = storedRedirectUris.length === 0 || storedRedirectUris.includes(this.redirectUrl);
|
|
2235
|
+
const hasMatchingRedirect = storedRedirectUris.length === 0 && this.allowClientSecret || storedRedirectUris.includes(this.redirectUrl);
|
|
2073
2236
|
if (!hasMatchingRedirect) {
|
|
2074
2237
|
console.info(
|
|
2075
|
-
`[${this.storageKeyPrefix}]
|
|
2238
|
+
`[${this.storageKeyPrefix}] Recovering cached OAuth credentials after a redirect URI change.`
|
|
2076
2239
|
);
|
|
2077
|
-
await this.
|
|
2078
|
-
await this.store.remove(this.credentialKey("tokens", ctx));
|
|
2079
|
-
await this.store.remove(this.getKey("last_auth_url"));
|
|
2240
|
+
await this.invalidateCredentials("registration");
|
|
2080
2241
|
return void 0;
|
|
2081
2242
|
}
|
|
2082
2243
|
return clientInfo;
|
|
@@ -2094,11 +2255,20 @@ var OAuthSessionStore = class _OAuthSessionStore {
|
|
|
2094
2255
|
"Browser OAuth clients must be public clients; client_secret persistence is not allowed."
|
|
2095
2256
|
);
|
|
2096
2257
|
}
|
|
2097
|
-
const
|
|
2258
|
+
const persistedClientInformation = !this.allowClientSecret && (!("redirect_uris" in clientInformation) || !Array.isArray(
|
|
2259
|
+
clientInformation.redirect_uris
|
|
2260
|
+
) || clientInformation.redirect_uris.length === 0) ? { ...clientInformation, redirect_uris: [this.redirectUrl] } : clientInformation;
|
|
2261
|
+
const serialized = JSON.stringify(persistedClientInformation);
|
|
2098
2262
|
await this.store.set(this.credentialKey("client_info", ctx), serialized);
|
|
2099
2263
|
if (ctx) {
|
|
2100
2264
|
await this.store.set(this.credentialKey("client_info"), serialized);
|
|
2101
2265
|
}
|
|
2266
|
+
if (!this.allowClientSecret) {
|
|
2267
|
+
await this.store.set(
|
|
2268
|
+
this.getKey("client_info_redirect_uri"),
|
|
2269
|
+
this.redirectUrl
|
|
2270
|
+
);
|
|
2271
|
+
}
|
|
2102
2272
|
}
|
|
2103
2273
|
async saveCodeVerifier(codeVerifier) {
|
|
2104
2274
|
await this.store.set(this.getKey("code_verifier"), codeVerifier);
|
|
@@ -2123,11 +2293,22 @@ var OAuthSessionStore = class _OAuthSessionStore {
|
|
|
2123
2293
|
}
|
|
2124
2294
|
};
|
|
2125
2295
|
switch (scope) {
|
|
2296
|
+
case "registration":
|
|
2297
|
+
await removeCredentialKeys("tokens");
|
|
2298
|
+
await removeCredentialKeys("client_info");
|
|
2299
|
+
await this.store.remove(this.getKey("code_verifier"));
|
|
2300
|
+
await this.store.remove(this.getKey("last_auth_url"));
|
|
2301
|
+
await this.store.remove(this.getKey("last_auth_callback_url"));
|
|
2302
|
+
await this.store.remove(this.getKey("client_info_redirect_uri"));
|
|
2303
|
+
await this.store.remove(this.getKey("token_endpoint"));
|
|
2304
|
+
break;
|
|
2126
2305
|
case "all":
|
|
2127
2306
|
await removeCredentialKeys("tokens");
|
|
2128
2307
|
await removeCredentialKeys("client_info");
|
|
2129
2308
|
await this.store.remove(this.getKey("code_verifier"));
|
|
2130
2309
|
await this.store.remove(this.getKey("last_auth_url"));
|
|
2310
|
+
await this.store.remove(this.getKey("last_auth_callback_url"));
|
|
2311
|
+
await this.store.remove(this.getKey("client_info_redirect_uri"));
|
|
2131
2312
|
await this.store.remove(this.getKey("discovery_state"));
|
|
2132
2313
|
await this.store.remove(this.getKey("token_endpoint"));
|
|
2133
2314
|
break;
|
|
@@ -2177,7 +2358,7 @@ var OAuthSessionStore = class _OAuthSessionStore {
|
|
|
2177
2358
|
*/
|
|
2178
2359
|
async storeAuthorizationState(authorizationUrl, opts = {}) {
|
|
2179
2360
|
const state = globalThis.crypto.randomUUID();
|
|
2180
|
-
const stateKey = `${this.storageKeyPrefix}
|
|
2361
|
+
const stateKey = `${this.storageKeyPrefix}_${this.serverUrlHash}_state_${state}`;
|
|
2181
2362
|
const stateData = {
|
|
2182
2363
|
serverUrlHash: this.serverUrlHash,
|
|
2183
2364
|
expiry: Date.now() + 1e3 * 60 * 10,
|
|
@@ -2197,6 +2378,10 @@ var OAuthSessionStore = class _OAuthSessionStore {
|
|
|
2197
2378
|
authorizationUrl.searchParams.set("state", state);
|
|
2198
2379
|
const sanitizedAuthUrl = sanitizeUrl(authorizationUrl.toString());
|
|
2199
2380
|
await this.store.set(stateKey, JSON.stringify(stateData));
|
|
2381
|
+
await this.store.set(
|
|
2382
|
+
this.getKey("last_auth_callback_url"),
|
|
2383
|
+
this.redirectUrl
|
|
2384
|
+
);
|
|
2200
2385
|
await this.store.set(this.getKey("last_auth_url"), sanitizedAuthUrl);
|
|
2201
2386
|
return sanitizedAuthUrl;
|
|
2202
2387
|
}
|
|
@@ -2222,8 +2407,16 @@ var DEFAULT_PORT = 33418;
|
|
|
2222
2407
|
var PORT_RANGE = 10;
|
|
2223
2408
|
var DEFAULT_AUTH_TIMEOUT_MS2 = 5 * 6e4;
|
|
2224
2409
|
var OAuthFlowError = class extends Error {
|
|
2410
|
+
/** OAuth or local-flow error code. */
|
|
2225
2411
|
code;
|
|
2412
|
+
/** Optional human-readable error description. */
|
|
2226
2413
|
description;
|
|
2414
|
+
/**
|
|
2415
|
+
* Creates an OAuth flow error.
|
|
2416
|
+
*
|
|
2417
|
+
* @param code - OAuth or local-flow error code.
|
|
2418
|
+
* @param description - Optional human-readable description.
|
|
2419
|
+
*/
|
|
2227
2420
|
constructor(code, description) {
|
|
2228
2421
|
super(description ? `${code}: ${description}` : code);
|
|
2229
2422
|
this.code = code;
|
|
@@ -2273,16 +2466,20 @@ h1{font-size:20px;margin:0 0 12px;color:#b00020}p{line-height:1.5}code{backgroun
|
|
|
2273
2466
|
<p><code>${escapeHtml(err)}</code>${desc ? `: ${escapeHtml(desc)}` : ""}</p>
|
|
2274
2467
|
<p>You can close this tab and return to your terminal.</p></body></html>`;
|
|
2275
2468
|
var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
|
|
2469
|
+
/** Protected MCP server URL associated with this provider. */
|
|
2276
2470
|
serverUrl;
|
|
2471
|
+
/** Reserved localhost callback port. */
|
|
2277
2472
|
port;
|
|
2278
2473
|
session;
|
|
2279
2474
|
kv;
|
|
2280
2475
|
authTimeoutMs;
|
|
2281
2476
|
openBrowserOverride;
|
|
2282
2477
|
server = null;
|
|
2478
|
+
/** Provider authorization URL, exposed only through the local redirect route. */
|
|
2479
|
+
authorizationUrl = null;
|
|
2283
2480
|
/** Currently in-flight deferred — used to prevent overlapping flows. */
|
|
2284
2481
|
pending = null;
|
|
2285
|
-
/** Latest deferred (settled or in-flight)
|
|
2482
|
+
/** Latest deferred (settled or in-flight) for the loopback response. */
|
|
2286
2483
|
lastFlow = null;
|
|
2287
2484
|
pendingTimer = null;
|
|
2288
2485
|
constructor(serverUrl, port, session, kv, options) {
|
|
@@ -2293,6 +2490,13 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
|
|
|
2293
2490
|
this.authTimeoutMs = options.authTimeoutMs ?? DEFAULT_AUTH_TIMEOUT_MS2;
|
|
2294
2491
|
this.openBrowserOverride = options.openBrowser;
|
|
2295
2492
|
}
|
|
2493
|
+
/**
|
|
2494
|
+
* Creates a Node OAuth provider and reserves a localhost callback port.
|
|
2495
|
+
*
|
|
2496
|
+
* @param serverUrl - Protected MCP server URL.
|
|
2497
|
+
* @param options - OAuth metadata, storage, loopback, and browser options.
|
|
2498
|
+
* @returns A provider ready to participate in the SDK OAuth flow.
|
|
2499
|
+
*/
|
|
2296
2500
|
static async create(serverUrl, options = {}) {
|
|
2297
2501
|
const serverUrlHash = OAuthSessionStore.hashString(serverUrl);
|
|
2298
2502
|
const kv = options.kvStore ?? new FileKVStore(serverUrlHash, options.baseDir);
|
|
@@ -2325,48 +2529,100 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
|
|
|
2325
2529
|
return new _NodeOAuthClientProvider(serverUrl, port, session, kv, options);
|
|
2326
2530
|
}
|
|
2327
2531
|
// --- Identity passthroughs (parallel to BrowserOAuthClientProvider) ---
|
|
2532
|
+
/** Prefix used for persisted OAuth session keys. */
|
|
2328
2533
|
get storageKeyPrefix() {
|
|
2329
2534
|
return this.session.storageKeyPrefix;
|
|
2330
2535
|
}
|
|
2536
|
+
/** Stable hash of the protected server URL used to namespace storage. */
|
|
2331
2537
|
get serverUrlHash() {
|
|
2332
2538
|
return this.session.serverUrlHash;
|
|
2333
2539
|
}
|
|
2334
2540
|
// --- SDK Interface (delegated to OAuthSessionStore) ---
|
|
2541
|
+
/** Loopback redirect URL registered for this provider. */
|
|
2335
2542
|
get redirectUrl() {
|
|
2336
2543
|
return this.session.redirectUrl;
|
|
2337
2544
|
}
|
|
2545
|
+
/** OAuth client metadata presented during registration. */
|
|
2338
2546
|
get clientMetadata() {
|
|
2339
2547
|
return this.session.clientMetadata;
|
|
2340
2548
|
}
|
|
2549
|
+
/** OAuth Client ID Metadata Document URL, when configured. */
|
|
2341
2550
|
get clientMetadataUrl() {
|
|
2342
2551
|
return this.session.clientMetadataUrl;
|
|
2343
2552
|
}
|
|
2553
|
+
/**
|
|
2554
|
+
* Loads saved OAuth tokens.
|
|
2555
|
+
*
|
|
2556
|
+
* @param ctx - Optional client registration context.
|
|
2557
|
+
* @returns Saved tokens, or `undefined` when none exist.
|
|
2558
|
+
*/
|
|
2344
2559
|
tokens(ctx) {
|
|
2345
2560
|
return this.session.tokens(ctx);
|
|
2346
2561
|
}
|
|
2562
|
+
/**
|
|
2563
|
+
* Persists OAuth tokens.
|
|
2564
|
+
*
|
|
2565
|
+
* @param tokens - Tokens to save.
|
|
2566
|
+
* @param ctx - Optional client registration context.
|
|
2567
|
+
*/
|
|
2347
2568
|
saveTokens(tokens, ctx) {
|
|
2348
2569
|
return this.session.saveTokens(tokens, ctx);
|
|
2349
2570
|
}
|
|
2571
|
+
/**
|
|
2572
|
+
* Loads saved OAuth client registration information.
|
|
2573
|
+
*
|
|
2574
|
+
* @param ctx - Optional registration context.
|
|
2575
|
+
* @returns Saved registration information, or `undefined`.
|
|
2576
|
+
*/
|
|
2350
2577
|
clientInformation(ctx) {
|
|
2351
2578
|
return this.session.clientInformation(ctx);
|
|
2352
2579
|
}
|
|
2580
|
+
/**
|
|
2581
|
+
* Persists OAuth client registration information.
|
|
2582
|
+
*
|
|
2583
|
+
* @param info - Client information to save.
|
|
2584
|
+
* @param ctx - Optional registration context.
|
|
2585
|
+
*/
|
|
2353
2586
|
saveClientInformation(info, ctx) {
|
|
2354
2587
|
return this.session.saveClientInformation(info, ctx);
|
|
2355
2588
|
}
|
|
2589
|
+
/**
|
|
2590
|
+
* Loads the saved PKCE code verifier.
|
|
2591
|
+
*
|
|
2592
|
+
* @returns The saved verifier.
|
|
2593
|
+
*/
|
|
2356
2594
|
codeVerifier() {
|
|
2357
2595
|
return this.session.codeVerifier();
|
|
2358
2596
|
}
|
|
2597
|
+
/**
|
|
2598
|
+
* Persists a PKCE code verifier.
|
|
2599
|
+
*
|
|
2600
|
+
* @param codeVerifier - Verifier to save.
|
|
2601
|
+
*/
|
|
2359
2602
|
saveCodeVerifier(codeVerifier) {
|
|
2360
2603
|
return this.session.saveCodeVerifier(codeVerifier);
|
|
2361
2604
|
}
|
|
2605
|
+
/**
|
|
2606
|
+
* Invalidates selected persisted OAuth credentials.
|
|
2607
|
+
*
|
|
2608
|
+
* @param scope - Credential group to remove.
|
|
2609
|
+
*/
|
|
2362
2610
|
invalidateCredentials(scope) {
|
|
2363
2611
|
return this.session.invalidateCredentials(scope);
|
|
2364
2612
|
}
|
|
2365
|
-
/**
|
|
2613
|
+
/**
|
|
2614
|
+
* Persists OAuth discovery state.
|
|
2615
|
+
*
|
|
2616
|
+
* @param state - Discovery state to save.
|
|
2617
|
+
*/
|
|
2366
2618
|
saveDiscoveryState(state) {
|
|
2367
2619
|
return this.session.saveDiscoveryState(state);
|
|
2368
2620
|
}
|
|
2369
|
-
/**
|
|
2621
|
+
/**
|
|
2622
|
+
* Returns previously saved OAuth discovery state.
|
|
2623
|
+
*
|
|
2624
|
+
* @returns Saved discovery state, or `undefined`.
|
|
2625
|
+
*/
|
|
2370
2626
|
discoveryState() {
|
|
2371
2627
|
return this.session.discoveryState();
|
|
2372
2628
|
}
|
|
@@ -2374,6 +2630,10 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
|
|
|
2374
2630
|
* Bind the loopback server, set up the pending-code deferred, and ask the
|
|
2375
2631
|
* platform to open the user's browser. Does NOT await the code; the
|
|
2376
2632
|
* orchestrator awaits via `getAuthorizationCode()`.
|
|
2633
|
+
*
|
|
2634
|
+
* @param authorizationUrl - Authorization URL generated by the SDK.
|
|
2635
|
+
* @returns A promise that resolves once the loopback listener is ready and
|
|
2636
|
+
* the browser-open attempt completes.
|
|
2377
2637
|
*/
|
|
2378
2638
|
async redirectToAuthorization(authorizationUrl) {
|
|
2379
2639
|
if (this.pending) {
|
|
@@ -2385,6 +2645,7 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
|
|
|
2385
2645
|
authorizationUrl,
|
|
2386
2646
|
{ flowType: "redirect" }
|
|
2387
2647
|
);
|
|
2648
|
+
this.authorizationUrl = sanitizedUrl;
|
|
2388
2649
|
await this.startLoopback();
|
|
2389
2650
|
this.pending = createDeferred();
|
|
2390
2651
|
this.lastFlow = this.pending;
|
|
@@ -2399,8 +2660,9 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
|
|
|
2399
2660
|
);
|
|
2400
2661
|
}, this.authTimeoutMs);
|
|
2401
2662
|
const opener = this.openBrowserOverride ?? defaultOpener;
|
|
2663
|
+
const launcherUrl = `http://127.0.0.1:${this.port}/authorize`;
|
|
2402
2664
|
try {
|
|
2403
|
-
await opener(
|
|
2665
|
+
await opener(launcherUrl);
|
|
2404
2666
|
} catch (err) {
|
|
2405
2667
|
console.error(
|
|
2406
2668
|
`[mcp-use] Could not open browser automatically: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -2409,15 +2671,30 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
|
|
|
2409
2671
|
}
|
|
2410
2672
|
/**
|
|
2411
2673
|
* Resolves with the authorization code captured by the loopback callback.
|
|
2674
|
+
*
|
|
2675
|
+
* @remarks This compatibility method omits the RFC 9207 issuer. OAuth flow
|
|
2676
|
+
* orchestrators should use {@link getAuthorizationResponse} when available.
|
|
2412
2677
|
* Must be called after `redirectToAuthorization()`. Returns the same
|
|
2413
2678
|
* promise whether the callback has fired or not — callers may subscribe
|
|
2414
2679
|
* before or after.
|
|
2680
|
+
*
|
|
2681
|
+
* @returns The authorization code received by the loopback callback.
|
|
2415
2682
|
*/
|
|
2416
2683
|
getAuthorizationCode() {
|
|
2684
|
+
return this.getAuthorizationResponse().then((response) => response.code);
|
|
2685
|
+
}
|
|
2686
|
+
/**
|
|
2687
|
+
* Resolves with the authorization code and RFC 9207 issuer captured by the
|
|
2688
|
+
* loopback callback.
|
|
2689
|
+
*
|
|
2690
|
+
* @returns The loopback authorization response.
|
|
2691
|
+
* @throws When called before {@link NodeOAuthClientProvider.redirectToAuthorization}.
|
|
2692
|
+
*/
|
|
2693
|
+
getAuthorizationResponse() {
|
|
2417
2694
|
if (!this.lastFlow) {
|
|
2418
2695
|
return Promise.reject(
|
|
2419
2696
|
new Error(
|
|
2420
|
-
"NodeOAuthClientProvider.
|
|
2697
|
+
"NodeOAuthClientProvider.getAuthorizationResponse() called before redirectToAuthorization()"
|
|
2421
2698
|
)
|
|
2422
2699
|
);
|
|
2423
2700
|
}
|
|
@@ -2425,6 +2702,9 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
|
|
|
2425
2702
|
}
|
|
2426
2703
|
/**
|
|
2427
2704
|
* Cancel an in-progress flow (timeout, SIGINT, etc.) and close the loopback.
|
|
2705
|
+
*
|
|
2706
|
+
* Pending calls to {@link NodeOAuthClientProvider.getAuthorizationResponse}
|
|
2707
|
+
* reject with an {@link OAuthFlowError} whose code is `"cancelled"`.
|
|
2428
2708
|
*/
|
|
2429
2709
|
dispose() {
|
|
2430
2710
|
if (this.pending) {
|
|
@@ -2433,7 +2713,7 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
|
|
|
2433
2713
|
this.stopLoopback();
|
|
2434
2714
|
}
|
|
2435
2715
|
}
|
|
2436
|
-
/**
|
|
2716
|
+
/** Local callback port, useful for status output and tests. */
|
|
2437
2717
|
get callbackPort() {
|
|
2438
2718
|
return this.port;
|
|
2439
2719
|
}
|
|
@@ -2471,12 +2751,13 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
|
|
|
2471
2751
|
this.server.close();
|
|
2472
2752
|
this.server = null;
|
|
2473
2753
|
}
|
|
2754
|
+
this.authorizationUrl = null;
|
|
2474
2755
|
}
|
|
2475
|
-
resolvePending(
|
|
2756
|
+
resolvePending(response) {
|
|
2476
2757
|
const p = this.pending;
|
|
2477
2758
|
this.pending = null;
|
|
2478
2759
|
this.stopLoopback();
|
|
2479
|
-
p?.resolve(
|
|
2760
|
+
p?.resolve(response);
|
|
2480
2761
|
}
|
|
2481
2762
|
rejectPending(err) {
|
|
2482
2763
|
const p = this.pending;
|
|
@@ -2486,6 +2767,19 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
|
|
|
2486
2767
|
}
|
|
2487
2768
|
handleCallback(rawUrl, res) {
|
|
2488
2769
|
const url = new URL(rawUrl, `http://127.0.0.1:${this.port}`);
|
|
2770
|
+
if (url.pathname === "/authorize") {
|
|
2771
|
+
if (this.authorizationUrl === null || this.pending === null) {
|
|
2772
|
+
res.statusCode = 410;
|
|
2773
|
+
res.end("Authorization flow is not active");
|
|
2774
|
+
return;
|
|
2775
|
+
}
|
|
2776
|
+
res.statusCode = 302;
|
|
2777
|
+
res.setHeader("location", this.authorizationUrl);
|
|
2778
|
+
res.setHeader("cache-control", "no-store");
|
|
2779
|
+
res.setHeader("referrer-policy", "no-referrer");
|
|
2780
|
+
res.end();
|
|
2781
|
+
return;
|
|
2782
|
+
}
|
|
2489
2783
|
if (url.pathname !== "/callback") {
|
|
2490
2784
|
res.statusCode = 404;
|
|
2491
2785
|
res.end("Not Found");
|
|
@@ -2493,6 +2787,7 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
|
|
|
2493
2787
|
}
|
|
2494
2788
|
const code = url.searchParams.get("code");
|
|
2495
2789
|
const state = url.searchParams.get("state");
|
|
2790
|
+
const iss = url.searchParams.get("iss") ?? void 0;
|
|
2496
2791
|
const err = url.searchParams.get("error");
|
|
2497
2792
|
const errDesc = url.searchParams.get("error_description") ?? void 0;
|
|
2498
2793
|
if (err) {
|
|
@@ -2510,7 +2805,7 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
|
|
|
2510
2805
|
res.statusCode = 200;
|
|
2511
2806
|
res.setHeader("content-type", "text/html; charset=utf-8");
|
|
2512
2807
|
res.end(SUCCESS_HTML);
|
|
2513
|
-
this.resolvePending(code);
|
|
2808
|
+
this.resolvePending({ code, ...iss !== void 0 ? { iss } : {} });
|
|
2514
2809
|
}
|
|
2515
2810
|
};
|
|
2516
2811
|
async function defaultOpener(url) {
|
|
@@ -2592,6 +2887,12 @@ var HttpConnector = class extends BaseConnector {
|
|
|
2592
2887
|
reconnectionOptions;
|
|
2593
2888
|
transportType = null;
|
|
2594
2889
|
streamableTransport = null;
|
|
2890
|
+
/**
|
|
2891
|
+
* Creates an HTTP connector.
|
|
2892
|
+
*
|
|
2893
|
+
* @param baseUrl - MCP endpoint URL.
|
|
2894
|
+
* @param opts - Authentication, transport, SDK, and reconnection options.
|
|
2895
|
+
*/
|
|
2595
2896
|
constructor(baseUrl, opts = {}) {
|
|
2596
2897
|
super(opts);
|
|
2597
2898
|
const originalUrl = baseUrl.replace(/\/$/, "");
|
|
@@ -2709,7 +3010,12 @@ var HttpConnector = class extends BaseConnector {
|
|
|
2709
3010
|
}
|
|
2710
3011
|
return { fallbackReason, is401Error, httpStatusCode };
|
|
2711
3012
|
}
|
|
2712
|
-
/**
|
|
3013
|
+
/**
|
|
3014
|
+
* Establishes a streamable HTTP connection to the MCP server.
|
|
3015
|
+
*
|
|
3016
|
+
* @returns A promise that resolves after protocol negotiation completes.
|
|
3017
|
+
* @throws An error with `code: 401` when authentication is required.
|
|
3018
|
+
*/
|
|
2713
3019
|
async connect() {
|
|
2714
3020
|
if (this.connected) {
|
|
2715
3021
|
logger.debug("Already connected to MCP implementation");
|
|
@@ -2937,6 +3243,11 @@ var HttpConnector = class extends BaseConnector {
|
|
|
2937
3243
|
throw err;
|
|
2938
3244
|
}
|
|
2939
3245
|
}
|
|
3246
|
+
/**
|
|
3247
|
+
* Returns fields that identify the endpoint and negotiated transport.
|
|
3248
|
+
*
|
|
3249
|
+
* @returns HTTP connector identity metadata.
|
|
3250
|
+
*/
|
|
2940
3251
|
get publicIdentifier() {
|
|
2941
3252
|
return {
|
|
2942
3253
|
type: "http",
|
|
@@ -2945,7 +3256,11 @@ var HttpConnector = class extends BaseConnector {
|
|
|
2945
3256
|
protocolEra: this.protocolEra ?? "unknown"
|
|
2946
3257
|
};
|
|
2947
3258
|
}
|
|
2948
|
-
/**
|
|
3259
|
+
/**
|
|
3260
|
+
* Returns the active transport type.
|
|
3261
|
+
*
|
|
3262
|
+
* @returns `"streamable-http"` after connection, otherwise `null`.
|
|
3263
|
+
*/
|
|
2949
3264
|
getTransportType() {
|
|
2950
3265
|
return this.transportType;
|
|
2951
3266
|
}
|
|
@@ -3320,7 +3635,7 @@ var MCPConnection = class {
|
|
|
3320
3635
|
/**
|
|
3321
3636
|
* Normalized server metadata for this ready connection.
|
|
3322
3637
|
*
|
|
3323
|
-
* @throws
|
|
3638
|
+
* @throws When called before protocol negotiation completes.
|
|
3324
3639
|
*/
|
|
3325
3640
|
get info() {
|
|
3326
3641
|
const protocolEra = this.protocolEra;
|
|
@@ -3532,12 +3847,10 @@ function isOAuthClientProvider(provider) {
|
|
|
3532
3847
|
var BaseMCPClient = class {
|
|
3533
3848
|
/**
|
|
3534
3849
|
* Internal configuration object containing MCP server definitions.
|
|
3535
|
-
* @protected
|
|
3536
3850
|
*/
|
|
3537
3851
|
config = {};
|
|
3538
3852
|
/**
|
|
3539
3853
|
* Map of server names to their active sessions.
|
|
3540
|
-
* @protected
|
|
3541
3854
|
*/
|
|
3542
3855
|
sessions = {};
|
|
3543
3856
|
/**
|
|
@@ -3581,7 +3894,7 @@ var BaseMCPClient = class {
|
|
|
3581
3894
|
*
|
|
3582
3895
|
* @param _cfg - Configuration dictionary
|
|
3583
3896
|
* @returns Client instance
|
|
3584
|
-
* @throws
|
|
3897
|
+
* @throws If called on the base class instead of a concrete implementation
|
|
3585
3898
|
*
|
|
3586
3899
|
* @example
|
|
3587
3900
|
* ```typescript
|
|
@@ -3723,7 +4036,7 @@ var BaseMCPClient = class {
|
|
|
3723
4036
|
* @param serverName - The name of the server as defined in the client configuration
|
|
3724
4037
|
* @param autoInitialize - Whether to automatically initialize the session (default: true)
|
|
3725
4038
|
* @returns A promise that resolves to the created MCPSession instance
|
|
3726
|
-
* @throws
|
|
4039
|
+
* @throws If the server is not found in the configuration
|
|
3727
4040
|
*
|
|
3728
4041
|
* @example
|
|
3729
4042
|
* ```typescript
|
|
@@ -3893,7 +4206,7 @@ var BaseMCPClient = class {
|
|
|
3893
4206
|
*
|
|
3894
4207
|
* @param serverName - Name of the server
|
|
3895
4208
|
* @returns The session instance
|
|
3896
|
-
* @throws
|
|
4209
|
+
* @throws If the session is not found
|
|
3897
4210
|
*
|
|
3898
4211
|
* @example
|
|
3899
4212
|
* ```typescript
|
|
@@ -4277,20 +4590,24 @@ global.search_tools = async (query, detailLevel = 'full') => {
|
|
|
4277
4590
|
for (const [serverName, serverTools] of Object.entries(tools)) {
|
|
4278
4591
|
if (!serverTools || serverTools.length === 0) continue;
|
|
4279
4592
|
const safeServerName = serverName.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
4593
|
+
const escapedServerName = JSON.stringify(serverName);
|
|
4594
|
+
const escapedSafeServerName = JSON.stringify(safeServerName);
|
|
4280
4595
|
shim += `
|
|
4281
|
-
global[
|
|
4596
|
+
global[${escapedServerName}] = {`;
|
|
4282
4597
|
for (const tool of serverTools) {
|
|
4598
|
+
const escapedToolName = JSON.stringify(tool.name);
|
|
4283
4599
|
shim += `
|
|
4284
|
-
|
|
4600
|
+
[${escapedToolName}]: async (args) => await global.__callMcpTool(${escapedServerName}, ${escapedToolName}, args),`;
|
|
4285
4601
|
}
|
|
4286
4602
|
shim += `
|
|
4287
4603
|
};
|
|
4288
|
-
|
|
4604
|
+
`;
|
|
4605
|
+
if (safeServerName !== serverName) {
|
|
4606
|
+
shim += `
|
|
4289
4607
|
// Also expose as safe name if different
|
|
4290
|
-
|
|
4291
|
-
global['${safeServerName}'] = global['${serverName}'];
|
|
4292
|
-
}
|
|
4608
|
+
global[${escapedSafeServerName}] = global[${escapedServerName}];
|
|
4293
4609
|
`;
|
|
4610
|
+
}
|
|
4294
4611
|
}
|
|
4295
4612
|
return shim;
|
|
4296
4613
|
}
|
|
@@ -4984,9 +5301,7 @@ var MCPClient = class _MCPClient extends BaseMCPClient {
|
|
|
4984
5301
|
* @param config - Configuration object or path to JSON config file. If omitted,
|
|
4985
5302
|
* starts with empty configuration
|
|
4986
5303
|
* @param options - Optional client behavior configuration
|
|
4987
|
-
*
|
|
4988
|
-
* @param options.onSampling - Callback for handling sampling requests from servers
|
|
4989
|
-
* @param options.onElicitation - Callback for handling elicitation requests
|
|
5304
|
+
* Options can enable code mode or provide sampling and elicitation callbacks.
|
|
4990
5305
|
*
|
|
4991
5306
|
* @example
|
|
4992
5307
|
* ```typescript
|
|
@@ -5087,7 +5402,7 @@ var MCPClient = class _MCPClient extends BaseMCPClient {
|
|
|
5087
5402
|
* });
|
|
5088
5403
|
* ```
|
|
5089
5404
|
*
|
|
5090
|
-
* @see {@link
|
|
5405
|
+
* @see {@link MCPClient} for direct instantiation
|
|
5091
5406
|
* @see {@link fromConfigFile} for loading from file
|
|
5092
5407
|
*/
|
|
5093
5408
|
static fromDict(cfg, options) {
|
|
@@ -5102,7 +5417,7 @@ var MCPClient = class _MCPClient extends BaseMCPClient {
|
|
|
5102
5417
|
* @param path - Path to the JSON configuration file
|
|
5103
5418
|
* @param options - Optional client behavior configuration
|
|
5104
5419
|
* @returns New MCPClient instance
|
|
5105
|
-
* @throws
|
|
5420
|
+
* @throws If the file cannot be read or parsed
|
|
5106
5421
|
*
|
|
5107
5422
|
* @example
|
|
5108
5423
|
* ```typescript
|
|
@@ -5118,7 +5433,7 @@ var MCPClient = class _MCPClient extends BaseMCPClient {
|
|
|
5118
5433
|
* });
|
|
5119
5434
|
* ```
|
|
5120
5435
|
*
|
|
5121
|
-
* @see {@link
|
|
5436
|
+
* @see {@link MCPClient} for direct instantiation
|
|
5122
5437
|
* @see {@link fromDict} for inline configuration
|
|
5123
5438
|
*/
|
|
5124
5439
|
static fromConfigFile(path2, options) {
|
|
@@ -5265,7 +5580,7 @@ var MCPClient = class _MCPClient extends BaseMCPClient {
|
|
|
5265
5580
|
* @param code - JavaScript/TypeScript code to execute
|
|
5266
5581
|
* @param timeout - Optional execution timeout in milliseconds
|
|
5267
5582
|
* @returns Execution result with output, errors, and return value
|
|
5268
|
-
* @throws
|
|
5583
|
+
* @throws If code mode is not enabled
|
|
5269
5584
|
*
|
|
5270
5585
|
* @example
|
|
5271
5586
|
* ```typescript
|
|
@@ -5311,7 +5626,7 @@ var MCPClient = class _MCPClient extends BaseMCPClient {
|
|
|
5311
5626
|
* @param query - Optional search query to filter tools (defaults to empty string for all tools)
|
|
5312
5627
|
* @param detailLevel - Level of detail to return: "names", "descriptions", or "full"
|
|
5313
5628
|
* @returns Tool search results with matching tools
|
|
5314
|
-
* @throws
|
|
5629
|
+
* @throws If code mode is not enabled
|
|
5315
5630
|
*
|
|
5316
5631
|
* @example
|
|
5317
5632
|
* ```typescript
|