# Adk Gas

> GASADK: Agent Development Kit for Google Apps Script. Build AI agents with Gemini API, MCP, A2A, Agent Skills, Human-in-the-Loop (HITL) suspension/resumption, token quota safeguards, and dynamic Google API MCP servers.

- **Type:** MCP server
- **Install:** `agentstack add mcp-tanaikech-adk-gas`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [tanaikech](https://agentstack.voostack.com/s/tanaikech)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [tanaikech](https://github.com/tanaikech)
- **Source:** https://github.com/tanaikech/adk-gas
- **Website:** https://medium.com/google-cloud/agent-development-kit-for-google-apps-script-2413e97e8d84

## Install

```sh
agentstack add mcp-tanaikech-adk-gas
```

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

## About

# GASADK (Agent Development Kit for Google Apps Script)

Welcome to **GASADK**, the ultimate Agent Development Kit (ADK) designed specifically for the Google Apps Script (GAS) environment.

Operating within the strict constraints of Google Apps Script—specifically the absolute 6-minute execution limit and synchronous blocking networking—demands an architecture that discards the optimistic assumptions of traditional Node.js environments. **GASADK is a highly engineered survival architecture.** Inspired by the `@google/adk`, this initial release of GASADK introduces the heavily optimized **LlmAgent**. It replaces unbounded, recursive ReAct loops with a deterministic, phase-separated orchestration model, fundamentally solving context bloat, execution latency, and API quota exhaustion.

> [!TIP]
> 🚀 **Looking to turn your Google Workspace APIs into a Model Context Protocol (MCP) server?**  
> Check out our new sample project: [Google API MCP Server Guide](https://github.com/tanaikech/adk-gas/tree/master/samples/googleapiapp-mcp-server) to instantly expose all Google Workspace APIs (Sheets, Drive, Docs, Calendar, Gmail, etc.) as dynamic MCP tools.

---

## 🌟 Architecture & Key Innovations

At the core of GASADK is the **LlmAgent**, powered by the **Planner-Executor-Synthesizer (PES)** architecture. It utilizes Directed Acyclic Graphs (DAGs) to orchestrate complex task delegations across external tools, Model Context Protocol (MCP) servers, Agent-to-Agent (A2A) networks, and file-based Agent Skills.

### Core Safeguards & Optimizations

1. **One-Pass Fast-Track (Zero-Latency Bypass)**
   If the LLM Planner determines that external capabilities are unnecessary for a given prompt (e.g., standard conversational queries), the execution and synthesis phases are completely bypassed. The agent returns a direct response, aggressively slashing API latency and token consumption by avoiding redundant tool queueing.
2. **Schema Interception**
   Even when the Fast-Track attempts to bypass execution, if developers enforce an `outputSchema` (strict JSON formatting), GASADK intelligently intercepts the bypass. It routes the output through a dummy task directly into the Synthesizer to mathematically guarantee adherence to the requested JSON schema under all circumstances.
3. **Temporal Context Anchoring**
   LLMs suffer from temporal blindness—they cannot natively resolve relative time like "tomorrow" or "last week". GASADK intercepts the system prompt and injects a hardcoded `new Date()` absolute anchor. The Planner autonomously converts relative requests into absolute ISO 8601 timestamps before pinging external tools (MCP/A2A), completely eliminating date-resolution errors on remote servers.
4. **Payload Bulletproofing (Pessimistic Memory Management)**
   When external servers or massive Google Drive files return tens of thousands of characters, feeding them directly into the context window triggers a fatal `400 Payload Too Large` error. GASADK enforces a strict `maxResultLength` threshold (default 20,000 chars), automatically truncating overflow data. It favors partial data over catastrophic runtime crashes.
5. **Dynamic Re-Planning (Targeted ReAct)**
   Unlike standard ADKs that rely on a continuous ReAct loop for every step, GASADK plans an entire DAG upfront. Only if a node in the DAG execution fails does the system trigger a Re-Plan. It discards the unexecuted queue, analyzes the failure report, and generates an alternative DAG utilizing different tools.
6. **Clean History Optimization (A2AApp v2.6.0)**
   Maintains and propagates conversation history dynamically to sub-agents, MCP servers, and remote A2A servers without polluting the core logic history. Massive internal intermediate LLM reasoning steps (function calls, planning thoughts) are filtered out, constructing a clean user/model role-based chat history to prevent token bloat and quota exhaustion.
7. **Fast-Track Halt Optimization**
   Allows server functions to forcefully bypass the server-side LLM synthesis loop (by returning `_gemini_halt: true`). This prevents endless generative loops, eliminates unnecessary token usage, and guarantees instant response times for purely algorithmic/computational tool executions.
8. **Direct JSON-RPC Bypass & Direct Routing (v1.3.1)**
   Bypasses the entire multi-phase LLM mock orchestration when `directRouting` is flagged and a single target card is assigned, dispatching the JSON-RPC request natively to slash network latency. It also supports local pre-fetched Agent Cards through `a2aServerAgentCardJSONs` to completely bypass remote HTTP fetches.
9. **Multi-Channel Log Propagation (v1.3.3)**
   Supports explicit log propagation from the orchestrator down to sub-clients (`MCPApp` and `A2AApp`), storing logs inside dedicated, isolated Sheets (`raw`, `MCP`, `A2A`, `MCPA2Aserver_log`) dynamically. It guarantees thread-safe writes using script lock protection under high-concurrency environments.
10. **Global Scope Initialization Fix (v1.3.4)**
    Resolves compilation ReferenceError during global script initialization in Google Apps Script by removing unbound variables (`accessKey`, `webAppsUrl`) from the global context of `agentCard_ToolsForMCPServer.js` and instead using runtime shadow cloning for context safety.

### GASADK vs. TS ADK (`@google/adk`) Paradigm Shift

| Feature              | TypeScript ADK (`@google/adk`)               | GASADK                                                  |
| :------------------- | :------------------------------------------- | :------------------------------------------------------ |
| **Execution Model**  | Recursive ReAct Loop (Step-by-Step).         | Phase-separated DAG execution.                          |
| **I/O Networking**   | Asynchronous I/O, local `stdio`, WebSockets. | Synchronous, thread-blocking HTTP (`UrlFetchApp`).      |
| **Concurrency**      | Highly parallelized (`Promise.all`).         | Strictly sequential execution to prevent quota burnout. |
| **Failure Handling** | Optimistic: Infinite loops possible.         | Pessimistic: Hard aborts at 280s to prevent 6-min kill. |
| **State Protection** | In-memory session tracking.                  | Infrastructure-level locking via `LockService`.         |

---

## ⚙️ GASADK Workflow Architecture

The execution lifecycle of `LlmAgent` is rigorously compartmentalized. The diagram below details the exact chronological flow from the moment `agent.run()` is invoked to the final synthesized response.

```mermaid
graph TD
    %% Styling Definitions
    classDef userReq fill:#f9f,stroke:#333,stroke-width:2px,color:#000;
    classDef core fill:#bbf,stroke:#333,stroke-width:2px,color:#000;
    classDef llm fill:#fbb,stroke:#333,stroke-width:2px,color:#000;
    classDef external fill:#bfb,stroke:#333,stroke-width:2px,color:#000;
    classDef decision fill:#ff9,stroke:#333,stroke-width:2px,color:#000;
    classDef safeguard fill:#f66,stroke:#333,stroke-width:2px,color:#000;

    %% Nodes
    Start(["User: agent.run(prompt)"])
    InitCaps["Initialize Capabilities(Tools, MCP, A2A, Skills)"]
    InjectTime["Inject Temporal ContextSystem Time Anchor"]
    Planner["LLM: Planner PhaseGenerate DAG & JSON Schema"]

    FastTrackDec{"requires_capabilities== false?"}
    SchemaDec{"outputSchemadefined?"}
    ReturnDirect(["Return direct_answerExecution Bypassed"])

    PopTask["Pop Task from planQueue"]
    CheckTime{"Elapsed Time >timeoutMs(280s)?"}
    TimeoutAbort["Trigger Safe AbortStop Queue"]

    InjectContext["Inject 'depends_on'Context to Prompt"]
    ExecRouter{"CapabilityType?"}

    ExecMCP["MCP Server Client"]
    ExecA2A["A2A Server Client"]
    ExecSkill["Agent Skill LLM Call"]
    ExecNative["Native Function Calling"]

    CheckErr{"ExecutionError?"}
    Truncate["Payload Truncation> maxResultLength"]
    SaveResult["Save to taskResults"]

    CheckEmpty{"planQueueEmpty?"}
    CheckReplan{"replanCount maxReplans?"}
    DropQueue["Discard Remaining DAG"]
    Replanner["LLM: Dynamic Re-PlannerAvoid Failed Method"]

    SynthPhase["LLM: Final SynthesisAnalyze Gathered Data"]
    End(["Return Final Answer"])

    A2A_Registry[("A2A App")]
    MCP_Servers[("MCP Servers")]
    GDrive[("Google Drive")]

    %% Edges
    Start --> InitCaps
    InitCaps -. "Fetch Agent Cards" .-> A2A_Registry
    InitCaps -. "tools/list Request" .-> MCP_Servers
    InitCaps -. "Read .md Skills" .-> GDrive

    InitCaps --> InjectTime --> Planner
    Planner --> FastTrackDec

    FastTrackDec -- "Yes (Fast-Track)" --> SchemaDec
    SchemaDec -- "No (Raw output fine)" --> ReturnDirect
    SchemaDec -- "Yes (Intercept)" --> SynthPhase

    FastTrackDec -- "No (Capabilities required)" --> PopTask

    PopTask --> CheckTime
    CheckTime -- "Timeout Exceeded" --> TimeoutAbort
    TimeoutAbort --> SynthPhase

    CheckTime -- "Safe" --> InjectContext
    InjectContext --> ExecRouter

    ExecRouter -- "MCP Server" --> ExecMCP
    ExecRouter -- "A2A Server" --> ExecA2A
    ExecRouter -- "Agent Skill" --> ExecSkill
    ExecRouter -- "Native/Built-in" --> ExecNative

    ExecMCP --> CheckErr
    ExecA2A --> CheckErr
    ExecSkill --> CheckErr
    ExecNative --> CheckErr

    CheckErr -- "Success" --> Truncate --> SaveResult
    SaveResult --> CheckEmpty
    CheckEmpty -- "No" --> PopTask
    CheckEmpty -- "Yes" --> SynthPhase

    CheckErr -- "Failed" --> CheckReplan
    CheckReplan -- "Yes (Can Replan)" --> DropQueue --> Replanner
    Replanner --> PopTask
    CheckReplan -- "No (Max Replans)" --> SaveResult

    SynthPhase --> End

    %% Assign Classes
    class Start,ReturnDirect,End userReq;
    class InitCaps,InjectTime,PopTask,InjectContext,ExecNative,SaveResult core;
    class Planner,ExecSkill,Replanner,SynthPhase llm;
    class ExecMCP,ExecA2A,A2A_Registry,MCP_Servers,GDrive external;
    class FastTrackDec,SchemaDec,CheckTime,ExecRouter,CheckErr,CheckEmpty,CheckReplan decision;
    class TimeoutAbort,Truncate,DropQueue safeguard;
```

---

## 🧩 Supported Capabilities

GASADK acts as a universal adapter, normalizing disparate protocols into a unified schema for the Planner.

- **Native Tools**: Wrap standard Google Apps Script functions directly into the capability schema.
- **MCP Servers**: Native integration to dynamically discover (`tools/list`) and invoke tools on external servers using the Model Context Protocol.
- **A2A Servers**: Cross-agent communication. Fetch remote Agent Cards and utilize other autonomous agents as local tools via the Agent-to-Agent protocol.
- **Sub-Agents**: Nest instances of `LlmAgent` locally. Delegate complex cognitive sub-tasks without corrupting the main orchestrator's context.
- **Agent Skills**: Dynamically load behavioral skills stored as Markdown (`.md`) files inside Google Drive. A native GAS hack for distributed, RAG-like prompt injection.
- **Built-in Tools**: Comes equipped with a Python `CodeExecutor` and native `GoogleSearch` capabilities.

---

## 📥 Installation & Core Dependencies

GASADK integrates multiple high-performance GAS libraries under the hood. You can use it as a standalone library or copy the source code directly.

GASADK is constructed by the following scripts.

- [GADADK](https://github.com/tanaikech/adk-gas)
- [GeminiWithFiles](https://github.com/tanaikech/GeminiWithFiles)
- [A2AApp](https://github.com/tanaikech/A2AApp)
- [MCPApp](https://github.com/tanaikech/MCPApp)
- [MCPA2Aserver](https://github.com/tanaikech/MCPA2Aserver-GAS-Library)
- [FileSearchApp](https://github.com/tanaikech/FileSearchApp)

### Option 1: Use as a GAS Library (Recommended)

1. Open your GAS project.
2. Navigate to **Libraries** on the left panel and click **"+"**.
3. Enter the Project Key: `1w2mwhWQd4_6rom-UBRPD8gayBoqGH_87awSBVqGI8DdaQI_pOeSuGYDu`
4. Select the latest version and set the identifier to `GASADK`.
5. Click **Add**.

After GASADK was installed, you can use it as follows.

```javascript
const { LlmAgent, MCPA2Aserver, FileSearch } = GASADK;
```

**All objects are the class objects.**

You can also directly use `GeminiWithFiles`, `A2AApp`, and `MCPApp` like `const { LlmAgent, GeminiWithFiles, MCPA2Aserver, FileSearch, GeminiWithFiles, A2AApp, MCPApp } = GASADK`.

### Option 2: Copy & Paste Directly

If you want to directly use GASADK by including all scripts in a Google Apps Script project, please copy and paste the following script. The following script includes all required scripts for using GASADK.

[https://github.com/tanaikech/adk-gas/blob/master/dist/GASADK.js](https://github.com/tanaikech/adk-gas/blob/master/dist/GASADK.js)

In this case, you can directly use the class objects. So, you are not required to set `const { LlmAgent, GeminiWithFiles, MCPA2Aserver, FileSearch, GeminiWithFiles, A2AApp, MCPApp } = GASADK`.

---

## 🛠 `LlmAgent` Configuration API

The `new LlmAgent(config)` constructor accepts an extensive configuration object to dictate agent behavior and safety parameters.

| Parameter                | Type          | Required | Description                                                                                                          |
| :----------------------- | :------------ | :------: | :------------------------------------------------------------------------------------------------------------------- |
| `apiKey`                 | String        | **Yes**  | Your Gemini API Key.                                                                                                 |
| `name`                   | String        |    No    | Internal name of the agent. Defaults to `"Agent"`.                                                                   |
| `description`            | String        |    No    | Agent description. Critical for parent orchestrators utilizing Sub-Agents.                                           |
| `model`                  | String        |    No    | The Gemini model. Defaults to `"models/gemini-3.1-flash-lite"`.                                                     |
| `instruction`            | String/Object |    No    | Global system instruction. Supports `{var_name}` interpolation.                                                      |
| `state`                  | Object        |    No    | Key-value mapping for dynamic state variables. Replaces `{var_name}`.                                                |
| `tools`                  | Array         |    No    | Array of native GAS functions mapped to the tool schema.                                                             |
| `mcpServers`             | Array         |    No    | Array of external MCP Server URLs or JSON objects (for custom server routing) for dynamic capability discovery.      |
| `a2aServerAgentCardURLs` | Array         |    No    | Array of remote Agent Card URLs or JSON objects (for custom server routing) for A2A collaboration.                     |
| `a2aServerAgentCardJSONs`| Array         |    No    | Array of local pre-fetched Agent Card JSON objects (supports custom name aliases) to bypass HTTP card retrieval.      |
| `subAgents`              | Array         |    No    | Array of child `LlmAgent` instances for hierarchical delegation.                                                     |
| `skillFolderId`          | String        |    No    | Google Drive Folder ID containing `.md` files for Agent Skills.                                                      |
| `codeExecutor`           | Object        |    No    | Configuration object to enable Python execution Built-in capabilities.                                               |
| `googleSearch`           | Object        |    No    | Configuration object to enable the Built-in Google Search tool.                                                      |
| `maxReplans`             | Number        |    No    | Maximum dynamic Re-Plan attempts on execution failure. Defaults to `2`.                                              |
| `timeoutMs`              | Number        |    No    | Milliseconds before trigg

…

## 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/adk-gas](https://github.com/tanaikech/adk-gas)
- **License:** MIT
- **Homepage:** https://medium.com/google-cloud/agent-development-kit-for-google-apps-script-2413e97e8d84

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-adk-gas
- 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%.
