Skip to content

Commit d6a0036

Browse files
committed
styling improvements, ability to edit mcp server description, etc
1 parent 0346aac commit d6a0036

File tree

10 files changed

+129
-134
lines changed

10 files changed

+129
-134
lines changed

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx renamed to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp/mcp.tsx

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
44
import { createLogger } from '@sim/logger'
5-
import { Server } from 'lucide-react'
65
import { useParams } from 'next/navigation'
76
import { Badge, Combobox, type ComboboxOption, Input, Label, Textarea } from '@/components/emcn'
87
import { Skeleton } from '@/components/ui'
@@ -19,6 +18,7 @@ import {
1918
type WorkflowMcpServer,
2019
type WorkflowMcpTool,
2120
} from '@/hooks/queries/workflow-mcp-servers'
21+
import { useSettingsModalStore } from '@/stores/settings-modal/store'
2222
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
2323
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
2424

@@ -27,7 +27,7 @@ const logger = createLogger('McpToolDeploy')
2727
/** InputFormatField with guaranteed name (after normalization) */
2828
type NormalizedField = InputFormatField & { name: string }
2929

30-
interface McpToolDeployProps {
30+
interface McpDeployProps {
3131
workflowId: string
3232
workflowName: string
3333
workflowDescription?: string | null
@@ -75,17 +75,18 @@ function ServerToolsQuery({
7575
return null
7676
}
7777

78-
export function McpToolDeploy({
78+
export function McpDeploy({
7979
workflowId,
8080
workflowName,
8181
workflowDescription,
8282
isDeployed,
8383
onAddedToServer,
8484
onSubmittingChange,
8585
onCanSaveChange,
86-
}: McpToolDeployProps) {
86+
}: McpDeployProps) {
8787
const params = useParams()
8888
const workspaceId = params.workspaceId as string
89+
const openSettingsModal = useSettingsModalStore((state) => state.openModal)
8990

9091
const {
9192
data: servers = [],
@@ -116,21 +117,24 @@ export function McpToolDeploy({
116117
const inputFormat = useMemo((): NormalizedField[] => {
117118
if (!starterBlockId) return []
118119

119-
// Try SubBlockStore first (runtime state)
120120
const storeValue = subBlockValues[starterBlockId]?.inputFormat
121121
const normalized = normalizeInputFormatValue(storeValue) as NormalizedField[]
122122
if (normalized.length > 0) return normalized
123123

124-
// Fallback to block definition
125124
const startBlock = blocks[starterBlockId]
126125
const blockValue = startBlock?.subBlocks?.inputFormat?.value
127126
return normalizeInputFormatValue(blockValue) as NormalizedField[]
128127
}, [starterBlockId, subBlockValues, blocks])
129128

130129
const [toolName, setToolName] = useState(() => sanitizeToolName(workflowName))
131-
const [toolDescription, setToolDescription] = useState(
132-
() => workflowDescription || `Execute ${workflowName} workflow`
133-
)
130+
const [toolDescription, setToolDescription] = useState(() => {
131+
const isDefaultDescription =
132+
!workflowDescription ||
133+
workflowDescription === workflowName ||
134+
workflowDescription.toLowerCase() === 'new workflow'
135+
136+
return isDefaultDescription ? '' : workflowDescription
137+
})
134138
const [parameterDescriptions, setParameterDescriptions] = useState<Record<string, string>>({})
135139
const [pendingServerChanges, setPendingServerChanges] = useState<Set<string>>(new Set())
136140

@@ -177,7 +181,13 @@ export function McpToolDeploy({
177181
const toolInfo = serverToolsMap[server.id]
178182
if (toolInfo?.tool) {
179183
setToolName(toolInfo.tool.toolName)
180-
setToolDescription(toolInfo.tool.toolDescription || '')
184+
185+
const loadedDescription = toolInfo.tool.toolDescription || ''
186+
const isDefaultDescription =
187+
!loadedDescription ||
188+
loadedDescription === workflowName ||
189+
loadedDescription.toLowerCase() === 'new workflow'
190+
setToolDescription(isDefaultDescription ? '' : loadedDescription)
181191

182192
const schema = toolInfo.tool.parameterSchema as Record<string, unknown> | undefined
183193
const properties = schema?.properties as
@@ -202,16 +212,14 @@ export function McpToolDeploy({
202212
break
203213
}
204214
}
205-
}, [servers, serverToolsMap])
215+
}, [servers, serverToolsMap, workflowName])
206216

207-
// Track saved values to detect changes (use state so updates trigger re-render)
208217
const [savedValues, setSavedValues] = useState<{
209218
toolName: string
210219
toolDescription: string
211220
parameterDescriptions: Record<string, string>
212221
} | null>(null)
213222

214-
// Store saved values once loaded
215223
useEffect(() => {
216224
if (hasLoadedInitialData.current && !savedValues) {
217225
setSavedValues({
@@ -222,7 +230,6 @@ export function McpToolDeploy({
222230
}
223231
}, [toolName, toolDescription, parameterDescriptions, savedValues])
224232

225-
// Determine if there are unsaved changes
226233
const hasDeployedTools = selectedServerIds.length > 0
227234
const hasChanges = useMemo(() => {
228235
if (!savedValues || !hasDeployedTools) return false
@@ -236,7 +243,6 @@ export function McpToolDeploy({
236243
return false
237244
}, [toolName, toolDescription, parameterDescriptions, hasDeployedTools, savedValues])
238245

239-
// Notify parent about save availability
240246
useEffect(() => {
241247
onCanSaveChange?.(hasChanges && hasDeployedTools && !!toolName.trim())
242248
}, [hasChanges, hasDeployedTools, toolName, onCanSaveChange])
@@ -298,7 +304,6 @@ export function McpToolDeploy({
298304
return servers.map((server) => ({
299305
label: server.name,
300306
value: server.id,
301-
icon: Server,
302307
}))
303308
}, [servers])
304309

@@ -394,14 +399,8 @@ export function McpToolDeploy({
394399

395400
if (!isDeployed) {
396401
return (
397-
<div className='flex h-full flex-col items-center justify-center gap-[12px] text-center'>
398-
<Server className='h-[32px] w-[32px] text-[var(--text-muted)]' />
399-
<div className='flex flex-col gap-[4px]'>
400-
<p className='text-[14px] text-[var(--text-primary)]'>Deploy workflow first</p>
401-
<p className='text-[13px] text-[var(--text-muted)]'>
402-
You need to deploy your workflow before adding it as an MCP tool.
403-
</p>
404-
</div>
402+
<div className='flex h-full items-center justify-center text-[13px] text-[var(--text-muted)]'>
403+
Deploy your workflow first to add it as an MCP tool.
405404
</div>
406405
)
407406
}
@@ -429,21 +428,21 @@ export function McpToolDeploy({
429428

430429
if (servers.length === 0) {
431430
return (
432-
<div className='flex h-full flex-col items-center justify-center gap-[12px] text-center'>
433-
<Server className='h-[32px] w-[32px] text-[var(--text-muted)]' />
434-
<div className='flex flex-col gap-[4px]'>
435-
<p className='text-[14px] text-[var(--text-primary)]'>No MCP servers yet</p>
436-
<p className='text-[13px] text-[var(--text-muted)]'>
437-
Create an MCP Server in Settings → MCP Servers first.
438-
</p>
439-
</div>
431+
<div className='flex h-full items-center justify-center text-[13px] text-[var(--text-muted)]'>
432+
<button
433+
type='button'
434+
onClick={() => openSettingsModal({ section: 'workflow-mcp-servers' })}
435+
className='transition-colors hover:text-[var(--text-secondary)]'
436+
>
437+
Create an MCP Server in Settings → MCP Servers first.
438+
</button>
440439
</div>
441440
)
442441
}
443442

444443
return (
445444
<form
446-
id='mcp-tool-deploy-form'
445+
id='mcp-deploy-form'
447446
className='-mx-1 space-y-[12px] overflow-y-auto px-1'
448447
onSubmit={(e) => {
449448
e.preventDefault()
@@ -538,10 +537,7 @@ export function McpToolDeploy({
538537
disabled={!toolName.trim() || isPending}
539538
isLoading={isPending}
540539
overlayContent={
541-
<span className='flex items-center gap-[6px] truncate text-[var(--text-primary)]'>
542-
<Server className='h-[12px] w-[12px] flex-shrink-0 text-[var(--text-tertiary)]' />
543-
<span className='truncate'>{selectedServersLabel}</span>
544-
</span>
540+
<span className='truncate text-[var(--text-primary)]'>{selectedServersLabel}</span>
545541
}
546542
/>
547543
{!toolName.trim() && (

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/deploy-modal.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import type { WorkflowState } from '@/stores/workflows/workflow/types'
2525
import { ApiDeploy } from './components/api/api'
2626
import { ChatDeploy, type ExistingChat } from './components/chat/chat'
2727
import { GeneralDeploy } from './components/general/general'
28-
import { McpToolDeploy } from './components/mcp-tool/mcp-tool'
28+
import { McpDeploy } from './components/mcp/mcp'
2929
import { TemplateDeploy } from './components/template/template'
3030

3131
const logger = createLogger('DeployModal')
@@ -50,7 +50,7 @@ interface WorkflowDeploymentInfo {
5050
needsRedeployment: boolean
5151
}
5252

53-
type TabView = 'general' | 'api' | 'chat' | 'template' | 'mcp-tool'
53+
type TabView = 'general' | 'api' | 'chat' | 'template' | 'mcp'
5454

5555
export function DeployModal({
5656
open,
@@ -532,7 +532,7 @@ export function DeployModal({
532532
}, [])
533533

534534
const handleMcpToolFormSubmit = useCallback(() => {
535-
const form = document.getElementById('mcp-tool-deploy-form') as HTMLFormElement
535+
const form = document.getElementById('mcp-deploy-form') as HTMLFormElement
536536
form?.requestSubmit()
537537
}, [])
538538

@@ -556,7 +556,7 @@ export function DeployModal({
556556
<ModalTabsList activeValue={activeTab}>
557557
<ModalTabsTrigger value='general'>General</ModalTabsTrigger>
558558
<ModalTabsTrigger value='api'>API</ModalTabsTrigger>
559-
<ModalTabsTrigger value='mcp-tool'>MCP Tool</ModalTabsTrigger>
559+
<ModalTabsTrigger value='mcp'>MCP</ModalTabsTrigger>
560560
<ModalTabsTrigger value='chat'>Chat</ModalTabsTrigger>
561561
<ModalTabsTrigger value='template'>Template</ModalTabsTrigger>
562562
</ModalTabsList>
@@ -618,9 +618,9 @@ export function DeployModal({
618618
)}
619619
</ModalTabsContent>
620620

621-
<ModalTabsContent value='mcp-tool'>
621+
<ModalTabsContent value='mcp' className='h-full'>
622622
{workflowId && (
623-
<McpToolDeploy
623+
<McpDeploy
624624
workflowId={workflowId}
625625
workflowName={workflowMetadata?.name || 'Workflow'}
626626
workflowDescription={workflowMetadata?.description}
@@ -674,11 +674,11 @@ export function DeployModal({
674674
</div>
675675
</ModalFooter>
676676
)}
677-
{activeTab === 'mcp-tool' && isDeployed && (
677+
{activeTab === 'mcp' && isDeployed && (
678678
<ModalFooter className='items-center'>
679679
<Button
680680
type='button'
681-
variant='primary'
681+
variant='tertiary'
682682
onClick={handleMcpToolFormSubmit}
683683
disabled={mcpToolSubmitting || !mcpToolCanSave}
684684
>

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/custom-tools/custom-tools.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ export function CustomTools() {
163163
Edit
164164
</Button>
165165
<Button
166-
variant='ghost'
166+
variant='destructive'
167167
onClick={() => handleDeleteClick(tool.id)}
168168
disabled={deletingTools.has(tool.id)}
169169
>

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/mcp/components/formatted-input/formatted-input.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export function FormattedInput({
4040
onChange={onChange}
4141
onScroll={handleScroll}
4242
onInput={handleScroll}
43-
className='h-9 text-transparent caret-foreground placeholder:text-[var(--text-tertiary)]'
43+
className='h-9 text-transparent caret-foreground placeholder:text-[var(--text-muted)]'
4444
/>
4545
<div className='pointer-events-none absolute inset-0 flex items-center overflow-hidden px-[8px] py-[6px] font-medium font-sans text-sm'>
4646
<div className='whitespace-nowrap' style={{ transform: `translateX(-${scrollLeft}px)` }}>

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/mcp/components/server-list-item/server-list-item.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export function ServerListItem({
6464
</p>
6565
</div>
6666
<div className='flex flex-shrink-0 items-center gap-[4px]'>
67-
<Button variant='tertiary' onClick={onViewDetails}>
67+
<Button variant='ghost' onClick={onViewDetails}>
6868
Details
6969
</Button>
7070
<Button variant='destructive' onClick={onRemove} disabled={isDeleting}>

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/mcp/mcp.tsx

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ export function MCP({ initialServerId }: MCPProps) {
489489

490490
const error = toolsError || serversError
491491
const hasServers = servers && servers.length > 0
492-
const showEmptyState = !hasServers && !showAddForm
492+
const shouldShowForm = showAddForm || !hasServers
493493
const showNoResults = searchTerm.trim() && filteredServers.length === 0 && servers.length > 0
494494

495495
const isFormValid = formData.name.trim() && formData.url?.trim()
@@ -568,9 +568,7 @@ export function MCP({ initialServerId }: MCPProps) {
568568
{server.url && (
569569
<div className='flex flex-col gap-[8px]'>
570570
<span className='font-medium text-[13px] text-[var(--text-primary)]'>URL</span>
571-
<p className='break-all font-mono text-[13px] text-[var(--text-secondary)]'>
572-
{server.url}
573-
</p>
571+
<p className='break-all text-[14px] text-[var(--text-secondary)]'>{server.url}</p>
574572
</div>
575573
)}
576574

@@ -684,8 +682,8 @@ export function MCP({ initialServerId }: MCPProps) {
684682
</Button>
685683
</div>
686684

687-
{showAddForm && !serversLoading && (
688-
<div className='rounded-[8px] border bg-[var(--surface-3)] p-[10px]'>
685+
{shouldShowForm && !serversLoading && (
686+
<div className='rounded-[8px] border p-[10px]'>
689687
<div className='flex flex-col gap-[8px]'>
690688
<FormField label='Server Name'>
691689
<EmcnInput
@@ -791,10 +789,6 @@ export function MCP({ initialServerId }: MCPProps) {
791789
<McpServerSkeleton />
792790
<McpServerSkeleton />
793791
</div>
794-
) : showEmptyState ? (
795-
<div className='flex h-full items-center justify-center text-[13px] text-[var(--text-muted)]'>
796-
Click "Add" above to get started
797-
</div>
798792
) : (
799793
<div className='flex flex-col gap-[8px]'>
800794
{filteredServers.map((server) => {

0 commit comments

Comments
 (0)