Skip to content

Commit ef94e09

Browse files
committed
additional improvements
1 parent d69055b commit ef94e09

9 files changed

Lines changed: 10 additions & 105 deletions

File tree

apps/sim/app/api/mcp/servers/test-connection/route.ts

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ export const POST = withMcpAuth('write')(
7070
workspaceId,
7171
})
7272

73-
// Validate required fields
7473
if (!body.name || !body.transport) {
7574
return createMcpErrorResponse(
7675
new Error('Missing required fields: name and transport are required'),
@@ -79,7 +78,6 @@ export const POST = withMcpAuth('write')(
7978
)
8079
}
8180

82-
// Validate URL if provided
8381
if (
8482
(body.transport === 'http' ||
8583
body.transport === 'sse' ||
@@ -97,7 +95,6 @@ export const POST = withMcpAuth('write')(
9795
body.url = urlValidation.normalizedUrl
9896
}
9997

100-
// Resolve environment variables in config
10198
let resolvedUrl = body.url
10299
let resolvedHeaders = body.headers || {}
103100

@@ -120,38 +117,33 @@ export const POST = withMcpAuth('write')(
120117
)
121118
}
122119

123-
// Create temporary server config for testing
124120
const testConfig: McpServerConfig = {
125121
id: `test-${requestId}`,
126122
name: body.name,
127123
transport: body.transport,
128124
url: resolvedUrl,
129125
headers: resolvedHeaders,
130-
timeout: body.timeout || 10000, // Shorter timeout for testing
126+
timeout: body.timeout || 10000,
131127
retries: 1, // Only one retry for tests
132128
enabled: true,
133129
}
134130

135-
// Test security policy (restrictive for testing)
136131
const testSecurityPolicy = {
137-
requireConsent: false, // Skip consent for connection testing
132+
requireConsent: false,
138133
auditLevel: 'none' as const,
139-
maxToolExecutionsPerHour: 0, // Don't allow tool execution during tests
134+
maxToolExecutionsPerHour: 0,
140135
}
141136

142137
const result: TestConnectionResult = { success: false }
143138
let client: McpClient | null = null
144139

145140
try {
146-
// Create and connect to the test client
147141
client = new McpClient(testConfig, testSecurityPolicy)
148142
await client.connect()
149143

150-
// If we get here, connection was successful
151144
result.success = true
152145
result.negotiatedVersion = client.getNegotiatedVersion()
153146

154-
// Try to discover tools (with timeout)
155147
try {
156148
const tools = await client.listTools()
157149
result.toolCount = tools.length
@@ -161,7 +153,6 @@ export const POST = withMcpAuth('write')(
161153
result.warnings.push('Could not list tools from server')
162154
}
163155

164-
// Check for version compatibility warnings
165156
const clientVersionInfo = McpClient.getVersionInfo()
166157
if (result.negotiatedVersion !== clientVersionInfo.preferred) {
167158
result.warnings = result.warnings || []
@@ -186,7 +177,6 @@ export const POST = withMcpAuth('write')(
186177
result.error = 'Unknown connection error'
187178
}
188179
} finally {
189-
// Always disconnect the test client
190180
if (client) {
191181
try {
192182
await client.disconnect()

apps/sim/app/api/workflows/[id]/execute/route.ts

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -201,11 +201,8 @@ async function executeWorkflow(
201201
}
202202
}
203203

204-
// Use the current block states as-is - parameter transformation will happen in the handlers
205-
const transformedBlockStates = currentBlockStates
206-
207204
// Process the block states to ensure response formats are properly parsed
208-
const processedBlockStates = Object.entries(transformedBlockStates).reduce(
205+
const processedBlockStates = Object.entries(currentBlockStates).reduce(
209206
(acc, [blockId, blockState]) => {
210207
// Check if this block has a responseFormat that needs to be parsed
211208
if (blockState.responseFormat && typeof blockState.responseFormat === 'string') {
@@ -265,42 +262,10 @@ async function executeWorkflow(
265262
logger.debug(`[${requestId}] No workflow variables found for: ${workflowId}`)
266263
}
267264

268-
// Create merged states that combine block metadata with transformed parameters
269-
const finalMergedStates = Object.entries(mergedStates).reduce(
270-
(acc, [blockId, blockData]) => {
271-
const transformedParams = processedBlockStates[blockId]
272-
if (transformedParams) {
273-
// Update the block's subBlocks with transformed parameters
274-
const updatedSubBlocks = Object.entries(transformedParams).reduce(
275-
(subAcc, [key, value]) => {
276-
// Preserve original subBlock structure but update the value
277-
const originalSubBlock = blockData.subBlocks[key]
278-
subAcc[key] = {
279-
id: originalSubBlock?.id || key,
280-
type: originalSubBlock?.type || 'text',
281-
value,
282-
}
283-
return subAcc
284-
},
285-
{} as Record<string, any>
286-
)
287-
288-
acc[blockId] = {
289-
...blockData,
290-
subBlocks: updatedSubBlocks,
291-
}
292-
} else {
293-
acc[blockId] = blockData
294-
}
295-
return acc
296-
},
297-
{} as typeof mergedStates
298-
)
299-
300265
// Serialize and execute the workflow
301266
logger.debug(`[${requestId}] Serializing workflow: ${workflowId}`)
302267
const serializedWorkflow = new Serializer().serializeWorkflow(
303-
finalMergedStates,
268+
mergedStates,
304269
edges,
305270
loops,
306271
parallels,

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/mcp-dynamic-args/mcp-dynamic-args.tsx

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,9 @@ export function McpDynamicArgs({
2727
const [selectedTool] = useSubBlockValue(blockId, 'tool')
2828
const [toolArgs, setToolArgs] = useSubBlockValue(blockId, subBlockId)
2929

30-
// Find the selected tool's schema
31-
// Note: selectedTool is the full tool ID (serverId-toolName), not just the name
3230
const selectedToolConfig = mcpTools.find((tool) => tool.id === selectedTool)
3331
const toolSchema = selectedToolConfig?.inputSchema
3432

35-
// Parse current arguments
3633
const currentArgs = useCallback(() => {
3734
if (isPreview && previewValue) {
3835
return typeof previewValue === 'string' ? JSON.parse(previewValue) : previewValue
@@ -47,27 +44,23 @@ export function McpDynamicArgs({
4744
return toolArgs || {}
4845
}, [toolArgs, previewValue, isPreview])
4946

50-
// Update a specific parameter
5147
const updateParameter = useCallback(
5248
(paramName: string, value: any) => {
5349
if (disabled) return
5450

5551
const current = currentArgs()
5652
const updated = { ...current, [paramName]: value }
5753

58-
// Convert back to JSON string for storage
5954
const jsonString = JSON.stringify(updated, null, 2)
6055
setToolArgs(jsonString)
6156
},
6257
[currentArgs, setToolArgs, disabled]
6358
)
6459

65-
// Render parameter input based on schema type
6660
const renderParameterInput = (paramName: string, paramSchema: any) => {
6761
const current = currentArgs()
6862
const value = current[paramName]
6963

70-
// Determine input type based on schema
7164
const getInputType = () => {
7265
if (paramSchema.enum) return 'dropdown'
7366
if (paramSchema.type === 'boolean') return 'switch'
@@ -190,7 +183,6 @@ export function McpDynamicArgs({
190183
value={value || ''}
191184
onChange={(e) => {
192185
let processedValue: any = e.target.value
193-
// Convert to appropriate type for numeric fields
194186
if (isNumeric && processedValue !== '') {
195187
processedValue =
196188
paramSchema.type === 'integer'
@@ -210,7 +202,6 @@ export function McpDynamicArgs({
210202
}
211203
}
212204

213-
// Show message when no tool is selected
214205
if (!selectedTool) {
215206
return (
216207
<div className='rounded-lg border border-gray-300 border-dashed p-8 text-center dark:border-gray-600'>
@@ -219,7 +210,6 @@ export function McpDynamicArgs({
219210
)
220211
}
221212

222-
// Show message when tool has no parameters
223213
if (!toolSchema?.properties || Object.keys(toolSchema.properties).length === 0) {
224214
return (
225215
<div className='rounded-lg border border-gray-300 border-dashed p-8 text-center dark:border-gray-600'>

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/mcp-server-modal/mcp-server-selector.tsx

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,9 @@ import {
1313
CommandList,
1414
} from '@/components/ui/command'
1515
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
16-
import { createLogger } from '@/lib/logs/console/logger'
1716
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/hooks/use-sub-block-value'
1817
import type { SubBlockConfig } from '@/blocks/types'
1918
import { useEnabledServers, useMcpServersStore } from '@/stores/mcp-servers/store'
20-
import type { McpServerWithStatus } from '@/stores/mcp-servers/types'
21-
22-
const logger = createLogger('McpServerSelector')
2319

2420
interface McpServerSelectorProps {
2521
blockId: string
@@ -40,57 +36,36 @@ export function McpServerSelector({
4036
const workspaceId = params.workspaceId as string
4137
const [open, setOpen] = useState(false)
4238

43-
// Get MCP servers from store
4439
const { fetchServers, isLoading, error } = useMcpServersStore()
4540
const enabledServers = useEnabledServers()
4641

47-
// Use collaborative state management via useSubBlockValue hook
4842
const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlock.id)
4943

50-
// Extract config values
5144
const label = subBlock.placeholder || 'Select MCP server'
5245

53-
// Get the effective value (preview or store value)
5446
const effectiveValue = isPreview && previewValue !== undefined ? previewValue : storeValue
5547
const selectedServerId = effectiveValue || ''
5648

57-
// Get the selected server
5849
const selectedServer = enabledServers.find((server) => server.id === selectedServerId)
5950

60-
// Fetch servers on initial mount
6151
useEffect(() => {
6252
fetchServers(workspaceId)
6353
}, [fetchServers, workspaceId])
6454

65-
// Handle popover open to fetch fresh servers
6655
const handleOpenChange = (isOpen: boolean) => {
6756
setOpen(isOpen)
6857
if (isOpen) {
6958
fetchServers(workspaceId)
7059
}
7160
}
7261

73-
// Handle server selection
7462
const handleSelect = (serverId: string) => {
7563
if (!isPreview) {
7664
setStoreValue(serverId)
7765
}
7866
setOpen(false)
7967
}
8068

81-
// Get server status indicator
82-
const getStatusIndicator = (server: McpServerWithStatus) => {
83-
switch (server.connectionStatus) {
84-
case 'connected':
85-
return <div className='h-2 w-2 rounded-full bg-green-500' />
86-
case 'error':
87-
return <div className='h-2 w-2 rounded-full bg-red-500' />
88-
default:
89-
return <div className='h-2 w-2 rounded-full bg-gray-400' />
90-
}
91-
}
92-
93-
// Get display text for selected server
9469
const getDisplayText = () => {
9570
if (selectedServer) {
9671
return <span className='truncate font-normal'>{selectedServer.name}</span>

apps/sim/blocks/blocks/agent.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,6 @@ Example 3 (Array Input):
422422
return usageControl !== 'none'
423423
})
424424
.map((tool: any) => {
425-
// Get the base tool configuration
426425
const toolConfig = {
427426
id:
428427
tool.type === 'custom-tool'
@@ -431,9 +430,9 @@ Example 3 (Array Input):
431430
name: tool.title,
432431
description: tool.type === 'custom-tool' ? tool.schema?.function?.description : '',
433432
params: tool.params || {},
434-
parameters: tool.type === 'custom-tool' ? tool.schema?.function?.parameters : {}, // We'd need to get actual parameters for non-custom tools
433+
parameters: tool.type === 'custom-tool' ? tool.schema?.function?.parameters : {},
435434
usageControl: tool.usageControl || 'auto',
436-
type: tool.type, // Preserve tool type for agent handler processing
435+
type: tool.type,
437436
}
438437
return toolConfig
439438
})

apps/sim/blocks/blocks/mcp.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export const McpBlock: BlockConfig<McpResponse> = {
3535
required: true,
3636
placeholder: 'Select a tool',
3737
description: 'Available tools from the selected MCP server',
38-
dependsOn: ['server'], // Tool options depend on selected server
38+
dependsOn: ['server'],
3939
condition: {
4040
field: 'server',
4141
value: '',
@@ -55,25 +55,20 @@ export const McpBlock: BlockConfig<McpResponse> = {
5555
},
5656
},
5757
],
58-
// MCP blocks use the tools framework with dynamic tool IDs
5958
tools: {
6059
access: [], // No static tool access needed - tools are dynamically resolved
6160
config: {
6261
tool: (params: any) => {
63-
// Build MCP tool ID from server and tool selections
6462
if (params.server && params.tool) {
6563
const serverId = params.server
6664
let toolName = params.tool
6765

68-
// Handle case where tool selection might include the full MCP tool ID
69-
// If tool contains the server ID, extract just the tool name
7066
if (toolName.startsWith(`${serverId}-`)) {
7167
toolName = toolName.substring(`${serverId}-`.length)
7268
}
7369

7470
return createMcpToolId(serverId, toolName)
7571
}
76-
// Fallback when no selection is made yet
7772
return 'mcp-dynamic'
7873
},
7974
},

apps/sim/components/ui/env-var-dropdown.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export const EnvVarDropdown: React.FC<EnvVarDropdownProps> = ({
132132
onClose?.()
133133
}
134134

135-
// Add and remove keyboard event listener with smooth scrolling
135+
// Add and remove keyboard event listener
136136
useEffect(() => {
137137
if (visible) {
138138
const handleKeyboardEvent = (e: KeyboardEvent) => {
@@ -144,7 +144,6 @@ export const EnvVarDropdown: React.FC<EnvVarDropdownProps> = ({
144144
e.stopPropagation()
145145
setSelectedIndex((prev) => {
146146
const newIndex = prev < filteredEnvVars.length - 1 ? prev + 1 : prev
147-
// Scroll to the newly selected item
148147
setTimeout(() => {
149148
const selectedElement = document.querySelector(`[data-env-var-index="${newIndex}"]`)
150149
if (selectedElement) {
@@ -159,7 +158,6 @@ export const EnvVarDropdown: React.FC<EnvVarDropdownProps> = ({
159158
e.stopPropagation()
160159
setSelectedIndex((prev) => {
161160
const newIndex = prev > 0 ? prev - 1 : prev
162-
// Scroll to the newly selected item
163161
setTimeout(() => {
164162
const selectedElement = document.querySelector(`[data-env-var-index="${newIndex}"]`)
165163
if (selectedElement) {

apps/sim/components/ui/tag-dropdown.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { describe, expect, vi } from 'vitest'
1+
import { describe, expect, it, vi } from 'vitest'
22
import { checkTagTrigger } from '@/components/ui/tag-dropdown'
33
import { extractFieldsFromSchema, parseResponseFormatSafely } from '@/lib/response-format'
44
import type { BlockState } from '@/stores/workflows/workflow/types'

apps/sim/tools/index.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,6 @@ export async function executeTool(
138138
logger.error(`[${requestId}] Custom tool not found: ${toolId}`)
139139
}
140140
} else if (toolId.startsWith('mcp-')) {
141-
// Handle MCP tools via server-side proxy
142141
return await executeMcpTool(toolId, params, executionContext, requestId, startTimeISO)
143142
} else {
144143
// For built-in tools, use the synchronous version
@@ -731,27 +730,21 @@ async function executeMcpTool(
731730
try {
732731
logger.info(`[${actualRequestId}] Executing MCP tool: ${toolId}`)
733732

734-
// Parse MCP tool ID to extract server ID and tool name
735733
const { serverId, toolName } = parseMcpToolId(toolId)
736734

737-
// Get base URL for API calls
738735
const baseUrl = getBaseUrl()
739736

740-
// Prepare headers for internal API call
741737
const headers: Record<string, string> = { 'Content-Type': 'application/json' }
742738

743-
// Add internal authorization if running on server
744739
if (typeof window === 'undefined') {
745740
try {
746741
const internalToken = await generateInternalToken()
747742
headers.Authorization = `Bearer ${internalToken}`
748743
} catch (error) {
749744
logger.error(`[${actualRequestId}] Failed to generate internal token:`, error)
750-
// Still continue with the request, but it will likely fail auth
751745
}
752746
}
753747

754-
// Execute MCP tool via API
755748
// Handle two different parameter structures:
756749
// 1. Direct MCP blocks: arguments are stored as JSON string in 'arguments' field
757750
// 2. Agent blocks: arguments are passed directly as top-level parameters

0 commit comments

Comments
 (0)