Skip to main content
Glama
nimjj

Nvidia NIM Nemotron Google Sheets Orchestrator

by nimjj
README.md
# Nvidia NIM Nemotron Google Sheets Orchestrator: MCP & Serverless Lambda

This repository contains a production-ready, AI-driven chatbot orchestrator that can read and write data to a Google Sheet using the **Nvidia NIM Nemotron-3 (120B)** model. It supports two distinct architectural implementations:
1. **Local Multi-Container MCP Stack**: Client-server separation using FastMCP and Server-Sent Events (SSE) private networks.
2. **Serverless AWS Lambda Container**: Consolidated, event-driven Lambda function behind API Gateway, using AWS Secrets Manager for OAuth token storage.

---

## šŸš€ Key Features

*   **Brain (LLM)**: Integrates the state-of-the-art `nvidia/nemotron-3-super-120b-a12b` model via Nvidia NIM.
*   **Decoupled MCP Architecture**: FastMCP Google Sheets server communicating with a FastAPI agent client over Server-Sent Events (SSE).
*   **Serverless Refactoring**: Collapse the SSE network architecture into a single-process containerized AWS Lambda handler with in-process tool calling.
*   **Security (Zero Secret Hardcoding)**: Google OAuth Client ID, Secret, and Refresh Token are fetched dynamically in-memory from **AWS Secrets Manager** at runtime (no token files baked into the image).
*   **Telegram Webhook Reply**: Optimized Lambda response payload supporting the Telegram Webhook Reply protocol (`method: "sendMessage"`) for instant response routing.
*   **Resilient OAuth Consent Helper**: Native local helper script (`refresh_oauth.py`) to trigger browser consent flows on the host machine and instantly sync refreshed tokens to AWS Secrets Manager.

---

## šŸ“ Architectures

### 1. Local Multi-Container (MCP)
```
  [User] ──(Webhook)──> [FastAPI Client] ──(SSE Network Bridge)──> [FastMCP Server] ──> [Google Sheets API]
                             │
                      (Nvidia NIM API)
                             ā–¼
                    [Nemotron-3 LLM]
```

### 2. Serverless AWS Lambda (Production)
```
  [User] ──(Telegram POST)──> [API Gateway /webhook]
                                      │
                                      ā–¼
                             [AWS Lambda Function] (Container Image)
                                 │          │
                     (In-Process Call)    (boto3) ──> [Secrets Manager]
                                 ā–¼
                          [app/tools.py]
                                 │
                                 ā–¼
                        [Google Sheets API]
```

---

## šŸ› ļø Folder Structure

```
ā”œā”€ā”€ app/                  # Consolidated serverless Lambda source code
│   ā”œā”€ā”€ __init__.py
│   ā”œā”€ā”€ secrets.py        # Credentials resolver (LOCAL_DEV env vs Production Secrets Manager)
│   ā”œā”€ā”€ tools.py          # Google Sheets API read/write tools (LangChain decorated)
│   ā”œā”€ā”€ agent.py          # LangGraph ReAct agent binding tools to ChatNVIDIA
│   └── main.py           # Lambda entrypoint handler & local CLI REPL
ā”œā”€ā”€ client/               # Original local FastAPI Agent Client (MCP mode)
ā”œā”€ā”€ server/               # Original local FastMCP Google Sheets Server (MCP mode)
ā”œā”€ā”€ Dockerfile            # Packages the app/ module for AWS Lambda
ā”œā”€ā”€ template.yaml         # AWS SAM Template declaration
ā”œā”€ā”€ requirements.txt      # Consolidated dependencies for AWS Lambda
ā”œā”€ā”€ refresh_oauth.py      # Local OAuth browser consent helper & Secrets Manager syncer
└── .env                  # Local environment file (ignored by Git)
```

---

## šŸ“¦ Running Locally

### Step 1: Initialize OAuth Credentials
1. Go to the [Google Cloud Console](https://console.cloud.google.com/).
2. Enable the **Google Sheets API**.
3. Setup the **OAuth Consent Screen** (User Type: External, Status: Testing, add your email as a **Test User**).
4. Create an **OAuth Client ID** of type **Desktop app**.
5. Download the secret JSON, rename it to `credentials.json`, and place it in `./server/credentials.json`.

### Step 2: Perform Initial Consent & Run Local Stack
1. Run the local consent flow:
   ```bash
   cd server
   pip install -r requirements.txt
   python sheets_mcp.py
   ```
   *A browser window will open. Click 'Allow' to grant access. This generates the initial `token.json` file.*
2. Copy `.env.example` to `.env` in the root and fill in your keys:
   *   `NVIDIA_API_KEY`: Your Nvidia API key.
   *   `SPREADSHEET_ID`: Your default target spreadsheet ID.
   *   `TELEGRAM_BOT_TOKEN`: Your Telegram Bot API token.
3. Start the local multi-container stack:
   ```bash
   docker-compose up --build -d
   ```

---

## ā˜ļø Deploying to AWS Lambda (Serverless)

AWS Lambda container images require the **Docker V2 Schema 2** format. Standard OCI manifests (with buildx attestations/SBOMs) will be rejected by AWS with an `InvalidParameterValueException`.

To compile, build ECR registries, build the container image securely, push, create IAM roles, upload credentials, and deploy your API Gateway triggers, a complete deployment helper is provided in the project history. You can perform these steps manually or use standard SAM CLI:

### Manual SAM Build & Deploy
1. **Save Google Credentials to Secrets Manager**:
   Create a secret in AWS Secrets Manager named `sheets-orchestrator-google-oauth` containing:
   ```json
   {
     "client_id": "YOUR_CLIENT_ID",
     "client_secret": "YOUR_CLIENT_SECRET",
     "refresh_token": "YOUR_REFRESH_TOKEN"
   }
   ```
2. **Build and Deploy**:
   ```bash
   sam build
   sam deploy --guided
   ```
   Provide your stack name, AWS Region, `NvidiaApiKey`, and the secret ARN. Once deployment is complete, SAM will output the public regional Webhook URL:
   `https://<api-id>.execute-api.<region>.amazonaws.com/Prod/webhook`

---

## šŸ”„ Refreshing OAuth Credentials (The 7-Day Limit)

If your Google Cloud Console project is in **Testing** publishing status, your Google refresh token will **expire after 7 days**. 

To resolve token expiry errors without having to redeploy your code:
1. Run the local OAuth syncer from your project root:
   ```bash
   python refresh_oauth.py
   ```
2. Sign in via your web browser.
3. The script will automatically fetch the new refresh token, write it to your local `.env`, connect to AWS, and update the secret in **AWS Secrets Manager**.
4. The Lambda function will pick up the new credentials on its next execution.