n8n-workflow-builder-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/cursor_rules.mdc +53 -0
- package/.cursor/rules/dev_workflow.mdc +219 -0
- package/.cursor/rules/mcp.mdc +430 -0
- package/.cursor/rules/self_improve.mdc +72 -0
- package/.cursor/rules/taskmaster.mdc +382 -0
- package/.cursorignore +1 -0
- package/.cursorrules +4 -0
- package/.env.example +23 -0
- package/.eslintrc.json +38 -0
- package/.github/workflows/npm-publish-github-packages.yml +55 -0
- package/.prettierrc +9 -0
- package/.roo/rules/dev_workflow.md +219 -0
- package/.roo/rules/mcp.md +430 -0
- package/.roo/rules/roo_rules.md +53 -0
- package/.roo/rules/self_improve.md +72 -0
- package/.roo/rules/taskmaster.md +382 -0
- package/.roo/rules-architect/architect-rules +93 -0
- package/.roo/rules-ask/ask-rules +89 -0
- package/.roo/rules-boomerang/boomerang-rules +181 -0
- package/.roo/rules-code/code-rules +61 -0
- package/.roo/rules-debug/debug-rules +68 -0
- package/.roo/rules-test/test-rules +61 -0
- package/.roomodes +63 -0
- package/.taskmasterconfig +31 -0
- package/.windsurfrules +2382 -0
- package/LICENSE +21 -0
- package/README.md +210 -0
- package/config/credentials/credentials.json +1 -0
- package/config/default.js +41 -0
- package/package.json +56 -0
- package/scripts/demo-n8n-integration.js +161 -0
- package/scripts/demo-workflow-generator.js +102 -0
- package/scripts/init.sh +36 -0
- package/scripts/prd.txt +197 -0
- package/src/index.ts +1440 -0
- package/src/middleware/auth.js +273 -0
- package/src/middleware/authorize.js +183 -0
- package/src/middleware/logging.js +64 -0
- package/src/middleware/mcp.js +187 -0
- package/src/middleware/rateLimiter.js +82 -0
- package/src/middleware/validation.js +241 -0
- package/src/models/credential.js +359 -0
- package/src/models/llmService.js +236 -0
- package/src/models/n8nIntegration.js +542 -0
- package/src/models/storage.js +196 -0
- package/src/models/tool.js +148 -0
- package/src/models/user.js +164 -0
- package/src/models/workflow.js +229 -0
- package/src/routes/toolDefinitions.js +62 -0
- package/src/routes/toolExecution.js +79 -0
- package/src/tools/__index.js +242 -0
- package/src/tools/connectionManagement.js +500 -0
- package/src/tools/n8nIntegration.js +370 -0
- package/src/tools/nodeDiscovery.js +488 -0
- package/src/tools/nodeManagement.js +674 -0
- package/src/tools/toolDefinitions.js +660 -0
- package/src/tools/workflowCreation.js +100 -0
- package/src/tools/workflowGenerator.js +152 -0
- package/src/tools/workflowStorage.js +113 -0
- package/src/tools/workflowTesting.js +285 -0
- package/src/utils/encryption.js +164 -0
- package/src/utils/logger.js +84 -0
- package/src/utils/mcp.js +85 -0
- package/src/utils/securityLogger.js +109 -0
- package/tests/auth.test.js +402 -0
- package/tests/authorize.test.js +208 -0
- package/tests/run-memory-tests.js +55 -0
- package/tests/run-tests.js +55 -0
- package/tests/server.test.js +203 -0
- package/tests/unit/add-ai-connections.test.js +385 -0
- package/tests/unit/connectionManagement.test.js +309 -0
- package/tests/unit/langchain-llm-format.test.js +259 -0
- package/tests/unit/memory-connection.test.js +140 -0
- package/tests/unit/memory-integration.test.js +253 -0
- package/tests/unit/n8nIntegration.test.js +291 -0
- package/tests/unit/nodeDiscovery.test.js +270 -0
- package/tests/unit/nodeManagement.test.js +522 -0
- package/tests/unit/utils/mcp-test-utils.js +94 -0
- package/tests/unit/workflowCreation.test.js +110 -0
- package/tests/unit/workflowTesting.test.js +269 -0
- package/tests/user.test.js +181 -0
- package/tsconfig.json +20 -0
- package/workflow_nodes/Brandfetch.json +85 -0
- package/workflow_nodes/WorkflowTrigger.json +28 -0
- package/workflow_nodes/actionNetwork.json +218 -0
- package/workflow_nodes/activeCampaign.json +722 -0
- package/workflow_nodes/activeCampaignTrigger.json +52 -0
- package/workflow_nodes/acuitySchedulingTrigger.json +8 -0
- package/workflow_nodes/adalo.json +123 -0
- package/workflow_nodes/affinity.json +203 -0
- package/workflow_nodes/affinityTrigger.json +124 -0
- package/workflow_nodes/aggregate.json +119 -0
- package/workflow_nodes/agileCrm.json +503 -0
- package/workflow_nodes/aiTransform.json +17 -0
- package/workflow_nodes/airtable.json +226 -0
- package/workflow_nodes/airtableTrigger.json +120 -0
- package/workflow_nodes/airtop.json +10 -0
- package/workflow_nodes/amqp.json +62 -0
- package/workflow_nodes/amqpTrigger.json +8 -0
- package/workflow_nodes/apiTemplateIo.json +147 -0
- package/workflow_nodes/asana.json +446 -0
- package/workflow_nodes/asanaTrigger.json +52 -0
- package/workflow_nodes/automizy.json +195 -0
- package/workflow_nodes/autopilot.json +287 -0
- package/workflow_nodes/autopilotTrigger.json +8 -0
- package/workflow_nodes/awsCertificateManager.json +223 -0
- package/workflow_nodes/awsComprehend.json +125 -0
- package/workflow_nodes/awsDynamoDb.json +251 -0
- package/workflow_nodes/awsElb.json +174 -0
- package/workflow_nodes/awsLambda.json +69 -0
- package/workflow_nodes/awsRekognition.json +191 -0
- package/workflow_nodes/awsS3.json +32 -0
- package/workflow_nodes/awsSes.json +302 -0
- package/workflow_nodes/awsSns.json +110 -0
- package/workflow_nodes/awsSnsTrigger.json +47 -0
- package/workflow_nodes/awsSqs.json +140 -0
- package/workflow_nodes/awsTextract.json +43 -0
- package/workflow_nodes/awsTranscribe.json +217 -0
- package/workflow_nodes/azureCosmosDb.json +8 -0
- package/workflow_nodes/azureStorage.json +17 -0
- package/workflow_nodes/bambooHr.json +8 -0
- package/workflow_nodes/bannerbear.json +126 -0
- package/workflow_nodes/baserow.json +277 -0
- package/workflow_nodes/beeminder.json +146 -0
- package/workflow_nodes/bitbucketTrigger.json +62 -0
- package/workflow_nodes/bitly.json +130 -0
- package/workflow_nodes/bitwarden.json +224 -0
- package/workflow_nodes/box.json +457 -0
- package/workflow_nodes/boxTrigger.json +8 -0
- package/workflow_nodes/brevo.json +41 -0
- package/workflow_nodes/brevoTrigger.json +145 -0
- package/workflow_nodes/bubble.json +212 -0
- package/workflow_nodes/calTrigger.json +91 -0
- package/workflow_nodes/calendlyTrigger.json +71 -0
- package/workflow_nodes/chargebee.json +217 -0
- package/workflow_nodes/chargebeeTrigger.json +187 -0
- package/workflow_nodes/circleCi.json +89 -0
- package/workflow_nodes/ciscoWebex.json +593 -0
- package/workflow_nodes/ciscoWebexTrigger.json +159 -0
- package/workflow_nodes/clearbit.json +138 -0
- package/workflow_nodes/clickUp.json +793 -0
- package/workflow_nodes/clickUpTrigger.json +188 -0
- package/workflow_nodes/clockify.json +372 -0
- package/workflow_nodes/clockifyTrigger.json +26 -0
- package/workflow_nodes/cloudflare.json +103 -0
- package/workflow_nodes/cockpit.json +161 -0
- package/workflow_nodes/coda.json +242 -0
- package/workflow_nodes/code.json +40 -0
- package/workflow_nodes/coinGecko.json +363 -0
- package/workflow_nodes/compareDatasets.json +14 -0
- package/workflow_nodes/compression.json +66 -0
- package/workflow_nodes/contentful.json +29 -0
- package/workflow_nodes/convertKit.json +159 -0
- package/workflow_nodes/convertKitTrigger.json +109 -0
- package/workflow_nodes/convertToFile.json +64 -0
- package/workflow_nodes/copper.json +239 -0
- package/workflow_nodes/copperTrigger.json +8 -0
- package/workflow_nodes/cortex.json +348 -0
- package/workflow_nodes/crateDb.json +90 -0
- package/workflow_nodes/cron.json +23 -0
- package/workflow_nodes/crowdDev.json +8 -0
- package/workflow_nodes/crowdDevTrigger.json +8 -0
- package/workflow_nodes/crypto.json +147 -0
- package/workflow_nodes/customerIo.json +206 -0
- package/workflow_nodes/customerIoTrigger.json +185 -0
- package/workflow_nodes/dateTime.json +39 -0
- package/workflow_nodes/debughelper.json +162 -0
- package/workflow_nodes/deepL.json +103 -0
- package/workflow_nodes/demio.json +187 -0
- package/workflow_nodes/dhl.json +53 -0
- package/workflow_nodes/discord.json +81 -0
- package/workflow_nodes/discourse.json +319 -0
- package/workflow_nodes/disqus.json +254 -0
- package/workflow_nodes/drift.json +112 -0
- package/workflow_nodes/dropbox.json +258 -0
- package/workflow_nodes/dropcontact.json +154 -0
- package/workflow_nodes/e2eTest.json +70 -0
- package/workflow_nodes/editImage.json +132 -0
- package/workflow_nodes/egoi.json +220 -0
- package/workflow_nodes/elasticSecurity.json +401 -0
- package/workflow_nodes/elasticsearch.json +422 -0
- package/workflow_nodes/emailReadImap.json +88 -0
- package/workflow_nodes/emailSend.json +38 -0
- package/workflow_nodes/emelia.json +201 -0
- package/workflow_nodes/emeliaTrigger.json +57 -0
- package/workflow_nodes/erpNext.json +139 -0
- package/workflow_nodes/errorTrigger.json +15 -0
- package/workflow_nodes/evaluationMetrics.json +21 -0
- package/workflow_nodes/eventbriteTrigger.json +125 -0
- package/workflow_nodes/executeCommand.json +25 -0
- package/workflow_nodes/executeWorkflow.json +102 -0
- package/workflow_nodes/executeWorkflowTrigger.json +65 -0
- package/workflow_nodes/executionData.json +35 -0
- package/workflow_nodes/extractFromFile.json +71 -0
- package/workflow_nodes/facebookGraphApi.json +234 -0
- package/workflow_nodes/facebookLeadAdsTrigger.json +8 -0
- package/workflow_nodes/facebookTrigger.json +112 -0
- package/workflow_nodes/figmaTrigger.json +8 -0
- package/workflow_nodes/filemaker.json +268 -0
- package/workflow_nodes/filter.json +24 -0
- package/workflow_nodes/flow.json +323 -0
- package/workflow_nodes/flowTrigger.json +52 -0
- package/workflow_nodes/form.json +25 -0
- package/workflow_nodes/formIoTrigger.json +59 -0
- package/workflow_nodes/formTrigger.json +8 -0
- package/workflow_nodes/formstackTrigger.json +8 -0
- package/workflow_nodes/freshdesk.json +584 -0
- package/workflow_nodes/freshservice.json +899 -0
- package/workflow_nodes/freshworksCrm.json +772 -0
- package/workflow_nodes/ftp.json +127 -0
- package/workflow_nodes/function.json +22 -0
- package/workflow_nodes/functionItem.json +22 -0
- package/workflow_nodes/gSuiteAdmin.json +562 -0
- package/workflow_nodes/getResponse.json +310 -0
- package/workflow_nodes/getResponseTrigger.json +82 -0
- package/workflow_nodes/ghost.json +290 -0
- package/workflow_nodes/git.json +184 -0
- package/workflow_nodes/github.json +732 -0
- package/workflow_nodes/githubTrigger.json +317 -0
- package/workflow_nodes/gitlab.json +544 -0
- package/workflow_nodes/gitlabTrigger.json +61 -0
- package/workflow_nodes/gmail.json +62 -0
- package/workflow_nodes/gmailTrigger.json +127 -0
- package/workflow_nodes/goToWebinar.json +430 -0
- package/workflow_nodes/gong.json +22 -0
- package/workflow_nodes/googleAds.json +116 -0
- package/workflow_nodes/googleAnalytics.json +28 -0
- package/workflow_nodes/googleBigQuery.json +38 -0
- package/workflow_nodes/googleBooks.json +154 -0
- package/workflow_nodes/googleBusinessProfile.json +277 -0
- package/workflow_nodes/googleBusinessProfileTrigger.json +55 -0
- package/workflow_nodes/googleCalendar.json +474 -0
- package/workflow_nodes/googleCalendarTrigger.json +72 -0
- package/workflow_nodes/googleChat.json +187 -0
- package/workflow_nodes/googleCloudNaturalLanguage.json +171 -0
- package/workflow_nodes/googleCloudStorage.json +466 -0
- package/workflow_nodes/googleContacts.json +481 -0
- package/workflow_nodes/googleDocs.json +312 -0
- package/workflow_nodes/googleDrive.json +920 -0
- package/workflow_nodes/googleDriveTrigger.json +181 -0
- package/workflow_nodes/googleFirebaseCloudFirestore.json +156 -0
- package/workflow_nodes/googleFirebaseRealtimeDatabase.json +75 -0
- package/workflow_nodes/googlePerspective.json +94 -0
- package/workflow_nodes/googleSheets.json +98 -0
- package/workflow_nodes/googleSheetsTrigger.json +192 -0
- package/workflow_nodes/googleSlides.json +186 -0
- package/workflow_nodes/googleTasks.json +198 -0
- package/workflow_nodes/googleTranslate.json +80 -0
- package/workflow_nodes/gotify.json +110 -0
- package/workflow_nodes/grafana.json +155 -0
- package/workflow_nodes/graphql.json +165 -0
- package/workflow_nodes/grist.json +13 -0
- package/workflow_nodes/gumroadTrigger.json +8 -0
- package/workflow_nodes/hackerNews.json +100 -0
- package/workflow_nodes/haloPSA.json +286 -0
- package/workflow_nodes/harvest.json +699 -0
- package/workflow_nodes/helpScout.json +629 -0
- package/workflow_nodes/helpScoutTrigger.json +8 -0
- package/workflow_nodes/highLevel.json +8 -0
- package/workflow_nodes/homeAssistant.json +201 -0
- package/workflow_nodes/html.json +118 -0
- package/workflow_nodes/htmlExtract.json +87 -0
- package/workflow_nodes/httpRequest.json +472 -0
- package/workflow_nodes/hubspot.json +62 -0
- package/workflow_nodes/hubspotTrigger.json +138 -0
- package/workflow_nodes/humanticAi.json +82 -0
- package/workflow_nodes/hunter.json +168 -0
- package/workflow_nodes/iCal.json +20 -0
- package/workflow_nodes/if.json +24 -0
- package/workflow_nodes/intercom.json +335 -0
- package/workflow_nodes/interval.json +8 -0
- package/workflow_nodes/invoiceNinja.json +882 -0
- package/workflow_nodes/invoiceNinjaTrigger.json +11 -0
- package/workflow_nodes/itemLists.json +313 -0
- package/workflow_nodes/iterable.json +168 -0
- package/workflow_nodes/jenkins.json +172 -0
- package/workflow_nodes/jira.json +529 -0
- package/workflow_nodes/jiraTrigger.json +308 -0
- package/workflow_nodes/jotFormTrigger.json +44 -0
- package/workflow_nodes/jwt.json +195 -0
- package/workflow_nodes/kafka.json +132 -0
- package/workflow_nodes/kafkaTrigger.json +11 -0
- package/workflow_nodes/keap.json +915 -0
- package/workflow_nodes/keapTrigger.json +37 -0
- package/workflow_nodes/kitemaker.json +153 -0
- package/workflow_nodes/koBoToolbox.json +337 -0
- package/workflow_nodes/koBoToolboxTrigger.json +8 -0
- package/workflow_nodes/langchain_Summarization Chain.json +60 -0
- package/workflow_nodes/langchain_agent.json +145 -0
- package/workflow_nodes/langchain_allowFileUploads.json +180 -0
- package/workflow_nodes/langchain_chainLlm.json +16 -0
- package/workflow_nodes/langchain_chainSummarization.json +119 -0
- package/workflow_nodes/langchain_code.json +62 -0
- package/workflow_nodes/langchain_documentBinaryInputLoader.json +8 -0
- package/workflow_nodes/langchain_documentDefaultDataLoader.json +8 -0
- package/workflow_nodes/langchain_documentGithubLoader.json +8 -0
- package/workflow_nodes/langchain_documentJsonInputLoader.json +8 -0
- package/workflow_nodes/langchain_embeddingDimensions.json +17 -0
- package/workflow_nodes/langchain_embeddingsAwsBedrock.json +8 -0
- package/workflow_nodes/langchain_embeddingsAzureOpenAi.json +151 -0
- package/workflow_nodes/langchain_embeddingsCohere.json +8 -0
- package/workflow_nodes/langchain_embeddingsGoogleGemini.json +8 -0
- package/workflow_nodes/langchain_embeddingsGoogleVertex.json +8 -0
- package/workflow_nodes/langchain_embeddingsHuggingFaceInference.json +8 -0
- package/workflow_nodes/langchain_embeddingsMistralCloud.json +8 -0
- package/workflow_nodes/langchain_embeddingsOllama.json +8 -0
- package/workflow_nodes/langchain_informationExtractor.json +81 -0
- package/workflow_nodes/langchain_lmChatAwsBedrock.json +8 -0
- package/workflow_nodes/langchain_lmChatAzureOpenAi.json +151 -0
- package/workflow_nodes/langchain_lmChatDeepSeek.json +10 -0
- package/workflow_nodes/langchain_lmChatGoogleGemini.json +31 -0
- package/workflow_nodes/langchain_lmChatGoogleVertex.json +32 -0
- package/workflow_nodes/langchain_lmChatGroq.json +8 -0
- package/workflow_nodes/langchain_lmChatMistralCloud.json +8 -0
- package/workflow_nodes/langchain_lmChatOllama.json +8 -0
- package/workflow_nodes/langchain_lmChatOpenAi.json +155 -0
- package/workflow_nodes/langchain_lmChatOpenRouter.json +10 -0
- package/workflow_nodes/langchain_lmChatXAiGrok.json +10 -0
- package/workflow_nodes/langchain_lmCohere.json +8 -0
- package/workflow_nodes/langchain_lmOllama.json +8 -0
- package/workflow_nodes/langchain_lmOpenAi.json +251 -0
- package/workflow_nodes/langchain_lmOpenHuggingFaceInference.json +8 -0
- package/workflow_nodes/langchain_manualChatTrigger.json +11 -0
- package/workflow_nodes/langchain_mcpClientTool.json +86 -0
- package/workflow_nodes/langchain_mcpTrigger.json +8 -0
- package/workflow_nodes/langchain_memoryBufferWindow.json +13 -0
- package/workflow_nodes/langchain_memoryChatRetriever.json +22 -0
- package/workflow_nodes/langchain_memoryManager.json +106 -0
- package/workflow_nodes/langchain_memoryMongoDbChat.json +10 -0
- package/workflow_nodes/langchain_memoryMotorhead.json +13 -0
- package/workflow_nodes/langchain_memoryPostgresChat.json +13 -0
- package/workflow_nodes/langchain_memoryRedisChat.json +15 -0
- package/workflow_nodes/langchain_memoryXata.json +14 -0
- package/workflow_nodes/langchain_memoryZep.json +13 -0
- package/workflow_nodes/langchain_model.json +155 -0
- package/workflow_nodes/langchain_mongoCollection.json +16 -0
- package/workflow_nodes/langchain_notice.json +22 -0
- package/workflow_nodes/langchain_openAiAssistant.json +132 -0
- package/workflow_nodes/langchain_options.json +17 -0
- package/workflow_nodes/langchain_outputParserAutofixing.json +8 -0
- package/workflow_nodes/langchain_outputParserItemList.json +8 -0
- package/workflow_nodes/langchain_outputParserStructured.json +12 -0
- package/workflow_nodes/langchain_pineconeNamespace.json +16 -0
- package/workflow_nodes/langchain_queryName.json +16 -0
- package/workflow_nodes/langchain_retrieverContextualCompression.json +8 -0
- package/workflow_nodes/langchain_retrieverMultiQuery.json +8 -0
- package/workflow_nodes/langchain_retrieverVectorStore.json +8 -0
- package/workflow_nodes/langchain_retrieverWorkflow.json +103 -0
- package/workflow_nodes/langchain_sentimentAnalysis.json +52 -0
- package/workflow_nodes/langchain_systemPromptTemplate.json +47 -0
- package/workflow_nodes/langchain_tableName.json +23 -0
- package/workflow_nodes/langchain_textClassifier.json +66 -0
- package/workflow_nodes/langchain_textSplitterCharacterTextSplitter.json +8 -0
- package/workflow_nodes/langchain_textSplitterRecursiveCharacterTextSplitter.json +8 -0
- package/workflow_nodes/langchain_textSplitterTokenSplitter.json +8 -0
- package/workflow_nodes/langchain_toolCalculator.json +8 -0
- package/workflow_nodes/langchain_toolCode.json +12 -0
- package/workflow_nodes/langchain_toolHttpRequest.json +232 -0
- package/workflow_nodes/langchain_toolSearXng.json +8 -0
- package/workflow_nodes/langchain_toolSerpApi.json +8 -0
- package/workflow_nodes/langchain_toolThink.json +8 -0
- package/workflow_nodes/langchain_toolVectorStore.json +11 -0
- package/workflow_nodes/langchain_toolWikipedia.json +8 -0
- package/workflow_nodes/langchain_toolWolframAlpha.json +8 -0
- package/workflow_nodes/langchain_toolWorkflow.json +8 -0
- package/workflow_nodes/langchain_vectorStoreInMemoryInsert.json +29 -0
- package/workflow_nodes/langchain_vectorStoreInMemoryLoad.json +8 -0
- package/workflow_nodes/langchain_vectorStorePineconeInsert.json +37 -0
- package/workflow_nodes/langchain_vectorStorePineconeLoad.json +8 -0
- package/workflow_nodes/langchain_vectorStoreSupabaseInsert.json +32 -0
- package/workflow_nodes/langchain_vectorStoreSupabaseLoad.json +8 -0
- package/workflow_nodes/langchain_vectorStoreZepInsert.json +46 -0
- package/workflow_nodes/langchain_vectorStoreZepLoad.json +8 -0
- package/workflow_nodes/ldap.json +182 -0
- package/workflow_nodes/lemlist.json +44 -0
- package/workflow_nodes/lemlistTrigger.json +45 -0
- package/workflow_nodes/limit.json +26 -0
- package/workflow_nodes/line.json +95 -0
- package/workflow_nodes/linear.json +151 -0
- package/workflow_nodes/linearTrigger.json +71 -0
- package/workflow_nodes/lingvaNex.json +66 -0
- package/workflow_nodes/linkedIn.json +142 -0
- package/workflow_nodes/localFileTrigger.json +120 -0
- package/workflow_nodes/lonescale.json +171 -0
- package/workflow_nodes/lonescaleTrigger.json +8 -0
- package/workflow_nodes/magento2.json +164 -0
- package/workflow_nodes/mailcheck.json +46 -0
- package/workflow_nodes/mailchimp.json +507 -0
- package/workflow_nodes/mailchimpTrigger.json +100 -0
- package/workflow_nodes/mailerLite.json +24 -0
- package/workflow_nodes/mailerLiteTrigger.json +74 -0
- package/workflow_nodes/mailgun.json +81 -0
- package/workflow_nodes/mailjet.json +201 -0
- package/workflow_nodes/mailjetTrigger.json +8 -0
- package/workflow_nodes/mandrill.json +372 -0
- package/workflow_nodes/manualTrigger.json +8 -0
- package/workflow_nodes/markdown.json +376 -0
- package/workflow_nodes/marketstack.json +126 -0
- package/workflow_nodes/matrix.json +264 -0
- package/workflow_nodes/mattermost.json +8 -0
- package/workflow_nodes/mautic.json +564 -0
- package/workflow_nodes/mauticTrigger.json +54 -0
- package/workflow_nodes/medium.json +209 -0
- package/workflow_nodes/merge.json +125 -0
- package/workflow_nodes/messageBird.json +182 -0
- package/workflow_nodes/metabase.json +175 -0
- package/workflow_nodes/microsoftDynamicsCrm.json +100 -0
- package/workflow_nodes/microsoftEntra.json +51 -0
- package/workflow_nodes/microsoftExcel.json +35 -0
- package/workflow_nodes/microsoftGraphSecurity.json +113 -0
- package/workflow_nodes/microsoftOneDrive.json +232 -0
- package/workflow_nodes/microsoftOneDriveTrigger.json +80 -0
- package/workflow_nodes/microsoftOutlook.json +40 -0
- package/workflow_nodes/microsoftOutlookTrigger.json +24 -0
- package/workflow_nodes/microsoftSql.json +81 -0
- package/workflow_nodes/microsoftTeams.json +36 -0
- package/workflow_nodes/microsoftToDo.json +181 -0
- package/workflow_nodes/mindee.json +86 -0
- package/workflow_nodes/misp.json +399 -0
- package/workflow_nodes/mocean.json +103 -0
- package/workflow_nodes/mondayCom.json +290 -0
- package/workflow_nodes/mongoDb.json +16 -0
- package/workflow_nodes/monicaCrm.json +543 -0
- package/workflow_nodes/moveBinaryData.json +121 -0
- package/workflow_nodes/mqtt.json +67 -0
- package/workflow_nodes/mqttTrigger.json +47 -0
- package/workflow_nodes/msg91.json +65 -0
- package/workflow_nodes/mySql.json +111 -0
- package/workflow_nodes/n8n.json +75 -0
- package/workflow_nodes/n8nTrigger.json +27 -0
- package/workflow_nodes/nasa.json +310 -0
- package/workflow_nodes/netlify.json +87 -0
- package/workflow_nodes/netlifyTrigger.json +68 -0
- package/workflow_nodes/netscalerAdc.json +243 -0
- package/workflow_nodes/nextCloud.json +312 -0
- package/workflow_nodes/noOp.json +8 -0
- package/workflow_nodes/nocoDb.json +276 -0
- package/workflow_nodes/notion.json +8 -0
- package/workflow_nodes/notionTrigger.json +75 -0
- package/workflow_nodes/npm.json +64 -0
- package/workflow_nodes/odoo.json +344 -0
- package/workflow_nodes/okta.json +97 -0
- package/workflow_nodes/oneSimpleApi.json +281 -0
- package/workflow_nodes/onfleet.json +316 -0
- package/workflow_nodes/onfleetTrigger.json +8 -0
- package/workflow_nodes/openAi.json +154 -0
- package/workflow_nodes/openThesaurus.json +81 -0
- package/workflow_nodes/openWeatherMap.json +129 -0
- package/workflow_nodes/orbit.json +375 -0
- package/workflow_nodes/oura.json +74 -0
- package/workflow_nodes/paddle.json +403 -0
- package/workflow_nodes/pagerDuty.json +351 -0
- package/workflow_nodes/payPal.json +196 -0
- package/workflow_nodes/payPalTrigger.json +40 -0
- package/workflow_nodes/peekalink.json +41 -0
- package/workflow_nodes/phantombuster.json +172 -0
- package/workflow_nodes/philipsHue.json +177 -0
- package/workflow_nodes/pipedrive.json +860 -0
- package/workflow_nodes/pipedriveTrigger.json +11 -0
- package/workflow_nodes/plivo.json +91 -0
- package/workflow_nodes/postHog.json +122 -0
- package/workflow_nodes/postbin.json +60 -0
- package/workflow_nodes/postgres.json +109 -0
- package/workflow_nodes/postgresTrigger.json +8 -0
- package/workflow_nodes/postmarkTrigger.json +72 -0
- package/workflow_nodes/profitWell.json +305 -0
- package/workflow_nodes/pushbullet.json +186 -0
- package/workflow_nodes/pushcut.json +75 -0
- package/workflow_nodes/pushcutTrigger.json +8 -0
- package/workflow_nodes/pushover.json +159 -0
- package/workflow_nodes/questDb.json +94 -0
- package/workflow_nodes/quickChart.json +188 -0
- package/workflow_nodes/quickbase.json +205 -0
- package/workflow_nodes/quickbooks.json +550 -0
- package/workflow_nodes/rabbitmq.json +165 -0
- package/workflow_nodes/rabbitmqTrigger.json +8 -0
- package/workflow_nodes/raindrop.json +216 -0
- package/workflow_nodes/readBinaryFile.json +26 -0
- package/workflow_nodes/readBinaryFiles.json +26 -0
- package/workflow_nodes/readPDF.json +31 -0
- package/workflow_nodes/readWriteFile.json +27 -0
- package/workflow_nodes/reddit.json +309 -0
- package/workflow_nodes/redis.json +183 -0
- package/workflow_nodes/redisTrigger.json +8 -0
- package/workflow_nodes/removeDuplicates.json +8 -0
- package/workflow_nodes/renameKeys.json +67 -0
- package/workflow_nodes/respondToWebhook.json +126 -0
- package/workflow_nodes/rocketchat.json +216 -0
- package/workflow_nodes/rssFeedRead.json +28 -0
- package/workflow_nodes/rssFeedReadTrigger.json +17 -0
- package/workflow_nodes/rundeck.json +79 -0
- package/workflow_nodes/s3.json +425 -0
- package/workflow_nodes/salesforce.json +1137 -0
- package/workflow_nodes/salesforceTrigger.json +122 -0
- package/workflow_nodes/salesmate.json +467 -0
- package/workflow_nodes/scheduleTrigger.json +270 -0
- package/workflow_nodes/seaTable.json +8 -0
- package/workflow_nodes/seaTableTrigger.json +87 -0
- package/workflow_nodes/securityScorecard.json +459 -0
- package/workflow_nodes/segment.json +219 -0
- package/workflow_nodes/sendGrid.json +359 -0
- package/workflow_nodes/sendy.json +225 -0
- package/workflow_nodes/sentryIo.json +426 -0
- package/workflow_nodes/serviceNow.json +544 -0
- package/workflow_nodes/set.json +124 -0
- package/workflow_nodes/shopify.json +707 -0
- package/workflow_nodes/shopifyTrigger.json +8 -0
- package/workflow_nodes/signl4.json +133 -0
- package/workflow_nodes/simulate.json +30 -0
- package/workflow_nodes/simulateTrigger.json +8 -0
- package/workflow_nodes/slack.json +62 -0
- package/workflow_nodes/slackTrigger.json +135 -0
- package/workflow_nodes/sms77.json +121 -0
- package/workflow_nodes/snowflake.json +65 -0
- package/workflow_nodes/sort.json +57 -0
- package/workflow_nodes/splitInBatches.json +30 -0
- package/workflow_nodes/splitOut.json +62 -0
- package/workflow_nodes/splunk.json +40 -0
- package/workflow_nodes/spontit.json +123 -0
- package/workflow_nodes/spotify.json +285 -0
- package/workflow_nodes/spreadsheetFile.json +8 -0
- package/workflow_nodes/sseTrigger.json +8 -0
- package/workflow_nodes/ssh.json +105 -0
- package/workflow_nodes/stackby.json +85 -0
- package/workflow_nodes/start.json +15 -0
- package/workflow_nodes/stickyNote.json +36 -0
- package/workflow_nodes/stopAndError.json +8 -0
- package/workflow_nodes/storyblok.json +138 -0
- package/workflow_nodes/strapi.json +138 -0
- package/workflow_nodes/strava.json +427 -0
- package/workflow_nodes/stravaTrigger.json +79 -0
- package/workflow_nodes/stripe.json +357 -0
- package/workflow_nodes/stripeTrigger.json +775 -0
- package/workflow_nodes/summarize.json +124 -0
- package/workflow_nodes/supabase.json +136 -0
- package/workflow_nodes/surveyMonkeyTrigger.json +160 -0
- package/workflow_nodes/switch.json +91 -0
- package/workflow_nodes/syncroMsp.json +8 -0
- package/workflow_nodes/taiga.json +340 -0
- package/workflow_nodes/taigaTrigger.json +81 -0
- package/workflow_nodes/tapfiliate.json +241 -0
- package/workflow_nodes/telegram.json +612 -0
- package/workflow_nodes/telegramTrigger.json +142 -0
- package/workflow_nodes/theHive.json +497 -0
- package/workflow_nodes/theHiveProject.json +8 -0
- package/workflow_nodes/theHiveProjectTrigger.json +162 -0
- package/workflow_nodes/theHiveTrigger.json +101 -0
- package/workflow_nodes/timescaleDb.json +95 -0
- package/workflow_nodes/todoist.json +285 -0
- package/workflow_nodes/togglTrigger.json +24 -0
- package/workflow_nodes/totp.json +86 -0
- package/workflow_nodes/travisCi.json +142 -0
- package/workflow_nodes/trello.json +609 -0
- package/workflow_nodes/trelloTrigger.json +8 -0
- package/workflow_nodes/twake.json +76 -0
- package/workflow_nodes/twilio.json +95 -0
- package/workflow_nodes/twilioTrigger.json +46 -0
- package/workflow_nodes/twist.json +376 -0
- package/workflow_nodes/twitter.json +40 -0
- package/workflow_nodes/typeformTrigger.json +62 -0
- package/workflow_nodes/unleashedSoftware.json +154 -0
- package/workflow_nodes/uplead.json +72 -0
- package/workflow_nodes/uproc.json +26 -0
- package/workflow_nodes/uptimeRobot.json +453 -0
- package/workflow_nodes/urlScanIo.json +113 -0
- package/workflow_nodes/venafiTlsProtectCloud.json +310 -0
- package/workflow_nodes/venafiTlsProtectCloudTrigger.json +38 -0
- package/workflow_nodes/venafiTlsProtectDatacenter.json +491 -0
- package/workflow_nodes/vero.json +158 -0
- package/workflow_nodes/vonage.json +125 -0
- package/workflow_nodes/wait.json +71 -0
- package/workflow_nodes/webflow.json +38 -0
- package/workflow_nodes/webflowTrigger.json +8 -0
- package/workflow_nodes/webhook.json +55 -0
- package/workflow_nodes/wekan.json +460 -0
- package/workflow_nodes/whatsApp.json +476 -0
- package/workflow_nodes/whatsAppTrigger.json +103 -0
- package/workflow_nodes/wise.json +330 -0
- package/workflow_nodes/wiseTrigger.json +8 -0
- package/workflow_nodes/wooCommerce.json +812 -0
- package/workflow_nodes/wooCommerceTrigger.json +8 -0
- package/workflow_nodes/wordpress.json +500 -0
- package/workflow_nodes/workableTrigger.json +51 -0
- package/workflow_nodes/writeBinaryFile.json +34 -0
- package/workflow_nodes/wufooTrigger.json +37 -0
- package/workflow_nodes/xero.json +530 -0
- package/workflow_nodes/xml.json +129 -0
- package/workflow_nodes/youTube.json +578 -0
- package/workflow_nodes/yourls.json +71 -0
- package/workflow_nodes/zammad.json +406 -0
- package/workflow_nodes/zendesk.json +526 -0
- package/workflow_nodes/zendeskTrigger.json +187 -0
- package/workflow_nodes/zohoCrm.json +721 -0
- package/workflow_nodes/zoom.json +507 -0
- package/workflow_nodes/zulip.json +371 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication Middleware
|
|
3
|
+
*
|
|
4
|
+
* Handles authentication for API requests
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const jwt = require('jsonwebtoken');
|
|
8
|
+
const { logger } = require('../utils/logger');
|
|
9
|
+
const { createErrorResponse } = require('../utils/mcp');
|
|
10
|
+
const { logSecurityEvent } = require('../utils/securityLogger');
|
|
11
|
+
|
|
12
|
+
// Get API key from environment
|
|
13
|
+
const API_KEY = process.env.MCP_API_KEY || 'development-key';
|
|
14
|
+
|
|
15
|
+
// Rate limiting storage
|
|
16
|
+
const rateLimitStore = new Map();
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Validate API key against environment variables or config
|
|
20
|
+
* @param {string} apiKey - The API key to validate
|
|
21
|
+
* @returns {boolean} - True if valid, false otherwise
|
|
22
|
+
*/
|
|
23
|
+
const validateApiKey = (apiKey) => {
|
|
24
|
+
// Check environment variables first
|
|
25
|
+
if (process.env.API_KEYS) {
|
|
26
|
+
const validKeys = process.env.API_KEYS.split(',').map(key => key.trim());
|
|
27
|
+
return validKeys.includes(apiKey);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Check config if available
|
|
31
|
+
try {
|
|
32
|
+
const config = require('../../config/default');
|
|
33
|
+
if (config.auth && config.auth.apiKeys && Array.isArray(config.auth.apiKeys)) {
|
|
34
|
+
return config.auth.apiKeys.includes(apiKey);
|
|
35
|
+
}
|
|
36
|
+
} catch (error) {
|
|
37
|
+
// Config not available, fall back to default
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Fall back to default API key
|
|
41
|
+
return apiKey === API_KEY;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Check rate limiting for an IP address
|
|
46
|
+
* @param {string} ip - The IP address to check
|
|
47
|
+
* @returns {boolean} - True if rate limited, false otherwise
|
|
48
|
+
*/
|
|
49
|
+
const isRateLimited = (ip) => {
|
|
50
|
+
const attempts = rateLimitStore.get(ip) || 0;
|
|
51
|
+
return attempts >= 5;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Increment failed attempts for an IP address
|
|
56
|
+
* @param {string} ip - The IP address to track
|
|
57
|
+
*/
|
|
58
|
+
const trackFailedAttempt = (ip) => {
|
|
59
|
+
const attempts = rateLimitStore.get(ip) || 0;
|
|
60
|
+
rateLimitStore.set(ip, attempts + 1);
|
|
61
|
+
|
|
62
|
+
// Clean up after 1 hour
|
|
63
|
+
setTimeout(() => {
|
|
64
|
+
rateLimitStore.delete(ip);
|
|
65
|
+
}, 3600000);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* API Key authentication middleware
|
|
70
|
+
* @param {Object} req - Express request object
|
|
71
|
+
* @param {Object} res - Express response object
|
|
72
|
+
* @param {Function} next - Express next middleware function
|
|
73
|
+
*/
|
|
74
|
+
const apiKeyAuth = (req, res, next) => {
|
|
75
|
+
const apiKey = req.headers['x-api-key'];
|
|
76
|
+
const ip = req.ip || req.connection?.remoteAddress || '127.0.0.1';
|
|
77
|
+
|
|
78
|
+
// Check rate limiting
|
|
79
|
+
if (isRateLimited(ip)) {
|
|
80
|
+
const errorResponse = createErrorResponse(
|
|
81
|
+
'Too many failed attempts',
|
|
82
|
+
'RATE_LIMITED',
|
|
83
|
+
429
|
|
84
|
+
);
|
|
85
|
+
return res.status(errorResponse.status).json({ error: errorResponse.error });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (!apiKey) {
|
|
89
|
+
trackFailedAttempt(ip);
|
|
90
|
+
logSecurityEvent({
|
|
91
|
+
level: 'warn',
|
|
92
|
+
eventType: 'authentication_failure',
|
|
93
|
+
ip,
|
|
94
|
+
details: {
|
|
95
|
+
reason: 'Missing API key',
|
|
96
|
+
endpoint: req.path
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const errorResponse = createErrorResponse(
|
|
101
|
+
'API key required',
|
|
102
|
+
'MISSING_API_KEY',
|
|
103
|
+
401
|
|
104
|
+
);
|
|
105
|
+
return res.status(errorResponse.status).json({ error: errorResponse.error });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (!validateApiKey(apiKey)) {
|
|
109
|
+
trackFailedAttempt(ip);
|
|
110
|
+
logSecurityEvent({
|
|
111
|
+
level: 'warn',
|
|
112
|
+
eventType: 'authentication_failure',
|
|
113
|
+
ip,
|
|
114
|
+
details: {
|
|
115
|
+
reason: 'Invalid API key',
|
|
116
|
+
endpoint: req.path
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const errorResponse = createErrorResponse(
|
|
121
|
+
'Invalid API key',
|
|
122
|
+
'INVALID_API_KEY',
|
|
123
|
+
401
|
|
124
|
+
);
|
|
125
|
+
return res.status(errorResponse.status).json({ error: errorResponse.error });
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Set auth info
|
|
129
|
+
req.auth = {
|
|
130
|
+
type: 'apikey',
|
|
131
|
+
key: apiKey
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
next();
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* JWT authentication middleware
|
|
139
|
+
* @param {Object} req - Express request object
|
|
140
|
+
* @param {Object} res - Express response object
|
|
141
|
+
* @param {Function} next - Express next middleware function
|
|
142
|
+
*/
|
|
143
|
+
const jwtAuth = (req, res, next) => {
|
|
144
|
+
const authHeader = req.headers.authorization;
|
|
145
|
+
const ip = req.ip || req.connection?.remoteAddress || '127.0.0.1';
|
|
146
|
+
|
|
147
|
+
// Check rate limiting
|
|
148
|
+
if (isRateLimited(ip)) {
|
|
149
|
+
const errorResponse = createErrorResponse(
|
|
150
|
+
'Too many failed attempts',
|
|
151
|
+
'RATE_LIMITED',
|
|
152
|
+
429
|
|
153
|
+
);
|
|
154
|
+
return res.status(errorResponse.status).json({ error: errorResponse.error });
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (!authHeader) {
|
|
158
|
+
trackFailedAttempt(ip);
|
|
159
|
+
const errorResponse = createErrorResponse(
|
|
160
|
+
'JWT token required',
|
|
161
|
+
'MISSING_JWT_TOKEN',
|
|
162
|
+
401
|
|
163
|
+
);
|
|
164
|
+
return res.status(errorResponse.status).json({ error: errorResponse.error });
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const parts = authHeader.split(' ');
|
|
168
|
+
if (parts.length !== 2 || parts[0] !== 'Bearer') {
|
|
169
|
+
trackFailedAttempt(ip);
|
|
170
|
+
const errorResponse = createErrorResponse(
|
|
171
|
+
'JWT token required',
|
|
172
|
+
'MISSING_JWT_TOKEN',
|
|
173
|
+
401
|
|
174
|
+
);
|
|
175
|
+
return res.status(errorResponse.status).json({ error: errorResponse.error });
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const token = parts[1];
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
// Use a default secret if not configured
|
|
182
|
+
const secret = process.env.JWT_SECRET || 'default-secret';
|
|
183
|
+
const decoded = jwt.verify(token, secret);
|
|
184
|
+
|
|
185
|
+
req.auth = {
|
|
186
|
+
type: 'jwt',
|
|
187
|
+
user: decoded
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
next();
|
|
191
|
+
} catch (error) {
|
|
192
|
+
trackFailedAttempt(ip);
|
|
193
|
+
|
|
194
|
+
let errorCode = 'INVALID_JWT_TOKEN';
|
|
195
|
+
let message = 'Invalid JWT token';
|
|
196
|
+
|
|
197
|
+
if (error.name === 'TokenExpiredError') {
|
|
198
|
+
errorCode = 'EXPIRED_JWT_TOKEN';
|
|
199
|
+
message = 'JWT token has expired';
|
|
200
|
+
} else if (error.name === 'JsonWebTokenError') {
|
|
201
|
+
if (error.message.includes('invalid signature')) {
|
|
202
|
+
errorCode = 'INVALID_JWT_SIGNATURE';
|
|
203
|
+
message = 'Invalid JWT signature';
|
|
204
|
+
} else if (error.message.includes('malformed')) {
|
|
205
|
+
errorCode = 'MALFORMED_JWT_TOKEN';
|
|
206
|
+
message = 'Malformed JWT token';
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const errorResponse = createErrorResponse(message, errorCode, 401);
|
|
211
|
+
return res.status(errorResponse.status).json({ error: errorResponse.error });
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Main authentication middleware - supports both API key and JWT
|
|
217
|
+
* @param {Object} req - Express request object
|
|
218
|
+
* @param {Object} res - Express response object
|
|
219
|
+
* @param {Function} next - Express next middleware function
|
|
220
|
+
*/
|
|
221
|
+
const authenticate = (req, res, next) => {
|
|
222
|
+
// Set MCP version header
|
|
223
|
+
res.setHeader('X-MCP-Version', '1.0');
|
|
224
|
+
|
|
225
|
+
// Skip authentication in development if configured
|
|
226
|
+
if (process.env.NODE_ENV === 'development' && process.env.SKIP_AUTH === 'true') {
|
|
227
|
+
logger.warn('Authentication bypassed in development mode');
|
|
228
|
+
req.auth = {
|
|
229
|
+
type: 'development',
|
|
230
|
+
user: { id: 'dev-user' }
|
|
231
|
+
};
|
|
232
|
+
return next();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const apiKey = req.headers['x-api-key'];
|
|
236
|
+
const authHeader = req.headers.authorization;
|
|
237
|
+
|
|
238
|
+
if (apiKey) {
|
|
239
|
+
// Use API key authentication
|
|
240
|
+
return apiKeyAuth(req, res, next);
|
|
241
|
+
} else if (authHeader) {
|
|
242
|
+
// Use JWT authentication
|
|
243
|
+
return jwtAuth(req, res, next);
|
|
244
|
+
} else {
|
|
245
|
+
// No authentication method provided
|
|
246
|
+
const ip = req.ip || req.connection?.remoteAddress || '127.0.0.1';
|
|
247
|
+
|
|
248
|
+
logSecurityEvent({
|
|
249
|
+
level: 'warn',
|
|
250
|
+
eventType: 'authentication_failure',
|
|
251
|
+
ip,
|
|
252
|
+
details: {
|
|
253
|
+
reason: 'Missing authorization header',
|
|
254
|
+
endpoint: req.path
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const errorResponse = createErrorResponse(
|
|
259
|
+
'Authentication required',
|
|
260
|
+
'AUTHENTICATION_REQUIRED',
|
|
261
|
+
401
|
|
262
|
+
);
|
|
263
|
+
return res.status(errorResponse.status).json({ error: errorResponse.error });
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
module.exports = {
|
|
268
|
+
authenticate,
|
|
269
|
+
apiKeyAuth,
|
|
270
|
+
jwtAuth,
|
|
271
|
+
validateApiKey,
|
|
272
|
+
rateLimitStore // Export for testing
|
|
273
|
+
};
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authorization Middleware
|
|
3
|
+
*
|
|
4
|
+
* Handles role-based authorization for the MCP server.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { PERMISSIONS, hasPermission } = require('../models/user');
|
|
8
|
+
const { createErrorResponse } = require('../utils/mcp');
|
|
9
|
+
const { logger } = require('../utils/logger');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Authorization middleware to check if the user has the required permission
|
|
13
|
+
*
|
|
14
|
+
* @param {String} permission - The permission required for the operation
|
|
15
|
+
* @returns {Function} Express middleware function
|
|
16
|
+
*/
|
|
17
|
+
const authorize = (permission) => {
|
|
18
|
+
return (req, res, next) => {
|
|
19
|
+
if (!req.auth) {
|
|
20
|
+
// No authentication data available
|
|
21
|
+
const errorResponse = createErrorResponse(
|
|
22
|
+
'Authorization requires authentication',
|
|
23
|
+
'AUTHENTICATION_REQUIRED',
|
|
24
|
+
401
|
|
25
|
+
);
|
|
26
|
+
return res.status(errorResponse.status).json({ error: errorResponse.error });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// For API key auth, assign default admin role
|
|
30
|
+
// In a real-world scenario, API keys would have specific permissions associated with them
|
|
31
|
+
if (req.auth.type === 'apikey') {
|
|
32
|
+
req.user = {
|
|
33
|
+
roles: ['admin']
|
|
34
|
+
};
|
|
35
|
+
return next();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// For JWT auth, use the user data from the token
|
|
39
|
+
if (req.auth.type === 'jwt') {
|
|
40
|
+
// User data should be available in req.auth.user
|
|
41
|
+
const user = req.auth.user;
|
|
42
|
+
|
|
43
|
+
// If no roles in the token, access is denied
|
|
44
|
+
if (!user || !user.roles) {
|
|
45
|
+
const errorResponse = createErrorResponse(
|
|
46
|
+
'User has no defined roles',
|
|
47
|
+
'MISSING_ROLES',
|
|
48
|
+
403
|
|
49
|
+
);
|
|
50
|
+
return res.status(errorResponse.status).json({ error: errorResponse.error });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Store the user object for use in other middleware/routes
|
|
54
|
+
req.user = user;
|
|
55
|
+
|
|
56
|
+
// Skip permission check if no specific permission required
|
|
57
|
+
if (!permission) {
|
|
58
|
+
return next();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Check if user has the required permission
|
|
62
|
+
if (hasPermission(user, permission)) {
|
|
63
|
+
return next();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Permission denied
|
|
67
|
+
logger.warn(`Access denied: User lacks permission: ${permission}`);
|
|
68
|
+
const errorResponse = createErrorResponse(
|
|
69
|
+
`You don't have permission to perform this action`,
|
|
70
|
+
'PERMISSION_DENIED',
|
|
71
|
+
403
|
|
72
|
+
);
|
|
73
|
+
return res.status(errorResponse.status).json({ error: errorResponse.error });
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Unsupported auth type
|
|
77
|
+
const errorResponse = createErrorResponse(
|
|
78
|
+
'Unsupported authentication type',
|
|
79
|
+
'UNSUPPORTED_AUTH_TYPE',
|
|
80
|
+
401
|
|
81
|
+
);
|
|
82
|
+
return res.status(errorResponse.status).json({ error: errorResponse.error });
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Middleware to handle workflow permissions
|
|
88
|
+
*/
|
|
89
|
+
const authorizeWorkflow = {
|
|
90
|
+
// Permission middleware for viewing workflows
|
|
91
|
+
view: authorize(PERMISSIONS.WORKFLOW_VIEW),
|
|
92
|
+
|
|
93
|
+
// Permission middleware for creating workflows
|
|
94
|
+
create: authorize(PERMISSIONS.WORKFLOW_CREATE),
|
|
95
|
+
|
|
96
|
+
// Permission middleware for editing workflows
|
|
97
|
+
edit: authorize(PERMISSIONS.WORKFLOW_EDIT),
|
|
98
|
+
|
|
99
|
+
// Permission middleware for deleting workflows
|
|
100
|
+
delete: authorize(PERMISSIONS.WORKFLOW_DELETE),
|
|
101
|
+
|
|
102
|
+
// Permission middleware for executing workflows
|
|
103
|
+
execute: authorize(PERMISSIONS.WORKFLOW_EXECUTE)
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Middleware to handle node permissions
|
|
108
|
+
*/
|
|
109
|
+
const authorizeNode = {
|
|
110
|
+
// Permission middleware for viewing nodes
|
|
111
|
+
view: authorize(PERMISSIONS.NODE_VIEW),
|
|
112
|
+
|
|
113
|
+
// Permission middleware for adding nodes
|
|
114
|
+
add: authorize(PERMISSIONS.NODE_ADD),
|
|
115
|
+
|
|
116
|
+
// Permission middleware for editing nodes
|
|
117
|
+
edit: authorize(PERMISSIONS.NODE_EDIT),
|
|
118
|
+
|
|
119
|
+
// Permission middleware for deleting nodes
|
|
120
|
+
delete: authorize(PERMISSIONS.NODE_DELETE)
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Middleware to handle connection permissions
|
|
125
|
+
*/
|
|
126
|
+
const authorizeConnection = {
|
|
127
|
+
// Permission middleware for viewing connections
|
|
128
|
+
view: authorize(PERMISSIONS.CONNECTION_VIEW),
|
|
129
|
+
|
|
130
|
+
// Permission middleware for creating connections
|
|
131
|
+
create: authorize(PERMISSIONS.CONNECTION_CREATE),
|
|
132
|
+
|
|
133
|
+
// Permission middleware for deleting connections
|
|
134
|
+
delete: authorize(PERMISSIONS.CONNECTION_DELETE)
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Middleware to handle credential permissions
|
|
139
|
+
*/
|
|
140
|
+
const authorizeCredential = {
|
|
141
|
+
// Permission middleware for viewing credentials
|
|
142
|
+
view: authorize(PERMISSIONS.CREDENTIAL_VIEW),
|
|
143
|
+
|
|
144
|
+
// Permission middleware for creating credentials
|
|
145
|
+
create: authorize(PERMISSIONS.CREDENTIAL_CREATE),
|
|
146
|
+
|
|
147
|
+
// Permission middleware for editing credentials
|
|
148
|
+
edit: authorize(PERMISSIONS.CREDENTIAL_EDIT),
|
|
149
|
+
|
|
150
|
+
// Permission middleware for deleting credentials
|
|
151
|
+
delete: authorize(PERMISSIONS.CREDENTIAL_DELETE)
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Middleware for system admin permissions
|
|
156
|
+
*/
|
|
157
|
+
const authorizeAdmin = authorize(PERMISSIONS.SYSTEM_ADMIN);
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Get middleware that logs access attempts and enforces permission check
|
|
161
|
+
*
|
|
162
|
+
* @param {String} permission - Permission required for the operation
|
|
163
|
+
* @param {String} operation - Description of the operation for logging
|
|
164
|
+
* @returns {Function} Express middleware function
|
|
165
|
+
*/
|
|
166
|
+
const logAndAuthorize = (permission, operation) => {
|
|
167
|
+
return (req, res, next) => {
|
|
168
|
+
logger.info(`Access attempt: ${operation}, User: ${req.auth?.user?.id || 'API Key'}`);
|
|
169
|
+
|
|
170
|
+
// Use the authorize middleware with the specified permission
|
|
171
|
+
authorize(permission)(req, res, next);
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
module.exports = {
|
|
176
|
+
authorize,
|
|
177
|
+
authorizeWorkflow,
|
|
178
|
+
authorizeNode,
|
|
179
|
+
authorizeConnection,
|
|
180
|
+
authorizeCredential,
|
|
181
|
+
authorizeAdmin,
|
|
182
|
+
logAndAuthorize
|
|
183
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logging Middleware
|
|
3
|
+
*
|
|
4
|
+
* Contains middleware functions for HTTP request logging
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { logger } = require('../utils/logger');
|
|
8
|
+
const { logSecurityEvent } = require('../utils/securityLogger');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Logs MCP requests for debugging and security purposes
|
|
12
|
+
*
|
|
13
|
+
* @param {Object} req - Express request object
|
|
14
|
+
* @param {Object} res - Express response object
|
|
15
|
+
* @param {Function} next - Express next middleware function
|
|
16
|
+
*/
|
|
17
|
+
const logMcpRequest = (req, res, next) => {
|
|
18
|
+
// Log basic request info
|
|
19
|
+
logger.debug(`MCP Request: ${req.method} ${req.path}`);
|
|
20
|
+
|
|
21
|
+
// Extract user ID if available
|
|
22
|
+
const userId = req.auth?.user?.id || 'anonymous';
|
|
23
|
+
|
|
24
|
+
// Log request details without sensitive information
|
|
25
|
+
if (req.body && Object.keys(req.body).length > 0) {
|
|
26
|
+
// Create a sanitized copy of the request body for logging
|
|
27
|
+
const sanitizedBody = { ...req.body };
|
|
28
|
+
|
|
29
|
+
// Redact sensitive information from parameters
|
|
30
|
+
if (sanitizedBody.parameters) {
|
|
31
|
+
const sensitiveKeys = ['apiKey', 'token', 'password', 'secret', 'key', 'auth'];
|
|
32
|
+
|
|
33
|
+
for (const key of Object.keys(sanitizedBody.parameters)) {
|
|
34
|
+
if (sensitiveKeys.some(sk => key.toLowerCase().includes(sk))) {
|
|
35
|
+
sanitizedBody.parameters[key] = '[REDACTED]';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
logger.debug(`Request Body: ${JSON.stringify(sanitizedBody)}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Log security event for non-GET requests
|
|
44
|
+
if (req.method !== 'GET') {
|
|
45
|
+
logSecurityEvent({
|
|
46
|
+
level: 'info',
|
|
47
|
+
eventType: 'mcp_request',
|
|
48
|
+
userId,
|
|
49
|
+
ip: req.ip || req.connection.remoteAddress,
|
|
50
|
+
details: {
|
|
51
|
+
method: req.method,
|
|
52
|
+
path: req.path,
|
|
53
|
+
userAgent: req.headers['user-agent'] || 'unknown'
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Call next middleware
|
|
59
|
+
next();
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
module.exports = {
|
|
63
|
+
logMcpRequest
|
|
64
|
+
};
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Protocol Middleware
|
|
3
|
+
*
|
|
4
|
+
* Handles validation and processing of MCP protocol requests
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const Ajv = require('ajv');
|
|
8
|
+
const { logger } = require('../utils/logger');
|
|
9
|
+
const { createErrorResponse } = require('../utils/mcp');
|
|
10
|
+
const { logValidationFailure } = require('../utils/securityLogger');
|
|
11
|
+
const { toolDefinitions } = require('../tools/toolDefinitions');
|
|
12
|
+
|
|
13
|
+
// Initialize AJV
|
|
14
|
+
const ajv = new Ajv({ allErrors: true });
|
|
15
|
+
|
|
16
|
+
// Create schema for MCP requests
|
|
17
|
+
const toolRequestSchema = {
|
|
18
|
+
type: 'object',
|
|
19
|
+
required: ['name', 'parameters'],
|
|
20
|
+
additionalProperties: false,
|
|
21
|
+
properties: {
|
|
22
|
+
name: { type: 'string' },
|
|
23
|
+
parameters: {
|
|
24
|
+
type: 'object',
|
|
25
|
+
additionalProperties: true
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Validate tool request against schema
|
|
32
|
+
*
|
|
33
|
+
* @param {Object} req - Express request object
|
|
34
|
+
* @param {Object} res - Express response object
|
|
35
|
+
* @param {Function} next - Express next middleware function
|
|
36
|
+
*/
|
|
37
|
+
const validateToolRequest = (req, res, next) => {
|
|
38
|
+
// Extract tool info from request
|
|
39
|
+
const { name, parameters = {} } = req.body;
|
|
40
|
+
|
|
41
|
+
// Basic request format validation
|
|
42
|
+
const validate = ajv.compile(toolRequestSchema);
|
|
43
|
+
const valid = validate(req.body);
|
|
44
|
+
|
|
45
|
+
if (!valid) {
|
|
46
|
+
const errors = validate.errors.map(err =>
|
|
47
|
+
`${err.instancePath} ${err.message}`
|
|
48
|
+
).join('; ');
|
|
49
|
+
|
|
50
|
+
// Log the validation error
|
|
51
|
+
logger.warn(`MCP protocol validation error: ${errors}`);
|
|
52
|
+
|
|
53
|
+
// Security logging
|
|
54
|
+
const clientIp = req.ip || req.connection.remoteAddress;
|
|
55
|
+
const userId = req.auth ? (req.auth.user ? req.auth.user.id : null) : null;
|
|
56
|
+
|
|
57
|
+
logValidationFailure({
|
|
58
|
+
ip: clientIp,
|
|
59
|
+
userId,
|
|
60
|
+
endpoint: req.path,
|
|
61
|
+
method: req.method,
|
|
62
|
+
violationType: 'mcp_protocol_validation',
|
|
63
|
+
inputField: 'request_format'
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const errorResponse = createErrorResponse(
|
|
67
|
+
`Invalid request format: ${errors}`,
|
|
68
|
+
'INVALID_REQUEST_FORMAT',
|
|
69
|
+
400
|
|
70
|
+
);
|
|
71
|
+
return res.status(errorResponse.status).json({ error: errorResponse.error });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Validate tool existence and parameter types if tool exists
|
|
75
|
+
const toolDef = toolDefinitions[name];
|
|
76
|
+
if (toolDef) {
|
|
77
|
+
// Create a validator for this tool's input schema
|
|
78
|
+
if (toolDef.input_schema && toolDef.input_schema.properties) {
|
|
79
|
+
try {
|
|
80
|
+
const inputValidator = ajv.compile(toolDef.input_schema);
|
|
81
|
+
const paramsValid = inputValidator(parameters);
|
|
82
|
+
|
|
83
|
+
if (!paramsValid) {
|
|
84
|
+
const paramErrors = inputValidator.errors.map(err =>
|
|
85
|
+
`${err.instancePath} ${err.message}`
|
|
86
|
+
).join('; ');
|
|
87
|
+
|
|
88
|
+
// Log the validation error
|
|
89
|
+
logger.warn(`Tool parameter validation error for ${name}: ${paramErrors}`);
|
|
90
|
+
|
|
91
|
+
// Security logging
|
|
92
|
+
const clientIp = req.ip || req.connection.remoteAddress;
|
|
93
|
+
const userId = req.auth ? (req.auth.user ? req.auth.user.id : null) : null;
|
|
94
|
+
|
|
95
|
+
logValidationFailure({
|
|
96
|
+
ip: clientIp,
|
|
97
|
+
userId,
|
|
98
|
+
endpoint: req.path,
|
|
99
|
+
method: req.method,
|
|
100
|
+
violationType: 'tool_parameter_validation',
|
|
101
|
+
inputField: name
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const errorResponse = createErrorResponse(
|
|
105
|
+
`Invalid parameters for tool ${name}: ${paramErrors}`,
|
|
106
|
+
'INVALID_TOOL_PARAMETERS',
|
|
107
|
+
400
|
|
108
|
+
);
|
|
109
|
+
return res.status(errorResponse.status).json({ error: errorResponse.error });
|
|
110
|
+
}
|
|
111
|
+
} catch (err) {
|
|
112
|
+
logger.error(`Error validating parameters for tool ${name}: ${err.message}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Continue to the next middleware
|
|
118
|
+
next();
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Sanitizes input parameters to prevent injection attacks
|
|
123
|
+
*/
|
|
124
|
+
const sanitizeParameters = (parameters) => {
|
|
125
|
+
// Recursive function to sanitize all string values
|
|
126
|
+
const sanitizeObject = (obj) => {
|
|
127
|
+
for (const key in obj) {
|
|
128
|
+
const value = obj[key];
|
|
129
|
+
|
|
130
|
+
if (typeof value === 'string') {
|
|
131
|
+
// Basic sanitization for strings
|
|
132
|
+
obj[key] = sanitizeString(value);
|
|
133
|
+
} else if (value !== null && typeof value === 'object') {
|
|
134
|
+
// Recursively sanitize nested objects and arrays
|
|
135
|
+
sanitizeObject(value);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
sanitizeObject(parameters);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Sanitizes a string to prevent common injection attacks
|
|
145
|
+
*/
|
|
146
|
+
const sanitizeString = (str) => {
|
|
147
|
+
// Replace potentially dangerous characters/patterns
|
|
148
|
+
// This is a simple example - in production, use a proper sanitization library
|
|
149
|
+
return str
|
|
150
|
+
.replace(/</g, '<')
|
|
151
|
+
.replace(/>/g, '>')
|
|
152
|
+
.replace(/"/g, '"')
|
|
153
|
+
.replace(/'/g, ''')
|
|
154
|
+
.replace(/\//g, '/');
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Logs MCP requests for debugging
|
|
159
|
+
*/
|
|
160
|
+
const logMcpRequest = (req, res, next) => {
|
|
161
|
+
// Only run in development mode
|
|
162
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
163
|
+
logger.debug(`MCP Request: ${req.method} ${req.path}`);
|
|
164
|
+
if (req.body && Object.keys(req.body).length > 0) {
|
|
165
|
+
// Avoid logging sensitive data in parameters
|
|
166
|
+
const sanitizedBody = { ...req.body };
|
|
167
|
+
if (sanitizedBody.parameters) {
|
|
168
|
+
// Replace potentially sensitive parameter values with "[REDACTED]"
|
|
169
|
+
const sensitiveKeys = ['apiKey', 'token', 'password', 'secret'];
|
|
170
|
+
for (const key of Object.keys(sanitizedBody.parameters)) {
|
|
171
|
+
if (sensitiveKeys.some(sk => key.toLowerCase().includes(sk))) {
|
|
172
|
+
sanitizedBody.parameters[key] = '[REDACTED]';
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
logger.debug(`Request Body: ${JSON.stringify(sanitizedBody)}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
next();
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
module.exports = {
|
|
183
|
+
validateToolRequest,
|
|
184
|
+
logMcpRequest,
|
|
185
|
+
sanitizeParameters,
|
|
186
|
+
sanitizeString
|
|
187
|
+
};
|