diff --git a/src/components/flow-editor.tsx b/src/components/flow-editor.tsx index 4bc56cd..183cddb 100644 --- a/src/components/flow-editor.tsx +++ b/src/components/flow-editor.tsx @@ -28,6 +28,7 @@ import { InputNode, OutputNode, CustomToolNode, + GatewayNode, } from './nodes'; import { MCPToolNode } from './nodes/mcp-tool-node'; import { isValidConnection } from '../lib/connection-validator'; @@ -41,6 +42,7 @@ const nodeTypes = { swarm: SwarmNode, tool: ToolNode, 'mcp-tool': MCPToolNode, + gateway: GatewayNode, input: InputNode, output: OutputNode, 'custom-tool': CustomToolNode, @@ -226,6 +228,16 @@ export function FlowEditor({ }); } + // Set default values for Gateway nodes + if (type === 'gateway') { + Object.assign(defaultData, { + label: 'Gateway', + gatewayArn: '', + allowedTools: [], + description: 'AgentCore Gateway for tool access control', + }); + } + const newNode: Node = { id: `${type}_${Date.now()}`, type, diff --git a/src/components/node-palette.tsx b/src/components/node-palette.tsx index 8d0f10b..df09a42 100644 --- a/src/components/node-palette.tsx +++ b/src/components/node-palette.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Bot, Wrench, ArrowRight, ArrowLeft, Code, Server, Crown, Users } from 'lucide-react'; +import { Bot, Wrench, ArrowRight, ArrowLeft, Code, Server, Crown, Users, Shield } from 'lucide-react'; interface NodeTypeItem { type: string; @@ -45,6 +45,13 @@ const nodeTypes: NodeTypeItem[] = [ description: 'Model Context Protocol server for external tools', category: 'Core', }, + { + type: 'gateway', + label: 'Gateway Node', + icon: Shield, + description: 'AgentCore Gateway for tool access control and filtering', + category: 'Core', + }, { type: 'input', label: 'Input Node', diff --git a/src/components/nodes/gateway-node.tsx b/src/components/nodes/gateway-node.tsx new file mode 100644 index 0000000..bf20a0d --- /dev/null +++ b/src/components/nodes/gateway-node.tsx @@ -0,0 +1,75 @@ +import { Handle, Position, type NodeProps, useReactFlow } from '@xyflow/react'; +import { Shield, Settings, X } from 'lucide-react'; + +interface GatewayNodeData { + label?: string; + gatewayArn?: string; + allowedTools?: string[]; + description?: string; +} + +export function GatewayNode({ data, selected, id }: NodeProps) { + const { deleteElements } = useReactFlow(); + const nodeData = data as GatewayNodeData || {}; + const { + label = 'Gateway', + allowedTools = [], + description = 'AgentCore Gateway for tool access control', + } = nodeData; + + const handleDelete = (event: React.MouseEvent) => { + event.stopPropagation(); + deleteElements({ nodes: [{ id }] }); + }; + + return ( +
+ {/* Node Header */} +
+ + {label} +
+ + {selected && ( + + )} +
+
+ + {/* Node Content */} +
+
+
+ Tools: {allowedTools.length > 0 ? `${allowedTools.length} selected` : 'None'} +
+ {description && ( +
+ {description} +
+ )} +
+
+ + {/* Output Handle (right side) - Gateway provides tools to agents */} +
+ + Gateway +
+
+ ); +} diff --git a/src/components/nodes/index.tsx b/src/components/nodes/index.tsx index 73437cc..95c64bc 100644 --- a/src/components/nodes/index.tsx +++ b/src/components/nodes/index.tsx @@ -6,4 +6,5 @@ export { InputNode } from './input-node'; export { OutputNode } from './output-node'; export { CustomToolNode } from './custom-tool-node'; export { MCPToolNode } from './mcp-tool-node'; -export { GraphBuilderNode } from './graph-builder-node'; \ No newline at end of file +export { GraphBuilderNode } from './graph-builder-node'; +export { GatewayNode } from './gateway-node'; \ No newline at end of file diff --git a/src/components/property-panel.tsx b/src/components/property-panel.tsx index 789b71a..8db083d 100644 --- a/src/components/property-panel.tsx +++ b/src/components/property-panel.tsx @@ -1140,6 +1140,137 @@ export function PropertyPanel({ ); + const renderGatewayProperties = (data: any) => { + // Common AgentCore Gateway tools + const availableTools = [ + 'calculator', + 'file_read', + 'file_write', + 'shell', + 'current_time', + 'http_request', + 'editor', + 'retrieve', + 'mem0_memory', + 'code_interpreter', + 'web_search', + 'database_query', + 'email_sender', + 'slack_messenger', + 'document_analyzer', + 'image_generator', + 'text_summarizer', + 'data_transformer', + ]; + + const handleToolToggle = (toolName: string) => { + const currentTools = data.allowedTools || []; + const newTools = currentTools.includes(toolName) + ? currentTools.filter((t: string) => t !== toolName) + : [...currentTools, toolName]; + + handleInputChange('allowedTools', newTools); + }; + + const handleSelectAll = () => { + handleInputChange('allowedTools', availableTools); + }; + + const handleDeselectAll = () => { + handleInputChange('allowedTools', []); + }; + + return ( +
+
+ + handleInputChange('label', e.target.value)} + className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-teal-500 focus:border-teal-500" + placeholder="Gateway Name" + /> +
+ +
+ + handleInputChange('gatewayArn', e.target.value)} + className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-teal-500 focus:border-teal-500" + placeholder="arn:aws:bedrock-agentcore:region:account:gateway/id" + /> +

+ Leave empty to use default gateway or create a new one during deployment +

+
+ +
+ +