# TriggerApp

> An optimized Google Apps Script library and MCP Server to efficiently manage complex, flexible, and automated time-driven triggers with high precision.

- **Type:** MCP server
- **Install:** `agentstack add mcp-tanaikech-triggerapp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [tanaikech](https://agentstack.voostack.com/s/tanaikech)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [tanaikech](https://github.com/tanaikech)
- **Source:** https://github.com/tanaikech/TriggerApp
- **Website:** https://medium.com/google-cloud/executing-google-apps-script-on-complex-schedules-using-vibe-coding-f3479c08a34a

## Install

```sh
agentstack add mcp-tanaikech-triggerapp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# TriggerApp

[MIT License](LICENCE)

### ☕ Support this project

_Currently, I have no consistent income. If you find this library useful in your business or daily tasks, your donation would make my life a little easier and heavily support the continuous maintenance of this project._
**[Donate via PayPal](https://tanaikech.github.io/donate/)**

# Overview

This is a Google Apps Script library for efficiently managing the time-driven triggers for executing Google Apps Script using Google Apps Script.

**🔥 [NEW in v2.0.8+] MCP Autonomous Server Architecture:** TriggerApp can now operate entirely as a **Model Context Protocol (MCP) Server**. This allows Generative AI Agents to autonomously install, retrieve, simulate, and delete your Google Apps Script time-driven triggers through natural language prompts. It includes an embedded, completely isolated state-persistence mechanism, freeing AI agents from complex recursive handler definitions without compromising your project's security scope.

# Description

Google Apps Script can execute with not only the manual operation but also several triggers. The time-driven trigger is one of them, and this is one of a lot of important functions. When the time-driven trigger is used, Google Apps Script can be automatically executed at the time you set without launching the user's PC.

There are various situations for using time-driven triggers. And, I thought that when I created each script for each situation, the script might tend to be complicated. [Ref](https://tanaikech.github.io/2023/01/18/opening-and-closing-google-forms-on-time-using-google-apps-script/) and [Ref](https://tanaikech.github.io/2021/09/22/executing-function-with-minutes-timer-in-specific-times-using-google-apps-script/) Actually, when I prepared the scripts for each situation in my work, I thought that each script was largely different. I have wished a logic for integrating time-driven triggers for Google Apps Script were existing. Unfortunately, I couldn't find the algorithm for efficiently managing the time-driven triggers for various situations before.

Fortunately, a while ago, I came up with an algorithm using one object. I think that the basic algorithm has been used for a very long time. But, I couldn't find the logic for adapting to various situations using one object. Because, when I started developing a script using this logic, I thought that the script will be much more complicated. Through this, I created this library.

However, I'm worried that the library using this algorithm can be actually used for various situations. So, I have tested various situations with my actual work using this library by taking time. From this test, it was found that it is very useful. So, I would like to publish this library because I believe that this will be useful for a lot of users. This library can efficiently manage time-driven triggers for executing Google Apps Script in various situations with a simple script. If this is useful for your situation, I'm glad.

# Algorithm of this library

The algorithm of this library is straightforward. **An important point of this algorithm is to use one object for managing various trigger tasks.** In order to explain this, the trigger process shown in the following figure is used.

This figure shows the trigger process. For example, when "00:00" is "00:00" of "2024-01-01", "workFunction1", "workFunction2", and "workFunction3" are run as follows.

- "workFunction1": "2024-01-01T00:00:00", "2024-01-01T06:00:00"
- "workFunction2": "2024-01-01T00:30:00",,, "2024-01-01T02:30:00", and "2024-01-01T03:30:00",,, "2024-01-01T05:30:00", and "2024-01-01T06:30:00",,, "2024-01-01T08:30:00".
- "workFunction3": "2024-01-01T03:00:00", "2024-01-01T09:00:00"

When this process is run, I thought that if only the next trigger time for the current time is set by giving one object, the script might be able to be used. When the above image is used,

- When the current date time is "2023-12-31T23:00:00", the following trigger time is "2024-01-01T00:00:00" with "workFunction1".
- When the current date time is "2024-01-01T00:00:00", the following trigger time is "2024-01-01T00:30:00" with "workFunction2".
- This is repeated to the last task.
- When the current date time is "2024-01-01T09:00:00", no next trigger is installed.

In the above flow, this process can be achieved even with only 2 time-driven triggers. Actually, I tested this logic many times, and I could obtain that this can be used. This algorithm can achieve various triggers by installing only 2 time-driven triggers.

### 🧠 Deep Dive: The `mcpTriggerHandler` Architecture & Workflow

Google Apps Script enforces strict quotas, typically limiting active project triggers to 20 per user/script. If you attempted to create hundreds of physical triggers for complex intervals, your project would immediately crash.

TriggerApp bypasses this limitation using a **Daisy-Chain (Recursive Scheduling) Algorithm**. When utilizing TriggerApp—especially via the MCP Server or dedicated handler patterns—you will notice a function named **`mcpTriggerHandler`** constantly appearing in your active triggers list.

#### **What is `mcpTriggerHandler`?**

It is the heart of TriggerApp's infinite loop mechanics. It acts as the **Recursive Orchestrator**. Instead of registering infinite triggers, TriggerApp registers exactly **two physical triggers** at a time:

1. One for your actual business logic function (`myTask`).
2. One for the `mcpTriggerHandler` (scheduled slightly after your task).

When `mcpTriggerHandler` fires, it autonomously reads your persisted configurations from `PropertiesService`, calculates the absolute next execution time mathematically, and reinstalls the next two triggers.

**⚠️ CRITICAL WARNING:** Do NOT manually delete `mcpTriggerHandler` from your GAS Triggers dashboard. If you delete it, the recursive chain is broken, and your automated tasks will halt indefinitely after their next execution.

#### **Architecture Flow Diagram**

The following Mermaid sequence diagram visualizes exactly how user intents (via AI) are mapped through `mcpTriggerHandler` to bypass quotas safely:

```mermaid
sequenceDiagram
    autonumber
    actor User as User / AI Agent
    participant MCP as MCP Server / Web App
    participant TA as TriggerApp (Core)
    participant Prop as PropertiesService
    participant GAS as GAS Time-Driven Triggers
    participant Task as Target Function (e.g., myTask)
    participant Handler as mcpTriggerHandler

    User->>MCP: Request: "Run myTask every day at 09:00"
    MCP->>TA: mcp({ ... }) -> Calls install_triggers
    TA->>Prop: Persists trigger configuration as JSON
    TA->>GAS: Installs Trigger 1: myTask (Executes at 09:00)
    TA->>GAS: Installs Trigger 2: mcpTriggerHandler (Executes at 09:01)

    Note over GAS: ... Time passes until execution ...

    GAS->>Task: Executes Trigger 1 (myTask)
    Note right of Task: User's business logic runs

    GAS->>Handler: Executes Trigger 2 (mcpTriggerHandler)
    Handler->>TA: executeMcpTriggers(e, properties)
    TA->>Prop: Reads persisted JSON configuration
    TA->>TA: Calculates next scheduled execution time
    TA->>GAS: Installs Next Trigger 1: myTask (Tomorrow 09:00)
    TA->>GAS: Installs Next Trigger 2: mcpTriggerHandler (Tomorrow 09:01)
    Note over TA, GAS: The infinite recursive loop is established
```

# Limitations

- The time-driven trigger follows "Current limitations of Quotas for Google Services". [Ref](https://developers.google.com/apps-script/guides/services/quotas#current_limitations)
- When `toDay` is not used, the trigger cycle is repeated to infinity. But., when an error occurs on the internal Google side for some reason, the trigger is stopped. At that time, please run the main function, again. By this, the trigger process is restarted.
- In this library, I set the minimum interval between triggers as 60 seconds. Because, in the current stage, when the minimum interval time is less than 60 seconds, the time-driven trigger cannot be installed by the function executed by the time-driven trigger. I would like to believe that this situation might be resolved in the future update.
- When I tested the time-driven triggers many times using this library, for example, even when the function is trying to execute at "00:00:00", at least, the script is run after "00:00:00" like "00:00:10". It seems that the function was not executed before "00:00:00". But, there were cases where the function is executed at "00:01:30". I guessed that the reason for this issue is due to the Google side. This might be also a limitation.
- I'm not sure whether this has to be included in the "Limitations" section. When you want to execute functions using the "everyYear" property, I'm worried that when it occurs no execution of the script for a long time in the Google Apps Script project, it might be required to reauthorize the scopes. But, in the current stage, I have no experience with this issue. If you got it, please tell me. I believe that it will be useful for other users.
- I believe that this library will be able to adapt to a lot of scenarios for using time-driven triggers. However, on the other hand, I think that this library cannot be used in all scenarios. Please be careful about this.

# Library's project key

```
1LihDPPHWBCcadYVBI3oZ4vOt7XqlowoHyBLdaDgRIx_5OpRBREA7Z1QB
```

# Usage

## 1. Install library

In order to use this library, please install the library as follows.

1. Create a GAS project.
   - You can use this library for the GAS project of both the standalone and container-bound script types.

2. [Install this library](https://developers.google.com/apps-script/guides/libraries).
   - Library's project key is **`1LihDPPHWBCcadYVBI3oZ4vOt7XqlowoHyBLdaDgRIx_5OpRBREA7Z1QB`**.

---

## 2. Setup as an Autonomous MCP Server (Generative AI Integration)

TriggerApp (v2.1+) bundles a native MCP Server with **State Persistence**. By deploying it as a Web App, you can empower AI Agents to interact with your Google Apps Script triggers intelligently. The AI doesn't need to understand complex daisy-chained triggers; it simply states what function to run and when.

### Step-by-Step Deployment

**Step 1: Write the client boilerplate code**  
In your Google Apps Script project, paste the following required code block. This handles the MCP web route and defines the global `mcpTriggerHandler` for recursive autonomy. Notice that `PropertiesService.getScriptProperties()` is injected to ensure your configuration is saved locally to your script and not leaked.

```javascript
// Exposes the MCP server logic to incoming web requests
const doPost = (e) => {
  return TriggerApp.mcp({
    e: e,
    accessKey: "my_super_secret_key", // Security key for MCP access
    log: true, // Set to true to automatically save raw request payloads and standard logs
    spreadsheetId: "YOUR_SHEET_ID", // Required if log is true
    lock: LockService.getScriptLock(),
    properties: PropertiesService.getScriptProperties(), // MANDATORY: Preserves trigger scope isolation
  });
};

// MANDATORY: Global handler enabling LLMs to build infinite triggers
function mcpTriggerHandler(e) {
  TriggerApp.executeMcpTriggers(e, PropertiesService.getScriptProperties());
}

// Add the functions you want the AI to trigger below:
function myTask1() {
  console.log("myTask1: Executed perfectly on schedule!");
  // Optional: Append execution timestamp to your sheet to verify autonomous runs
  // SpreadsheetApp.openById("YOUR_SHEET_ID").getSheetByName("test").appendRow([new Date(), "myTask1"]);
}

function myTask2() {
  console.log("myTask2: Executed perfectly on schedule!");
  // Optional: Append execution timestamp to your sheet to verify autonomous runs
  // SpreadsheetApp.openById("YOUR_SHEET_ID").getSheetByName("test").appendRow([new Date(), "myTask2"]);
}
```

**Step 2: Deploy as a Web App**

1. Click the **Deploy** button at the top right of the GAS editor, then select **New deployment**.
2. Click the gear icon and select **Web app**.
3. Under **Execute as**, select **Me**.
4. Under **Who has access**, select **Anyone**.
5. Click **Deploy** and copy the generated **Web App URL**.

> ⚠️ **Security Notice:** Because the Web App must be deployed with the "Anyone" setting for the external MCP client to reach it, it is openly exposed to the internet. **You must define a strong `accessKey`** in your script. Without the correct `accessKey` in the URL parameter, TriggerApp rejects all incoming unauthorized requests.

**Step 3: Configure your MCP Client (e.g., Antigravity CLI)**  
Pass the copied Web App URL to your MCP configuration file, making sure to append your `accessKey` as a URL query parameter.

**`~/.gemini/antigravity/mcp_config.json`**

```json
{
  "mcpServers": {
    "set-trigge-test-project1": {
      "serverUrl": "https://script.google.com/macros/s/{your_deployment_ID}/exec?accessKey=my_super_secret_key"
    }
  }
}
```

Now, you can jump to the AI Prompts section below and start controlling your App Script natively using the exact functions (`myTask1`, `myTask2`) defined in your script.

**The MCP server named `set-trigge-test-project1` manages time-driven triggers for a specific Google Apps Script project. Therefore, if you want to manage triggers across multiple Google Apps Script projects, you must deploy the MCP server as a Web App. This follows the specification at the Google side.**

---

### 🤖 Generative AI Prompts (MCP Integration)

When connected as an MCP server, you can use these natural language prompts with your AI (like Claude or Gemini) to completely control TriggerApp without writing any code. The AI will utilize the mapped tools comprehensively based on the `myTask1` and `myTask2` functions provided in the sample script.

**1. Getting Information (Get Triggers List)**

> "Can you check and list all currently active time-driven triggers in my Google Apps Script project?"

**2. Simulation & Installation (Simulate & Install Triggers)**

> "Use the MCP server set-trigge-test-project1. I need to run the function `myTask1` every Monday, Wednesday, and Friday at 09:00 and 15:00. Please simulate this first to show me the exact times it will run this week. If the simulated timing looks correct to you, proceed to install the triggers."

**3. Complex Intervals**

> "Use the MCP server set-trigge-test-project1. Install a continuous trigger for `myTask2` that runs every 30 minutes from 10:00 to 18:00 on weekdays only."

**4. Deleting Specific Triggers**

> "Please delete the triggers associated with the function `myTask1`. Verify the deletion by checking the triggers list again."

**5. Complete Purge (Delete All Triggers)**

> "I want to start fresh. Purge and delete all active triggers completely."

---

# Scopes

This library uses the following 1 scope. This scope is used for installing the time-driven triggers.

- `https://www.googleapis.com/auth/script.scriptapp`

# Methods

| Methods                                                 | Description                                                                                                                                                                                                                                                                                                           |
| :------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [setEventObject](#seteventobject)                       | (Require) Give the event object from the time-driven trigger.

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [tanaikech](https://github.com/tanaikech)
- **Source:** [tanaikech/TriggerApp](https://github.com/tanaikech/TriggerApp)
- **License:** MIT
- **Homepage:** https://medium.com/google-cloud/executing-google-apps-script-on-complex-schedules-using-vibe-coding-f3479c08a34a

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-tanaikech-triggerapp
- Seller: https://agentstack.voostack.com/s/tanaikech
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
