@agent-native/core 0.106.3 → 0.107.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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +13 -0
- package/corpus/core/docs/content/integrations.mdx +597 -0
- package/corpus/core/docs/content/locales/ar-SA/mcp-clients.mdx +19 -1
- package/corpus/core/docs/content/locales/de-DE/mcp-clients.mdx +22 -1
- package/corpus/core/docs/content/locales/es-ES/mcp-clients.mdx +23 -1
- package/corpus/core/docs/content/locales/fr-FR/mcp-clients.mdx +23 -1
- package/corpus/core/docs/content/locales/hi-IN/mcp-clients.mdx +22 -1
- package/corpus/core/docs/content/locales/ja-JP/mcp-clients.mdx +21 -1
- package/corpus/core/docs/content/locales/ko-KR/mcp-clients.mdx +20 -1
- package/corpus/core/docs/content/locales/pt-BR/mcp-clients.mdx +22 -1
- package/corpus/core/docs/content/locales/zh-CN/mcp-clients.mdx +17 -1
- package/corpus/core/docs/content/locales/zh-TW/mcp-clients.mdx +17 -1
- package/corpus/core/docs/content/mcp-clients.mdx +51 -1
- package/corpus/core/docs/content/organizations-teams-permissions.mdx +413 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/AssistantChat.tsx +13 -1
- package/corpus/core/src/client/chat/message-components.tsx +41 -0
- package/corpus/core/src/client/composer/TiptapComposer.tsx +45 -8
- package/corpus/core/src/client/integrations/IntegrationsPanel.tsx +30 -11
- package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +240 -0
- package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +159 -40
- package/corpus/core/src/client/resources/mcp-integration-catalog.ts +433 -4
- package/corpus/core/src/client/resources/mcp-integration-logos.ts +108 -0
- package/corpus/core/src/deploy/build.ts +32 -0
- package/corpus/core/src/extensions/html-shell.ts +33 -1
- package/corpus/core/src/ingestion/office.ts +1 -2
- package/corpus/core/src/ingestion/pptx.ts +2 -4
- package/corpus/core/src/localization/default-messages.ts +126 -1
- package/corpus/core/src/mcp/actions/call-mcp-tool.ts +1 -0
- package/corpus/core/src/server/index.ts +4 -0
- package/corpus/core/src/server/org-admin.ts +28 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +9 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/references/api.md +31 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +9 -0
- package/corpus/templates/analytics/.agents/skills/creative-context/SKILL.md +64 -0
- package/corpus/templates/analytics/AGENTS.md +5 -0
- package/corpus/templates/analytics/actions/clone-creative-context-dashboard.ts +86 -0
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +2 -0
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/analytics/app/i18n-data.ts +1 -0
- package/corpus/templates/analytics/app/pages/Ask.tsx +8 -4
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +59 -0
- package/corpus/templates/analytics/app/routes/agent.tsx +7 -1
- package/corpus/templates/analytics/changelog/2026-07-17-library-now-flags-published-dashboards-with-newer-versions-a.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
- package/corpus/templates/analytics/package.json +1 -0
- package/corpus/templates/analytics/server/lib/native-creative-context.ts +158 -0
- package/corpus/templates/analytics/server/plugins/creative-context.ts +10 -0
- package/corpus/templates/assets/.agents/skills/creative-context/SKILL.md +12 -3
- package/corpus/templates/assets/AGENTS.md +5 -0
- package/corpus/templates/assets/actions/clone-creative-context-asset.ts +74 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +2 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +308 -178
- package/corpus/templates/assets/app/routes/library.tsx +5 -11
- package/corpus/templates/assets/changelog/2026-07-17-library-now-flags-published-assets-with-newer-versions-and-l.md +6 -0
- package/corpus/templates/assets/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
- package/corpus/templates/assets/server/lib/native-creative-context.ts +198 -0
- package/corpus/templates/assets/server/plugins/creative-context.ts +4 -0
- package/corpus/templates/brain/actions/provider-api-request.ts +1 -0
- package/corpus/templates/calendar/actions/provider-api-request.ts +1 -0
- package/corpus/templates/clips/actions/get-recording-insights.ts +7 -4
- package/corpus/templates/clips/actions/list-recordings.ts +48 -0
- package/corpus/templates/clips/actions/list-viewers.ts +2 -1
- package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +3 -1
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +1 -3
- package/corpus/templates/clips/app/hooks/use-desktop-promo.ts +11 -6
- package/corpus/templates/clips/app/hooks/use-view-tracking.ts +6 -1
- package/corpus/templates/clips/app/lib/ffmpeg-export.ts +4 -2
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +21 -3
- package/corpus/templates/clips/changelog/2026-07-17-dictation-keeps-sentence-spacing-and-no-longer-crashes-when-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-17-shared-clips-now-preserve-editor-access-and-show-editor-insi.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-17-stitching-clips-no-longer-fails-when-editor-media-metadata-i.md +6 -0
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +14 -8
- package/corpus/templates/clips/shared/view-analytics.ts +4 -0
- package/corpus/templates/content/.agents/skills/creative-context/SKILL.md +12 -3
- package/corpus/templates/content/AGENTS.md +5 -0
- package/corpus/templates/content/actions/clone-creative-context-document.ts +61 -0
- package/corpus/templates/content/actions/provider-api-request.ts +1 -0
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +21 -0
- package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +29 -0
- package/corpus/templates/content/changelog/2026-07-17-library-now-flags-published-documents-with-newer-versions-an.md +6 -0
- package/corpus/templates/content/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
- package/corpus/templates/content/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
- package/corpus/templates/content/parity/matrix.md +1 -1
- package/corpus/templates/content/parity/matrix.ts +1 -0
- package/corpus/templates/content/server/lib/native-creative-context.ts +191 -0
- package/corpus/templates/content/server/plugins/creative-context.ts +8 -1
- package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +11 -3
- package/corpus/templates/design/AGENTS.md +5 -0
- package/corpus/templates/design/actions/clone-creative-context-design-native.ts +111 -0
- package/corpus/templates/design/actions/provider-api-request.ts +1 -0
- package/corpus/templates/design/app/pages/Index.tsx +44 -0
- package/corpus/templates/design/app/pages/design-editor/types.ts +1 -0
- package/corpus/templates/design/changelog/2026-07-17-library-now-flags-published-designs-with-newer-versions-and-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
- package/corpus/templates/design/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
- package/corpus/templates/design/server/lib/native-creative-context.ts +265 -0
- package/corpus/templates/design/server/plugins/creative-context.ts +8 -1
- package/corpus/templates/dispatch/actions/provider-api-request.ts +1 -0
- package/corpus/templates/mail/actions/provider-api-request.ts +1 -0
- package/corpus/templates/slides/.agents/skills/creative-context/SKILL.md +11 -3
- package/corpus/templates/slides/AGENTS.md +5 -0
- package/corpus/templates/slides/actions/clone-creative-context-deck.ts +96 -0
- package/corpus/templates/slides/actions/extract-pdf.ts +3 -2
- package/corpus/templates/slides/actions/import-file.ts +3 -2
- package/corpus/templates/slides/actions/provider-api-request.ts +1 -0
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +27 -0
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +21 -0
- package/corpus/templates/slides/changelog/2026-07-17-library-now-flags-published-decks-with-newer-versions-and-le.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-17-pdf-and-powerpoint-imports-now-work-reliably-in-hosted-decks.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
- package/corpus/templates/slides/server/lib/native-creative-context.ts +288 -0
- package/corpus/templates/slides/server/plugins/creative-context.ts +4 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +8 -2
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +35 -1
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +7 -0
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +37 -8
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.js +3 -2
- package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
- package/dist/client/resources/McpConnectionSuggestion.d.ts +9 -0
- package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -0
- package/dist/client/resources/McpConnectionSuggestion.js +115 -0
- package/dist/client/resources/McpConnectionSuggestion.js.map +1 -0
- package/dist/client/resources/McpIntegrationDialog.d.ts +2 -1
- package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
- package/dist/client/resources/McpIntegrationDialog.js +48 -20
- package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.d.ts +9 -0
- package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.js +387 -4
- package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
- package/dist/client/resources/mcp-integration-logos.d.ts +2 -0
- package/dist/client/resources/mcp-integration-logos.d.ts.map +1 -0
- package/dist/client/resources/mcp-integration-logos.js +109 -0
- package/dist/client/resources/mcp-integration-logos.js.map +1 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +23 -0
- package/dist/deploy/build.js.map +1 -1
- package/dist/extensions/html-shell.d.ts.map +1 -1
- package/dist/extensions/html-shell.js +33 -1
- package/dist/extensions/html-shell.js.map +1 -1
- package/dist/ingestion/office.d.ts.map +1 -1
- package/dist/ingestion/office.js +1 -2
- package/dist/ingestion/office.js.map +1 -1
- package/dist/ingestion/pptx.js +2 -4
- package/dist/ingestion/pptx.js.map +1 -1
- package/dist/localization/default-messages.d.ts +98 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +99 -1
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp/actions/call-mcp-tool.js +1 -0
- package/dist/mcp/actions/call-mcp-tool.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/org-admin.d.ts +3 -0
- package/dist/server/org-admin.d.ts.map +1 -0
- package/dist/server/org-admin.js +24 -0
- package/dist/server/org-admin.js.map +1 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +9 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +31 -0
- package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +9 -0
- package/docs/content/integrations.mdx +597 -0
- package/docs/content/locales/ar-SA/mcp-clients.mdx +19 -1
- package/docs/content/locales/de-DE/mcp-clients.mdx +22 -1
- package/docs/content/locales/es-ES/mcp-clients.mdx +23 -1
- package/docs/content/locales/fr-FR/mcp-clients.mdx +23 -1
- package/docs/content/locales/hi-IN/mcp-clients.mdx +22 -1
- package/docs/content/locales/ja-JP/mcp-clients.mdx +21 -1
- package/docs/content/locales/ko-KR/mcp-clients.mdx +20 -1
- package/docs/content/locales/pt-BR/mcp-clients.mdx +22 -1
- package/docs/content/locales/zh-CN/mcp-clients.mdx +17 -1
- package/docs/content/locales/zh-TW/mcp-clients.mdx +17 -1
- package/docs/content/mcp-clients.mdx +51 -1
- package/docs/content/organizations-teams-permissions.mdx +413 -0
- package/package.json +1 -1
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +9 -0
- package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +31 -0
- package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +9 -0
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "@tabler/icons-react";
|
|
15
15
|
import React, { useState, useCallback, useEffect } from "react";
|
|
16
16
|
|
|
17
|
+
import { AgentAskPopover } from "../AgentAskPopover.js";
|
|
17
18
|
import { agentNativePath } from "../api-path.js";
|
|
18
19
|
import {
|
|
19
20
|
Tooltip,
|
|
@@ -511,6 +512,14 @@ export function IntegrationsPanel() {
|
|
|
511
512
|
<div className="text-[10px] font-medium text-muted-foreground mb-1.5">
|
|
512
513
|
{t("integrations.addChatIntegration")}
|
|
513
514
|
</div>
|
|
515
|
+
<AgentAskPopover
|
|
516
|
+
label={t("integrations.addSomething")}
|
|
517
|
+
title={t("integrations.addSomethingTitle")}
|
|
518
|
+
placeholder={t("integrations.addSomethingPlaceholder")}
|
|
519
|
+
prompt=""
|
|
520
|
+
context="The user wants to add a chat or workspace integration that is not in the current directory. Research the provider's official OAuth or MCP setup, explain any app registration or allowlist requirements, and add a reusable integration preset when it is supported. Never ask the user to paste credentials into a prompt."
|
|
521
|
+
className="mb-2 h-7 w-full justify-center border-dashed px-2 text-[10px]"
|
|
522
|
+
/>
|
|
514
523
|
<AddIntegrationPicker
|
|
515
524
|
connectedIds={connectedIds}
|
|
516
525
|
onSelect={(p) => {
|
|
@@ -533,17 +542,27 @@ export function IntegrationsPanel() {
|
|
|
533
542
|
{t("integrations.chatIntegrationsDescription")}
|
|
534
543
|
</div>
|
|
535
544
|
</div>
|
|
536
|
-
<
|
|
537
|
-
<
|
|
538
|
-
<
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
545
|
+
<div className="flex items-center gap-1">
|
|
546
|
+
<Tooltip>
|
|
547
|
+
<TooltipTrigger asChild>
|
|
548
|
+
<button
|
|
549
|
+
onClick={() => setShowPicker(true)}
|
|
550
|
+
className="flex h-5 w-5 items-center justify-center rounded text-muted-foreground hover:bg-accent/50 hover:text-foreground"
|
|
551
|
+
>
|
|
552
|
+
<IconPlus size={12} />
|
|
553
|
+
</button>
|
|
554
|
+
</TooltipTrigger>
|
|
555
|
+
<TooltipContent>{t("integrations.addIntegration")}</TooltipContent>
|
|
556
|
+
</Tooltip>
|
|
557
|
+
<AgentAskPopover
|
|
558
|
+
label={t("integrations.addSomething")}
|
|
559
|
+
title={t("integrations.addSomethingTitle")}
|
|
560
|
+
placeholder={t("integrations.addSomethingPlaceholder")}
|
|
561
|
+
prompt=""
|
|
562
|
+
context="The user wants to add a chat or workspace integration that is not in the current directory. Research the provider's official OAuth or MCP setup, explain any app registration or allowlist requirements, and add a reusable integration preset when it is supported. Never ask the user to paste credentials into a prompt."
|
|
563
|
+
className="h-7 px-2 text-[10px]"
|
|
564
|
+
/>
|
|
565
|
+
</div>
|
|
547
566
|
</div>
|
|
548
567
|
|
|
549
568
|
{loading ? (
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IconArrowUpRight,
|
|
3
|
+
IconLoader2,
|
|
4
|
+
IconPlugConnected,
|
|
5
|
+
IconX,
|
|
6
|
+
} from "@tabler/icons-react";
|
|
7
|
+
import { useEffect, useMemo, useState } from "react";
|
|
8
|
+
|
|
9
|
+
import { agentNativePath } from "../api-path.js";
|
|
10
|
+
import { useT } from "../i18n.js";
|
|
11
|
+
import {
|
|
12
|
+
buildMcpOAuthStartUrl,
|
|
13
|
+
findMcpIntegrationForText,
|
|
14
|
+
getDefaultMcpIntegrations,
|
|
15
|
+
isMcpConnectionFailureText,
|
|
16
|
+
type DefaultMcpIntegration,
|
|
17
|
+
} from "./mcp-integration-catalog.js";
|
|
18
|
+
import { McpIntegrationDialog } from "./McpIntegrationDialog.js";
|
|
19
|
+
import {
|
|
20
|
+
useCreateMcpServer,
|
|
21
|
+
useMcpServers,
|
|
22
|
+
type McpServer,
|
|
23
|
+
} from "./use-mcp-servers.js";
|
|
24
|
+
|
|
25
|
+
export type McpConnectionSuggestionVariant = "composer" | "response";
|
|
26
|
+
|
|
27
|
+
interface McpConnectionSuggestionProps {
|
|
28
|
+
text: string;
|
|
29
|
+
contextText?: string;
|
|
30
|
+
variant?: McpConnectionSuggestionVariant;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function compareUrl(value: string): string {
|
|
34
|
+
try {
|
|
35
|
+
const url = new URL(value.trim());
|
|
36
|
+
url.hash = "";
|
|
37
|
+
return url.toString().replace(/\/+$/, "");
|
|
38
|
+
} catch {
|
|
39
|
+
return value.trim().replace(/\/+$/, "");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isConnected(
|
|
44
|
+
integration: DefaultMcpIntegration,
|
|
45
|
+
servers: McpServer[],
|
|
46
|
+
): boolean {
|
|
47
|
+
const targetUrl = compareUrl(integration.url);
|
|
48
|
+
return servers.some(
|
|
49
|
+
(server) =>
|
|
50
|
+
server.status.state === "connected" &&
|
|
51
|
+
compareUrl(server.url) === targetUrl,
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function returnUrl(): string {
|
|
56
|
+
if (typeof window === "undefined") return "/";
|
|
57
|
+
return (
|
|
58
|
+
window.location.pathname + window.location.search + window.location.hash
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function canStartOAuth(integration: DefaultMcpIntegration): boolean {
|
|
63
|
+
return (
|
|
64
|
+
integration.authMode === "oauth" &&
|
|
65
|
+
integration.connectionMode === "oauth" &&
|
|
66
|
+
integration.availability === "ready"
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function McpConnectionSuggestion({
|
|
71
|
+
text,
|
|
72
|
+
contextText = "",
|
|
73
|
+
variant = "composer",
|
|
74
|
+
}: McpConnectionSuggestionProps) {
|
|
75
|
+
const t = useT();
|
|
76
|
+
const mcpServersQuery = useMcpServers();
|
|
77
|
+
const createMcpServer = useCreateMcpServer();
|
|
78
|
+
const [dialogOpen, setDialogOpen] = useState(false);
|
|
79
|
+
const [dismissedId, setDismissedId] = useState<string | null>(null);
|
|
80
|
+
const [connecting, setConnecting] = useState(false);
|
|
81
|
+
const [error, setError] = useState<string | null>(null);
|
|
82
|
+
const integrations = useMemo(() => getDefaultMcpIntegrations(), []);
|
|
83
|
+
const textIntegration = useMemo(
|
|
84
|
+
() => findMcpIntegrationForText(text, integrations),
|
|
85
|
+
[integrations, text],
|
|
86
|
+
);
|
|
87
|
+
const contextIntegration = useMemo(
|
|
88
|
+
() =>
|
|
89
|
+
contextText ? findMcpIntegrationForText(contextText, integrations) : null,
|
|
90
|
+
[contextText, integrations],
|
|
91
|
+
);
|
|
92
|
+
const integration =
|
|
93
|
+
variant === "response" &&
|
|
94
|
+
textIntegration &&
|
|
95
|
+
contextIntegration &&
|
|
96
|
+
textIntegration.id !== contextIntegration.id
|
|
97
|
+
? null
|
|
98
|
+
: (textIntegration ?? contextIntegration);
|
|
99
|
+
const servers = useMemo(
|
|
100
|
+
() => [
|
|
101
|
+
...(mcpServersQuery.data?.user ?? []),
|
|
102
|
+
...(mcpServersQuery.data?.org ?? []),
|
|
103
|
+
],
|
|
104
|
+
[mcpServersQuery.data],
|
|
105
|
+
);
|
|
106
|
+
const connected = integration ? isConnected(integration, servers) : false;
|
|
107
|
+
const shouldSuggest =
|
|
108
|
+
mcpServersQuery.isSuccess &&
|
|
109
|
+
integration &&
|
|
110
|
+
!connected &&
|
|
111
|
+
dismissedId !== integration.id &&
|
|
112
|
+
(variant === "composer" || isMcpConnectionFailureText(text));
|
|
113
|
+
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
setError(null);
|
|
116
|
+
setConnecting(false);
|
|
117
|
+
}, [integration?.id, variant]);
|
|
118
|
+
|
|
119
|
+
if (!shouldSuggest) return null;
|
|
120
|
+
|
|
121
|
+
const connect = async () => {
|
|
122
|
+
if (!integration || connecting) return;
|
|
123
|
+
setError(null);
|
|
124
|
+
|
|
125
|
+
if (canStartOAuth(integration)) {
|
|
126
|
+
window.location.assign(
|
|
127
|
+
agentNativePath(
|
|
128
|
+
buildMcpOAuthStartUrl({
|
|
129
|
+
name: integration.name,
|
|
130
|
+
url: integration.url,
|
|
131
|
+
description: integration.description,
|
|
132
|
+
scope: "user",
|
|
133
|
+
returnUrl: returnUrl(),
|
|
134
|
+
}),
|
|
135
|
+
),
|
|
136
|
+
);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (
|
|
141
|
+
integration.authMode === "none" &&
|
|
142
|
+
integration.connectionMode === "direct"
|
|
143
|
+
) {
|
|
144
|
+
setConnecting(true);
|
|
145
|
+
try {
|
|
146
|
+
await createMcpServer.mutateAsync({
|
|
147
|
+
scope: "user",
|
|
148
|
+
name: integration.name,
|
|
149
|
+
url: integration.url,
|
|
150
|
+
description: integration.description,
|
|
151
|
+
});
|
|
152
|
+
setDismissedId(integration.id);
|
|
153
|
+
} catch (cause) {
|
|
154
|
+
setError(
|
|
155
|
+
cause instanceof Error ? cause.message : t("mcpIntegrations.failed"),
|
|
156
|
+
);
|
|
157
|
+
} finally {
|
|
158
|
+
setConnecting(false);
|
|
159
|
+
}
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
setDialogOpen(true);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const actionLabel = canStartOAuth(integration)
|
|
167
|
+
? t("mcpIntegrations.connectWithOAuth")
|
|
168
|
+
: integration.availability === "client-restricted" ||
|
|
169
|
+
integration.availability === "provider-setup"
|
|
170
|
+
? t("mcpIntegrations.viewSetup")
|
|
171
|
+
: t("mcpIntegrations.connect");
|
|
172
|
+
|
|
173
|
+
return (
|
|
174
|
+
<>
|
|
175
|
+
<div
|
|
176
|
+
className={
|
|
177
|
+
variant === "response"
|
|
178
|
+
? "mt-3 flex max-w-[520px] items-center gap-2 rounded-lg border border-primary/20 bg-primary/5 px-3 py-2 text-[12px]"
|
|
179
|
+
: "mx-auto mb-2 flex w-[min(100%,680px)] items-center gap-2 rounded-lg border border-primary/20 bg-primary/5 px-3 py-2 text-[12px]"
|
|
180
|
+
}
|
|
181
|
+
data-mcp-connection-suggestion={integration.id}
|
|
182
|
+
>
|
|
183
|
+
<div className="relative flex h-6 w-6 shrink-0 items-center justify-center overflow-hidden rounded-md border border-border bg-background text-[10px] font-semibold text-muted-foreground">
|
|
184
|
+
<span aria-hidden="true">{integration.name.slice(0, 1)}</span>
|
|
185
|
+
{integration.logoUrl && (
|
|
186
|
+
<img
|
|
187
|
+
src={integration.logoUrl}
|
|
188
|
+
alt=""
|
|
189
|
+
className="absolute h-5 w-5 object-contain"
|
|
190
|
+
onError={(event) => {
|
|
191
|
+
event.currentTarget.hidden = true;
|
|
192
|
+
}}
|
|
193
|
+
/>
|
|
194
|
+
)}
|
|
195
|
+
</div>
|
|
196
|
+
<span className="min-w-0 flex-1 leading-snug text-foreground">
|
|
197
|
+
{t("mcpIntegrations.connectSuggestion", { name: integration.name })}
|
|
198
|
+
</span>
|
|
199
|
+
<button
|
|
200
|
+
type="button"
|
|
201
|
+
onClick={() => void connect()}
|
|
202
|
+
disabled={connecting}
|
|
203
|
+
className="inline-flex shrink-0 items-center gap-1 rounded-md bg-primary px-2.5 py-1.5 text-[11px] font-medium text-primary-foreground hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-60"
|
|
204
|
+
>
|
|
205
|
+
{connecting && <IconLoader2 className="h-3 w-3 animate-spin" />}
|
|
206
|
+
{!connecting && canStartOAuth(integration) && (
|
|
207
|
+
<IconPlugConnected className="h-3 w-3" />
|
|
208
|
+
)}
|
|
209
|
+
{actionLabel}
|
|
210
|
+
{!connecting && !canStartOAuth(integration) && (
|
|
211
|
+
<IconArrowUpRight className="h-3 w-3" />
|
|
212
|
+
)}
|
|
213
|
+
</button>
|
|
214
|
+
<button
|
|
215
|
+
type="button"
|
|
216
|
+
onClick={() => setDismissedId(integration.id)}
|
|
217
|
+
className="inline-flex h-6 w-6 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-background hover:text-foreground"
|
|
218
|
+
aria-label={t("mcpIntegrations.dismissSuggestion")}
|
|
219
|
+
>
|
|
220
|
+
<IconX className="h-3.5 w-3.5" />
|
|
221
|
+
</button>
|
|
222
|
+
</div>
|
|
223
|
+
{error && (
|
|
224
|
+
<div className="mx-auto mb-2 w-[min(100%,680px)] text-[11px] text-destructive">
|
|
225
|
+
{error}
|
|
226
|
+
</div>
|
|
227
|
+
)}
|
|
228
|
+
<McpIntegrationDialog
|
|
229
|
+
open={dialogOpen}
|
|
230
|
+
onOpenChange={setDialogOpen}
|
|
231
|
+
initialIntegrationId={integration.id}
|
|
232
|
+
defaultScope="user"
|
|
233
|
+
canCreateOrgMcp={false}
|
|
234
|
+
hasOrg={Boolean(mcpServersQuery.data?.orgId)}
|
|
235
|
+
onCreateMcpServer={(args) => createMcpServer.mutateAsync(args)}
|
|
236
|
+
onCreated={() => setDismissedId(integration.id)}
|
|
237
|
+
/>
|
|
238
|
+
</>
|
|
239
|
+
);
|
|
240
|
+
}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
} from "@tabler/icons-react";
|
|
8
8
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
9
9
|
|
|
10
|
+
import { AgentAskPopover } from "../AgentAskPopover.js";
|
|
10
11
|
import { agentNativePath } from "../api-path.js";
|
|
11
12
|
import {
|
|
12
13
|
Dialog,
|
|
@@ -45,6 +46,7 @@ type DialogMode = "catalog" | "form";
|
|
|
45
46
|
interface McpIntegrationDialogProps {
|
|
46
47
|
open: boolean;
|
|
47
48
|
onOpenChange: (open: boolean) => void;
|
|
49
|
+
initialIntegrationId?: string | null;
|
|
48
50
|
defaultScope: McpServerScope;
|
|
49
51
|
canCreateOrgMcp: boolean;
|
|
50
52
|
hasOrg: boolean;
|
|
@@ -85,6 +87,7 @@ function compareUrl(value: string): string {
|
|
|
85
87
|
export function McpIntegrationDialog({
|
|
86
88
|
open,
|
|
87
89
|
onOpenChange,
|
|
90
|
+
initialIntegrationId = null,
|
|
88
91
|
defaultScope,
|
|
89
92
|
canCreateOrgMcp,
|
|
90
93
|
hasOrg,
|
|
@@ -138,21 +141,41 @@ export function McpIntegrationDialog({
|
|
|
138
141
|
[defaultIntegrations, query],
|
|
139
142
|
);
|
|
140
143
|
|
|
144
|
+
const selectedRequiresSetup = Boolean(
|
|
145
|
+
selected &&
|
|
146
|
+
(selected.connectionMode === "manual" ||
|
|
147
|
+
selected.availability === "provider-setup" ||
|
|
148
|
+
selected.availability === "client-restricted"),
|
|
149
|
+
);
|
|
150
|
+
|
|
141
151
|
useEffect(() => {
|
|
142
152
|
if (!open) return;
|
|
143
|
-
|
|
153
|
+
const initialIntegration = initialIntegrationId
|
|
154
|
+
? defaultIntegrations.find(
|
|
155
|
+
(integration) => integration.id === initialIntegrationId,
|
|
156
|
+
)
|
|
157
|
+
: null;
|
|
158
|
+
const initialDefaults =
|
|
159
|
+
createMcpIntegrationFormDefaults(initialIntegration);
|
|
160
|
+
setMode(initialIntegration || !showCatalog ? "form" : "catalog");
|
|
144
161
|
setQuery("");
|
|
145
|
-
setSelected(null);
|
|
162
|
+
setSelected(initialIntegration ?? null);
|
|
146
163
|
setScope(safeDefaultScope);
|
|
147
|
-
setName(
|
|
148
|
-
setUrl(
|
|
149
|
-
setDescription(
|
|
150
|
-
setHeadersText(
|
|
164
|
+
setName(initialDefaults.name);
|
|
165
|
+
setUrl(initialDefaults.url);
|
|
166
|
+
setDescription(initialDefaults.description);
|
|
167
|
+
setHeadersText(initialDefaults.headersText);
|
|
151
168
|
setBusy(false);
|
|
152
169
|
setQuickBusyId(null);
|
|
153
170
|
setError(null);
|
|
154
171
|
setTestResult(null);
|
|
155
|
-
}, [
|
|
172
|
+
}, [
|
|
173
|
+
defaultIntegrations,
|
|
174
|
+
initialIntegrationId,
|
|
175
|
+
open,
|
|
176
|
+
safeDefaultScope,
|
|
177
|
+
showCatalog,
|
|
178
|
+
]);
|
|
156
179
|
|
|
157
180
|
useEffect(() => {
|
|
158
181
|
if (open && mode === "form") {
|
|
@@ -268,6 +291,12 @@ export function McpIntegrationDialog({
|
|
|
268
291
|
};
|
|
269
292
|
|
|
270
293
|
const quickConnect = (integration: DefaultMcpIntegration) => {
|
|
294
|
+
if (
|
|
295
|
+
integration.connectionMode === "manual" ||
|
|
296
|
+
integration.availability === "provider-setup"
|
|
297
|
+
) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
271
300
|
if (integration.authMode === "oauth") {
|
|
272
301
|
connectWithOAuth(integration);
|
|
273
302
|
return;
|
|
@@ -399,6 +428,14 @@ export function McpIntegrationDialog({
|
|
|
399
428
|
>
|
|
400
429
|
{t("mcpIntegrations.addYourOwn")}
|
|
401
430
|
</button>
|
|
431
|
+
<AgentAskPopover
|
|
432
|
+
label={t("mcpIntegrations.addSomething")}
|
|
433
|
+
title={t("mcpIntegrations.addSomethingTitle")}
|
|
434
|
+
placeholder={t("mcpIntegrations.addSomethingPlaceholder")}
|
|
435
|
+
prompt=""
|
|
436
|
+
context="The user wants to add an MCP or provider integration that is not in the current directory. Research the provider's official remote MCP endpoint and OAuth, client-registration, or allowlist requirements. Prefer Streamable HTTP endpoints over legacy SSE, reuse an existing provider OAuth connector when appropriate, and never ask the user to paste credentials into a prompt. If this should become a reusable preset, update the integration catalog, official docs link, bundled logo, localization, and tests."
|
|
437
|
+
className="h-9 whitespace-nowrap border-dashed px-3 text-[12px] font-medium"
|
|
438
|
+
/>
|
|
402
439
|
</div>
|
|
403
440
|
<div className="min-h-0 flex-1 overflow-y-auto px-7 pb-7">
|
|
404
441
|
{error && (
|
|
@@ -412,42 +449,101 @@ export function McpIntegrationDialog({
|
|
|
412
449
|
compareUrl(integration.url),
|
|
413
450
|
);
|
|
414
451
|
const requiresHeaders = integration.authMode === "headers";
|
|
452
|
+
const setupOnly =
|
|
453
|
+
integration.connectionMode === "manual" ||
|
|
454
|
+
integration.availability === "provider-setup" ||
|
|
455
|
+
integration.availability === "client-restricted";
|
|
415
456
|
return (
|
|
416
457
|
<article
|
|
417
458
|
key={integration.id}
|
|
418
459
|
className="flex min-h-[128px] flex-col rounded-md border border-border bg-card p-4 transition-colors hover:border-border/80 hover:bg-accent/20"
|
|
419
460
|
>
|
|
420
|
-
<
|
|
421
|
-
|
|
422
|
-
|
|
461
|
+
<div className="flex items-center gap-3">
|
|
462
|
+
<div className="relative flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-md border border-border bg-background text-[11px] font-semibold text-muted-foreground">
|
|
463
|
+
<span aria-hidden="true">
|
|
464
|
+
{integration.name.slice(0, 1)}
|
|
465
|
+
</span>
|
|
466
|
+
<img
|
|
467
|
+
src={integration.logoUrl}
|
|
468
|
+
alt=""
|
|
469
|
+
loading="lazy"
|
|
470
|
+
decoding="async"
|
|
471
|
+
className="absolute inset-1 h-6 w-6 object-contain"
|
|
472
|
+
onError={(event) => {
|
|
473
|
+
event.currentTarget.hidden = true;
|
|
474
|
+
}}
|
|
475
|
+
/>
|
|
476
|
+
</div>
|
|
477
|
+
<div className="min-w-0">
|
|
478
|
+
<h3 className="truncate text-[13px] font-semibold text-foreground">
|
|
479
|
+
{integration.name}
|
|
480
|
+
</h3>
|
|
481
|
+
{integration.availability !== "ready" && (
|
|
482
|
+
<span className="mt-0.5 inline-flex rounded-full border border-amber-500/20 bg-amber-500/5 px-1.5 py-0.5 text-[9px] font-medium text-amber-700 dark:text-amber-300">
|
|
483
|
+
{integration.availability === "beta"
|
|
484
|
+
? t("mcpIntegrations.status.beta")
|
|
485
|
+
: integration.availability ===
|
|
486
|
+
"client-restricted"
|
|
487
|
+
? t("mcpIntegrations.status.clientRestricted")
|
|
488
|
+
: t("mcpIntegrations.status.setupRequired")}
|
|
489
|
+
</span>
|
|
490
|
+
)}
|
|
491
|
+
<span className="ms-1 mt-0.5 inline-flex rounded-full border border-border/70 bg-muted/40 px-1.5 py-0.5 text-[9px] font-medium text-muted-foreground">
|
|
492
|
+
{integration.verification === "verified"
|
|
493
|
+
? t("mcpIntegrations.status.verified")
|
|
494
|
+
: integration.verification === "restricted"
|
|
495
|
+
? t("mcpIntegrations.status.restricted")
|
|
496
|
+
: t("mcpIntegrations.status.preflightOnly")}
|
|
497
|
+
</span>
|
|
498
|
+
</div>
|
|
499
|
+
</div>
|
|
423
500
|
<p className="mt-1 line-clamp-2 flex-1 text-[12px] leading-relaxed text-muted-foreground">
|
|
424
501
|
{t(integration.descriptionKey)}
|
|
425
502
|
</p>
|
|
503
|
+
{integration.setupNoteKey && (
|
|
504
|
+
<p className="mt-2 line-clamp-3 text-[10px] leading-relaxed text-amber-700 dark:text-amber-300">
|
|
505
|
+
{t(integration.setupNoteKey)}
|
|
506
|
+
</p>
|
|
507
|
+
)}
|
|
426
508
|
<div className="mt-3 flex items-center gap-2">
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
connected
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
509
|
+
{connected ? (
|
|
510
|
+
<button
|
|
511
|
+
type="button"
|
|
512
|
+
disabled
|
|
513
|
+
className="inline-flex h-8 flex-1 cursor-not-allowed items-center justify-center gap-1.5 rounded-md border border-border bg-muted px-2.5 text-[12px] font-medium text-muted-foreground opacity-70"
|
|
514
|
+
>
|
|
515
|
+
{t("mcpIntegrations.connected")}
|
|
516
|
+
</button>
|
|
517
|
+
) : setupOnly ? (
|
|
518
|
+
<a
|
|
519
|
+
href={integration.docsUrl}
|
|
520
|
+
target="_blank"
|
|
521
|
+
rel="noopener noreferrer"
|
|
522
|
+
className="inline-flex h-8 flex-1 items-center justify-center gap-1.5 rounded-md border border-border bg-background px-2.5 text-[12px] font-medium text-foreground hover:bg-accent"
|
|
523
|
+
>
|
|
524
|
+
{t("mcpIntegrations.viewSetup")}
|
|
525
|
+
<IconExternalLink className="h-3.5 w-3.5" />
|
|
526
|
+
</a>
|
|
527
|
+
) : (
|
|
528
|
+
<button
|
|
529
|
+
type="button"
|
|
530
|
+
onClick={() => quickConnect(integration)}
|
|
531
|
+
disabled={busy}
|
|
532
|
+
className={cn(
|
|
533
|
+
"inline-flex h-8 flex-1 items-center justify-center gap-1.5 rounded-md bg-primary px-2.5 text-[12px] font-medium text-primary-foreground hover:bg-primary/90",
|
|
534
|
+
busy && "cursor-not-allowed opacity-70",
|
|
535
|
+
)}
|
|
536
|
+
>
|
|
537
|
+
{quickBusyId === integration.id ? (
|
|
538
|
+
<IconLoader2 className="h-3.5 w-3.5 animate-spin" />
|
|
539
|
+
) : null}
|
|
540
|
+
{integration.authMode === "oauth"
|
|
446
541
|
? t("mcpIntegrations.connectWithOAuth")
|
|
447
542
|
: requiresHeaders
|
|
448
543
|
? t("mcpIntegrations.configure")
|
|
449
544
|
: t("mcpIntegrations.connect")}
|
|
450
|
-
|
|
545
|
+
</button>
|
|
546
|
+
)}
|
|
451
547
|
{integration.docsUrl && (
|
|
452
548
|
<Tooltip>
|
|
453
549
|
<TooltipTrigger asChild>
|
|
@@ -638,7 +734,16 @@ export function McpIntegrationDialog({
|
|
|
638
734
|
>
|
|
639
735
|
{t("mcpIntegrations.test")}
|
|
640
736
|
</button>
|
|
641
|
-
{
|
|
737
|
+
{selected?.authMode === "oauth" && !selectedRequiresSetup ? (
|
|
738
|
+
<button
|
|
739
|
+
type="button"
|
|
740
|
+
onClick={() => connectWithOAuth(selected)}
|
|
741
|
+
disabled={!name.trim() || !url.trim() || busy}
|
|
742
|
+
className="rounded-md border border-border bg-background px-3 py-1.5 text-[12px] font-medium text-foreground hover:bg-accent disabled:pointer-events-none disabled:opacity-40"
|
|
743
|
+
>
|
|
744
|
+
{t("mcpIntegrations.connectWithOAuth")}
|
|
745
|
+
</button>
|
|
746
|
+
) : !selected ? (
|
|
642
747
|
<button
|
|
643
748
|
type="button"
|
|
644
749
|
onClick={connectCustomWithOAuth}
|
|
@@ -647,16 +752,30 @@ export function McpIntegrationDialog({
|
|
|
647
752
|
>
|
|
648
753
|
{t("mcpIntegrations.connectWithOAuth")}
|
|
649
754
|
</button>
|
|
755
|
+
) : null}
|
|
756
|
+
{selectedRequiresSetup ? (
|
|
757
|
+
selected?.docsUrl ? (
|
|
758
|
+
<a
|
|
759
|
+
href={selected.docsUrl}
|
|
760
|
+
target="_blank"
|
|
761
|
+
rel="noopener noreferrer"
|
|
762
|
+
className="inline-flex min-w-[92px] items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-[12px] font-medium text-primary-foreground hover:bg-primary/90"
|
|
763
|
+
>
|
|
764
|
+
{t("mcpIntegrations.viewSetup")}
|
|
765
|
+
<IconExternalLink className="h-3 w-3" />
|
|
766
|
+
</a>
|
|
767
|
+
) : null
|
|
768
|
+
) : (
|
|
769
|
+
<button
|
|
770
|
+
type="button"
|
|
771
|
+
onClick={submitForm}
|
|
772
|
+
disabled={!name.trim() || !url.trim() || busy}
|
|
773
|
+
className="inline-flex min-w-[92px] items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-[12px] font-medium text-primary-foreground hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-40"
|
|
774
|
+
>
|
|
775
|
+
{busy && <IconLoader2 className="h-3.5 w-3.5 animate-spin" />}
|
|
776
|
+
{t("mcpIntegrations.connect")}
|
|
777
|
+
</button>
|
|
650
778
|
)}
|
|
651
|
-
<button
|
|
652
|
-
type="button"
|
|
653
|
-
onClick={submitForm}
|
|
654
|
-
disabled={!name.trim() || !url.trim() || busy}
|
|
655
|
-
className="inline-flex min-w-[92px] items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-[12px] font-medium text-primary-foreground hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-40"
|
|
656
|
-
>
|
|
657
|
-
{busy && <IconLoader2 className="h-3.5 w-3.5 animate-spin" />}
|
|
658
|
-
{t("mcpIntegrations.connect")}
|
|
659
|
-
</button>
|
|
660
779
|
</div>
|
|
661
780
|
</>
|
|
662
781
|
)}
|