mcp-use 1.2.1 → 1.2.2-canary.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.
@@ -4,10 +4,11 @@ import {
4
4
  useWidgetProps,
5
5
  useWidgetState,
6
6
  useWidgetTheme
7
- } from "../../chunk-JV7HAYUT.js";
7
+ } from "../../chunk-CPV4QNHD.js";
8
8
  import {
9
9
  onMcpAuthorization
10
- } from "../../chunk-62GFHYCL.js";
10
+ } from "../../chunk-C3SRZK7H.js";
11
+ import "../../chunk-VPPILX7B.js";
11
12
  import "../../chunk-SHUYVCID.js";
12
13
  export {
13
14
  onMcpAuthorization,
@@ -1,4 +1,5 @@
1
1
  import type { Prompt, Resource, ResourceTemplate, Tool } from '@modelcontextprotocol/sdk/types.js';
2
+ import type { BrowserMCPClient } from '../client/browser.js';
2
3
  export type UseMcpOptions = {
3
4
  /** The /sse URL of your remote MCP server */
4
5
  url?: string;
@@ -139,5 +140,26 @@ export type UseMcpResult = {
139
140
  authenticate: () => void;
140
141
  /** Clears all stored authentication data (tokens, client info, etc.) for this server URL from localStorage. */
141
142
  clearStorage: () => void;
143
+ /**
144
+ * The underlying BrowserMCPClient instance.
145
+ * Use this to create an MCPAgent for AI chat functionality.
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * import { MCPAgent } from 'mcp-use'
150
+ * import { ChatOpenAI } from '@langchain/openai'
151
+ *
152
+ * const mcp = useMcp({ url: 'http://localhost:3000/mcp' })
153
+ * const llm = new ChatOpenAI({ model: 'gpt-4' })
154
+ *
155
+ * const agent = new MCPAgent({ llm, client: mcp.client })
156
+ * await agent.initialize()
157
+ *
158
+ * for await (const event of agent.streamEvents('Hello')) {
159
+ * console.log(event)
160
+ * }
161
+ * ```
162
+ */
163
+ client: BrowserMCPClient | null;
142
164
  };
143
165
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/react/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/react/types.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,34 @@
1
1
  import type { UseMcpOptions, UseMcpResult } from './types.js';
2
+ /**
3
+ * React hook for connecting to and interacting with MCP servers
4
+ *
5
+ * Provides a complete interface for MCP server connections including:
6
+ * - Automatic connection management with reconnection
7
+ * - OAuth authentication with automatic token refresh
8
+ * - Tool, resource, and prompt access
9
+ * - AI chat functionality with conversation memory
10
+ * - Multi-transport support (HTTP, SSE) with automatic fallback
11
+ *
12
+ * @param options - Configuration options for the MCP connection
13
+ * @returns MCP connection state and methods
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const mcp = useMcp({
18
+ * url: 'http://localhost:3000/mcp',
19
+ * customHeaders: { Authorization: 'Bearer YOUR_API_KEY' }
20
+ * })
21
+ *
22
+ * // Wait for connection
23
+ * useEffect(() => {
24
+ * if (mcp.state === 'ready') {
25
+ * console.log('Connected!', mcp.tools)
26
+ * }
27
+ * }, [mcp.state])
28
+ *
29
+ * // Call a tool
30
+ * const result = await mcp.callTool('send-email', { to: 'user@example.com' })
31
+ * ```
32
+ */
2
33
  export declare function useMcp(options: UseMcpOptions): UseMcpResult;
3
34
  //# sourceMappingURL=useMcp.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useMcp.d.ts","sourceRoot":"","sources":["../../../src/react/useMcp.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAS9D,wBAAgB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,YAAY,CA4vB3D"}
1
+ {"version":3,"file":"useMcp.d.ts","sourceRoot":"","sources":["../../../src/react/useMcp.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAS9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,YAAY,CAstB3D"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mcp-use",
3
3
  "type": "module",
4
- "version": "1.2.1",
4
+ "version": "1.2.2-canary.0",
5
5
  "description": "Opinionated MCP Framework for TypeScript (@modelcontextprotocol/sdk compatible) - Build MCP Agents and Clients + MCP Servers with support for MCP-UI.",
6
6
  "author": "mcp-use, Inc.",
7
7
  "license": "MIT",
@@ -112,8 +112,8 @@
112
112
  "ws": "^8.18.2",
113
113
  "zod": "^3.25.48",
114
114
  "zod-to-json-schema": "^3.24.6",
115
- "@mcp-use/cli": "2.1.22",
116
- "@mcp-use/inspector": "0.4.10"
115
+ "@mcp-use/cli": "2.1.23-canary.0",
116
+ "@mcp-use/inspector": "0.4.11-canary.0"
117
117
  },
118
118
  "devDependencies": {
119
119
  "@antfu/eslint-config": "^4.13.2",
@@ -1,300 +0,0 @@
1
- import {
2
- __name
3
- } from "./chunk-SHUYVCID.js";
4
-
5
- // src/auth/browser-provider.ts
6
- import { sanitizeUrl } from "strict-url-sanitise";
7
- var BrowserOAuthClientProvider = class {
8
- static {
9
- __name(this, "BrowserOAuthClientProvider");
10
- }
11
- serverUrl;
12
- storageKeyPrefix;
13
- serverUrlHash;
14
- clientName;
15
- clientUri;
16
- callbackUrl;
17
- preventAutoAuth;
18
- onPopupWindow;
19
- constructor(serverUrl, options = {}) {
20
- this.serverUrl = serverUrl;
21
- this.storageKeyPrefix = options.storageKeyPrefix || "mcp:auth";
22
- this.serverUrlHash = this.hashString(serverUrl);
23
- this.clientName = options.clientName || "mcp-use";
24
- this.clientUri = options.clientUri || (typeof window !== "undefined" ? window.location.origin : "");
25
- this.callbackUrl = sanitizeUrl(
26
- options.callbackUrl || (typeof window !== "undefined" ? new URL("/oauth/callback", window.location.origin).toString() : "/oauth/callback")
27
- );
28
- this.preventAutoAuth = options.preventAutoAuth;
29
- this.onPopupWindow = options.onPopupWindow;
30
- }
31
- // --- SDK Interface Methods ---
32
- get redirectUrl() {
33
- return sanitizeUrl(this.callbackUrl);
34
- }
35
- get clientMetadata() {
36
- return {
37
- redirect_uris: [this.redirectUrl],
38
- token_endpoint_auth_method: "none",
39
- // Public client
40
- grant_types: ["authorization_code", "refresh_token"],
41
- response_types: ["code"],
42
- client_name: this.clientName,
43
- client_uri: this.clientUri
44
- // scope: 'openid profile email mcp', // Example scopes, adjust as needed
45
- };
46
- }
47
- async clientInformation() {
48
- const key = this.getKey("client_info");
49
- const data = localStorage.getItem(key);
50
- if (!data) return void 0;
51
- try {
52
- return JSON.parse(data);
53
- } catch (e) {
54
- console.warn(`[${this.storageKeyPrefix}] Failed to parse client information:`, e);
55
- localStorage.removeItem(key);
56
- return void 0;
57
- }
58
- }
59
- // NOTE: The SDK's auth() function uses this if dynamic registration is needed.
60
- // Ensure your OAuthClientInformationFull matches the expected structure if DCR is used.
61
- async saveClientInformation(clientInformation) {
62
- const key = this.getKey("client_info");
63
- localStorage.setItem(key, JSON.stringify(clientInformation));
64
- }
65
- async tokens() {
66
- const key = this.getKey("tokens");
67
- const data = localStorage.getItem(key);
68
- if (!data) return void 0;
69
- try {
70
- return JSON.parse(data);
71
- } catch (e) {
72
- console.warn(`[${this.storageKeyPrefix}] Failed to parse tokens:`, e);
73
- localStorage.removeItem(key);
74
- return void 0;
75
- }
76
- }
77
- async saveTokens(tokens) {
78
- const key = this.getKey("tokens");
79
- localStorage.setItem(key, JSON.stringify(tokens));
80
- localStorage.removeItem(this.getKey("code_verifier"));
81
- localStorage.removeItem(this.getKey("last_auth_url"));
82
- }
83
- async saveCodeVerifier(codeVerifier) {
84
- const key = this.getKey("code_verifier");
85
- localStorage.setItem(key, codeVerifier);
86
- }
87
- async codeVerifier() {
88
- const key = this.getKey("code_verifier");
89
- const verifier = localStorage.getItem(key);
90
- if (!verifier) {
91
- throw new Error(
92
- `[${this.storageKeyPrefix}] Code verifier not found in storage for key ${key}. Auth flow likely corrupted or timed out.`
93
- );
94
- }
95
- return verifier;
96
- }
97
- /**
98
- * Generates and stores the authorization URL with state, without opening a popup.
99
- * Used when preventAutoAuth is enabled to provide the URL for manual navigation.
100
- * @param authorizationUrl The fully constructed authorization URL from the SDK.
101
- * @returns The full authorization URL with state parameter.
102
- */
103
- async prepareAuthorizationUrl(authorizationUrl) {
104
- const state = globalThis.crypto.randomUUID();
105
- const stateKey = `${this.storageKeyPrefix}:state_${state}`;
106
- const stateData = {
107
- serverUrlHash: this.serverUrlHash,
108
- expiry: Date.now() + 1e3 * 60 * 10,
109
- // State expires in 10 minutes
110
- // Store provider options needed to reconstruct on callback
111
- providerOptions: {
112
- serverUrl: this.serverUrl,
113
- storageKeyPrefix: this.storageKeyPrefix,
114
- clientName: this.clientName,
115
- clientUri: this.clientUri,
116
- callbackUrl: this.callbackUrl
117
- }
118
- };
119
- localStorage.setItem(stateKey, JSON.stringify(stateData));
120
- authorizationUrl.searchParams.set("state", state);
121
- const authUrlString = authorizationUrl.toString();
122
- const sanitizedAuthUrl = sanitizeUrl(authUrlString);
123
- localStorage.setItem(this.getKey("last_auth_url"), sanitizedAuthUrl);
124
- return sanitizedAuthUrl;
125
- }
126
- /**
127
- * Redirects the user agent to the authorization URL, storing necessary state.
128
- * This now adheres to the SDK's void return type expectation for the interface.
129
- * @param authorizationUrl The fully constructed authorization URL from the SDK.
130
- */
131
- async redirectToAuthorization(authorizationUrl) {
132
- if (this.preventAutoAuth) return;
133
- const sanitizedAuthUrl = await this.prepareAuthorizationUrl(authorizationUrl);
134
- const popupFeatures = "width=600,height=700,resizable=yes,scrollbars=yes,status=yes";
135
- try {
136
- const popup = window.open(sanitizedAuthUrl, `mcp_auth_${this.serverUrlHash}`, popupFeatures);
137
- if (this.onPopupWindow) {
138
- this.onPopupWindow(sanitizedAuthUrl, popupFeatures, popup);
139
- }
140
- if (!popup || popup.closed || typeof popup.closed === "undefined") {
141
- console.warn(
142
- `[${this.storageKeyPrefix}] Popup likely blocked by browser. Manual navigation might be required using the stored URL.`
143
- );
144
- } else {
145
- popup.focus();
146
- console.info(`[${this.storageKeyPrefix}] Redirecting to authorization URL in popup.`);
147
- }
148
- } catch (e) {
149
- console.error(`[${this.storageKeyPrefix}] Error opening popup window:`, e);
150
- }
151
- }
152
- // --- Helper Methods ---
153
- /**
154
- * Retrieves the last URL passed to `redirectToAuthorization`. Useful for manual fallback.
155
- */
156
- getLastAttemptedAuthUrl() {
157
- const storedUrl = localStorage.getItem(this.getKey("last_auth_url"));
158
- return storedUrl ? sanitizeUrl(storedUrl) : null;
159
- }
160
- clearStorage() {
161
- const prefixPattern = `${this.storageKeyPrefix}_${this.serverUrlHash}_`;
162
- const statePattern = `${this.storageKeyPrefix}:state_`;
163
- const keysToRemove = [];
164
- let count = 0;
165
- for (let i = 0; i < localStorage.length; i++) {
166
- const key = localStorage.key(i);
167
- if (!key) continue;
168
- if (key.startsWith(prefixPattern)) {
169
- keysToRemove.push(key);
170
- } else if (key.startsWith(statePattern)) {
171
- try {
172
- const item = localStorage.getItem(key);
173
- if (item) {
174
- const state = JSON.parse(item);
175
- if (state.serverUrlHash === this.serverUrlHash) {
176
- keysToRemove.push(key);
177
- }
178
- }
179
- } catch (e) {
180
- console.warn(`[${this.storageKeyPrefix}] Error parsing state key ${key} during clearStorage:`, e);
181
- }
182
- }
183
- }
184
- const uniqueKeysToRemove = [...new Set(keysToRemove)];
185
- uniqueKeysToRemove.forEach((key) => {
186
- localStorage.removeItem(key);
187
- count++;
188
- });
189
- return count;
190
- }
191
- hashString(str) {
192
- let hash = 0;
193
- for (let i = 0; i < str.length; i++) {
194
- const char = str.charCodeAt(i);
195
- hash = (hash << 5) - hash + char;
196
- hash = hash & hash;
197
- }
198
- return Math.abs(hash).toString(16);
199
- }
200
- getKey(keySuffix) {
201
- return `${this.storageKeyPrefix}_${this.serverUrlHash}_${keySuffix}`;
202
- }
203
- };
204
-
205
- // src/auth/callback.ts
206
- import { auth } from "@modelcontextprotocol/sdk/client/auth.js";
207
- async function onMcpAuthorization() {
208
- const queryParams = new URLSearchParams(window.location.search);
209
- const code = queryParams.get("code");
210
- const state = queryParams.get("state");
211
- const error = queryParams.get("error");
212
- const errorDescription = queryParams.get("error_description");
213
- const logPrefix = "[mcp-callback]";
214
- console.log(`${logPrefix} Handling callback...`, { code, state, error, errorDescription });
215
- let provider = null;
216
- let storedStateData = null;
217
- const stateKey = state ? `mcp:auth:state_${state}` : null;
218
- try {
219
- if (error) {
220
- throw new Error(`OAuth error: ${error} - ${errorDescription || "No description provided."}`);
221
- }
222
- if (!code) {
223
- throw new Error("Authorization code not found in callback query parameters.");
224
- }
225
- if (!state || !stateKey) {
226
- throw new Error("State parameter not found or invalid in callback query parameters.");
227
- }
228
- const storedStateJSON = localStorage.getItem(stateKey);
229
- if (!storedStateJSON) {
230
- throw new Error(`Invalid or expired state parameter "${state}". No matching state found in storage.`);
231
- }
232
- try {
233
- storedStateData = JSON.parse(storedStateJSON);
234
- } catch (e) {
235
- throw new Error("Failed to parse stored OAuth state.");
236
- }
237
- if (!storedStateData.expiry || storedStateData.expiry < Date.now()) {
238
- localStorage.removeItem(stateKey);
239
- throw new Error("OAuth state has expired. Please try initiating authentication again.");
240
- }
241
- if (!storedStateData.providerOptions) {
242
- throw new Error("Stored state is missing required provider options.");
243
- }
244
- const { serverUrl, ...providerOptions } = storedStateData.providerOptions;
245
- console.log(`${logPrefix} Re-instantiating provider for server: ${serverUrl}`);
246
- provider = new BrowserOAuthClientProvider(serverUrl, providerOptions);
247
- console.log(`${logPrefix} Calling SDK auth() to exchange code...`);
248
- const baseUrl = new URL(serverUrl).origin;
249
- const authResult = await auth(provider, { serverUrl: baseUrl, authorizationCode: code });
250
- if (authResult === "AUTHORIZED") {
251
- console.log(`${logPrefix} Authorization successful via SDK auth(). Notifying opener...`);
252
- if (window.opener && !window.opener.closed) {
253
- window.opener.postMessage({ type: "mcp_auth_callback", success: true }, window.location.origin);
254
- window.close();
255
- } else {
256
- console.warn(`${logPrefix} No opener window detected. Redirecting to root.`);
257
- const pathParts = window.location.pathname.split("/").filter(Boolean);
258
- const basePath = pathParts.length > 0 && pathParts[pathParts.length - 1] === "callback" ? "/" + pathParts.slice(0, -2).join("/") : "/";
259
- window.location.href = basePath || "/";
260
- }
261
- localStorage.removeItem(stateKey);
262
- } else {
263
- console.warn(`${logPrefix} SDK auth() returned unexpected status: ${authResult}`);
264
- throw new Error(`Unexpected result from authentication library: ${authResult}`);
265
- }
266
- } catch (err) {
267
- console.error(`${logPrefix} Error during OAuth callback handling:`, err);
268
- const errorMessage = err instanceof Error ? err.message : String(err);
269
- if (window.opener && !window.opener.closed) {
270
- window.opener.postMessage({ type: "mcp_auth_callback", success: false, error: errorMessage }, window.location.origin);
271
- }
272
- try {
273
- document.body.innerHTML = `
274
- <div style="font-family: sans-serif; padding: 20px;">
275
- <h1>Authentication Error</h1>
276
- <p style="color: red; background-color: #ffebeb; border: 1px solid red; padding: 10px; border-radius: 4px;">
277
- ${errorMessage}
278
- </p>
279
- <p>You can close this window or <a href="#" onclick="window.close(); return false;">click here to close</a>.</p>
280
- <pre style="font-size: 0.8em; color: #555; margin-top: 20px; white-space: pre-wrap;">${err instanceof Error ? err.stack : ""}</pre>
281
- </div>
282
- `;
283
- } catch (displayError) {
284
- console.error(`${logPrefix} Could not display error in callback window:`, displayError);
285
- }
286
- if (stateKey) {
287
- localStorage.removeItem(stateKey);
288
- }
289
- if (provider) {
290
- localStorage.removeItem(provider.getKey("code_verifier"));
291
- localStorage.removeItem(provider.getKey("last_auth_url"));
292
- }
293
- }
294
- }
295
- __name(onMcpAuthorization, "onMcpAuthorization");
296
-
297
- export {
298
- BrowserOAuthClientProvider,
299
- onMcpAuthorization
300
- };