@assistant-ui/react-mcp 0.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/dist/auth/buildHeaders.d.ts +9 -0
- package/dist/auth/buildHeaders.d.ts.map +1 -0
- package/dist/auth/buildHeaders.js +15 -0
- package/dist/auth/buildHeaders.js.map +1 -0
- package/dist/auth/createOAuthProvider.d.ts +22 -0
- package/dist/auth/createOAuthProvider.d.ts.map +1 -0
- package/dist/auth/createOAuthProvider.js +148 -0
- package/dist/auth/createOAuthProvider.js.map +1 -0
- package/dist/auth/types.d.ts +9 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +2 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/connector.d.ts +3 -0
- package/dist/connector.d.ts.map +1 -0
- package/dist/connector.js +6 -0
- package/dist/connector.js.map +1 -0
- package/dist/context/McpConnectorByIndexProvider.d.ts +5 -0
- package/dist/context/McpConnectorByIndexProvider.d.ts.map +1 -0
- package/dist/context/McpConnectorByIndexProvider.js +13 -0
- package/dist/context/McpConnectorByIndexProvider.js.map +1 -0
- package/dist/context/McpCustomServerByIndexProvider.d.ts +5 -0
- package/dist/context/McpCustomServerByIndexProvider.d.ts.map +1 -0
- package/dist/context/McpCustomServerByIndexProvider.js +13 -0
- package/dist/context/McpCustomServerByIndexProvider.js.map +1 -0
- package/dist/context/McpServerByIdProvider.d.ts +5 -0
- package/dist/context/McpServerByIdProvider.d.ts.map +1 -0
- package/dist/context/McpServerByIdProvider.js +13 -0
- package/dist/context/McpServerByIdProvider.js.map +1 -0
- package/dist/hooks/useMcpOAuthCallback.d.ts +17 -0
- package/dist/hooks/useMcpOAuthCallback.d.ts.map +1 -0
- package/dist/hooks/useMcpOAuthCallback.js +59 -0
- package/dist/hooks/useMcpOAuthCallback.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-scope.d.ts +109 -0
- package/dist/mcp-scope.d.ts.map +1 -0
- package/dist/mcp-scope.js +2 -0
- package/dist/mcp-scope.js.map +1 -0
- package/dist/primitives/addForm/McpAddFormAuthFields.d.ts +15 -0
- package/dist/primitives/addForm/McpAddFormAuthFields.d.ts.map +1 -0
- package/dist/primitives/addForm/McpAddFormAuthFields.js +18 -0
- package/dist/primitives/addForm/McpAddFormAuthFields.js.map +1 -0
- package/dist/primitives/addForm/McpAddFormAuthSelect.d.ts +8 -0
- package/dist/primitives/addForm/McpAddFormAuthSelect.d.ts.map +1 -0
- package/dist/primitives/addForm/McpAddFormAuthSelect.js +24 -0
- package/dist/primitives/addForm/McpAddFormAuthSelect.js.map +1 -0
- package/dist/primitives/addForm/McpAddFormCancel.d.ts +10 -0
- package/dist/primitives/addForm/McpAddFormCancel.d.ts.map +1 -0
- package/dist/primitives/addForm/McpAddFormCancel.js +15 -0
- package/dist/primitives/addForm/McpAddFormCancel.js.map +1 -0
- package/dist/primitives/addForm/McpAddFormError.d.ts +10 -0
- package/dist/primitives/addForm/McpAddFormError.d.ts.map +1 -0
- package/dist/primitives/addForm/McpAddFormError.js +12 -0
- package/dist/primitives/addForm/McpAddFormError.js.map +1 -0
- package/dist/primitives/addForm/McpAddFormNameField.d.ts +8 -0
- package/dist/primitives/addForm/McpAddFormNameField.d.ts.map +1 -0
- package/dist/primitives/addForm/McpAddFormNameField.js +10 -0
- package/dist/primitives/addForm/McpAddFormNameField.js.map +1 -0
- package/dist/primitives/addForm/McpAddFormRoot.d.ts +16 -0
- package/dist/primitives/addForm/McpAddFormRoot.d.ts.map +1 -0
- package/dist/primitives/addForm/McpAddFormRoot.js +102 -0
- package/dist/primitives/addForm/McpAddFormRoot.js.map +1 -0
- package/dist/primitives/addForm/McpAddFormSubmit.d.ts +10 -0
- package/dist/primitives/addForm/McpAddFormSubmit.d.ts.map +1 -0
- package/dist/primitives/addForm/McpAddFormSubmit.js +10 -0
- package/dist/primitives/addForm/McpAddFormSubmit.js.map +1 -0
- package/dist/primitives/addForm/McpAddFormUrlField.d.ts +8 -0
- package/dist/primitives/addForm/McpAddFormUrlField.d.ts.map +1 -0
- package/dist/primitives/addForm/McpAddFormUrlField.js +10 -0
- package/dist/primitives/addForm/McpAddFormUrlField.js.map +1 -0
- package/dist/primitives/addForm/context.d.ts +21 -0
- package/dist/primitives/addForm/context.d.ts.map +1 -0
- package/dist/primitives/addForm/context.js +10 -0
- package/dist/primitives/addForm/context.js.map +1 -0
- package/dist/primitives/addForm.d.ts +9 -0
- package/dist/primitives/addForm.d.ts.map +1 -0
- package/dist/primitives/addForm.js +9 -0
- package/dist/primitives/addForm.js.map +1 -0
- package/dist/primitives/manager/McpManagerAddCustomTrigger.d.ts +10 -0
- package/dist/primitives/manager/McpManagerAddCustomTrigger.d.ts.map +1 -0
- package/dist/primitives/manager/McpManagerAddCustomTrigger.js +9 -0
- package/dist/primitives/manager/McpManagerAddCustomTrigger.js.map +1 -0
- package/dist/primitives/manager/McpManagerConnectors.d.ts +31 -0
- package/dist/primitives/manager/McpManagerConnectors.d.ts.map +1 -0
- package/dist/primitives/manager/McpManagerConnectors.js +41 -0
- package/dist/primitives/manager/McpManagerConnectors.js.map +1 -0
- package/dist/primitives/manager/McpManagerCustomServers.d.ts +31 -0
- package/dist/primitives/manager/McpManagerCustomServers.d.ts.map +1 -0
- package/dist/primitives/manager/McpManagerCustomServers.js +37 -0
- package/dist/primitives/manager/McpManagerCustomServers.js.map +1 -0
- package/dist/primitives/manager/McpManagerRoot.d.ts +10 -0
- package/dist/primitives/manager/McpManagerRoot.d.ts.map +1 -0
- package/dist/primitives/manager/McpManagerRoot.js +10 -0
- package/dist/primitives/manager/McpManagerRoot.js.map +1 -0
- package/dist/primitives/manager.d.ts +5 -0
- package/dist/primitives/manager.d.ts.map +1 -0
- package/dist/primitives/manager.js +5 -0
- package/dist/primitives/manager.js.map +1 -0
- package/dist/primitives/server/McpServerConnectButton.d.ts +10 -0
- package/dist/primitives/server/McpServerConnectButton.d.ts.map +1 -0
- package/dist/primitives/server/McpServerConnectButton.js +20 -0
- package/dist/primitives/server/McpServerConnectButton.js.map +1 -0
- package/dist/primitives/server/McpServerDisconnectButton.d.ts +10 -0
- package/dist/primitives/server/McpServerDisconnectButton.d.ts.map +1 -0
- package/dist/primitives/server/McpServerDisconnectButton.js +20 -0
- package/dist/primitives/server/McpServerDisconnectButton.js.map +1 -0
- package/dist/primitives/server/McpServerError.d.ts +10 -0
- package/dist/primitives/server/McpServerError.d.ts.map +1 -0
- package/dist/primitives/server/McpServerError.js +12 -0
- package/dist/primitives/server/McpServerError.js.map +1 -0
- package/dist/primitives/server/McpServerIcon.d.ts +18 -0
- package/dist/primitives/server/McpServerIcon.d.ts.map +1 -0
- package/dist/primitives/server/McpServerIcon.js +14 -0
- package/dist/primitives/server/McpServerIcon.js.map +1 -0
- package/dist/primitives/server/McpServerName.d.ts +10 -0
- package/dist/primitives/server/McpServerName.d.ts.map +1 -0
- package/dist/primitives/server/McpServerName.js +10 -0
- package/dist/primitives/server/McpServerName.js.map +1 -0
- package/dist/primitives/server/McpServerOAuthLink.d.ts +16 -0
- package/dist/primitives/server/McpServerOAuthLink.d.ts.map +1 -0
- package/dist/primitives/server/McpServerOAuthLink.js +13 -0
- package/dist/primitives/server/McpServerOAuthLink.js.map +1 -0
- package/dist/primitives/server/McpServerRemoveButton.d.ts +10 -0
- package/dist/primitives/server/McpServerRemoveButton.d.ts.map +1 -0
- package/dist/primitives/server/McpServerRemoveButton.js +18 -0
- package/dist/primitives/server/McpServerRemoveButton.js.map +1 -0
- package/dist/primitives/server/McpServerRoot.d.ts +10 -0
- package/dist/primitives/server/McpServerRoot.d.ts.map +1 -0
- package/dist/primitives/server/McpServerRoot.js +13 -0
- package/dist/primitives/server/McpServerRoot.js.map +1 -0
- package/dist/primitives/server/McpServerStatus.d.ts +10 -0
- package/dist/primitives/server/McpServerStatus.d.ts.map +1 -0
- package/dist/primitives/server/McpServerStatus.js +10 -0
- package/dist/primitives/server/McpServerStatus.js.map +1 -0
- package/dist/primitives/server/McpServerToolName.d.ts +10 -0
- package/dist/primitives/server/McpServerToolName.d.ts.map +1 -0
- package/dist/primitives/server/McpServerToolName.js +10 -0
- package/dist/primitives/server/McpServerToolName.js.map +1 -0
- package/dist/primitives/server/McpServerTools.d.ts +10 -0
- package/dist/primitives/server/McpServerTools.d.ts.map +1 -0
- package/dist/primitives/server/McpServerTools.js +19 -0
- package/dist/primitives/server/McpServerTools.js.map +1 -0
- package/dist/primitives/server.d.ts +12 -0
- package/dist/primitives/server.d.ts.map +1 -0
- package/dist/primitives/server.js +12 -0
- package/dist/primitives/server.js.map +1 -0
- package/dist/resources/McpManagerResource.d.ts +13 -0
- package/dist/resources/McpManagerResource.d.ts.map +1 -0
- package/dist/resources/McpManagerResource.js +191 -0
- package/dist/resources/McpManagerResource.js.map +1 -0
- package/dist/resources/McpServerResource.d.ts +17 -0
- package/dist/resources/McpServerResource.d.ts.map +1 -0
- package/dist/resources/McpServerResource.js +239 -0
- package/dist/resources/McpServerResource.js.map +1 -0
- package/dist/resources/storage/McpCustomStorage.d.ts +3 -0
- package/dist/resources/storage/McpCustomStorage.d.ts.map +1 -0
- package/dist/resources/storage/McpCustomStorage.js +3 -0
- package/dist/resources/storage/McpCustomStorage.js.map +1 -0
- package/dist/resources/storage/McpLocalStorage.d.ts +9 -0
- package/dist/resources/storage/McpLocalStorage.d.ts.map +1 -0
- package/dist/resources/storage/McpLocalStorage.js +67 -0
- package/dist/resources/storage/McpLocalStorage.js.map +1 -0
- package/dist/resources/storage/McpMemoryStorage.d.ts +3 -0
- package/dist/resources/storage/McpMemoryStorage.d.ts.map +1 -0
- package/dist/resources/storage/McpMemoryStorage.js +19 -0
- package/dist/resources/storage/McpMemoryStorage.js.map +1 -0
- package/dist/resources/storage/types.d.ts +12 -0
- package/dist/resources/storage/types.d.ts.map +1 -0
- package/dist/resources/storage/types.js +2 -0
- package/dist/resources/storage/types.js.map +1 -0
- package/dist/utils/serverId.d.ts +2 -0
- package/dist/utils/serverId.d.ts.map +1 -0
- package/dist/utils/serverId.js +16 -0
- package/dist/utils/serverId.js.map +1 -0
- package/package.json +67 -0
- package/src/auth/buildHeaders.ts +19 -0
- package/src/auth/createOAuthProvider.ts +172 -0
- package/src/auth/types.ts +12 -0
- package/src/connector.ts +7 -0
- package/src/context/McpConnectorByIndexProvider.tsx +16 -0
- package/src/context/McpCustomServerByIndexProvider.tsx +16 -0
- package/src/context/McpServerByIdProvider.tsx +17 -0
- package/src/hooks/useMcpOAuthCallback.tsx +79 -0
- package/src/index.ts +68 -0
- package/src/mcp-scope.ts +110 -0
- package/src/primitives/addForm/McpAddFormAuthFields.tsx +51 -0
- package/src/primitives/addForm/McpAddFormAuthSelect.tsx +55 -0
- package/src/primitives/addForm/McpAddFormCancel.tsx +33 -0
- package/src/primitives/addForm/McpAddFormError.tsx +27 -0
- package/src/primitives/addForm/McpAddFormNameField.tsx +34 -0
- package/src/primitives/addForm/McpAddFormRoot.tsx +141 -0
- package/src/primitives/addForm/McpAddFormSubmit.tsx +30 -0
- package/src/primitives/addForm/McpAddFormUrlField.tsx +35 -0
- package/src/primitives/addForm/context.tsx +37 -0
- package/src/primitives/addForm.ts +8 -0
- package/src/primitives/manager/McpManagerAddCustomTrigger.tsx +21 -0
- package/src/primitives/manager/McpManagerConnectors.tsx +76 -0
- package/src/primitives/manager/McpManagerCustomServers.tsx +72 -0
- package/src/primitives/manager/McpManagerRoot.tsx +28 -0
- package/src/primitives/manager.ts +4 -0
- package/src/primitives/server/McpServerConnectButton.tsx +39 -0
- package/src/primitives/server/McpServerDisconnectButton.tsx +38 -0
- package/src/primitives/server/McpServerError.tsx +27 -0
- package/src/primitives/server/McpServerIcon.tsx +35 -0
- package/src/primitives/server/McpServerName.tsx +26 -0
- package/src/primitives/server/McpServerOAuthLink.tsx +38 -0
- package/src/primitives/server/McpServerRemoveButton.tsx +35 -0
- package/src/primitives/server/McpServerRoot.tsx +35 -0
- package/src/primitives/server/McpServerStatus.tsx +26 -0
- package/src/primitives/server/McpServerToolName.tsx +26 -0
- package/src/primitives/server/McpServerTools.tsx +39 -0
- package/src/primitives/server.ts +14 -0
- package/src/resources/McpManagerResource.ts +253 -0
- package/src/resources/McpServerResource.ts +292 -0
- package/src/resources/storage/McpCustomStorage.ts +6 -0
- package/src/resources/storage/McpLocalStorage.ts +77 -0
- package/src/resources/storage/McpMemoryStorage.ts +22 -0
- package/src/resources/storage/types.ts +16 -0
- package/src/utils/serverId.ts +19 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serverId.d.ts","sourceRoot":"","sources":["../../src/utils/serverId.ts"],"names":[],"mappings":"AAIA,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAcpD"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Server ids are joined with tool names via `__` to form unique tool
|
|
2
|
+
// names for the AI SDK. The separator must not appear inside ids,
|
|
3
|
+
// otherwise two distinct `(serverId, toolName)` pairs could produce
|
|
4
|
+
// the same composite name.
|
|
5
|
+
export function assertValidServerId(id) {
|
|
6
|
+
if (id.length === 0) {
|
|
7
|
+
throw new Error("MCP server id must not be empty.");
|
|
8
|
+
}
|
|
9
|
+
if (id.includes("__")) {
|
|
10
|
+
throw new Error(`MCP server id "${id}" must not contain "__" — that sequence is reserved for separating server id from tool name.`);
|
|
11
|
+
}
|
|
12
|
+
if (id.includes("\x1f")) {
|
|
13
|
+
throw new Error(`MCP server id "${id}" must not contain the ASCII Unit Separator (\\x1f) — it is reserved as the list delimiter in primitive id-list selectors.`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=serverId.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serverId.js","sourceRoot":"","sources":["../../src/utils/serverId.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,kEAAkE;AAClE,oEAAoE;AACpE,2BAA2B;AAC3B,MAAM,UAAU,mBAAmB,CAAC,EAAU;IAC5C,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,kBAAkB,EAAE,8FAA8F,CACnH,CAAC;IACJ,CAAC;IACD,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,kBAAkB,EAAE,4HAA4H,CACjJ,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@assistant-ui/react-mcp",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "MCP server configuration and connection primitives for @assistant-ui",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"model-context-protocol",
|
|
8
|
+
"oauth",
|
|
9
|
+
"assistant-ui",
|
|
10
|
+
"react"
|
|
11
|
+
],
|
|
12
|
+
"author": "AgentbaseAI Inc.",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"main": "./dist/index.js",
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"src",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "aui-build"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@assistant-ui/core": "workspace:*",
|
|
34
|
+
"@assistant-ui/store": "workspace:*",
|
|
35
|
+
"@assistant-ui/tap": "workspace:*",
|
|
36
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
37
|
+
"@radix-ui/react-primitive": "^2.1.4",
|
|
38
|
+
"assistant-stream": "workspace:*"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"@types/react": "*",
|
|
42
|
+
"react": "^18 || ^19"
|
|
43
|
+
},
|
|
44
|
+
"peerDependenciesMeta": {
|
|
45
|
+
"@types/react": {
|
|
46
|
+
"optional": true
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@assistant-ui/x-buildutils": "workspace:*",
|
|
51
|
+
"@types/react": "^19.2.14",
|
|
52
|
+
"react": "^19.2.5"
|
|
53
|
+
},
|
|
54
|
+
"publishConfig": {
|
|
55
|
+
"access": "public",
|
|
56
|
+
"provenance": true
|
|
57
|
+
},
|
|
58
|
+
"homepage": "https://www.assistant-ui.com/",
|
|
59
|
+
"repository": {
|
|
60
|
+
"type": "git",
|
|
61
|
+
"url": "git+https://github.com/assistant-ui/assistant-ui.git",
|
|
62
|
+
"directory": "packages/react-mcp"
|
|
63
|
+
},
|
|
64
|
+
"bugs": {
|
|
65
|
+
"url": "https://github.com/assistant-ui/assistant-ui/issues"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MCPAuthConfig } from "../mcp-scope";
|
|
2
|
+
import type { MCPPersistedAuthState } from "./types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Build request headers for the bearer/none flows. For bearer, prefer a token
|
|
6
|
+
* stored at add-form time (persisted), falling back to a static token on the
|
|
7
|
+
* config (used by connectors that hardcode a token, rare in practice).
|
|
8
|
+
*/
|
|
9
|
+
export function buildHeaders(
|
|
10
|
+
auth: MCPAuthConfig,
|
|
11
|
+
persisted: MCPPersistedAuthState | null,
|
|
12
|
+
): Record<string, string> | undefined {
|
|
13
|
+
if (auth.type === "bearer") {
|
|
14
|
+
const token = persisted?.token ?? auth.token;
|
|
15
|
+
if (!token) return undefined;
|
|
16
|
+
return { Authorization: `Bearer ${token}` };
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { OAuthClientProvider } from "@modelcontextprotocol/sdk/client/auth.js";
|
|
2
|
+
import type {
|
|
3
|
+
OAuthClientInformationFull,
|
|
4
|
+
OAuthClientMetadata,
|
|
5
|
+
OAuthTokens,
|
|
6
|
+
} from "@modelcontextprotocol/sdk/shared/auth.js";
|
|
7
|
+
import type { MCPStorage } from "../resources/storage/types";
|
|
8
|
+
import type { MCPAuthConfig } from "../mcp-scope";
|
|
9
|
+
|
|
10
|
+
const STATE_PREFIX = "aui-mcp:";
|
|
11
|
+
|
|
12
|
+
function bytesToBase64Url(bytes: Uint8Array): string {
|
|
13
|
+
let s = "";
|
|
14
|
+
for (const b of bytes) s += String.fromCharCode(b);
|
|
15
|
+
return btoa(s).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function base64UrlToBytes(b64url: string): Uint8Array {
|
|
19
|
+
const padded =
|
|
20
|
+
b64url.replace(/-/g, "+").replace(/_/g, "/") +
|
|
21
|
+
"=".repeat((4 - (b64url.length % 4)) % 4);
|
|
22
|
+
const bin = atob(padded);
|
|
23
|
+
const out = new Uint8Array(bin.length);
|
|
24
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function encodeServerIdInState(serverId: string): string {
|
|
29
|
+
const bytes = new TextEncoder().encode(serverId);
|
|
30
|
+
return `${STATE_PREFIX}${bytesToBase64Url(bytes)}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function decodeServerIdFromState(state: string): string | null {
|
|
34
|
+
if (!state.startsWith(STATE_PREFIX)) return null;
|
|
35
|
+
const dot = state.indexOf(".", STATE_PREFIX.length);
|
|
36
|
+
const encoded =
|
|
37
|
+
dot === -1
|
|
38
|
+
? state.slice(STATE_PREFIX.length)
|
|
39
|
+
: state.slice(STATE_PREFIX.length, dot);
|
|
40
|
+
try {
|
|
41
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(
|
|
42
|
+
base64UrlToBytes(encoded),
|
|
43
|
+
);
|
|
44
|
+
} catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export type CreateOAuthProviderOptions = {
|
|
50
|
+
serverId: string;
|
|
51
|
+
/** Must be `auth.type === "oauth"`. */
|
|
52
|
+
config: Extract<MCPAuthConfig, { type: "oauth" }>;
|
|
53
|
+
storage: MCPStorage;
|
|
54
|
+
redirectUri: string;
|
|
55
|
+
/** Called by the SDK to start the authorization redirect. */
|
|
56
|
+
onAuthorizationUrl: (url: URL) => void;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Builds an OAuthClientProvider for the MCP SDK, backed by MCPStorage.
|
|
61
|
+
* Token refresh and DCR are handled by the SDK; this provider only mediates
|
|
62
|
+
* load/save and the redirect step.
|
|
63
|
+
*/
|
|
64
|
+
export function createOAuthProvider(
|
|
65
|
+
opts: CreateOAuthProviderOptions,
|
|
66
|
+
): OAuthClientProvider {
|
|
67
|
+
const { serverId, config, storage, redirectUri, onAuthorizationUrl } = opts;
|
|
68
|
+
|
|
69
|
+
type Cache = {
|
|
70
|
+
tokens?: OAuthTokens | undefined;
|
|
71
|
+
clientInformation?: OAuthClientInformationFull | undefined;
|
|
72
|
+
codeVerifier?: string | undefined;
|
|
73
|
+
};
|
|
74
|
+
let cached: Cache | null = null;
|
|
75
|
+
|
|
76
|
+
const loadCache = async (): Promise<Cache> => {
|
|
77
|
+
if (cached) return cached;
|
|
78
|
+
const persisted = await storage.loadAuthState(serverId);
|
|
79
|
+
const initial: Cache = {};
|
|
80
|
+
if (persisted?.tokens) initial.tokens = persisted.tokens;
|
|
81
|
+
if (config.clientId) {
|
|
82
|
+
const ci: OAuthClientInformationFull = {
|
|
83
|
+
client_id: config.clientId,
|
|
84
|
+
redirect_uris: [redirectUri],
|
|
85
|
+
};
|
|
86
|
+
if (config.clientSecret) ci.client_secret = config.clientSecret;
|
|
87
|
+
initial.clientInformation = ci;
|
|
88
|
+
} else if (persisted?.clientInformation) {
|
|
89
|
+
initial.clientInformation = persisted.clientInformation;
|
|
90
|
+
}
|
|
91
|
+
if (persisted?.codeVerifier) initial.codeVerifier = persisted.codeVerifier;
|
|
92
|
+
cached = initial;
|
|
93
|
+
return cached;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const persist = async () => {
|
|
97
|
+
const c = cached;
|
|
98
|
+
if (!c) return;
|
|
99
|
+
const next: Parameters<typeof storage.saveAuthState>[1] = {};
|
|
100
|
+
if (c.tokens) next.tokens = c.tokens;
|
|
101
|
+
if (c.clientInformation) next.clientInformation = c.clientInformation;
|
|
102
|
+
if (c.codeVerifier) next.codeVerifier = c.codeVerifier;
|
|
103
|
+
await storage.saveAuthState(serverId, next);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const clientMetadata: OAuthClientMetadata = {
|
|
107
|
+
client_name: "assistant-ui",
|
|
108
|
+
redirect_uris: [redirectUri],
|
|
109
|
+
grant_types: ["authorization_code", "refresh_token"],
|
|
110
|
+
response_types: ["code"],
|
|
111
|
+
token_endpoint_auth_method: "none",
|
|
112
|
+
scope: config.scopes?.join(" "),
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
get redirectUrl() {
|
|
117
|
+
return redirectUri;
|
|
118
|
+
},
|
|
119
|
+
get clientMetadata() {
|
|
120
|
+
return clientMetadata;
|
|
121
|
+
},
|
|
122
|
+
state() {
|
|
123
|
+
// Embed the server id so the callback handler can route it back to the
|
|
124
|
+
// right MCPServerResource without app-level wiring.
|
|
125
|
+
const nonce =
|
|
126
|
+
typeof crypto !== "undefined" && "randomUUID" in crypto
|
|
127
|
+
? crypto.randomUUID()
|
|
128
|
+
: `${Date.now()}.${Math.random()}`;
|
|
129
|
+
return `${encodeServerIdInState(serverId)}.${nonce}`;
|
|
130
|
+
},
|
|
131
|
+
async clientInformation() {
|
|
132
|
+
const c = await loadCache();
|
|
133
|
+
return c.clientInformation;
|
|
134
|
+
},
|
|
135
|
+
async saveClientInformation(info) {
|
|
136
|
+
const c = await loadCache();
|
|
137
|
+
c.clientInformation = info as OAuthClientInformationFull;
|
|
138
|
+
await persist();
|
|
139
|
+
},
|
|
140
|
+
async tokens() {
|
|
141
|
+
const c = await loadCache();
|
|
142
|
+
return c.tokens;
|
|
143
|
+
},
|
|
144
|
+
async saveTokens(tokens) {
|
|
145
|
+
const c = await loadCache();
|
|
146
|
+
c.tokens = tokens;
|
|
147
|
+
await persist();
|
|
148
|
+
},
|
|
149
|
+
async redirectToAuthorization(url) {
|
|
150
|
+
onAuthorizationUrl(url);
|
|
151
|
+
},
|
|
152
|
+
async saveCodeVerifier(codeVerifier) {
|
|
153
|
+
const c = await loadCache();
|
|
154
|
+
c.codeVerifier = codeVerifier;
|
|
155
|
+
await persist();
|
|
156
|
+
},
|
|
157
|
+
async codeVerifier() {
|
|
158
|
+
const c = await loadCache();
|
|
159
|
+
if (!c.codeVerifier) {
|
|
160
|
+
throw new Error("No code verifier saved for this OAuth flow");
|
|
161
|
+
}
|
|
162
|
+
return c.codeVerifier;
|
|
163
|
+
},
|
|
164
|
+
async invalidateCredentials(scope) {
|
|
165
|
+
const c = await loadCache();
|
|
166
|
+
if (scope === "all" || scope === "tokens") delete c.tokens;
|
|
167
|
+
if (scope === "all" || scope === "client") delete c.clientInformation;
|
|
168
|
+
if (scope === "all" || scope === "verifier") delete c.codeVerifier;
|
|
169
|
+
await persist();
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
OAuthTokens,
|
|
3
|
+
OAuthClientInformationFull,
|
|
4
|
+
} from "@modelcontextprotocol/sdk/shared/auth.js";
|
|
5
|
+
|
|
6
|
+
export type MCPPersistedAuthState = {
|
|
7
|
+
tokens?: OAuthTokens;
|
|
8
|
+
clientInformation?: OAuthClientInformationFull;
|
|
9
|
+
codeVerifier?: string;
|
|
10
|
+
/** Bearer token (entered at add-form time). */
|
|
11
|
+
token?: string;
|
|
12
|
+
};
|
package/src/connector.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FC, PropsWithChildren } from "react";
|
|
2
|
+
import { useAui, AuiProvider, Derived } from "@assistant-ui/store";
|
|
3
|
+
|
|
4
|
+
export const McpConnectorByIndexProvider: FC<
|
|
5
|
+
PropsWithChildren<{ index: number }>
|
|
6
|
+
> = ({ index, children }) => {
|
|
7
|
+
const aui = useAui({
|
|
8
|
+
mcpServer: Derived({
|
|
9
|
+
source: "mcp",
|
|
10
|
+
query: { kind: "connector", index },
|
|
11
|
+
get: (parent) => parent.mcp().connector({ index }),
|
|
12
|
+
}),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return <AuiProvider value={aui}>{children}</AuiProvider>;
|
|
16
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FC, PropsWithChildren } from "react";
|
|
2
|
+
import { useAui, AuiProvider, Derived } from "@assistant-ui/store";
|
|
3
|
+
|
|
4
|
+
export const McpCustomServerByIndexProvider: FC<
|
|
5
|
+
PropsWithChildren<{ index: number }>
|
|
6
|
+
> = ({ index, children }) => {
|
|
7
|
+
const aui = useAui({
|
|
8
|
+
mcpServer: Derived({
|
|
9
|
+
source: "mcp",
|
|
10
|
+
query: { kind: "custom", index },
|
|
11
|
+
get: (parent) => parent.mcp().customServer({ index }),
|
|
12
|
+
}),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return <AuiProvider value={aui}>{children}</AuiProvider>;
|
|
16
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FC, PropsWithChildren } from "react";
|
|
2
|
+
import { useAui, AuiProvider, Derived } from "@assistant-ui/store";
|
|
3
|
+
|
|
4
|
+
export const McpServerByIdProvider: FC<PropsWithChildren<{ id: string }>> = ({
|
|
5
|
+
id,
|
|
6
|
+
children,
|
|
7
|
+
}) => {
|
|
8
|
+
const aui = useAui({
|
|
9
|
+
mcpServer: Derived({
|
|
10
|
+
source: "mcp",
|
|
11
|
+
query: { id },
|
|
12
|
+
get: (parent) => parent.mcp().server({ id }),
|
|
13
|
+
}),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
return <AuiProvider value={aui}>{children}</AuiProvider>;
|
|
17
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type FC, type ReactNode, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { useAui } from "@assistant-ui/store";
|
|
3
|
+
import { decodeServerIdFromState } from "../auth/createOAuthProvider";
|
|
4
|
+
|
|
5
|
+
export type UseMcpOAuthCallbackOptions = {
|
|
6
|
+
/** Defaults to `window.location.href`. */
|
|
7
|
+
url?: string;
|
|
8
|
+
onComplete?: (serverId: string) => void;
|
|
9
|
+
onError?: (err: Error) => void;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type UseMcpOAuthCallbackResult = {
|
|
13
|
+
status: "idle" | "running" | "done" | "error";
|
|
14
|
+
serverId: string | null;
|
|
15
|
+
error: Error | null;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export function useMcpOAuthCallback(
|
|
19
|
+
opts: UseMcpOAuthCallbackOptions = {},
|
|
20
|
+
): UseMcpOAuthCallbackResult {
|
|
21
|
+
const aui = useAui();
|
|
22
|
+
const [result, setResult] = useState<UseMcpOAuthCallbackResult>({
|
|
23
|
+
status: "idle",
|
|
24
|
+
serverId: null,
|
|
25
|
+
error: null,
|
|
26
|
+
});
|
|
27
|
+
// Guard against React 18 Strict Mode's mount-unmount-remount: the effect
|
|
28
|
+
// body must not run completeAuth twice for the same URL, otherwise the
|
|
29
|
+
// single-use OAuth code is double-redeemed and the second attempt 4xxs.
|
|
30
|
+
const startedRef = useRef<string | null>(null);
|
|
31
|
+
const optsRef = useRef(opts);
|
|
32
|
+
optsRef.current = opts;
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
const url =
|
|
36
|
+
opts.url ?? (typeof window !== "undefined" ? window.location.href : null);
|
|
37
|
+
if (!url) return;
|
|
38
|
+
if (startedRef.current === url) return;
|
|
39
|
+
startedRef.current = url;
|
|
40
|
+
|
|
41
|
+
(async () => {
|
|
42
|
+
try {
|
|
43
|
+
const parsed = new URL(url);
|
|
44
|
+
const state = parsed.searchParams.get("state");
|
|
45
|
+
const error = parsed.searchParams.get("error");
|
|
46
|
+
if (error) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
parsed.searchParams.get("error_description") ?? error,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
if (!state) throw new Error("missing state parameter in callback URL");
|
|
52
|
+
const serverId = decodeServerIdFromState(state);
|
|
53
|
+
if (!serverId) {
|
|
54
|
+
throw new Error("callback state does not match an MCP server");
|
|
55
|
+
}
|
|
56
|
+
setResult({ status: "running", serverId, error: null });
|
|
57
|
+
await aui.mcp().server({ id: serverId }).completeAuth(url);
|
|
58
|
+
setResult({ status: "done", serverId, error: null });
|
|
59
|
+
optsRef.current.onComplete?.(serverId);
|
|
60
|
+
} catch (err) {
|
|
61
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
62
|
+
setResult((prev) => ({ ...prev, status: "error", error: e }));
|
|
63
|
+
optsRef.current.onError?.(e);
|
|
64
|
+
}
|
|
65
|
+
})();
|
|
66
|
+
}, [aui, opts.url]);
|
|
67
|
+
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const McpOAuthCallback: FC<
|
|
72
|
+
UseMcpOAuthCallbackOptions & {
|
|
73
|
+
children?: (result: UseMcpOAuthCallbackResult) => ReactNode;
|
|
74
|
+
}
|
|
75
|
+
> = ({ children, ...opts }) => {
|
|
76
|
+
const result = useMcpOAuthCallback(opts);
|
|
77
|
+
if (children) return <>{children(result)}</>;
|
|
78
|
+
return null;
|
|
79
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Scope augmentation must be imported for module declaration side-effect.
|
|
2
|
+
import "./mcp-scope";
|
|
3
|
+
|
|
4
|
+
// Resource — the entry point. Mount via:
|
|
5
|
+
// useAui({ mcp: McpManagerResource({ connectors }) })
|
|
6
|
+
export {
|
|
7
|
+
McpManagerResource,
|
|
8
|
+
type McpManagerResourceProps,
|
|
9
|
+
} from "./resources/McpManagerResource";
|
|
10
|
+
|
|
11
|
+
// Internal — exported for advanced cases (custom manager / lookup wiring).
|
|
12
|
+
export {
|
|
13
|
+
McpServerResource,
|
|
14
|
+
type McpServerResourceProps,
|
|
15
|
+
} from "./resources/McpServerResource";
|
|
16
|
+
|
|
17
|
+
// Connector helper
|
|
18
|
+
export { defineConnector } from "./connector";
|
|
19
|
+
|
|
20
|
+
// Storage resources
|
|
21
|
+
export {
|
|
22
|
+
McpLocalStorage,
|
|
23
|
+
type McpLocalStorageOptions,
|
|
24
|
+
} from "./resources/storage/McpLocalStorage";
|
|
25
|
+
export { McpMemoryStorage } from "./resources/storage/McpMemoryStorage";
|
|
26
|
+
export { McpCustomStorage } from "./resources/storage/McpCustomStorage";
|
|
27
|
+
export type {
|
|
28
|
+
MCPStorage,
|
|
29
|
+
MCPStorageElement,
|
|
30
|
+
} from "./resources/storage/types";
|
|
31
|
+
|
|
32
|
+
// Primitives (namespaced)
|
|
33
|
+
export * as McpManagerPrimitive from "./primitives/manager";
|
|
34
|
+
export * as McpServerPrimitive from "./primitives/server";
|
|
35
|
+
export * as McpAddFormPrimitive from "./primitives/addForm";
|
|
36
|
+
|
|
37
|
+
// Per-server scope providers. The iteration primitives wrap each item in
|
|
38
|
+
// the appropriate ByIndex provider. The ById provider is useful for
|
|
39
|
+
// rendering server UI outside the iteration primitives (static id known).
|
|
40
|
+
export { McpServerByIdProvider } from "./context/McpServerByIdProvider";
|
|
41
|
+
export { McpConnectorByIndexProvider } from "./context/McpConnectorByIndexProvider";
|
|
42
|
+
export { McpCustomServerByIndexProvider } from "./context/McpCustomServerByIndexProvider";
|
|
43
|
+
|
|
44
|
+
// OAuth callback
|
|
45
|
+
export {
|
|
46
|
+
useMcpOAuthCallback,
|
|
47
|
+
McpOAuthCallback,
|
|
48
|
+
type UseMcpOAuthCallbackOptions,
|
|
49
|
+
type UseMcpOAuthCallbackResult,
|
|
50
|
+
} from "./hooks/useMcpOAuthCallback";
|
|
51
|
+
|
|
52
|
+
// Auth state shape
|
|
53
|
+
export type { MCPPersistedAuthState } from "./auth/types";
|
|
54
|
+
|
|
55
|
+
// Public types
|
|
56
|
+
export type {
|
|
57
|
+
MCPAuthConfig,
|
|
58
|
+
MCPConnector,
|
|
59
|
+
MCPCustomServerRecord,
|
|
60
|
+
MCPServerKind,
|
|
61
|
+
MCPConnectionState,
|
|
62
|
+
MCPToolInfo,
|
|
63
|
+
MCPServerState,
|
|
64
|
+
MCPManagerState,
|
|
65
|
+
MCPServerMethods,
|
|
66
|
+
MCPManagerMethods,
|
|
67
|
+
MCPServerQuery,
|
|
68
|
+
} from "./mcp-scope";
|
package/src/mcp-scope.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import "@assistant-ui/store";
|
|
2
|
+
|
|
3
|
+
export type MCPAuthConfig =
|
|
4
|
+
| { type: "none" }
|
|
5
|
+
| { type: "bearer"; token?: string | undefined }
|
|
6
|
+
| {
|
|
7
|
+
type: "oauth";
|
|
8
|
+
scopes?: string[] | undefined;
|
|
9
|
+
authorizationEndpoint?: string | undefined;
|
|
10
|
+
tokenEndpoint?: string | undefined;
|
|
11
|
+
registrationEndpoint?: string | undefined;
|
|
12
|
+
clientId?: string | undefined;
|
|
13
|
+
clientSecret?: string | undefined;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type MCPConnector = {
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
url: string;
|
|
20
|
+
icon?: string | undefined;
|
|
21
|
+
auth: MCPAuthConfig;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type MCPCustomServerRecord = {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
url: string;
|
|
28
|
+
auth: MCPAuthConfig;
|
|
29
|
+
createdAt: number;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type MCPServerKind = "connector" | "custom";
|
|
33
|
+
|
|
34
|
+
export type MCPConnectionState =
|
|
35
|
+
| "disconnected"
|
|
36
|
+
| "authRequired"
|
|
37
|
+
| "authPending"
|
|
38
|
+
| "connecting"
|
|
39
|
+
| "connected"
|
|
40
|
+
| "error";
|
|
41
|
+
|
|
42
|
+
export type MCPToolInfo = {
|
|
43
|
+
name: string;
|
|
44
|
+
description?: string | undefined;
|
|
45
|
+
inputSchema: unknown;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export type MCPServerState = {
|
|
49
|
+
id: string;
|
|
50
|
+
kind: MCPServerKind;
|
|
51
|
+
name: string;
|
|
52
|
+
url: string;
|
|
53
|
+
icon?: string | undefined;
|
|
54
|
+
connectionState: MCPConnectionState;
|
|
55
|
+
lastError: { message: string } | null;
|
|
56
|
+
tools: MCPToolInfo[];
|
|
57
|
+
authorizationUrl: string | null;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export type MCPManagerState = {
|
|
61
|
+
servers: MCPServerState[];
|
|
62
|
+
connectors: MCPServerState[];
|
|
63
|
+
customServers: MCPServerState[];
|
|
64
|
+
isHydrated: boolean;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export type MCPServerMethods = {
|
|
68
|
+
getState: () => MCPServerState;
|
|
69
|
+
connect: () => Promise<void>;
|
|
70
|
+
disconnect: () => Promise<void>;
|
|
71
|
+
remove: () => Promise<void>;
|
|
72
|
+
callTool: (name: string, args: unknown) => Promise<unknown>;
|
|
73
|
+
/** Read a resource by URI. Returns the raw MCP `ReadResourceResult`. */
|
|
74
|
+
readResource: (uri: string) => Promise<unknown>;
|
|
75
|
+
/** OAuth only: pass full callback URL (e.g. window.location.href) */
|
|
76
|
+
completeAuth: (callbackUrl: string) => Promise<void>;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export type MCPServerQuery =
|
|
80
|
+
| { id: string }
|
|
81
|
+
| { kind: "connector"; index: number }
|
|
82
|
+
| { kind: "custom"; index: number };
|
|
83
|
+
|
|
84
|
+
export type MCPManagerMethods = {
|
|
85
|
+
getState: () => MCPManagerState;
|
|
86
|
+
/** Look up a server by id, or by index within its kind. */
|
|
87
|
+
server: (query: MCPServerQuery) => MCPServerMethods;
|
|
88
|
+
/** Convenience: equivalent to `server({ kind: "connector", index })`. */
|
|
89
|
+
connector: (query: { index: number }) => MCPServerMethods;
|
|
90
|
+
/** Convenience: equivalent to `server({ kind: "custom", index })`. */
|
|
91
|
+
customServer: (query: { index: number }) => MCPServerMethods;
|
|
92
|
+
addCustomServer: (input: {
|
|
93
|
+
name: string;
|
|
94
|
+
url: string;
|
|
95
|
+
auth: MCPAuthConfig;
|
|
96
|
+
}) => Promise<string>;
|
|
97
|
+
removeServer: (id: string) => Promise<void>;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
declare module "@assistant-ui/store" {
|
|
101
|
+
interface ScopeRegistry {
|
|
102
|
+
mcp: {
|
|
103
|
+
methods: MCPManagerMethods;
|
|
104
|
+
};
|
|
105
|
+
mcpServer: {
|
|
106
|
+
methods: MCPServerMethods;
|
|
107
|
+
meta: { source: "mcp"; query: MCPServerQuery };
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { FC } from "react";
|
|
2
|
+
import { type AddFormAuthType, useAddForm } from "./context";
|
|
3
|
+
|
|
4
|
+
export namespace McpAddFormPrimitiveAuthFields {
|
|
5
|
+
export type Props = {
|
|
6
|
+
/**
|
|
7
|
+
* Optional render override. Receives the current auth type so apps can render
|
|
8
|
+
* fully custom inputs. Defaults to a minimal built-in for bearer / oauth.
|
|
9
|
+
*/
|
|
10
|
+
children?: FC<{ authType: AddFormAuthType }>;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const McpAddFormPrimitiveAuthFields: FC<
|
|
15
|
+
McpAddFormPrimitiveAuthFields.Props
|
|
16
|
+
> = ({ children }) => {
|
|
17
|
+
const { state, setField } = useAddForm();
|
|
18
|
+
|
|
19
|
+
if (children) {
|
|
20
|
+
const Render = children;
|
|
21
|
+
return <Render authType={state.authType} />;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (state.authType === "bearer") {
|
|
25
|
+
return (
|
|
26
|
+
<input
|
|
27
|
+
type="password"
|
|
28
|
+
placeholder="Bearer token"
|
|
29
|
+
value={state.bearerToken}
|
|
30
|
+
onChange={(e) => setField("bearerToken", e.target.value)}
|
|
31
|
+
data-mcp-auth-field="bearer-token"
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (state.authType === "oauth") {
|
|
37
|
+
return (
|
|
38
|
+
<input
|
|
39
|
+
type="text"
|
|
40
|
+
placeholder="Scopes (space-separated, optional)"
|
|
41
|
+
value={state.scopes}
|
|
42
|
+
onChange={(e) => setField("scopes", e.target.value)}
|
|
43
|
+
data-mcp-auth-field="oauth-scopes"
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return null;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
McpAddFormPrimitiveAuthFields.displayName = "McpAddFormPrimitive.AuthFields";
|