Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions apps/docs/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ interface LucidIconProps extends SVGProps<SVGSVGElement> {}
export function LucidIcon(props: LucidIconProps) {
return (
<svg {...props} viewBox='0 0 192 192' fill='none' xmlns='http://www.w3.org/2000/svg'>
<rect width='192' height='192' rx='32' fill='#282C33' />
<g transform='translate(46 24)' fill='#FFFFFF'>
<g transform='translate(46 24)' fill='currentColor'>
<path d='M50 0L0 28.9V144.5L50 115.6V0Z' />
<path d='M100 142.7V86.7L50 115.6V142.7H100Z' />
</g>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export function LiveMemberIntegrations({ organizationId, search }: LiveMemberInt
)
const available = LIVE_SEARCH_SOURCE_TYPES.filter(
([provider]) =>
(approvals.get(provider)?.available !== false || accountsForProvider(provider).length > 0) &&
LIVE_SEARCH_SCOPE_FIELDS[provider] &&
((provider !== 'hubspot' && provider !== 'zoom') ||
data.availableMcpConnectors.includes(provider) ||
Expand Down Expand Up @@ -130,6 +131,7 @@ export function LiveMemberIntegrations({ organizationId, search }: LiveMemberInt
: undefined
const accounts = accountsForProvider(provider)
const ready =
approval?.available !== false &&
group?.status === 'active' &&
Boolean(option || server) &&
approved &&
Expand All @@ -140,15 +142,18 @@ export function LiveMemberIntegrations({ organizationId, search }: LiveMemberInt
approval?.policy?.accessMode === 'service_account'
? 'Selected resources you can access'
: 'All accessible content'
const state = !approved
? 'Disabled by your organization'
: group && group.status !== 'active'
? 'Connections are paused by your organization'
: !ready
? 'Not configured'
: accounts.length
? scope
: undefined
const state =
approval?.available === false
? 'Currently unavailable'
: !approved
? 'Disabled by your organization'
: group && group.status !== 'active'
? 'Connections are paused by your organization'
: !ready
? 'Not configured'
: accounts.length
? scope
: undefined
const description = [
accounts
.map(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ export function LiveSearchSettings() {
secretSource && GENERIC_SECRETS_META.name.toLowerCase().includes(search.toLowerCase())
const availableToAdd = [
...LIVE_SEARCH_SOURCE_TYPES.filter(
([type]) => LIVE_SEARCH_SCOPE_FIELDS[type] && !added.some((row) => row.connectorType === type)
([type]) =>
(type !== 'zoom' ||
policies.data?.some((row) => row.connectorType === type && row.available !== false)) &&
LIVE_SEARCH_SCOPE_FIELDS[type] &&
!added.some((row) => row.connectorType === type)
).map(([type, meta]) => ({
type,
meta,
Expand Down Expand Up @@ -160,6 +164,7 @@ export function LiveSearchSettings() {
const mcpProvider = liveSearchMcpConnector(type)
const group = accounts.data?.credentialGroup
const needsMemberSetup =
integration.available !== false &&
accounts.data &&
(memberProvider || mcpProvider) &&
(group?.status !== 'active' ||
Expand Down Expand Up @@ -188,7 +193,7 @@ export function LiveSearchSettings() {
iconVariant='custom'
icon={<IntegrationTile blockType={type} icon={meta.icon} />}
title={meta.name}
description={scope}
description={integration.available === false ? 'Currently unavailable' : scope}
trailing={
<div className='flex gap-2'>
{serviceAccount && (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { ComponentType } from 'react'
import { cn } from '@sim/emcn'
import { getManagedMcpConnectorBgColor } from '@/lib/credential-groups/managed-mcp-connectors'
import { BrandTile } from '@/app/workspace/[workspaceId]/components/resource-tile'
import { getBlock } from '@/blocks'
import { getTileIconColorClass } from '@/blocks/icon-color'
Expand Down Expand Up @@ -47,11 +48,11 @@ const SHOWCASE_TILES = [
] as const

/**
* Resolves the brand background color for a block type from the block registry.
* Returns `null` when the block is unknown or has no brand color configured.
* Resolves the brand background color for workflow blocks and managed MCP connectors.
* Returns `null` when neither catalog provides a brand color.
*/
function resolveBrandTileBg(blockType: string): string | null {
return getBlock(blockType)?.bgColor || null
return getBlock(blockType)?.bgColor || getManagedMcpConnectorBgColor(blockType) || null
}

interface IntegrationTileProps {
Expand All @@ -61,7 +62,7 @@ interface IntegrationTileProps {
}

/**
* Brand-colored square tile that renders a block's icon. The unframed variant
* Brand-colored square tile that renders an integration's icon. The unframed variant
* is a 36px tile used in list rows and headers; the framed variant adds an
* outer 44px halo used inside the showcase grid.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { useParams } from 'next/navigation'
import { McpIcon, WorkflowIcon } from '@/components/icons'
import { McpOperationPolicyEditor } from '@/components/mcp/operation-policy-editor'
import { getManagedMcpConnectorIcon } from '@/lib/credential-groups/managed-mcp-connector-icons'
import { getManagedMcpConnectorBgColor } from '@/lib/credential-groups/managed-mcp-connectors'
import { MCP_SERVER_ADVANCED_TOOL_TYPE } from '@/lib/mcp/shared'
import {
getIssueBadgeLabel,
Expand Down Expand Up @@ -1200,7 +1201,10 @@ export const ToolInput = memo(function ToolInput({
serverToolItems.push({
label: 'Configure operations access',
value: `mcp-server-all-${mcpServerDrilldown}`,
iconElement: createToolIcon('var(--brand-agent)', ServerIcon),
iconElement: createToolIcon(
getManagedMcpConnectorBgColor(server?.managedConnectorId) ?? 'var(--brand-agent)',
ServerIcon
),
onSelect: () => {
if (allAlreadySelected) return
const filteredTools = selectedTools.filter(
Expand Down Expand Up @@ -1350,7 +1354,10 @@ export const ToolInput = memo(function ToolInput({
serverItems.push({
label: `${serverName} (${toolCount} tools)`,
value: `mcp-server-folder-${serverId}`,
iconElement: createToolIcon('#6366F1', ServerIcon),
iconElement: createToolIcon(
getManagedMcpConnectorBgColor(server.managedConnectorId) ?? '#6366F1',
ServerIcon
),
suffixElement: <ChevronRight className='size-[12px] text-[var(--text-tertiary)]' />,
onSelect: () => {
setMcpServerDrilldown(serverId)
Expand Down Expand Up @@ -1572,7 +1579,10 @@ export const ToolInput = memo(function ToolInput({
: advancedMcpServer?.managedConnectorId
? getManagedMcpConnectorIcon(advancedMcpServer.managedConnectorId)
: McpIcon
const mcpTileColor = mcpTool?.bgColor || 'var(--brand-agent)'
const mcpTileColor =
mcpTool?.bgColor ||
getManagedMcpConnectorBgColor(advancedMcpServer?.managedConnectorId) ||
'var(--brand-agent)'
const mcpToolSchema = isMcpTool ? tool.schema || mcpTool?.inputSchema : null

// Canonical name wins; stored title only when nothing resolves
Expand Down
3 changes: 1 addition & 2 deletions apps/sim/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ interface LucidIconProps extends SVGProps<SVGSVGElement> {}
export function LucidIcon(props: LucidIconProps) {
return (
<svg {...props} viewBox='0 0 192 192' fill='none' xmlns='http://www.w3.org/2000/svg'>
<rect width='192' height='192' rx='32' fill='#282C33' />
<g transform='translate(46 24)' fill='#FFFFFF'>
<g transform='translate(46 24)' fill='currentColor'>
<path d='M50 0L0 28.9V144.5L50 115.6V0Z' />
<path d='M100 142.7V86.7L50 115.6V142.7H100Z' />
</g>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import type { ComponentType } from 'react'
import { getIntegrationTypesForOAuthServiceId } from '@sim/deployment-config/integration-availability'
import { INTEGRATION_METADATA } from '@sim/deployment-config/integration-metadata'
import type { ManagedMcpConnectorId } from '@/lib/credential-groups/managed-mcp-connectors'
import {
getManagedMcpConnectorBgColor,
type ManagedMcpConnectorId,
} from '@/lib/credential-groups/managed-mcp-connectors'
import type { CredentialGroupProvider } from '@/lib/credential-groups/providers'
import { blockTypeToIconMap } from '@/lib/integrations/icon-mapping'
import { BrandTile } from '@/app/workspace/[workspaceId]/components/resource-tile'
Expand All @@ -18,7 +21,9 @@ export function CredentialGroupProviderTile({ provider, icon }: CredentialGroupP
return (
<BrandTile
icon={blockTypeToIconMap[blockType] ?? icon}
background={INTEGRATION_BY_TYPE.get(blockType)?.bgColor}
background={
INTEGRATION_BY_TYPE.get(blockType)?.bgColor ?? getManagedMcpConnectorBgColor(provider)
}
/>
)
}
3 changes: 2 additions & 1 deletion apps/sim/hooks/mcp/use-mcp-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { createLogger } from '@sim/logger'
import { useQueryClient } from '@tanstack/react-query'
import { McpIcon } from '@/components/icons'
import { getManagedMcpConnectorIcon } from '@/lib/credential-groups/managed-mcp-connector-icons'
import { getManagedMcpConnectorBgColor } from '@/lib/credential-groups/managed-mcp-connectors'
import { createMcpToolId } from '@/lib/mcp/shared'
import type { McpToolSchema } from '@/lib/mcp/types'
import { useMcpToolsQuery } from '@/hooks/queries/mcp'
Expand Down Expand Up @@ -54,7 +55,7 @@ export function useMcpTools(workspaceId: string): UseMcpToolsResult {
serverName: tool.serverName,
type: 'mcp' as const,
inputSchema: tool.inputSchema,
bgColor: '#6366F1',
bgColor: getManagedMcpConnectorBgColor(tool.managedConnectorId) ?? '#6366F1',
icon: tool.managedConnectorId ? getManagedMcpConnectorIcon(tool.managedConnectorId) : McpIcon,
}))
}, [mcpToolsData])
Expand Down
7 changes: 6 additions & 1 deletion apps/sim/lib/api/contracts/knowledge/search-integrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ export const searchIntegrationApprovalSchema = z.object({
})
export type SearchIntegrationApproval = z.output<typeof searchIntegrationApprovalSchema>

export const searchIntegrationStatusSchema = searchIntegrationApprovalSchema.extend({
available: z.boolean().optional(),
})
export type SearchIntegrationStatus = z.output<typeof searchIntegrationStatusSchema>

export const listSearchIntegrationsQuerySchema = z.object({ organizationId: organizationIdSchema })
export type ListSearchIntegrationsQuery = z.input<typeof listSearchIntegrationsQuerySchema>
export const listSearchIntegrationsContract = defineRouteContract({
Expand All @@ -19,7 +24,7 @@ export const listSearchIntegrationsContract = defineRouteContract({
query: listSearchIntegrationsQuerySchema,
response: {
mode: 'json',
schema: successResponseSchema(z.array(searchIntegrationApprovalSchema).max(100)),
schema: successResponseSchema(z.array(searchIntegrationStatusSchema).max(100)),
},
})

Expand Down
7 changes: 5 additions & 2 deletions apps/sim/lib/api/contracts/mothership-search-sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import {
searchSourcePageSchema,
searchSourceSummarySchema,
} from '@/lib/api/contracts/knowledge/connectors'
import { searchIntegrationApprovalSchema } from '@/lib/api/contracts/knowledge/search-integrations'
import {
searchIntegrationApprovalSchema,
searchIntegrationStatusSchema,
} from '@/lib/api/contracts/knowledge/search-integrations'

const connectorTypeSchema = z.string().trim().min(1).max(100)

Expand Down Expand Up @@ -36,7 +39,7 @@ export const organizationSearchSourcesOutputSchema = z.discriminatedUnion('actio
z.object({ action: z.literal('get'), source: searchSourceSummarySchema }),
z.object({
action: z.literal('providers'),
providers: z.array(searchIntegrationApprovalSchema).max(100),
providers: z.array(searchIntegrationStatusSchema).max(100),
}),
z.object({
action: z.literal('setup'),
Expand Down
1 change: 1 addition & 0 deletions apps/sim/lib/core/config/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,7 @@ export const env = createEnv({
INSTAGRAM_CLIENT_SECRET: z.string().optional(), // Instagram App Secret (Business Login)
SHOPIFY_CLIENT_ID: z.string().optional(), // Shopify OAuth client ID
SHOPIFY_CLIENT_SECRET: z.string().optional(), // Shopify OAuth client secret
ZOOM_SEARCH: z.boolean().optional(),
ZOOM_MCP_CLIENT_ID: z.string().optional(), // Zoom Search MCP OAuth client ID
ZOOM_MCP_CLIENT_SECRET: z.string().optional(), // Zoom Search MCP OAuth client secret
ZOOM_CLIENT_ID: z.string().optional(), // Zoom OAuth client ID
Expand Down
5 changes: 5 additions & 0 deletions apps/sim/lib/core/config/feature-flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ const FEATURE_FLAGS = {
'Capture durable Workflow Agent tool history and continue existing retries. Supports workspace rollout targeting; version-aware memory storage remains active when capture is disabled.',
fallback: 'AGENT_MEMORY_HISTORY',
},
'zoom-search': {
description:
'Enable Zoom Search setup, personal authorization and retrieval. Organization targeting only; disabled by default. Standard workflow Zoom OAuth is unchanged.',
fallback: 'ZOOM_SEARCH',
},
'slack-search-shared-app': {
description:
'Enable the official shared Slack app for existing Search customers. Supports orgId ' +
Expand Down
Loading
Loading