{
  "id": "aOB31uw3PCRkygAt",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "MCP Enterprise AI Control Layer with Claude AI",
  "tags": [],
  "nodes": [
    {
      "id": "a82ebe3f-7654-469c-a024-fa44486fef2c",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -16,
        32
      ],
      "parameters": {
        "width": 780,
        "height": 1296,
        "content": "## MCP Enterprise AI Control Layer with Claude AI\n\nA secure, scalable enterprise AI orchestration layer built on the Model Context Protocol (MCP). This workflow standardizes tool access across all business systems, enforces permission-based data handling, applies contextual reasoning via Claude AI, and provides a single governance plane for multi-agent AI deployments.\n\n### How it works\n\n1. **Receive AI Agent Request** - Unified MCP webhook accepts tool or context requests from any agent\n2. **Enterprise Auth & RBAC** - Validates JWT, resolves role-based access controls, enforces tenant isolation\n3. **Context Assembly** - Builds full enterprise context: user profile, org policies, active sessions, prior tool calls\n4. **Claude AI Orchestration** - Reasons over context to select optimal tool chain, validate intent, plan execution\n5. **Policy Enforcement Engine** - Applies data classification, DLP rules, and geo/time-based restrictions\n6. **Multi-System Tool Dispatch** - Routes to CRM, ERP, HRMS, Data Warehouse, or custom APIs in parallel\n7. **Response Aggregation** - Merges multi-tool results, applies post-processing and redaction rules\n8. **Compliance Logging** - SOC2/ISO27001-ready audit trail with data lineage tracking\n9. **Return Enriched Context** - Delivers MCP-compliant response with reasoning trace back to agent\n\n### Setup Steps\n\n1. Import workflow into n8n\n2. Configure credentials:\n   - **Anthropic API** - Claude AI for orchestration and contextual reasoning\n   - **Google Sheets** - RBAC policy store, session registry, audit log\n   - **SMTP / Slack** - Security and compliance notifications\n   - **JWT Secret** - For enterprise token validation\n3. Populate the RBAC policy sheet with roles, permissions, and data classifications\n4. Configure your enterprise system endpoints in the tool dispatch nodes\n5. Set your tenant IDs and org-level data policies\n6. Activate workflow and register the webhook URL with your AI agent platform\n\n### Sample Enterprise MCP Request\n```json\n{\n  \"mcpVersion\": \"1.1\",\n  \"agentId\": \"sales-agent-prod-007\",\n  \"jwtToken\": \"eyJhbGciOiJIUzI1NiJ9...\",\n  \"tenantId\": \"ORG-ACME-001\",\n  \"userId\": \"john.doe@acme.com\",\n  \"userRole\": \"sales_manager\",\n  \"toolRequests\": [\n    { \"toolName\": \"crm.get_pipeline\", \"parameters\": { \"region\": \"APAC\" } },\n    { \"toolName\": \"erp.get_inventory\", \"parameters\": { \"sku\": \"PROD-001\" } }\n  ],\n  \"agentGoal\": \"Prepare a quarterly sales brief for the APAC team meeting\",\n  \"dataClassification\": \"INTERNAL\",\n  \"sessionId\": \"sess-xyz-001\"\n}\n```\n\n### Enterprise Features\n- **Multi-tenant isolation** \u2014 strict org boundary enforcement\n- **RBAC + ABAC** \u2014 role and attribute-based access control per tool per data class\n- **Data Loss Prevention (DLP)** \u2014 redacts PII/secrets before returning to agent\n- **Contextual AI reasoning** \u2014 Claude plans the optimal tool chain for agent goals\n- **SOC2 / ISO 27001** audit trail with data lineage\n- **Geo & time-based policy** \u2014 restrict tool access by region or business hours"
      },
      "typeVersion": 1
    },
    {
      "id": "d235129f-95d6-468b-a6cf-4b6048e85fcc",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        960,
        464
      ],
      "parameters": {
        "color": 3,
        "width": 440,
        "height": 360,
        "content": "## 1. Enterprise Auth, RBAC & Context Assembly"
      },
      "typeVersion": 1
    },
    {
      "id": "0f2c36e7-1926-4645-95c9-4e143e2bae11",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1424,
        208
      ],
      "parameters": {
        "color": 5,
        "width": 780,
        "height": 812,
        "content": "## 2. AI Orchestration & Policy Enforcement"
      },
      "typeVersion": 1
    },
    {
      "id": "481fcca8-7706-4813-812d-5070326f0df5",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2240,
        112
      ],
      "parameters": {
        "color": 3,
        "width": 608,
        "height": 940,
        "content": "## 3. Multi-System Tool Dispatch"
      },
      "typeVersion": 1
    },
    {
      "id": "e9e6399c-5c60-4ace-a01c-48972a237745",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2896,
        272
      ],
      "parameters": {
        "color": 5,
        "width": 924,
        "height": 828,
        "content": "## 4. Aggregation, DLP Redaction, Audit & MCP Response"
      },
      "typeVersion": 1
    },
    {
      "id": "293a3eef-0079-42a5-8002-09dc1ea300cc",
      "name": "Receive Enterprise AI Agent Request",
      "type": "n8n-nodes-base.webhook",
      "position": [
        1008,
        640
      ],
      "parameters": {
        "path": "mcp-enterprise",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "8b987331-a09d-4a27-b387-2c45dc5bbae6",
      "name": "Enterprise Auth, JWT and RBAC Validation",
      "type": "n8n-nodes-base.code",
      "position": [
        1232,
        640
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const body = $input.item.json.body || $input.item.json;\n\n// ---- MCP Schema validation ----\nconst required = ['mcpVersion', 'agentId', 'jwtToken', 'tenantId', 'userId', 'toolRequests', 'agentGoal'];\nconst missing = required.filter(f => !body[f]);\nif (missing.length > 0) {\n  throw new Error(`Enterprise MCP Schema Violation \u2014 Missing fields: ${missing.join(', ')}`);\n}\n\n// ---- MCP version check ----\nconst supportedVersions = ['1.0', '1.1', '1.2'];\nif (!supportedVersions.includes(body.mcpVersion)) {\n  throw new Error(`Unsupported MCP version: ${body.mcpVersion}`);\n}\n\n// ---- JWT validation (simplified \u2014 use proper JWT library in production) ----\nconst jwtParts = body.jwtToken.split('.');\nif (jwtParts.length !== 3) {\n  throw new Error('Invalid JWT format: token must have 3 parts');\n}\n// Decode JWT payload (base64)\nlet jwtPayload;\ntry {\n  const base64Payload = jwtParts[1].replace(/-/g, '+').replace(/_/g, '/');\n  jwtPayload = JSON.parse(Buffer.from(base64Payload, 'base64').toString('utf8'));\n} catch (e) {\n  throw new Error('JWT payload decode failed: ' + e.message);\n}\n\n// Validate JWT claims\nconst now = Math.floor(Date.now() / 1000);\nif (jwtPayload.exp && jwtPayload.exp < now) {\n  throw new Error(`JWT token expired at ${new Date(jwtPayload.exp * 1000).toISOString()}`);\n}\nif (jwtPayload.iss && jwtPayload.iss !== 'enterprise-idp') {\n  throw new Error(`JWT issuer mismatch: expected 'enterprise-idp', got '${jwtPayload.iss}'`);\n}\n\n// ---- Tenant isolation check ----\nconst jwtTenant = jwtPayload.tenantId || jwtPayload.org;\nif (jwtTenant && jwtTenant !== body.tenantId) {\n  throw new Error(`Tenant isolation violation: JWT tenant '${jwtTenant}' does not match request tenant '${body.tenantId}'`);\n}\n\n// ---- Tool request validation ----\nif (!Array.isArray(body.toolRequests) || body.toolRequests.length === 0) {\n  throw new Error('toolRequests must be a non-empty array');\n}\nif (body.toolRequests.length > 10) {\n  throw new Error(`Too many tool requests: ${body.toolRequests.length}. Maximum is 10 per orchestration call`);\n}\n\n// Validate each tool name format\nconst toolPattern = /^[a-z][a-z0-9_]*\\.[a-z][a-z0-9_]*$/;\nfor (const tr of body.toolRequests) {\n  if (!tr.toolName || !toolPattern.test(tr.toolName)) {\n    throw new Error(`Invalid toolName format: '${tr.toolName}'. Must match category.action`);\n  }\n}\n\n// ---- RBAC role normalization ----\nconst validRoles = ['viewer', 'analyst', 'sales_rep', 'sales_manager', 'hr_admin', 'finance_admin', 'it_admin', 'super_admin', 'ai_agent'];\nconst userRole = body.userRole?.toLowerCase() || 'viewer';\nif (!validRoles.includes(userRole)) {\n  throw new Error(`Unknown role: '${userRole}'. Valid roles: ${validRoles.join(', ')}`);\n}\n\n// Role privilege levels\nconst roleLevels = {\n  'viewer': 1, 'analyst': 2, 'sales_rep': 3, 'sales_manager': 4,\n  'hr_admin': 4, 'finance_admin': 4, 'it_admin': 5, 'super_admin': 6, 'ai_agent': 3\n};\n\n// ---- Build enterprise request context ----\nconst enterpriseRequest = {\n  // Gateway metadata\n  gatewayRequestId: `ECTL-${Date.now()}-${Math.random().toString(36).substr(2, 9).toUpperCase()}`,\n  mcpVersion: body.mcpVersion,\n  receivedAt: new Date().toISOString(),\n\n  // Agent identity\n  agentId: body.agentId.trim(),\n  agentGoal: body.agentGoal.trim(),\n  sessionId: body.sessionId || `sess-${Date.now()}`,\n\n  // Enterprise identity\n  tenantId: body.tenantId.trim().toUpperCase(),\n  userId: body.userId.trim().toLowerCase(),\n  userRole,\n  roleLevel: roleLevels[userRole] || 1,\n  department: body.department || jwtPayload.department || 'UNKNOWN',\n  costCenter: body.costCenter || jwtPayload.costCenter || null,\n  geoRegion: body.geoRegion || jwtPayload.region || 'GLOBAL',\n  jwtClaims: jwtPayload,\n\n  // Tool requests\n  toolRequests: body.toolRequests,\n  toolCount: body.toolRequests.length,\n\n  // Data classification\n  dataClassification: body.dataClassification || 'INTERNAL',\n  maxResponseClassification: body.maxResponseClassification || 'INTERNAL',\n\n  // Execution preferences\n  parallelExecution: body.parallelExecution !== false,\n  maxExecutionTimeMs: Math.min(parseInt(body.maxExecutionTimeMs) || 30000, 60000),\n  dryRun: body.dryRun === true,\n\n  // Tracing\n  traceId: body.traceId || `trace-${Date.now()}`,\n  correlationId: body.correlationId || null,\n  sourceIP: body.sourceIP || 'NOT_CAPTURED',\n\n  status: 'AUTHENTICATED'\n};\n\nreturn { json: { enterpriseRequest } };"
      },
      "typeVersion": 2
    },
    {
      "id": "ee5a3af1-59e6-409a-bf92-aa8e1d50790e",
      "name": "Fetch RBAC Policies for Role and Tools",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1456,
        448
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "="
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "="
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5,
      "continueOnFail": true
    },
    {
      "id": "8443a71f-8cd9-4fdd-98e7-dd6956d7ba5f",
      "name": "Fetch Active Session and Prior Context",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1456,
        640
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "="
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "="
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5,
      "continueOnFail": true
    },
    {
      "id": "9f28db33-810a-4c6d-baa5-9ff93e76d080",
      "name": "Build Enterprise Context Package",
      "type": "n8n-nodes-base.code",
      "position": [
        1680,
        608
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const enterpriseRequest = $('Enterprise Auth, JWT and RBAC Validation').item.json.enterpriseRequest;\nconst rbacPolicies = $('Fetch RBAC Policies for Role and Tools').all().map(i => i.json);\nconst sessionData = $('Fetch Active Session and Prior Context').all();\n\n// Build allowed tools map from RBAC policies\nconst allowedTools = {};\nconst deniedTools = [];\n\nfor (const policy of rbacPolicies) {\n  if (policy.permission === 'ALLOW') {\n    allowedTools[policy.toolName] = {\n      allowedDataClasses: policy.allowedDataClasses?.split(',').map(d => d.trim()) || ['PUBLIC', 'INTERNAL'],\n      maxRecords: parseInt(policy.maxRecords) || 1000,\n      allowWrite: policy.allowWrite === 'true',\n      allowDelete: policy.allowDelete === 'false',\n      requiresApproval: policy.requiresApproval === 'true',\n      fieldRestrictions: policy.fieldRestrictions?.split(',').map(f => f.trim()) || []\n    };\n  }\n}\n\n// Check each requested tool against RBAC\nconst authorizedRequests = [];\nconst unauthorizedRequests = [];\n\nfor (const toolRequest of enterpriseRequest.toolRequests) {\n  const policy = allowedTools[toolRequest.toolName] || allowedTools[`${toolRequest.toolName.split('.')[0]}.*`];\n  if (policy || enterpriseRequest.roleLevel >= 5) {\n    // it_admin and super_admin bypass most tool restrictions\n    authorizedRequests.push({\n      ...toolRequest,\n      policy: policy || { allowedDataClasses: ['CONFIDENTIAL'], maxRecords: 10000, allowWrite: true }\n    });\n  } else {\n    unauthorizedRequests.push(toolRequest.toolName);\n  }\n}\n\nif (authorizedRequests.length === 0) {\n  throw new Error(\n    `RBAC Denial: Role '${enterpriseRequest.userRole}' has no permission for any of the requested tools: ${enterpriseRequest.toolRequests.map(t => t.toolName).join(', ')}`\n  );\n}\n\n// Restore session history\nconst sessionRecord = sessionData.length > 0 ? sessionData[0].json : null;\nconst sessionHistory = sessionRecord ? JSON.parse(sessionRecord.toolCallHistory || '[]') : [];\nconst sessionAge = sessionRecord ? Math.floor((Date.now() - new Date(sessionRecord.createdAt).getTime()) / 60000) : 0;\n\n// Geo + time policy check\nconst hour = new Date().getUTCHours();\nconst isBusinessHours = hour >= 6 && hour <= 22; // 06:00\u201322:00 UTC\nconst geoAllowed = !['RESTRICTED_REGION_1', 'RESTRICTED_REGION_2'].includes(enterpriseRequest.geoRegion);\n\nif (!geoAllowed) {\n  throw new Error(`Geo-policy violation: Access from region '${enterpriseRequest.geoRegion}' is restricted`);\n}\n\nreturn {\n  json: {\n    enterpriseRequest,\n    contextPackage: {\n      rbacSummary: {\n        totalPolicies: rbacPolicies.length,\n        authorizedTools: authorizedRequests.map(t => t.toolName),\n        unauthorizedTools: unauthorizedRequests,\n        authorizedCount: authorizedRequests.length,\n        deniedCount: unauthorizedRequests.length\n      },\n      authorizedRequests,\n      sessionContext: {\n        sessionId: enterpriseRequest.sessionId,\n        isNewSession: !sessionRecord,\n        sessionAgeMinutes: sessionAge,\n        priorToolCallCount: sessionHistory.length,\n        recentToolCalls: sessionHistory.slice(-5)\n      },\n      environmentContext: {\n        isBusinessHours,\n        geoRegion: enterpriseRequest.geoRegion,\n        geoAllowed,\n        utcHour: hour\n      }\n    }\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "76cbacda-f0c3-47cc-a4d5-8c092ed13ca6",
      "name": "Claude AI Contextual Orchestration and Tool Planning",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1904,
        608
      ],
      "parameters": {
        "text": "=You are an enterprise AI orchestration engine with deep knowledge of business systems, data governance, and multi-agent coordination. Your role is to reason over the enterprise context, plan the optimal tool execution strategy, validate every tool call for safety and policy compliance, and produce a structured execution plan.\n\n**Enterprise Request:**\n- Gateway Request ID: {{ $json.enterpriseRequest.gatewayRequestId }}\n- Tenant: {{ $json.enterpriseRequest.tenantId }}\n- Agent ID: {{ $json.enterpriseRequest.agentId }}\n- Agent Goal: {{ $json.enterpriseRequest.agentGoal }}\n- User: {{ $json.enterpriseRequest.userId }} (Role: {{ $json.enterpriseRequest.userRole }}, Level: {{ $json.enterpriseRequest.roleLevel }})\n- Department: {{ $json.enterpriseRequest.department }}\n- Geo Region: {{ $json.enterpriseRequest.geoRegion }}\n- Data Classification Ceiling: {{ $json.enterpriseRequest.maxResponseClassification }}\n- Session Age: {{ $json.contextPackage.sessionContext.sessionAgeMinutes }} minutes\n- Prior Tool Calls This Session: {{ $json.contextPackage.sessionContext.priorToolCallCount }}\n- Is Business Hours: {{ $json.contextPackage.environmentContext.isBusinessHours }}\n\n**Requested Tool Calls ({{ $json.contextPackage.rbacSummary.authorizedCount }} authorized of {{ $json.enterpriseRequest.toolCount }} requested):**\n{{ JSON.stringify($json.contextPackage.authorizedRequests, null, 2) }}\n\n**Denied Tools (RBAC):**\n{{ JSON.stringify($json.contextPackage.rbacSummary.unauthorizedTools, null, 2) }}\n\n**Recent Session History:**\n{{ JSON.stringify($json.contextPackage.sessionContext.recentToolCalls, null, 2) }}\n\n**Orchestration Tasks:**\n1. Analyze the agent goal and determine if the authorized tool set is sufficient to achieve it\n2. Identify optimal execution order and any dependencies between tools (e.g. tool B needs output from tool A)\n3. Flag any tool calls that appear anomalous, excessive, or misaligned with the stated agent goal\n4. Assess data sensitivity of the planned tool calls and recommend redaction needs\n5. Recommend whether parallel or sequential execution is safer given the goal and tool types\n6. Identify any tools that should be deferred, require human approval, or be skipped entirely\n7. Provide contextual reasoning that will be included in the audit trace\n\n**Enterprise Policy Rules:**\n- Tools accessing CONFIDENTIAL or RESTRICTED data require explicit goal justification\n- Write/mutating tools require sequential execution (never parallel) unless explicitly safe\n- Super-admin tools (user mgmt, tenant config) always require human confirmation\n- Agents must not chain more than 5 tool calls in a single request without elevated role\n- PII fields must be redacted in responses unless the requesting role has PII clearance\n- Cross-tenant data access is strictly prohibited\n\n**Response Format (JSON only, no markdown):**\n{\n  \"goalAchievable\": true,\n  \"goalAlignmentScore\": 91,\n  \"executionPlan\": [\n    {\n      \"step\": 1,\n      \"toolName\": \"crm.get_pipeline\",\n      \"executionMode\": \"parallel | sequential\",\n      \"dependsOn\": [],\n      \"priority\": \"high | medium | low\",\n      \"estimatedRiskLevel\": \"LOW\",\n      \"requiresHumanApproval\": false,\n      \"skipReason\": null,\n      \"orchestratorNotes\": \"Safe read-only call, no PII expected\"\n    }\n  ],\n  \"parallelGroups\": [[\"crm.get_pipeline\", \"erp.get_inventory\"], [\"analytics.run_report\"]],\n  \"sequentialTools\": [],\n  \"skipList\": [],\n  \"skipReasons\": {},\n  \"overallRiskLevel\": \"LOW | MEDIUM | HIGH | CRITICAL\",\n  \"overallRiskScore\": 18,\n  \"dataClassificationRequired\": \"INTERNAL\",\n  \"piiLikely\": false,\n  \"piiTools\": [],\n  \"redactionRecommended\": false,\n  \"redactionFields\": [],\n  \"humanApprovalRequired\": false,\n  \"humanApprovalTools\": [],\n  \"estimatedCompletionMs\": 3500,\n  \"orchestrationNotes\": \"Brief explanation of the plan for the audit log\",\n  \"warningsForAgent\": [\"list of non-blocking warnings the agent should know\"],\n  \"goalGapAnalysis\": \"What the agent can and cannot achieve with the authorized tool set\"\n}",
        "options": {
          "systemMessage": "You are an enterprise AI orchestration engine. Respond with valid JSON only \u2014 no markdown, no code blocks, no preamble. Apply strict enterprise data governance principles. Always err on the side of caution for mutating or high-risk tool calls."
        },
        "promptType": "define"
      },
      "typeVersion": 1.6
    },
    {
      "id": "0e792162-53ba-49bf-a3f4-9906c9fed8f3",
      "name": "Claude AI Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "position": [
        1984,
        832
      ],
      "parameters": {
        "model": "=claude-sonnet-4-20250514",
        "options": {
          "temperature": 0.15
        }
      },
      "credentials": {
        "anthropicApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a43b9b81-c3a6-40cf-879f-27ce35ae43fc",
      "name": "Parse Orchestration Plan and Enforce Policies",
      "type": "n8n-nodes-base.code",
      "position": [
        2256,
        608
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const aiResponse = $input.item.json;\nlet aiText = aiResponse.response || aiResponse.output || aiResponse.text || '';\n\nif (aiResponse.content && Array.isArray(aiResponse.content)) {\n  aiText = aiResponse.content[0]?.text || '';\n}\n\nconst cleanText = aiText.replace(/```json\\s*/g, '').replace(/```\\s*/g, '').trim();\n\nlet orchestrationPlan;\ntry {\n  orchestrationPlan = JSON.parse(cleanText);\n} catch (e) {\n  throw new Error(`Failed to parse orchestration plan: ${e.message}. Raw: ${cleanText.substring(0, 200)}`);\n}\n\n// Pull upstream context\nconst upstream = $('Build Enterprise Context Package').item.json;\n\n// Hard block on CRITICAL risk\nif (orchestrationPlan.overallRiskLevel === 'CRITICAL') {\n  throw new Error(\n    `Enterprise Policy Block: CRITICAL risk orchestration plan rejected. Risk score: ${orchestrationPlan.overallRiskScore}. Notes: ${orchestrationPlan.orchestrationNotes}`\n  );\n}\n\n// Filter execution plan to only non-skipped tools\nconst activeTools = (orchestrationPlan.executionPlan || []).filter(\n  step => !step.skipReason && !orchestrationPlan.skipList?.includes(step.toolName)\n);\n\n// Build tool dispatch map with parameters\nconst toolDispatchMap = {};\nfor (const authorizedReq of upstream.contextPackage.authorizedRequests) {\n  toolDispatchMap[authorizedReq.toolName] = authorizedReq.parameters || {};\n}\n\nreturn {\n  json: {\n    enterpriseRequest: upstream.enterpriseRequest,\n    contextPackage: upstream.contextPackage,\n    orchestrationPlan,\n    activeTools,\n    toolDispatchMap,\n    requiresHumanApproval: orchestrationPlan.humanApprovalRequired,\n    redactionRequired: orchestrationPlan.redactionRecommended,\n    redactionFields: orchestrationPlan.redactionFields || [],\n    piiTools: orchestrationPlan.piiTools || [],\n    plannedAt: new Date().toISOString()\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "f776c1b3-488c-4720-b9d4-dbc321382c15",
      "name": "Dispatch \u2014 CRM System",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2480,
        448
      ],
      "parameters": {
        "url": "https://YOUR_CRM_API/api/v2/mcp-dispatch",
        "method": "POST",
        "options": {
          "timeout": 12000
        },
        "jsonBody": "={\n  \"tools\": {{ JSON.stringify($json.activeTools.filter(t => t.toolName.startsWith('crm.'))) }},\n  \"parameters\": {{ JSON.stringify(Object.fromEntries(Object.entries($json.toolDispatchMap).filter(([k]) => k.startsWith('crm.')))) }},\n  \"userId\": \"{{ $json.enterpriseRequest.userId }}\",\n  \"tenantId\": \"{{ $json.enterpriseRequest.tenantId }}\",\n  \"requestId\": \"{{ $json.enterpriseRequest.gatewayRequestId }}\"\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            },
            {
              "name": "X-Tenant-ID",
              "value": "={{ $json.enterpriseRequest.tenantId }}"
            },
            {
              "name": "X-Gateway-Request-ID",
              "value": "={{ $json.enterpriseRequest.gatewayRequestId }}"
            },
            {
              "name": "X-User-Role",
              "value": "={{ $json.enterpriseRequest.userRole }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2,
      "continueOnFail": true
    },
    {
      "id": "c85e587e-3d1f-4aec-b859-967c189b7af8",
      "name": "Dispatch \u2014 ERP System",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2480,
        640
      ],
      "parameters": {
        "url": "https://YOUR_ERP_API/api/v2/mcp-dispatch",
        "method": "POST",
        "options": {
          "timeout": 12000
        },
        "jsonBody": "={\n  \"tools\": {{ JSON.stringify($json.activeTools.filter(t => t.toolName.startsWith('erp.'))) }},\n  \"parameters\": {{ JSON.stringify(Object.fromEntries(Object.entries($json.toolDispatchMap).filter(([k]) => k.startsWith('erp.')))) }},\n  \"userId\": \"{{ $json.enterpriseRequest.userId }}\",\n  \"tenantId\": \"{{ $json.enterpriseRequest.tenantId }}\",\n  \"requestId\": \"{{ $json.enterpriseRequest.gatewayRequestId }}\"\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            },
            {
              "name": "X-Tenant-ID",
              "value": "={{ $json.enterpriseRequest.tenantId }}"
            },
            {
              "name": "X-Gateway-Request-ID",
              "value": "={{ $json.enterpriseRequest.gatewayRequestId }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2,
      "continueOnFail": true
    },
    {
      "id": "32ad4f69-1c7d-45e1-b577-b145ce2aae94",
      "name": "Dispatch \u2014 Analytics and Data Warehouse",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2480,
        832
      ],
      "parameters": {
        "url": "https://YOUR_ANALYTICS_API/api/v2/mcp-dispatch",
        "method": "POST",
        "options": {
          "timeout": 20000
        },
        "jsonBody": "={\n  \"tools\": {{ JSON.stringify($json.activeTools.filter(t => t.toolName.startsWith('analytics.') || t.toolName.startsWith('data.'))) }},\n  \"parameters\": {{ JSON.stringify(Object.fromEntries(Object.entries($json.toolDispatchMap).filter(([k]) => k.startsWith('analytics.') || k.startsWith('data.')))) }},\n  \"userId\": \"{{ $json.enterpriseRequest.userId }}\",\n  \"tenantId\": \"{{ $json.enterpriseRequest.tenantId }}\",\n  \"maxClassification\": \"{{ $json.enterpriseRequest.maxResponseClassification }}\",\n  \"requestId\": \"{{ $json.enterpriseRequest.gatewayRequestId }}\"\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            },
            {
              "name": "X-Tenant-ID",
              "value": "={{ $json.enterpriseRequest.tenantId }}"
            },
            {
              "name": "X-Gateway-Request-ID",
              "value": "={{ $json.enterpriseRequest.gatewayRequestId }}"
            },
            {
              "name": "X-Data-Classification",
              "value": "={{ $json.enterpriseRequest.dataClassification }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2,
      "continueOnFail": true
    },
    {
      "id": "12826b7a-bf7a-4013-9f6a-caebd014f04e",
      "name": "Merge All System Dispatch Results",
      "type": "n8n-nodes-base.merge",
      "position": [
        2704,
        640
      ],
      "parameters": {
        "mode": "mergeByPosition"
      },
      "typeVersion": 3
    },
    {
      "id": "70059601-b742-4e7e-8d59-b6173c1b1b07",
      "name": "Aggregate Results and Apply DLP Redaction",
      "type": "n8n-nodes-base.code",
      "position": [
        2928,
        640
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Collect all dispatch results\nconst crmResult = $('Dispatch \u2014 CRM System').item.json;\nconst erpResult = $('Dispatch \u2014 ERP System').item.json;\nconst analyticsResult = $('Dispatch \u2014 Analytics and Data Warehouse').item.json;\nconst orchestrationData = $('Parse Orchestration Plan and Enforce Policies').item.json;\n\n// ---- Aggregate raw results ----\nconst rawResults = {\n  crm: crmResult?.error ? { error: crmResult.error, status: 'FAILED' } : (crmResult || { status: 'SKIPPED' }),\n  erp: erpResult?.error ? { error: erpResult.error, status: 'FAILED' } : (erpResult || { status: 'SKIPPED' }),\n  analytics: analyticsResult?.error ? { error: analyticsResult.error, status: 'FAILED' } : (analyticsResult || { status: 'SKIPPED' })\n};\n\n// ---- DLP Redaction Engine ----\nconst PII_PATTERNS = [\n  { field: 'email', pattern: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g, replacement: '[EMAIL_REDACTED]' },\n  { field: 'phone', pattern: /\\b\\d{3}[-.]?\\d{3}[-.]?\\d{4}\\b/g, replacement: '[PHONE_REDACTED]' },\n  { field: 'ssn', pattern: /\\b\\d{3}-\\d{2}-\\d{4}\\b/g, replacement: '[SSN_REDACTED]' },\n  { field: 'creditCard', pattern: /\\b\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}\\b/g, replacement: '[CC_REDACTED]' },\n  { field: 'apiKey', pattern: /([Aa]pi[_-]?[Kk]ey|[Tt]oken|[Ss]ecret)[\"']?\\s*[:=]\\s*[\"']?[a-zA-Z0-9_\\-]{20,}/g, replacement: '[CREDENTIAL_REDACTED]' }\n];\n\nconst ROLE_HAS_PII_CLEARANCE = ['hr_admin', 'it_admin', 'super_admin'].includes(\n  orchestrationData.enterpriseRequest.userRole\n);\n\nfunction redactText(text) {\n  if (typeof text !== 'string') return text;\n  let redacted = text;\n  for (const pattern of PII_PATTERNS) {\n    redacted = redacted.replace(pattern.pattern, pattern.replacement);\n  }\n  return redacted;\n}\n\nfunction deepRedact(obj, depth = 0) {\n  if (depth > 8) return obj;\n  if (typeof obj === 'string') return redactText(obj);\n  if (Array.isArray(obj)) return obj.map(item => deepRedact(item, depth + 1));\n  if (obj && typeof obj === 'object') {\n    const result = {};\n    for (const [key, value] of Object.entries(obj)) {\n      // Redact entire field if it's a known sensitive field name\n      const sensitiveKeys = ['password', 'secret', 'token', 'apiKey', 'api_key', 'private_key', 'ssn', 'dob', 'dateOfBirth'];\n      if (sensitiveKeys.some(sk => key.toLowerCase().includes(sk))) {\n        result[key] = '[FIELD_REDACTED]';\n      } else {\n        result[key] = deepRedact(value, depth + 1);\n      }\n    }\n    return result;\n  }\n  return obj;\n}\n\n// Apply redaction based on role clearance and orchestration recommendation\nconst applyRedaction = orchestrationData.redactionRequired && !ROLE_HAS_PII_CLEARANCE;\nconst processedResults = applyRedaction ? deepRedact(rawResults) : rawResults;\n\n// ---- Compute execution summary ----\nconst systemStatuses = Object.entries(rawResults).map(([system, result]) => ({\n  system,\n  status: result.error ? 'FAILED' : result.status === 'SKIPPED' ? 'SKIPPED' : 'SUCCESS',\n  hasData: !result.error && result.status !== 'SKIPPED' && Object.keys(result).length > 0\n}));\n\nconst successCount = systemStatuses.filter(s => s.status === 'SUCCESS').length;\nconst failureCount = systemStatuses.filter(s => s.status === 'FAILED').length;\nconst skippedCount = systemStatuses.filter(s => s.status === 'SKIPPED').length;\n\nreturn {\n  json: {\n    enterpriseRequest: orchestrationData.enterpriseRequest,\n    orchestrationPlan: orchestrationData.orchestrationPlan,\n    contextPackage: orchestrationData.contextPackage,\n    redactionApplied: applyRedaction,\n    redactionFields: orchestrationData.redactionFields,\n    results: processedResults,\n    executionSummary: {\n      totalSystems: 3,\n      successCount,\n      failureCount,\n      skippedCount,\n      systemStatuses,\n      overallSuccess: failureCount === 0\n    },\n    aggregatedAt: new Date().toISOString()\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "d7f1ab6e-451f-4dbc-b8b0-748da71af581",
      "name": "Send Policy and Security Alert",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        3152,
        416
      ],
      "parameters": {
        "options": {},
        "subject": "=[MCP ENTERPRISE ALERT] {{ $json.orchestrationPlan.overallRiskLevel }} Risk Orchestration \u2014 {{ $json.enterpriseRequest.tenantId }} | {{ $json.enterpriseRequest.agentId }}",
        "toEmail": "=",
        "fromEmail": "="
      },
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1,
      "continueOnFail": true
    },
    {
      "id": "d432bb79-6ba8-45e0-80f0-8358e13fdf4d",
      "name": "Write SOC2 Compliance Audit Log",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3152,
        608
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "="
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "="
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5,
      "continueOnFail": true
    },
    {
      "id": "b712c7a8-c736-4c27-8f13-2c0fbe5111fd",
      "name": "Update Session Registry",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3152,
        800
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "="
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "="
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5,
      "continueOnFail": true
    },
    {
      "id": "111a1e21-32f6-435b-8e56-92ee63d632e2",
      "name": "Build Final MCP Enterprise Response",
      "type": "n8n-nodes-base.code",
      "position": [
        3376,
        640
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const data = $input.item.json;\n\n// Build clean, MCP-compliant enterprise response\nreturn {\n  json: {\n    // MCP response envelope\n    mcpVersion: data.enterpriseRequest.mcpVersion,\n    gatewayRequestId: data.enterpriseRequest.gatewayRequestId,\n    requestId: data.enterpriseRequest.sessionId,\n    traceId: data.enterpriseRequest.traceId,\n\n    // Execution outcome\n    success: data.executionSummary.overallSuccess,\n    isDryRun: data.enterpriseRequest.dryRun,\n\n    // Tool results per system (DLP-redacted)\n    results: data.results,\n\n    // Execution summary for agent\n    executionSummary: data.executionSummary,\n\n    // Orchestration insights for agent\n    orchestrationInsights: {\n      goalAchievable: data.orchestrationPlan.goalAchievable,\n      goalAlignmentScore: data.orchestrationPlan.goalAlignmentScore,\n      goalGapAnalysis: data.orchestrationPlan.goalGapAnalysis,\n      warningsForAgent: data.orchestrationPlan.warningsForAgent || [],\n      toolsSkipped: data.orchestrationPlan.skipList || [],\n      skipReasons: data.orchestrationPlan.skipReasons || {}\n    },\n\n    // Governance metadata\n    governance: {\n      overallRiskLevel: data.orchestrationPlan.overallRiskLevel,\n      redactionApplied: data.redactionApplied,\n      redactionFields: data.redactionFields,\n      humanApprovalRequired: data.orchestrationPlan.humanApprovalRequired,\n      humanApprovalTools: data.orchestrationPlan.humanApprovalTools || [],\n      dataClassification: data.enterpriseRequest.dataClassification,\n      rbacDeniedTools: data.contextPackage.rbacSummary.unauthorizedTools\n    },\n\n    // Timing\n    respondedAt: new Date().toISOString()\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "cf0b540a-e21a-4b2b-8b04-e88b3eebf203",
      "name": "Return MCP Enterprise Result to Agent",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        3600,
        640
      ],
      "parameters": {
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "application/json"
              },
              {
                "name": "X-MCP-Gateway-Request-ID",
                "value": "={{ $json.gatewayRequestId }}"
              },
              {
                "name": "X-MCP-Risk-Level",
                "value": "={{ $json.governance.overallRiskLevel }}"
              },
              {
                "name": "X-MCP-Tenant-ID",
                "value": "={{ $json.gatewayRequestId.split('-')[0] }}"
              },
              {
                "name": "X-MCP-Trace-ID",
                "value": "={{ $json.traceId }}"
              }
            ]
          }
        },
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify($json, null, 2) }}"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "7f258627-e824-442b-a44d-fd6cc6a38fe0",
  "connections": {
    "Claude AI Model": {
      "ai_languageModel": [
        [
          {
            "node": "Claude AI Contextual Orchestration and Tool Planning",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Dispatch \u2014 CRM System": {
      "main": [
        [
          {
            "node": "Merge All System Dispatch Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Dispatch \u2014 ERP System": {
      "main": [
        [
          {
            "node": "Merge All System Dispatch Results",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Update Session Registry": {
      "main": [
        [
          {
            "node": "Build Final MCP Enterprise Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Policy and Security Alert": {
      "main": [
        [
          {
            "node": "Build Final MCP Enterprise Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write SOC2 Compliance Audit Log": {
      "main": [
        [
          {
            "node": "Build Final MCP Enterprise Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Enterprise Context Package": {
      "main": [
        [
          {
            "node": "Claude AI Contextual Orchestration and Tool Planning",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge All System Dispatch Results": {
      "main": [
        [
          {
            "node": "Aggregate Results and Apply DLP Redaction",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Final MCP Enterprise Response": {
      "main": [
        [
          {
            "node": "Return MCP Enterprise Result to Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Receive Enterprise AI Agent Request": {
      "main": [
        [
          {
            "node": "Enterprise Auth, JWT and RBAC Validation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Active Session and Prior Context": {
      "main": [
        [
          {
            "node": "Build Enterprise Context Package",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch RBAC Policies for Role and Tools": {
      "main": [
        [
          {
            "node": "Build Enterprise Context Package",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Enterprise Auth, JWT and RBAC Validation": {
      "main": [
        [
          {
            "node": "Fetch RBAC Policies for Role and Tools",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Active Session and Prior Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Results and Apply DLP Redaction": {
      "main": [
        [
          {
            "node": "Send Policy and Security Alert",
            "type": "main",
            "index": 0
          },
          {
            "node": "Write SOC2 Compliance Audit Log",
            "type": "main",
            "index": 0
          },
          {
            "node": "Update Session Registry",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Dispatch \u2014 Analytics and Data Warehouse": {
      "main": [
        [
          {
            "node": "Merge All System Dispatch Results",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Parse Orchestration Plan and Enforce Policies": {
      "main": [
        [
          {
            "node": "Dispatch \u2014 CRM System",
            "type": "main",
            "index": 0
          },
          {
            "node": "Dispatch \u2014 ERP System",
            "type": "main",
            "index": 0
          },
          {
            "node": "Dispatch \u2014 Analytics and Data Warehouse",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Claude AI Contextual Orchestration and Tool Planning": {
      "main": [
        [
          {
            "node": "Parse Orchestration Plan and Enforce Policies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}