This workflow corresponds to n8n.io template #4231 — we link there as the canonical source.
This workflow follows the Execute Workflow Trigger → Toolworkflow recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "aiKrExd0rAxJO6xi",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "MCP_google_calendar",
"tags": [],
"nodes": [
{
"id": "17ccfdbf-d121-4ff0-95d4-bb38644d2bb1",
"name": "MCP Server Trigger",
"type": "@n8n/n8n-nodes-langchain.mcpTrigger",
"position": [
80,
-40
],
"parameters": {
"path": "c734cf98-3d5a-4cbd-af97-8ad2da760944"
},
"typeVersion": 1
},
{
"id": "174a13be-04f1-417c-8510-26798dae3447",
"name": "When Executed by Another Workflow",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"position": [
1060,
220
],
"parameters": {
"workflowInputs": {
"values": [
{
"name": "operation"
},
{
"name": "startDate"
},
{
"name": "endDate"
},
{
"name": "eventId"
},
{
"name": "timeZone"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "f74799f0-67b4-4247-905c-46adb1be4739",
"name": "Operation",
"type": "n8n-nodes-base.switch",
"position": [
1460,
180
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "getEvent",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "81b134bc-d671-4493-b3ad-8df9be3f49a6",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.operation }}",
"rightValue": "getEvent"
}
]
},
"renameOutput": true
},
{
"outputKey": "deleteEvent",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "8d57914f-6587-4fb3-88e0-aa1de6ba56c1",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.operation }}",
"rightValue": "deleteEvent"
}
]
},
"renameOutput": true
},
{
"outputKey": "createEvent",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "7c38f238-213a-46ec-aefe-22e0bcb8dffc",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.operation }}",
"rightValue": "createEvent"
}
]
},
"renameOutput": true
},
{
"outputKey": "updateEvent",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "ee9b6783-a0f2-4848-9166-aba6645c1ebc",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.operation }}",
"rightValue": "updateEvent"
}
]
},
"renameOutput": true
},
{
"outputKey": "getEventData",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "9ea6980d-a7be-4dec-8ddf-d2fcffb00af1",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "getEventData",
"rightValue": "getEventData"
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "b8007362-0d41-4875-872b-877f33b74bf8",
"name": "validate_busy_time",
"type": "@n8n/n8n-nodes-langchain.toolWorkflow",
"position": [
-80,
240
],
"parameters": {
"name": "validate_busy_time",
"workflowId": {
"__rl": true,
"mode": "list",
"value": "aiKrExd0rAxJO6xi",
"cachedResultName": "MCP_google_calendar"
},
"description": "Call this tool to validate if the gap of time is already busy. it is useful to validate before creating a new event",
"workflowInputs": {
"value": {
"endDate": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('endDate', ``, 'string') }}",
"eventId": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('eventId', ``, 'string') }}",
"timeZone": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('timeZone', ``, 'string') }}",
"operation": "=getEvent",
"startDate": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('startDate', ``, 'string') }}"
},
"schema": [
{
"id": "operation",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "operation",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "startDate",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "startDate",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "endDate",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "endDate",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "eventId",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "eventId",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "timeZone",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "timeZone",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
}
},
"typeVersion": 2.1
},
{
"id": "51f39673-4657-401b-b1bf-34e816318acf",
"name": "create_new_event",
"type": "@n8n/n8n-nodes-langchain.toolWorkflow",
"position": [
80,
240
],
"parameters": {
"name": "create_new_event",
"workflowId": {
"__rl": true,
"mode": "list",
"value": "aiKrExd0rAxJO6xi",
"cachedResultName": "MCP_google_calendar"
},
"description": "Use this tool to create a new event; always validate if the gap of time is available before creating a new event ",
"workflowInputs": {
"value": {
"endDate": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('endDate', ``, 'string') }}",
"eventId": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('eventId', ``, 'string') }}",
"timeZone": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('timeZone', ``, 'string') }}",
"operation": "createEvent",
"startDate": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('startDate', ``, 'string') }}"
},
"schema": [
{
"id": "operation",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "operation",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "startDate",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "startDate",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "endDate",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "endDate",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "eventId",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "eventId",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "timeZone",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "timeZone",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
}
},
"typeVersion": 2.1
},
{
"id": "3587c022-2f57-4bf6-8066-c292bcab5399",
"name": "delete_event",
"type": "@n8n/n8n-nodes-langchain.toolWorkflow",
"position": [
360,
240
],
"parameters": {
"name": "delete_event",
"workflowId": {
"__rl": true,
"mode": "list",
"value": "aiKrExd0rAxJO6xi",
"cachedResultName": "MCP_google_calendar"
},
"description": "Call this tool to delete a event, to delete a event you need the even id. it is required",
"workflowInputs": {
"value": {
"endDate": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('endDate', ``, 'string') }}",
"eventId": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('eventId', ``, 'string') }}",
"timeZone": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('timeZone', ``, 'string') }}",
"operation": "deleteEvent",
"startDate": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('startDate', ``, 'string') }}"
},
"schema": [
{
"id": "operation",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "operation",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "startDate",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "startDate",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "endDate",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "endDate",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "eventId",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "eventId",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "timeZone",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "timeZone",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
}
},
"typeVersion": 2.1
},
{
"id": "1da9a808-b478-47cd-b129-2a11d83d8735",
"name": "update_event",
"type": "@n8n/n8n-nodes-langchain.toolWorkflow",
"position": [
220,
240
],
"parameters": {
"name": "update_event",
"workflowId": {
"__rl": true,
"mode": "list",
"value": "aiKrExd0rAxJO6xi",
"cachedResultName": "MCP_google_calendar"
},
"description": "Call this tool to update the event name, startDate or endDate. Validate with validate_busy_time before any action",
"workflowInputs": {
"value": {
"endDate": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('endDate', ``, 'string') }}",
"eventId": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('eventId', ``, 'string') }}",
"timeZone": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('timeZone', ``, 'string') }}",
"operation": "updateEvent",
"startDate": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('startDate', ``, 'string') }}"
},
"schema": [
{
"id": "operation",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "operation",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "startDate",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "startDate",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "endDate",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "endDate",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "eventId",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "eventId",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "timeZone",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "timeZone",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
}
},
"typeVersion": 2.1
},
{
"id": "f3105e5b-0dec-44d0-ba5c-5bd91b0887d1",
"name": "validate_availability_event",
"type": "n8n-nodes-base.googleCalendar",
"position": [
2100,
-220
],
"parameters": {
"options": {},
"timeMax": "={{ $json.endDate }}",
"timeMin": "={{ $json.startDate }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "user@example.com",
"cachedResultName": "user@example.com"
},
"resource": "calendar"
},
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "43f2125b-85ea-455d-92ed-b84d0eb4a566",
"name": "check_availability_to_create",
"type": "n8n-nodes-base.googleCalendar",
"position": [
1780,
220
],
"parameters": {
"options": {},
"timeMax": "={{ $('map_data').item.json.endDate }}",
"timeMin": "={{ $('map_data').item.json.startDate }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "user@example.com",
"cachedResultName": "user@example.com"
},
"resource": "calendar"
},
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "7f2e1fef-79cb-4728-aa63-1afe038598ab",
"name": "If",
"type": "n8n-nodes-base.if",
"position": [
2000,
220
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "4ee8a84d-c48a-416f-aa31-0633ee59124b",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.available }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "b2523fe9-526b-4617-b404-59a0b0e6d0e0",
"name": "Stop and Error",
"type": "n8n-nodes-base.stopAndError",
"position": [
2220,
320
],
"parameters": {
"errorMessage": "The time you are trying to create the event is busy"
},
"typeVersion": 1
},
{
"id": "c72026c4-820d-4be0-9bbd-37b9ec6d2bf1",
"name": "create_event",
"type": "n8n-nodes-base.googleCalendar",
"position": [
2220,
160
],
"parameters": {
"end": "={{ $('map_data').item.json.endDate }}",
"start": "={{ $('map_data').item.json.startDate }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "user@example.com",
"cachedResultName": "user@example.com"
},
"additionalFields": {}
},
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "61f84fdb-768e-4b5f-9df9-21316dfa7678",
"name": "delete_event1",
"type": "n8n-nodes-base.googleCalendar",
"position": [
2120,
-20
],
"parameters": {
"eventId": "={{ $('map_data').item.json.eventId }}",
"options": {},
"calendar": {
"__rl": true,
"mode": "list",
"value": "user@example.com",
"cachedResultName": "user@example.com"
},
"operation": "delete"
},
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "2544e1e6-e620-4794-b1d4-898b2e9722ad",
"name": "Edit Fields",
"type": "n8n-nodes-base.set",
"position": [
2320,
-220
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "973dfb96-eeda-45be-bc93-668c9118677f",
"name": "available",
"type": "boolean",
"value": "={{ $json.available }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "966dc7bb-b2c8-40b1-95d9-ad10b232d1b2",
"name": "get_event_in_time_gap",
"type": "n8n-nodes-base.googleCalendar",
"position": [
1860,
700
],
"parameters": {
"options": {},
"timeMax": "={{ $('map_data').item.json.endDate }}",
"timeMin": "={{ $('map_data').item.json.startDate }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "user@example.com",
"cachedResultName": "user@example.com"
},
"operation": "getAll"
},
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1.3,
"alwaysOutputData": true
},
{
"id": "7010b476-f500-4891-a795-30c75f0f077c",
"name": "update_calendar",
"type": "n8n-nodes-base.googleCalendar",
"position": [
1860,
480
],
"parameters": {
"eventId": "={{ $json.eventId }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "user@example.com",
"cachedResultName": "user@example.com"
},
"operation": "update",
"updateFields": {
"end": "={{ $json.endDate }}",
"start": "={{ $json.startDate }}"
}
},
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "933163a6-5597-48da-95de-7067dd55ad84",
"name": "get_events_in_gap_time",
"type": "@n8n/n8n-nodes-langchain.toolWorkflow",
"position": [
520,
240
],
"parameters": {
"name": "get_events_in_gap_time",
"workflowId": {
"__rl": true,
"mode": "list",
"value": "aiKrExd0rAxJO6xi",
"cachedResultName": "MCP_google_calendar"
},
"description": "Use this tool to get event data in a gap of time. but if you have just validate the availibity of the time use \"validate_busy_time\" tool this is tool is to get data",
"workflowInputs": {
"value": {
"endDate": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('endDate', ``, 'string') }}",
"eventId": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('eventId', ``, 'string') }}",
"timeZone": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('timeZone', ``, 'string') }}",
"operation": "getEventData",
"startDate": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('startDate', ``, 'string') }}"
},
"schema": [
{
"id": "operation",
"type": "string",
"display": true,
"required": false,
"displayName": "operation",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "startDate",
"type": "string",
"display": true,
"required": false,
"displayName": "startDate",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "endDate",
"type": "string",
"display": true,
"required": false,
"displayName": "endDate",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "eventId",
"type": "string",
"display": true,
"required": false,
"displayName": "eventId",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "timeZone",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "timeZone",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
}
},
"typeVersion": 2.1
},
{
"id": "01c9435e-0258-4048-a3ad-cf84424fad6c",
"name": "map_data",
"type": "n8n-nodes-base.set",
"position": [
1240,
220
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "={\n \"operation\": \"{{ $json.operation }}\",\n \"startDate\": \"{{ DateTime.fromISO($json.startDate).setZone($json.timeZone).toISO() }}\",\n \"endDate\": \"{{ DateTime.fromISO($json.endDate).setZone($json.timeZone).toISO() }}\",\n \"eventId\": \"{{ $json.eventId }}\",\n \"timeZone\": \"{{ $json.timeZone }}\"\n}\n"
},
"typeVersion": 3.4
},
{
"id": "0e3a8817-7485-499c-9692-7b920bb34b3f",
"name": "response_data_get_data",
"type": "n8n-nodes-base.set",
"position": [
2080,
700
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "={\n \"isAvailableTime\":{{$json.values().length === 0}},\n\"eventData\":{\nid:\"{{ $json.id }}\"\n}\n}\n"
},
"typeVersion": 3.4
}
],
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "fbb67adf-7d52-4b42-8b61-a3c01470a1f9",
"connections": {
"If": {
"main": [
[
{
"node": "create_event",
"type": "main",
"index": 0
}
],
[
{
"node": "Stop and Error",
"type": "main",
"index": 0
}
]
]
},
"map_data": {
"main": [
[
{
"node": "Operation",
"type": "main",
"index": 0
}
]
]
},
"Operation": {
"main": [
[
{
"node": "validate_availability_event",
"type": "main",
"index": 0
}
],
[
{
"node": "delete_event1",
"type": "main",
"index": 0
}
],
[
{
"node": "check_availability_to_create",
"type": "main",
"index": 0
}
],
[
{
"node": "update_calendar",
"type": "main",
"index": 0
}
],
[
{
"node": "get_event_in_time_gap",
"type": "main",
"index": 0
}
]
]
},
"delete_event": {
"ai_tool": [
[
{
"node": "MCP Server Trigger",
"type": "ai_tool",
"index": 0
}
]
]
},
"update_event": {
"ai_tool": [
[
{
"node": "MCP Server Trigger",
"type": "ai_tool",
"index": 0
}
]
]
},
"create_new_event": {
"ai_tool": [
[
{
"node": "MCP Server Trigger",
"type": "ai_tool",
"index": 0
}
]
]
},
"validate_busy_time": {
"ai_tool": [
[
{
"node": "MCP Server Trigger",
"type": "ai_tool",
"index": 0
}
]
]
},
"get_event_in_time_gap": {
"main": [
[
{
"node": "response_data_get_data",
"type": "main",
"index": 0
}
]
]
},
"get_events_in_gap_time": {
"ai_tool": [
[
{
"node": "MCP Server Trigger",
"type": "ai_tool",
"index": 0
}
]
]
},
"validate_availability_event": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"check_availability_to_create": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"When Executed by Another Workflow": {
"main": [
[
{
"node": "map_data",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
googleCalendarOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This n8n template implements an MCP (Model Context Protocol)-compliant module for managing Google Calendar events in a context-aware, conflict-free manner.
Source: https://n8n.io/workflows/4231/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Googledrivetool Extractfromfile. Uses stickyNote, executeWorkflowTrigger, mcpTrigger, googleDrive. Event-driven trigger; 17 nodes.
Stickynote Executeworkflow. Uses executeWorkflowTrigger, stickyNote, mcpTrigger, toolCode. Event-driven trigger; 16 nodes.
Executeworkflow Executecommandtool. Uses stickyNote, mcpTrigger, executeCommandTool, executeWorkflowTrigger. Event-driven trigger; 14 nodes.
Workflow 3630. Uses mcpTrigger, executeCommandTool, executeWorkflowTrigger, executeCommand. Event-driven trigger; 14 nodes.
This workflow exposes appointment management tools through an n8n MCP Server webhook so an external AI voice agent (for example, Vapi or Retell) can check availability, book appointments, suggest alte