@puredesktop/puredesktop-ui-bridge 2.1.8 → 2.1.9
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/package.json +35 -5
- package/src/agents/mcpServerPresets.test.ts +105 -0
- package/src/agents/mcpServerPresets.ts +380 -0
- package/src/agents/runtime/index.ts +7 -0
- package/src/agents/runtime/mapAgentSnapshot.ts +11 -8
- package/src/agents/runtime/pendingAsks.test.ts +117 -0
- package/src/agents/runtime/pendingAsks.ts +110 -0
- package/src/bridge/agentScopeDefaults.ts +65 -0
- package/src/bridge/agentTypes.ts +36 -2
- package/src/bridge/agents.d.mts +6 -0
- package/src/bridge/agents.mjs +10 -0
- package/src/bridge/agents.ts +4 -0
- package/src/bridge/credentials.d.mts +62 -0
- package/src/bridge/credentials.mjs +53 -0
- package/src/bridge/events.d.mts +1 -0
- package/src/bridge/events.mjs +1 -0
- package/src/bridge/googleAuth.ts +7 -152
- package/src/bridge/mcpClient.d.mts +74 -0
- package/src/bridge/mcpClient.mjs +79 -0
- package/src/bridge/methods.d.mts +22 -0
- package/src/bridge/methods.mjs +23 -0
- package/src/bridge/notifications.d.mts +12 -0
- package/src/bridge/notifications.mjs +36 -0
- package/src/bridge/operations.d.mts +44 -0
- package/src/bridge/operations.mjs +40 -0
- package/src/bridge/react/usePlatformAgentSessionDrive.test.tsx +29 -10
- package/src/bridge/react/usePlatformAgentSessionDrive.tsx +10 -81
- package/src/bridge/react/usePlatformAppSettings.test.tsx +105 -105
- package/src/bridge/react/usePlatformAppSettings.tsx +104 -104
- package/src/bridge/react/usePlatformJsonStore.test.tsx +152 -152
- package/src/bridge/react/usePlatformJsonStore.tsx +149 -149
- package/src/bridge/react/usePlatformOperations.tsx +75 -0
- package/src/bridge/storage.d.mts +17 -4
- package/src/bridge/storage.mjs +6 -3
- package/src/components/agents/AgentComposer.tsx +10 -6
- package/src/components/agents/AgentDrawerPanel.test.tsx +2 -205
- package/src/components/agents/AgentDrawerPanel.tsx +23 -64
- package/src/components/agents/AgentMessageBubble.tsx +59 -33
- package/src/components/agents/AgentMessageList.tsx +4 -9
- package/src/components/agents/AgentQuestionPromptList.tsx +34 -212
- package/src/components/agents/AgentToolApprovalActions.tsx +13 -11
- package/src/components/agents/AgentToolPendingList.tsx +6 -6
- package/src/components/agents/AgentToolPendingReview.tsx +6 -6
- package/src/components/agents/QuestionRequestList.tsx +278 -0
- package/src/components/agents/agentPanelStyles.ts +9 -33
- package/src/components/agents/agentTypes.ts +25 -43
- package/src/components/agents/index.ts +4 -0
- package/src/components/assets/asset-library/sidebar/AssetLibraryList.tsx +10 -4
- package/src/components/chrome/WorkspaceTabStrip.tsx +4 -3
- package/src/components/common/chat/ChatBox.tsx +9 -9
- package/src/components/common/chat/ChatModelMenu.tsx +34 -4
- package/src/components/common/chat/ChatThread.tsx +23 -7
- package/src/components/common/connections/ProviderConnection.test.tsx +208 -0
- package/src/components/common/connections/ProviderConnection.tsx +277 -0
- package/src/components/common/connections/index.ts +5 -0
- package/src/components/common/containers/AppFrame.tsx +26 -19
- package/src/components/common/containers/AppHeader.tsx +20 -20
- package/src/components/common/documents/DocumentSwitcher.tsx +63 -58
- package/src/components/common/dropdown/MenuDropdownItem.tsx +14 -2
- package/src/components/common/dropdown/MenuPortal.tsx +3 -1
- package/src/components/common/dropdown/menuViewportPosition.test.ts +20 -10
- package/src/components/common/dropdown/menuViewportPosition.ts +35 -27
- package/src/components/common/overlays/Modal.tsx +13 -2
- package/src/components/editor/EditorLinkPromptDialog.tsx +1 -1
- package/src/ics/generateIcs.test.ts +153 -0
- package/src/ics/generateIcs.ts +197 -0
- package/src/index.ts +3 -0
- package/src/net/httpRetry.test.ts +117 -0
- package/src/net/httpRetry.ts +111 -0
- package/src/theme/appAccents.ts +6 -0
- package/src/theme/appIdentityCss.mjs +11 -0
- package/src/theme/appIdentityCss.ts +11 -0
- package/src/theme/themes/dark.ts +3 -1
- package/src/theme/themes/light.ts +3 -1
- package/src/bridge/googleProviderConfig.ts +0 -73
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@puredesktop/puredesktop-ui-bridge",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.9",
|
|
4
4
|
"description": "PureScience plugin SDK — bridge client, theme, and shared UI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"directory": "packages/ui"
|
|
10
10
|
},
|
|
11
11
|
"publishConfig": {
|
|
12
|
-
"access": "
|
|
12
|
+
"access": "public",
|
|
13
13
|
"registry": "https://registry.npmjs.org"
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
@@ -20,6 +20,9 @@
|
|
|
20
20
|
"./agents/appAgentConnectors.ts": "./src/agents/appAgentConnectors.ts",
|
|
21
21
|
"./agents/appAgentConnectors": "./src/agents/appAgentConnectors.ts",
|
|
22
22
|
"./agents/appAgentConnectors.js": "./src/agents/appAgentConnectors.ts",
|
|
23
|
+
"./agents/mcpServerPresets.ts": "./src/agents/mcpServerPresets.ts",
|
|
24
|
+
"./agents/mcpServerPresets": "./src/agents/mcpServerPresets.ts",
|
|
25
|
+
"./agents/mcpServerPresets.js": "./src/agents/mcpServerPresets.ts",
|
|
23
26
|
"./agents/runtime/agentLiveReducer.ts": "./src/agents/runtime/agentLiveReducer.ts",
|
|
24
27
|
"./agents/runtime/agentLiveReducer": "./src/agents/runtime/agentLiveReducer.ts",
|
|
25
28
|
"./agents/runtime/agentLiveReducer.js": "./src/agents/runtime/agentLiveReducer.ts",
|
|
@@ -43,6 +46,9 @@
|
|
|
43
46
|
"./agents/runtime/mergeUsageTurn.ts": "./src/agents/runtime/mergeUsageTurn.ts",
|
|
44
47
|
"./agents/runtime/mergeUsageTurn": "./src/agents/runtime/mergeUsageTurn.ts",
|
|
45
48
|
"./agents/runtime/mergeUsageTurn.js": "./src/agents/runtime/mergeUsageTurn.ts",
|
|
49
|
+
"./agents/runtime/pendingAsks.ts": "./src/agents/runtime/pendingAsks.ts",
|
|
50
|
+
"./agents/runtime/pendingAsks": "./src/agents/runtime/pendingAsks.ts",
|
|
51
|
+
"./agents/runtime/pendingAsks.js": "./src/agents/runtime/pendingAsks.ts",
|
|
46
52
|
"./agents/runtime/pendingToolCalls.ts": "./src/agents/runtime/pendingToolCalls.ts",
|
|
47
53
|
"./agents/runtime/pendingToolCalls": "./src/agents/runtime/pendingToolCalls.ts",
|
|
48
54
|
"./agents/runtime/pendingToolCalls.js": "./src/agents/runtime/pendingToolCalls.ts",
|
|
@@ -59,6 +65,9 @@
|
|
|
59
65
|
"./bridge/agents": "./src/bridge/agents.ts",
|
|
60
66
|
"./bridge/agents.js": "./src/bridge/agents.ts",
|
|
61
67
|
"./bridge/agents.ts": "./src/bridge/agents.ts",
|
|
68
|
+
"./bridge/agentScopeDefaults.ts": "./src/bridge/agentScopeDefaults.ts",
|
|
69
|
+
"./bridge/agentScopeDefaults": "./src/bridge/agentScopeDefaults.ts",
|
|
70
|
+
"./bridge/agentScopeDefaults.js": "./src/bridge/agentScopeDefaults.ts",
|
|
62
71
|
"./bridge/agentToolHandlers.ts": "./src/bridge/agentToolHandlers.ts",
|
|
63
72
|
"./bridge/agentToolHandlers": "./src/bridge/agentToolHandlers.ts",
|
|
64
73
|
"./bridge/agentToolHandlers.js": "./src/bridge/agentToolHandlers.ts",
|
|
@@ -129,9 +138,6 @@
|
|
|
129
138
|
"./bridge/googleAuth.ts": "./src/bridge/googleAuth.ts",
|
|
130
139
|
"./bridge/googleAuth": "./src/bridge/googleAuth.ts",
|
|
131
140
|
"./bridge/googleAuth.js": "./src/bridge/googleAuth.ts",
|
|
132
|
-
"./bridge/googleProviderConfig.ts": "./src/bridge/googleProviderConfig.ts",
|
|
133
|
-
"./bridge/googleProviderConfig": "./src/bridge/googleProviderConfig.ts",
|
|
134
|
-
"./bridge/googleProviderConfig.js": "./src/bridge/googleProviderConfig.ts",
|
|
135
141
|
"./bridge/index.ts": "./src/bridge/index.ts",
|
|
136
142
|
"./bridge/index": "./src/bridge/index.ts",
|
|
137
143
|
"./bridge/index.js": "./src/bridge/index.ts",
|
|
@@ -141,12 +147,21 @@
|
|
|
141
147
|
"./bridge/inlinePreview": "./src/bridge/inlinePreview.ts",
|
|
142
148
|
"./bridge/inlinePreview.js": "./src/bridge/inlinePreview.ts",
|
|
143
149
|
"./bridge/inlinePreview.ts": "./src/bridge/inlinePreview.ts",
|
|
150
|
+
"./bridge/mcpClient.mjs": "./src/bridge/mcpClient.mjs",
|
|
151
|
+
"./bridge/mcpClient": "./src/bridge/mcpClient.mjs",
|
|
152
|
+
"./bridge/mcpClient.js": "./src/bridge/mcpClient.mjs",
|
|
144
153
|
"./bridge/methods.mjs": "./src/bridge/methods.mjs",
|
|
145
154
|
"./bridge/methods": "./src/bridge/methods.mjs",
|
|
146
155
|
"./bridge/methods.js": "./src/bridge/methods.mjs",
|
|
147
156
|
"./bridge/network.mjs": "./src/bridge/network.mjs",
|
|
148
157
|
"./bridge/network": "./src/bridge/network.mjs",
|
|
149
158
|
"./bridge/network.js": "./src/bridge/network.mjs",
|
|
159
|
+
"./bridge/notifications.mjs": "./src/bridge/notifications.mjs",
|
|
160
|
+
"./bridge/notifications": "./src/bridge/notifications.mjs",
|
|
161
|
+
"./bridge/notifications.js": "./src/bridge/notifications.mjs",
|
|
162
|
+
"./bridge/operations.mjs": "./src/bridge/operations.mjs",
|
|
163
|
+
"./bridge/operations": "./src/bridge/operations.mjs",
|
|
164
|
+
"./bridge/operations.js": "./src/bridge/operations.mjs",
|
|
150
165
|
"./bridge/os.mjs": "./src/bridge/os.mjs",
|
|
151
166
|
"./bridge/os": "./src/bridge/os.mjs",
|
|
152
167
|
"./bridge/os.js": "./src/bridge/os.mjs",
|
|
@@ -255,6 +270,9 @@
|
|
|
255
270
|
"./bridge/react/usePlatformJsonStore.tsx": "./src/bridge/react/usePlatformJsonStore.tsx",
|
|
256
271
|
"./bridge/react/usePlatformJsonStore": "./src/bridge/react/usePlatformJsonStore.tsx",
|
|
257
272
|
"./bridge/react/usePlatformJsonStore.js": "./src/bridge/react/usePlatformJsonStore.tsx",
|
|
273
|
+
"./bridge/react/usePlatformOperations.tsx": "./src/bridge/react/usePlatformOperations.tsx",
|
|
274
|
+
"./bridge/react/usePlatformOperations": "./src/bridge/react/usePlatformOperations.tsx",
|
|
275
|
+
"./bridge/react/usePlatformOperations.js": "./src/bridge/react/usePlatformOperations.tsx",
|
|
258
276
|
"./bridge/react/usePlatformPreferences.tsx": "./src/bridge/react/usePlatformPreferences.tsx",
|
|
259
277
|
"./bridge/react/usePlatformPreferences": "./src/bridge/react/usePlatformPreferences.tsx",
|
|
260
278
|
"./bridge/react/usePlatformPreferences.js": "./src/bridge/react/usePlatformPreferences.tsx",
|
|
@@ -389,6 +407,9 @@
|
|
|
389
407
|
"./components/agents/index.js": "./src/components/agents/index.ts",
|
|
390
408
|
"./components/agents": "./src/components/agents/index.ts",
|
|
391
409
|
"./components/agents.js": "./src/components/agents/index.ts",
|
|
410
|
+
"./components/agents/QuestionRequestList.tsx": "./src/components/agents/QuestionRequestList.tsx",
|
|
411
|
+
"./components/agents/QuestionRequestList": "./src/components/agents/QuestionRequestList.tsx",
|
|
412
|
+
"./components/agents/QuestionRequestList.js": "./src/components/agents/QuestionRequestList.tsx",
|
|
392
413
|
"./components/assets/asset-library/AssetLibraryDialog.tsx": "./src/components/assets/asset-library/AssetLibraryDialog.tsx",
|
|
393
414
|
"./components/assets/asset-library/AssetLibraryDialog": "./src/components/assets/asset-library/AssetLibraryDialog.tsx",
|
|
394
415
|
"./components/assets/asset-library/AssetLibraryDialog.js": "./src/components/assets/asset-library/AssetLibraryDialog.tsx",
|
|
@@ -623,6 +644,9 @@
|
|
|
623
644
|
"./components/common/connections/index.js": "./src/components/common/connections/index.ts",
|
|
624
645
|
"./components/common/connections": "./src/components/common/connections/index.ts",
|
|
625
646
|
"./components/common/connections.js": "./src/components/common/connections/index.ts",
|
|
647
|
+
"./components/common/connections/ProviderConnection.tsx": "./src/components/common/connections/ProviderConnection.tsx",
|
|
648
|
+
"./components/common/connections/ProviderConnection": "./src/components/common/connections/ProviderConnection.tsx",
|
|
649
|
+
"./components/common/connections/ProviderConnection.js": "./src/components/common/connections/ProviderConnection.tsx",
|
|
626
650
|
"./components/common/containers/AppFrame.tsx": "./src/components/common/containers/AppFrame.tsx",
|
|
627
651
|
"./components/common/containers/AppFrame": "./src/components/common/containers/AppFrame.tsx",
|
|
628
652
|
"./components/common/containers/AppFrame.js": "./src/components/common/containers/AppFrame.tsx",
|
|
@@ -1122,6 +1146,12 @@
|
|
|
1122
1146
|
"./editor/toolbarOverlays.ts": "./src/editor/toolbarOverlays.ts",
|
|
1123
1147
|
"./editor/toolbarOverlays": "./src/editor/toolbarOverlays.ts",
|
|
1124
1148
|
"./editor/toolbarOverlays.js": "./src/editor/toolbarOverlays.ts",
|
|
1149
|
+
"./ics/generateIcs.ts": "./src/ics/generateIcs.ts",
|
|
1150
|
+
"./ics/generateIcs": "./src/ics/generateIcs.ts",
|
|
1151
|
+
"./ics/generateIcs.js": "./src/ics/generateIcs.ts",
|
|
1152
|
+
"./net/httpRetry.ts": "./src/net/httpRetry.ts",
|
|
1153
|
+
"./net/httpRetry": "./src/net/httpRetry.ts",
|
|
1154
|
+
"./net/httpRetry.js": "./src/net/httpRetry.ts",
|
|
1125
1155
|
"./theme/appAccents.ts": "./src/theme/appAccents.ts",
|
|
1126
1156
|
"./theme/appAccents": "./src/theme/appAccents.ts",
|
|
1127
1157
|
"./theme/appAccents.js": "./src/theme/appAccents.ts",
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import {
|
|
3
|
+
MCP_SERVER_PRESETS,
|
|
4
|
+
MCP_SERVER_PRESET_CATEGORY_LABELS,
|
|
5
|
+
MCP_PRESET_RUNTIME_RANK,
|
|
6
|
+
findMcpServerPreset,
|
|
7
|
+
mcpPresetRuntime,
|
|
8
|
+
} from './mcpServerPresets.js'
|
|
9
|
+
|
|
10
|
+
describe('MCP_SERVER_PRESETS', () => {
|
|
11
|
+
it('uses unique registry-safe ids', () => {
|
|
12
|
+
const ids = MCP_SERVER_PRESETS.map(preset => preset.id)
|
|
13
|
+
expect(new Set(ids).size).toBe(ids.length)
|
|
14
|
+
for (const id of ids) {
|
|
15
|
+
// Registry constraint from the mcp-client store: [a-z0-9-]+ (no `__`).
|
|
16
|
+
expect(id).toMatch(/^[a-z0-9-]+$/)
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('gives every preset a coherent transport target', () => {
|
|
21
|
+
for (const preset of MCP_SERVER_PRESETS) {
|
|
22
|
+
if (preset.transport === 'stdio') {
|
|
23
|
+
expect(preset.command, preset.id).toBeTruthy()
|
|
24
|
+
expect(preset.url, preset.id).toBeUndefined()
|
|
25
|
+
} else {
|
|
26
|
+
expect(preset.url, preset.id).toMatch(/^https:\/\//)
|
|
27
|
+
expect(preset.command, preset.id).toBeUndefined()
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('labels every category used by a preset', () => {
|
|
33
|
+
for (const preset of MCP_SERVER_PRESETS) {
|
|
34
|
+
expect(MCP_SERVER_PRESET_CATEGORY_LABELS[preset.category]).toBeTruthy()
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('includes the academic core (arxiv, pubmed, wikipedia)', () => {
|
|
39
|
+
for (const id of ['arxiv', 'pubmed', 'wikipedia']) {
|
|
40
|
+
expect(findMcpServerPreset(id), id).toBeDefined()
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('marks token-gated presets so the UI can ask up front', () => {
|
|
45
|
+
expect(findMcpServerPreset('github')?.requiresToken).toBe(true)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('gives local (stdio) academic presets an iconDomain so they get a real logo', () => {
|
|
49
|
+
for (const id of ['arxiv', 'pubmed', 'wikipedia']) {
|
|
50
|
+
const preset = findMcpServerPreset(id)
|
|
51
|
+
expect(preset?.transport, id).toBe('stdio')
|
|
52
|
+
expect(preset?.iconDomain, id).toBeTruthy()
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('keeps every iconDomain a bare host (no scheme or path)', () => {
|
|
57
|
+
for (const preset of MCP_SERVER_PRESETS) {
|
|
58
|
+
if (!preset.iconDomain) continue
|
|
59
|
+
expect(preset.iconDomain, preset.id).toMatch(/^[a-z0-9.-]+$/i)
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('classifies runtime by transport and runner', () => {
|
|
64
|
+
expect(mcpPresetRuntime(findMcpServerPreset('deepwiki')!)).toBe('remote')
|
|
65
|
+
expect(mcpPresetRuntime(findMcpServerPreset('memory')!)).toBe('node')
|
|
66
|
+
expect(mcpPresetRuntime(findMcpServerPreset('arxiv')!)).toBe('python')
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('ranks no-install runtimes ahead of Python', () => {
|
|
70
|
+
expect(MCP_PRESET_RUNTIME_RANK.remote).toBeLessThan(
|
|
71
|
+
MCP_PRESET_RUNTIME_RANK.node,
|
|
72
|
+
)
|
|
73
|
+
expect(MCP_PRESET_RUNTIME_RANK.node).toBeLessThan(
|
|
74
|
+
MCP_PRESET_RUNTIME_RANK.python,
|
|
75
|
+
)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
it('offers a broad set of no-install (remote+node) servers', () => {
|
|
79
|
+
const noInstall = MCP_SERVER_PRESETS.filter(
|
|
80
|
+
p => mcpPresetRuntime(p) !== 'python',
|
|
81
|
+
)
|
|
82
|
+
expect(noInstall.length).toBeGreaterThanOrEqual(12)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
it('carries auth + env var for apiKey presets', () => {
|
|
86
|
+
const exa = findMcpServerPreset('exa')
|
|
87
|
+
expect(exa?.auth).toBe('apiKey')
|
|
88
|
+
expect(exa?.apiKeyEnvVar).toBe('EXA_API_KEY')
|
|
89
|
+
expect(exa?.requiresToken).toBe(true)
|
|
90
|
+
expect(mcpPresetRuntime(exa!)).toBe('node')
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('marks remote token servers as bearer', () => {
|
|
94
|
+
expect(findMcpServerPreset('github')?.auth).toBe('bearer')
|
|
95
|
+
expect(findMcpServerPreset('stripe')?.auth).toBe('bearer')
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('keeps keyless remote servers auth-free', () => {
|
|
99
|
+
for (const id of ['deepwiki', 'context7', 'cloudflare-docs']) {
|
|
100
|
+
const preset = findMcpServerPreset(id)
|
|
101
|
+
expect(preset, id).toBeDefined()
|
|
102
|
+
expect(preset?.auth ?? 'none', id).toBe('none')
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
})
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Curated MCP servers preloaded with PureDesktop — one click to add from the
|
|
3
|
+
* assistant Tools library (nothing is enabled until the user confirms).
|
|
4
|
+
* Selection favors keyless servers; entries that need a key say so and the
|
|
5
|
+
* UI asks for the bearer token after the first failing test.
|
|
6
|
+
*
|
|
7
|
+
* `stdio` presets run locally and need their runner on PATH (`npx` → Node,
|
|
8
|
+
* `uvx` → uv); remote presets need nothing. The Test button verifies either
|
|
9
|
+
* way, so a missing runner or a renamed package fails loudly, not silently.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export type McpServerPresetTransport = 'http' | 'sse' | 'stdio'
|
|
13
|
+
|
|
14
|
+
export type McpServerPresetCategory =
|
|
15
|
+
| 'academic'
|
|
16
|
+
| 'knowledge'
|
|
17
|
+
| 'documentation'
|
|
18
|
+
| 'developer'
|
|
19
|
+
|
|
20
|
+
export type McpServerPresetAuth = 'none' | 'bearer' | 'apiKey'
|
|
21
|
+
|
|
22
|
+
export interface McpServerPreset {
|
|
23
|
+
/** Registry id — `[a-z0-9-]+`, stable across releases. */
|
|
24
|
+
id: string
|
|
25
|
+
label: string
|
|
26
|
+
description: string
|
|
27
|
+
category: McpServerPresetCategory
|
|
28
|
+
transport: McpServerPresetTransport
|
|
29
|
+
url?: string
|
|
30
|
+
command?: string
|
|
31
|
+
args?: string[]
|
|
32
|
+
/**
|
|
33
|
+
* How the server authenticates: `bearer` (Authorization header on a remote
|
|
34
|
+
* server) or `apiKey` (an env var, named by `apiKeyEnvVar`, on a local stdio
|
|
35
|
+
* server). Omitted → no auth.
|
|
36
|
+
*/
|
|
37
|
+
auth?: McpServerPresetAuth
|
|
38
|
+
/** Env var the key is passed as, for `auth: 'apiKey'` servers. */
|
|
39
|
+
apiKeyEnvVar?: string
|
|
40
|
+
/** Preset needs a secret (bearer token or API key) before it will connect. */
|
|
41
|
+
requiresToken?: boolean
|
|
42
|
+
/** Short caveat shown with the entry (runner needed, rate limits, …). */
|
|
43
|
+
note?: string
|
|
44
|
+
/**
|
|
45
|
+
* Site to pull a favicon from for the row logo. Auto-derived from `url` for
|
|
46
|
+
* remote presets; set explicitly for local (stdio) presets that still have a
|
|
47
|
+
* recognizable home page (arXiv, PubMed, …) so they don't fall back to plain
|
|
48
|
+
* initials.
|
|
49
|
+
*/
|
|
50
|
+
iconDomain?: string
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const MCP_SERVER_PRESETS: readonly McpServerPreset[] = [
|
|
54
|
+
// ---- Academic research ----------------------------------------------------
|
|
55
|
+
{
|
|
56
|
+
id: 'arxiv',
|
|
57
|
+
label: 'arXiv',
|
|
58
|
+
description:
|
|
59
|
+
'Search arXiv preprints, fetch abstracts, and download papers for analysis.',
|
|
60
|
+
category: 'academic',
|
|
61
|
+
transport: 'stdio',
|
|
62
|
+
command: 'uvx',
|
|
63
|
+
args: ['arxiv-mcp-server'],
|
|
64
|
+
note: 'Python server — needs uv (one-time install).',
|
|
65
|
+
iconDomain: 'arxiv.org',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: 'pubmed',
|
|
69
|
+
label: 'PubMed',
|
|
70
|
+
description:
|
|
71
|
+
'Search PubMed biomedical literature and fetch article metadata and abstracts.',
|
|
72
|
+
category: 'academic',
|
|
73
|
+
transport: 'stdio',
|
|
74
|
+
command: 'uvx',
|
|
75
|
+
args: ['pubmedmcp'],
|
|
76
|
+
note: 'Python server — needs uv (one-time install).',
|
|
77
|
+
iconDomain: 'pubmed.ncbi.nlm.nih.gov',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: 'wikipedia',
|
|
81
|
+
label: 'Wikipedia',
|
|
82
|
+
description:
|
|
83
|
+
'Look up and summarize Wikipedia articles with full-text search.',
|
|
84
|
+
category: 'academic',
|
|
85
|
+
transport: 'stdio',
|
|
86
|
+
command: 'uvx',
|
|
87
|
+
args: ['wikipedia-mcp'],
|
|
88
|
+
note: 'Python server — needs uv (one-time install).',
|
|
89
|
+
iconDomain: 'wikipedia.org',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: 'huggingface',
|
|
93
|
+
label: 'Hugging Face',
|
|
94
|
+
description:
|
|
95
|
+
'Search models, datasets, Spaces, and daily papers on the Hugging Face Hub.',
|
|
96
|
+
category: 'academic',
|
|
97
|
+
transport: 'http',
|
|
98
|
+
url: 'https://huggingface.co/mcp',
|
|
99
|
+
note: 'Remote server; anonymous access is rate-limited.',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: 'exa',
|
|
103
|
+
label: 'Exa research',
|
|
104
|
+
description:
|
|
105
|
+
'Neural web + research-paper search with full-text retrieval — strong for academic literature.',
|
|
106
|
+
category: 'academic',
|
|
107
|
+
transport: 'stdio',
|
|
108
|
+
command: 'npx',
|
|
109
|
+
args: ['-y', 'exa-mcp-server'],
|
|
110
|
+
auth: 'apiKey',
|
|
111
|
+
apiKeyEnvVar: 'EXA_API_KEY',
|
|
112
|
+
requiresToken: true,
|
|
113
|
+
note: 'Runs via npx (Node). Needs a free Exa API key (asked for after adding).',
|
|
114
|
+
iconDomain: 'exa.ai',
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
// ---- General knowledge work ----------------------------------------------
|
|
118
|
+
{
|
|
119
|
+
id: 'fetch',
|
|
120
|
+
label: 'Web fetch',
|
|
121
|
+
description:
|
|
122
|
+
'Fetch a web page and convert it to markdown for reading and citation.',
|
|
123
|
+
category: 'knowledge',
|
|
124
|
+
transport: 'stdio',
|
|
125
|
+
command: 'uvx',
|
|
126
|
+
args: ['mcp-server-fetch'],
|
|
127
|
+
note: 'Python reference server — needs uv (one-time install).',
|
|
128
|
+
iconDomain: 'developer.mozilla.org',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
id: 'duckduckgo',
|
|
132
|
+
label: 'DuckDuckGo search',
|
|
133
|
+
description: 'Key-free web search with content extraction.',
|
|
134
|
+
category: 'knowledge',
|
|
135
|
+
transport: 'stdio',
|
|
136
|
+
command: 'uvx',
|
|
137
|
+
args: ['duckduckgo-mcp-server'],
|
|
138
|
+
note: 'Python server — needs uv (one-time install).',
|
|
139
|
+
iconDomain: 'duckduckgo.com',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
id: 'memory',
|
|
143
|
+
label: 'Memory (knowledge graph)',
|
|
144
|
+
description:
|
|
145
|
+
'Persistent knowledge-graph memory agents can read and extend across sessions.',
|
|
146
|
+
category: 'knowledge',
|
|
147
|
+
transport: 'stdio',
|
|
148
|
+
command: 'npx',
|
|
149
|
+
args: ['-y', '@modelcontextprotocol/server-memory'],
|
|
150
|
+
note: 'Reference server; runs locally via npx.',
|
|
151
|
+
iconDomain: 'modelcontextprotocol.io',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: 'sequential-thinking',
|
|
155
|
+
label: 'Sequential thinking',
|
|
156
|
+
description:
|
|
157
|
+
'Structured step-by-step reasoning scratchpad for complex problems.',
|
|
158
|
+
category: 'knowledge',
|
|
159
|
+
transport: 'stdio',
|
|
160
|
+
command: 'npx',
|
|
161
|
+
args: ['-y', '@modelcontextprotocol/server-sequential-thinking'],
|
|
162
|
+
note: 'Reference server; runs locally via npx.',
|
|
163
|
+
iconDomain: 'modelcontextprotocol.io',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: 'time',
|
|
167
|
+
label: 'Time & timezones',
|
|
168
|
+
description: 'Current time and timezone conversion.',
|
|
169
|
+
category: 'knowledge',
|
|
170
|
+
transport: 'stdio',
|
|
171
|
+
command: 'uvx',
|
|
172
|
+
args: ['mcp-server-time'],
|
|
173
|
+
note: 'Python reference server — needs uv (one-time install).',
|
|
174
|
+
iconDomain: 'modelcontextprotocol.io',
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
id: 'tavily',
|
|
178
|
+
label: 'Tavily search',
|
|
179
|
+
description:
|
|
180
|
+
'Web search, extract, and crawl tuned for LLM answers with citations.',
|
|
181
|
+
category: 'knowledge',
|
|
182
|
+
transport: 'stdio',
|
|
183
|
+
command: 'npx',
|
|
184
|
+
args: ['-y', 'tavily-mcp'],
|
|
185
|
+
auth: 'apiKey',
|
|
186
|
+
apiKeyEnvVar: 'TAVILY_API_KEY',
|
|
187
|
+
requiresToken: true,
|
|
188
|
+
note: 'Runs via npx (Node). Needs a Tavily API key (asked for after adding).',
|
|
189
|
+
iconDomain: 'tavily.com',
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
id: 'brave-search',
|
|
193
|
+
label: 'Brave Search',
|
|
194
|
+
description: 'Independent web and local search index.',
|
|
195
|
+
category: 'knowledge',
|
|
196
|
+
transport: 'stdio',
|
|
197
|
+
command: 'npx',
|
|
198
|
+
args: ['-y', '@modelcontextprotocol/server-brave-search'],
|
|
199
|
+
auth: 'apiKey',
|
|
200
|
+
apiKeyEnvVar: 'BRAVE_API_KEY',
|
|
201
|
+
requiresToken: true,
|
|
202
|
+
note: 'Runs via npx (Node). Needs a Brave Search API key (asked for after adding).',
|
|
203
|
+
iconDomain: 'search.brave.com',
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
id: 'firecrawl',
|
|
207
|
+
label: 'Firecrawl',
|
|
208
|
+
description:
|
|
209
|
+
'Scrape, crawl, and structure whole websites into clean markdown or JSON.',
|
|
210
|
+
category: 'knowledge',
|
|
211
|
+
transport: 'stdio',
|
|
212
|
+
command: 'npx',
|
|
213
|
+
args: ['-y', 'firecrawl-mcp'],
|
|
214
|
+
auth: 'apiKey',
|
|
215
|
+
apiKeyEnvVar: 'FIRECRAWL_API_KEY',
|
|
216
|
+
requiresToken: true,
|
|
217
|
+
note: 'Runs via npx (Node). Needs a Firecrawl API key (asked for after adding).',
|
|
218
|
+
iconDomain: 'firecrawl.dev',
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
// ---- Documentation --------------------------------------------------------
|
|
222
|
+
{
|
|
223
|
+
id: 'context7',
|
|
224
|
+
label: 'Context7 docs',
|
|
225
|
+
description:
|
|
226
|
+
'Version-accurate library and framework documentation for grounded answers.',
|
|
227
|
+
category: 'documentation',
|
|
228
|
+
transport: 'http',
|
|
229
|
+
url: 'https://mcp.context7.com/mcp',
|
|
230
|
+
note: 'Remote server; anonymous tier is rate-limited.',
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
id: 'deepwiki',
|
|
234
|
+
label: 'DeepWiki',
|
|
235
|
+
description:
|
|
236
|
+
'Ask questions about public GitHub repositories via generated wikis.',
|
|
237
|
+
category: 'documentation',
|
|
238
|
+
transport: 'http',
|
|
239
|
+
url: 'https://mcp.deepwiki.com/mcp',
|
|
240
|
+
note: 'Remote server, key-free.',
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
id: 'microsoft-learn',
|
|
244
|
+
label: 'Microsoft Learn',
|
|
245
|
+
description:
|
|
246
|
+
'Search and read Microsoft/Azure documentation grounded to current pages.',
|
|
247
|
+
category: 'documentation',
|
|
248
|
+
transport: 'http',
|
|
249
|
+
url: 'https://learn.microsoft.com/api/mcp',
|
|
250
|
+
note: 'Remote server, key-free.',
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
id: 'cloudflare-docs',
|
|
254
|
+
label: 'Cloudflare Docs',
|
|
255
|
+
description:
|
|
256
|
+
'Search and read Cloudflare developer documentation, grounded to current pages.',
|
|
257
|
+
category: 'documentation',
|
|
258
|
+
transport: 'sse',
|
|
259
|
+
url: 'https://docs.mcp.cloudflare.com/sse',
|
|
260
|
+
note: 'Remote server, key-free.',
|
|
261
|
+
iconDomain: 'cloudflare.com',
|
|
262
|
+
},
|
|
263
|
+
|
|
264
|
+
// ---- Developer ------------------------------------------------------------
|
|
265
|
+
{
|
|
266
|
+
id: 'git',
|
|
267
|
+
label: 'Git (local repos)',
|
|
268
|
+
description:
|
|
269
|
+
'Inspect and search local git repositories: log, diff, blame, status.',
|
|
270
|
+
category: 'developer',
|
|
271
|
+
transport: 'stdio',
|
|
272
|
+
command: 'uvx',
|
|
273
|
+
args: ['mcp-server-git'],
|
|
274
|
+
note: 'Python reference server — needs uv (one-time install).',
|
|
275
|
+
iconDomain: 'git-scm.com',
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
id: 'github',
|
|
279
|
+
label: 'GitHub',
|
|
280
|
+
description:
|
|
281
|
+
'Repositories, issues, and pull requests through the official GitHub MCP.',
|
|
282
|
+
category: 'developer',
|
|
283
|
+
transport: 'http',
|
|
284
|
+
url: 'https://api.githubcopilot.com/mcp/',
|
|
285
|
+
auth: 'bearer',
|
|
286
|
+
requiresToken: true,
|
|
287
|
+
note: 'Needs a GitHub personal access token (asked for after adding).',
|
|
288
|
+
iconDomain: 'github.com',
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
id: 'playwright',
|
|
292
|
+
label: 'Playwright browser',
|
|
293
|
+
description:
|
|
294
|
+
'Drive a real browser: navigate, click, fill, and read pages for the agent.',
|
|
295
|
+
category: 'developer',
|
|
296
|
+
transport: 'stdio',
|
|
297
|
+
command: 'npx',
|
|
298
|
+
args: ['-y', '@playwright/mcp@latest'],
|
|
299
|
+
note: 'Runs via npx (Node); downloads a browser on first use.',
|
|
300
|
+
iconDomain: 'playwright.dev',
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
id: 'everything',
|
|
304
|
+
label: 'Everything (demo)',
|
|
305
|
+
description:
|
|
306
|
+
'Reference server exercising every MCP feature — handy for trying tools out.',
|
|
307
|
+
category: 'developer',
|
|
308
|
+
transport: 'stdio',
|
|
309
|
+
command: 'npx',
|
|
310
|
+
args: ['-y', '@modelcontextprotocol/server-everything'],
|
|
311
|
+
note: 'Reference server; runs locally via npx.',
|
|
312
|
+
iconDomain: 'modelcontextprotocol.io',
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
id: 'chart',
|
|
316
|
+
label: 'Charts (AntV)',
|
|
317
|
+
description:
|
|
318
|
+
'Generate 25+ chart types (line, bar, pie, maps, …) as images from data.',
|
|
319
|
+
category: 'developer',
|
|
320
|
+
transport: 'stdio',
|
|
321
|
+
command: 'npx',
|
|
322
|
+
args: ['-y', '@antv/mcp-server-chart'],
|
|
323
|
+
note: 'Runs via npx (Node).',
|
|
324
|
+
iconDomain: 'antv.antgroup.com',
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
id: 'stripe',
|
|
328
|
+
label: 'Stripe',
|
|
329
|
+
description:
|
|
330
|
+
'Query and manage Stripe: customers, payments, invoices, and products.',
|
|
331
|
+
category: 'developer',
|
|
332
|
+
transport: 'http',
|
|
333
|
+
url: 'https://mcp.stripe.com',
|
|
334
|
+
auth: 'bearer',
|
|
335
|
+
requiresToken: true,
|
|
336
|
+
note: 'Needs a Stripe restricted API key as the bearer token (asked for after adding).',
|
|
337
|
+
iconDomain: 'stripe.com',
|
|
338
|
+
},
|
|
339
|
+
]
|
|
340
|
+
|
|
341
|
+
export const MCP_SERVER_PRESET_CATEGORY_LABELS: Record<
|
|
342
|
+
McpServerPresetCategory,
|
|
343
|
+
string
|
|
344
|
+
> = {
|
|
345
|
+
academic: 'Academic research',
|
|
346
|
+
knowledge: 'Knowledge work',
|
|
347
|
+
documentation: 'Documentation',
|
|
348
|
+
developer: 'Developer',
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export function findMcpServerPreset(id: string): McpServerPreset | undefined {
|
|
352
|
+
return MCP_SERVER_PRESETS.find(preset => preset.id === id)
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* What a preset needs on the user's machine to run:
|
|
357
|
+
* - `remote` — nothing (an HTTP/SSE endpoint the shell just calls);
|
|
358
|
+
* - `node` — a system `npx` (Node.js), usually already present;
|
|
359
|
+
* - `python` — `uvx` (uv), the least commonly installed.
|
|
360
|
+
*
|
|
361
|
+
* The Tools UI privileges lower-friction runtimes and clearly flags the ones
|
|
362
|
+
* that need an extra install, rather than requiring uv across the board.
|
|
363
|
+
*/
|
|
364
|
+
export type McpPresetRuntime = 'remote' | 'node' | 'python'
|
|
365
|
+
|
|
366
|
+
const NODE_RUNNERS = new Set(['npx', 'node', 'bunx'])
|
|
367
|
+
|
|
368
|
+
export function mcpPresetRuntime(
|
|
369
|
+
preset: Pick<McpServerPreset, 'transport' | 'command'>,
|
|
370
|
+
): McpPresetRuntime {
|
|
371
|
+
if (preset.transport !== 'stdio') return 'remote'
|
|
372
|
+
return preset.command && NODE_RUNNERS.has(preset.command) ? 'node' : 'python'
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/** Sort rank so no-install servers come first, then Node, then Python. */
|
|
376
|
+
export const MCP_PRESET_RUNTIME_RANK: Record<McpPresetRuntime, number> = {
|
|
377
|
+
remote: 0,
|
|
378
|
+
node: 1,
|
|
379
|
+
python: 2,
|
|
380
|
+
}
|
|
@@ -8,6 +8,13 @@ export {
|
|
|
8
8
|
export { createIdleLiveTurn, reduceAgentLiveTurn } from './agentLiveReducer.js'
|
|
9
9
|
export { unresolvedToolCalls } from './unresolvedToolCalls.js'
|
|
10
10
|
export { derivePendingToolCalls } from './pendingToolCalls.js'
|
|
11
|
+
export {
|
|
12
|
+
derivePendingAsks,
|
|
13
|
+
sessionPendingAskCalls,
|
|
14
|
+
type PendingAsk,
|
|
15
|
+
type PendingAskDelegation,
|
|
16
|
+
type PendingAskSession,
|
|
17
|
+
} from './pendingAsks.js'
|
|
11
18
|
export { toolRequiresApproval } from './toolRequiresApproval.js'
|
|
12
19
|
export { mergeUsageTurn } from './mergeUsageTurn.js'
|
|
13
20
|
export {
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
type AgentUiToolCall,
|
|
9
9
|
} from '../../components/agents/agentTypes.js'
|
|
10
10
|
import { derivePendingToolCalls } from './pendingToolCalls.js'
|
|
11
|
-
import {
|
|
11
|
+
import { sessionPendingAskCalls } from './pendingAsks.js'
|
|
12
12
|
|
|
13
13
|
const VISIBLE_ROLES = new Set(['user', 'assistant', 'tool'])
|
|
14
14
|
|
|
@@ -76,19 +76,22 @@ export function mapPendingToolCalls(
|
|
|
76
76
|
)
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
/**
|
|
79
|
+
/**
|
|
80
|
+
* Pending tools that still need explicit user approval — the shared
|
|
81
|
+
* pending-asks selector's per-session slice (docs/09 §Card states).
|
|
82
|
+
*/
|
|
80
83
|
export function mapApprovalPendingToolCalls(
|
|
81
84
|
snapshot: PlatformAgentRunSnapshot | null,
|
|
82
85
|
policy: PlatformAgentSessionToolPolicy | undefined,
|
|
83
86
|
acceptedPendingToolCallIds: readonly string[] = [],
|
|
84
87
|
): AgentUiToolCall[] {
|
|
85
88
|
if (!snapshot || !policy) return []
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
return sessionPendingAskCalls({
|
|
90
|
+
state: snapshot.state,
|
|
91
|
+
messages: snapshot.messages,
|
|
92
|
+
acceptedPendingToolCallIds,
|
|
93
|
+
toolPolicy: policy,
|
|
94
|
+
})
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
function mapToolCall(call: AgentUiToolCall): AgentUiToolCall {
|