#
tokens: 49763/50000 59/72 files (page 1/2)
lines: off (toggle) GitHub
raw markdown copy
This is page 1 of 2. Use http://codebase.md/mohalmah/google-appscript-mcp-server?page={x} to view the full context.

# Directory Structure

```
├── .env.example
├── .gitattributes
├── .gitignore
├── .gitkeep
├── commands
│   └── tools.js
├── demo
│   └── google app script mcp demo.gif
├── Dockerfile
├── ERROR_HANDLING_ENHANCEMENT.md
├── helpers
│   ├── check-deployments.js
│   ├── check-head-deployment.js
│   ├── convert-to-oauth.js
│   ├── create-proper-webapp.js
│   ├── create-web-app-fixed.js
│   ├── create-web-app.js
│   └── create-webapp-deployment.js
├── index.js
├── lib
│   ├── authHelper.js
│   ├── logger.js
│   ├── oauth-helper.js
│   ├── tokenManager.js
│   └── tools.js
├── LOGGING.md
├── mcpServer.js
├── OAUTH_IMPLEMENTATION.md
├── OAUTH_SETUP.md
├── oauth-setup.js
├── package-lock.json
├── package.json
├── README.md
├── test
│   ├── debug-content-fetch.js
│   ├── debug-deployment.js
│   ├── debug-mcp-deployment.js
│   ├── debug-test.js
│   ├── deploy-complete-webapp.js
│   ├── oauth-setup-broken.js
│   ├── oauth-setup-fixed.js
│   ├── simple-oauth-test.js
│   ├── simple-test.js
│   ├── test-complete-mcp-webapp.js
│   ├── test-fields-issue.js
│   ├── test-logging.js
│   ├── test-mcp-content.js
│   ├── test-mcp-deployment-direct.js
│   ├── test-mcp-deployment-fix.js
│   ├── test-mcp-deployment-get.js
│   ├── test-mcp-errors.js
│   ├── test-mcp-fetch-processes.js
│   ├── test-mcp-processes.js
│   ├── test-mcp-tools.js
│   ├── test-mcp-version-fix.js
│   ├── test-oauth.js
│   ├── test-token-management.js
│   ├── test-versions-list.js
│   ├── update-and-deploy-dark-theme.js
│   ├── update-error-handling.js
│   ├── update-tools.js
│   └── update-webapp-deployment.js
└── tools
    ├── google-app-script-api
    │   └── apps-script-api
    │       ├── script-processes-list-script-processes.js
    │       ├── script-processes-list.js
    │       ├── script-projects-create.js
    │       ├── script-projects-deployments-create.js
    │       ├── script-projects-deployments-delete.js
    │       ├── script-projects-deployments-get.js
    │       ├── script-projects-deployments-list.js
    │       ├── script-projects-deployments-update.js
    │       ├── script-projects-get-content.js
    │       ├── script-projects-get-metrics.js
    │       ├── script-projects-get.js
    │       ├── script-projects-update-content.js
    │       ├── script-projects-versions-create.js
    │       ├── script-projects-versions-get.js
    │       ├── script-projects-versions-list.js
    │       └── script-scripts-run.js
    └── paths.js
```

# Files

--------------------------------------------------------------------------------
/.gitkeep:
--------------------------------------------------------------------------------

```

```

--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------

```
# Auto detect text files and perform LF normalization
* text=auto

```

--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------

```
# OAuth 2.0 Configuration for Google Apps Script API
# Get these values from Google Cloud Console -> APIs & Credentials -> OAuth 2.0 Client IDs

# Your OAuth 2.0 Client ID
GOOGLE_APP_SCRIPT_API_CLIENT_ID=your_client_id_here

# Your OAuth 2.0 Client Secret
GOOGLE_APP_SCRIPT_API_CLIENT_SECRET=your_client_secret_here

# Note: Refresh tokens are stored securely in OS-specific locations
# and do not need to be added to this .env file.

```

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# Google Apps Script MCP Server

**Author**: [mohalmah](https://github.com/mohalmah)  
**License**: MIT License  
**Repository**: [google-apps-script-mcp-server](https://github.com/mohalmah/google-apps-script-mcp-server)

Welcome to the Google Apps Script MCP (Model Context Protocol) Server! 🚀 

This MCP server provides comprehensive integration with the Google Apps Script API, allowing you to manage script projects, deployments, versions, and executions through any MCP-compatible client like Claude Desktop, VS Code with Cline, or Postman.

## 📋 Table of Contents

- [Overview](#overview)
- [Features](#features)
- [Prerequisites](#prerequisites)
- [Quick Start Guide](#quick-start-guide)
- [Detailed Setup Instructions](#detailed-setup-instructions)
- [Available Tools](#available-tools)
- [MCP Client Configuration](#mcp-client-configuration)
- [Troubleshooting](#troubleshooting)
- [Advanced Usage](#advanced-usage)

## 🌟 Overview

This MCP server enables seamless interaction with Google Apps Script through:

- ✅ **OAuth 2.0 Authentication** - Secure token management with automatic refresh
- ✅ **16 Comprehensive Tools** - Complete Google Apps Script API coverage
- ✅ **MCP Protocol Compliance** - Works with Claude Desktop, VS Code, and other MCP clients
- ✅ **Secure Token Storage** - OS-specific secure storage for refresh tokens
- ✅ **Auto Token Refresh** - Handles token expiration automatically
- ✅ **Detailed Logging** - Comprehensive error handling and debugging

## 🎥 Demo Video

![Google Apps Script MCP Server Demo](https://github.com/mohalmah/google-appscript-mcp-server/blob/main/demo/google%20app%20script%20mcp%20demo.gif?raw=true)

*Watch the Google Apps Script MCP Server in action - creating projects, managing deployments, and executing scripts through VS Code AI Agent.*

## 🚀 Features

### Core Capabilities
- **Project Management**: Create, retrieve, and update Google Apps Script projects
- **Deployment Management**: Create, list, update, and delete script deployments
- **Version Control**: Create and manage script versions
- **Content Management**: Get and update script content and files
- **Process Monitoring**: List and monitor script execution processes
- **Metrics Access**: Retrieve script execution metrics and analytics
- **Script Execution**: Run Google Apps Script functions remotely

### Security Features
- **OAuth 2.0 Flow**: Full Google OAuth implementation
- **Secure Token Storage**: Refresh tokens stored in OS keychain/credential manager
- **Automatic Token Refresh**: No manual token management required
- **Environment Variable Support**: Secure credential configuration

## ⚙️ Prerequisites

Before starting, ensure you have:

- **Node.js** (v18+ required, v20+ recommended) - [Download here](https://nodejs.org/)
- **npm** (included with Node.js)
- **Google Account** with access to Google Cloud Console
- **Git** (for cloning the repository)

## 🚀 Quick Start Guide

### 1. Clone the Repository
```bash
git clone https://github.com/mohalmah/google-apps-script-mcp-server.git
cd google-apps-script-mcp-server
```

### 2. Install Dependencies
```bash
npm install
```

### 3. Set Up Google Cloud OAuth
Follow the [detailed OAuth setup guide](#detailed-setup-instructions) below.

### 4. Run OAuth Setup
```bash
npm run setup-oauth
```

### 5. Test the Server
```bash
npm start
```

## 📖 Detailed Setup Instructions

### Step 1: Clone and Install

**Clone the repository:**
```bash
git clone https://github.com/mohalmah/google-apps-script-mcp-server.git
cd google-apps-script-mcp-server
```

**Install dependencies:**
```bash
npm install
```

### Step 2: Google Cloud Console Setup

#### 2.1 Create or Select a Google Cloud Project

1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Click the project dropdown at the top
3. Click **"New Project"** or select an existing project
4. If creating new:
   - Enter a project name (e.g., "Google Apps Script MCP")
   - Note your Project ID (you'll need this)
   - Click **"Create"**

#### 2.2 Enable Required APIs

1. In the Google Cloud Console, navigate to **APIs & Services** → **Library**
2. Search for and enable the following APIs:
   - **Google Apps Script API** (required)
   - **Google Drive API** (recommended for file access)
   - **Google Cloud Resource Manager API** (for project operations)

**For Google Apps Script API:**
1. Search "Google Apps Script API"
2. Click on the result
3. Click **"Enable"**
4. Wait for the API to be enabled (may take a few minutes)

#### 2.3 Configure OAuth Consent Screen

1. Go to **APIs & Services** → **OAuth consent screen**
2. Choose **External** (unless you're in a Google Workspace organization)
3. Fill in the required information:
   - **App name**: "Google Apps Script MCP Server"
   - **User support email**: Your email address
   - **App logo**: (optional)
   - **App domain**: Leave blank for development
   - **Developer contact information**: Your email address
4. Click **"Save and Continue"**

**Configure Scopes (Optional but Recommended):**
1. Click **"Add or Remove Scopes"**
2. Add these scopes:
   - `https://www.googleapis.com/auth/script.projects`
   - `https://www.googleapis.com/auth/script.projects.readonly`
   - `https://www.googleapis.com/auth/script.deployments`
   - `https://www.googleapis.com/auth/script.deployments.readonly`
   - `https://www.googleapis.com/auth/script.metrics`
   - `https://www.googleapis.com/auth/script.processes`
3. Click **"Update"**

**Add Test Users (for External apps):**
1. Click **"Add Users"**
2. Add your Gmail address as a test user
3. Click **"Save and Continue"**

#### 2.4 Create OAuth 2.0 Credentials

1. Go to **APIs & Services** → **Credentials**
2. Click **"+ CREATE CREDENTIALS"** → **"OAuth 2.0 Client IDs"**
3. For Application Type, select **"Web application"**
4. Configure the client:
   - **Name**: "Google Apps Script MCP Client"
   - **Authorized JavaScript origins**: (leave empty for now)
   - **Authorized redirect URIs**: Add exactly this URL:
     ```
     http://localhost:3001/oauth/callback
     ```
5. Click **"Create"**
6. **IMPORTANT**: Copy your **Client ID** and **Client Secret** immediately
   - Client ID looks like: `1234567890-abcdefghijklmnop.apps.googleusercontent.com`
   - Client Secret looks like: `GOCSPX-abcdefghijklmnopqrstuvwxyz`

### Step 3: Configure Environment Variables

#### 3.1 Create .env File

Create a `.env` file in your project root:

```bash
# On Windows
type nul > .env

# On macOS/Linux
touch .env
```

#### 3.2 Add OAuth Credentials

Edit the `.env` file and add your credentials:

```env
# Google Apps Script API OAuth Configuration
GOOGLE_APP_SCRIPT_API_CLIENT_ID=your_client_id_here
GOOGLE_APP_SCRIPT_API_CLIENT_SECRET=your_client_secret_here

# Optional: Logging level
LOG_LEVEL=info
```

**Replace the placeholders with your actual values:**
- Replace `your_client_id_here` with your Client ID
- Replace `your_client_secret_here` with your Client Secret

### Step 4: OAuth Authentication Setup

#### 4.1 Run OAuth Setup

Execute the OAuth setup script:

```bash
npm run setup-oauth
```

**What this does:**
1. Starts a temporary local server on `http://localhost:3001`
2. Opens your default browser to Google's authorization page
3. Asks you to grant permissions to the application
4. Captures the authorization code via the callback URL
5. Exchanges the code for access and refresh tokens
6. Stores the refresh token securely in your OS credential store
7. Tests the token by making a test API call

#### 4.2 Grant Permissions

When your browser opens:

1. **Select your Google account** (must be the test user you added)
2. **Review the permissions** being requested:
   - See and manage your Google Apps Script projects
   - See your script executions and metrics
   - Access your script deployments
3. **Click "Continue"** or **"Allow"**
4. **You should see**: "OAuth setup completed successfully!"

#### 4.3 Verify Token Storage

The setup process stores tokens securely:
- **Windows**: Windows Credential Manager
- **macOS**: Keychain Access
- **Linux**: Secret Service API (GNOME Keyring/KDE Wallet)

### Step 5: Test Your Setup

#### 5.1 Test the MCP Server

```bash
npm start
```

You should see output like:
```
Google Apps Script MCP Server running on stdio
OAuth tokens loaded successfully
Server ready to handle MCP requests
```

#### 5.2 Test with Available Commands

```bash
# List all available tools
npm run list-tools

# Test OAuth connection
npm run test-oauth

# Enable debug logging
npm run debug
```

## 🛠️ Available Tools

This MCP server provides 16 comprehensive tools for Google Apps Script management:

### Project Management Tools

#### 1. `script-projects-create`
**Purpose**: Create a new Google Apps Script project
**Parameters**:
- `title` (required): The title of the new script project
- `parentId` (optional): The ID of the parent project

**Example Usage**: Create a new script for automation tasks
```javascript
// Creates: "My Automation Script" project
{
  "title": "My Automation Script",
  "parentId": "1234567890"
}
```

#### 2. `script-projects-get`
**Purpose**: Get metadata of a Google Apps Script project
**Parameters**:
- `scriptId` (required): The ID of the script project to retrieve
- `fields` (optional): Specific fields to include in response
- `alt` (optional): Data format for response (default: 'json')

**Example Usage**: Retrieve project information
```javascript
// Gets project details for script ID
{
  "scriptId": "1ABC123def456GHI789jkl"
}
```

#### 3. `script-projects-get-content`
**Purpose**: Get the content of a Google Apps Script project
**Parameters**:
- `scriptId` (required): The ID of the script project
- `versionNumber` (optional): Specific version number to retrieve

**What it returns**: Complete source code and files in the project
**Example Usage**: Download script source code for backup or analysis

#### 4. `script-projects-update-content`
**Purpose**: Update the content of a Google Apps Script project
**Parameters**:
- `scriptId` (required): The ID of the script project to update
- `files` (required): Array of file objects with name, type, and source

**Example Usage**: Deploy code changes to your script project

### Version Management Tools

#### 5. `script-projects-versions-create`
**Purpose**: Create a new version of a Google Apps Script project
**Parameters**:
- `scriptId` (required): The ID of the script project
- `description` (required): Description for the new version

**Example Usage**: Create versioned snapshots for deployment
```javascript
{
  "scriptId": "1ABC123def456GHI789jkl",
  "description": "Added email notification feature"
}
```

#### 6. `script-projects-versions-get`
**Purpose**: Get details of a specific script version
**Parameters**:
- `scriptId` (required): The ID of the script project
- `versionNumber` (required): The version number to retrieve

#### 7. `script-projects-versions-list`
**Purpose**: List all versions of a script project
**Parameters**:
- `scriptId` (required): The ID of the script project
- `pageSize` (optional): Number of versions per page
- `pageToken` (optional): Token for pagination

### Deployment Management Tools

#### 8. `script-projects-deployments-create`
**Purpose**: Create a deployment of a Google Apps Script project
**Parameters**:
- `scriptId` (required): The ID of the script to deploy
- `versionNumber` (required): Version number to deploy
- `manifestFileName` (required): Name of the manifest file
- `description` (required): Description for the deployment

**Example Usage**: Deploy your script as a web app or API executable
```javascript
{
  "scriptId": "1ABC123def456GHI789jkl",
  "versionNumber": 3,
  "manifestFileName": "appsscript.json",
  "description": "Production deployment v1.2"
}
```

#### 9. `script-projects-deployments-get`
**Purpose**: Get details of a specific deployment
**Parameters**:
- `scriptId` (required): The ID of the script project
- `deploymentId` (required): The ID of the deployment

#### 10. `script-projects-deployments-list`
**Purpose**: List all deployments of a script project
**Parameters**:
- `scriptId` (required): The ID of the script project
- `pageSize` (optional): Number of deployments per page

#### 11. `script-projects-deployments-update`
**Purpose**: Update an existing deployment
**Parameters**:
- `scriptId` (required): The ID of the script project
- `deploymentId` (required): The ID of the deployment to update
- `deploymentConfig` (required): New deployment configuration

#### 12. `script-projects-deployments-delete`
**Purpose**: Delete a deployment
**Parameters**:
- `scriptId` (required): The ID of the script project
- `deploymentId` (required): The ID of the deployment to delete

### Execution and Monitoring Tools

#### 13. `script-scripts-run`
**Purpose**: Execute a Google Apps Script function
**Parameters**:
- `scriptId` (required): The ID of the script to run
- Additional parameters specific to the function being executed

**Example Usage**: Trigger script execution remotely
**Note**: The script must be deployed and you must have execution permissions

#### 14. `script-processes-list`
**Purpose**: List execution processes for a script project
**Parameters**:
- `scriptId` (required): The ID of the script project
- `pageSize` (optional): Number of processes per page
- `pageToken` (optional): Token for pagination
- `statuses` (optional): Filter by process statuses
- `types` (optional): Filter by process types
- `functionName` (optional): Filter by function name
- `startTime` (optional): Filter by start time
- `endTime` (optional): Filter by end time

**What it shows**: Running, completed, and failed script executions

#### 15. `script-processes-list-script-processes`
**Purpose**: Alternative method to list script processes with additional filtering
**Parameters**: Similar to `script-processes-list` with enhanced filtering options

#### 16. `script-projects-get-metrics`
**Purpose**: Get execution metrics and analytics for a script project
**Parameters**:
- `scriptId` (required): The ID of the script project
- `deploymentId` (required): The ID of the deployment
- `metricsGranularity` (required): Granularity of metrics data
- `fields` (required): Specific metric fields to retrieve

**What it provides**: 
- Execution counts
- Error rates
- Performance metrics
- Usage analytics

### Tool Categories Summary

| Category | Tools | Purpose |
|----------|-------|---------|
| **Project Management** | create, get, get-content, update-content | Manage script projects and source code |
| **Version Control** | versions-create, versions-get, versions-list | Handle script versioning |
| **Deployment** | deployments-create, deployments-get, deployments-list, deployments-update, deployments-delete | Manage script deployments |
| **Execution** | scripts-run | Execute script functions |
| **Monitoring** | processes-list, get-metrics | Monitor execution and performance |

### Common Use Cases

**Development Workflow**:
1. Use `script-projects-create` to create new projects
2. Use `script-projects-update-content` to upload code
3. Use `script-projects-versions-create` to create stable versions
4. Use `script-projects-deployments-create` to deploy for production

**Monitoring and Debugging**:
1. Use `script-processes-list` to see execution history
2. Use `script-projects-get-metrics` to analyze performance
3. Use `script-projects-get-content` to backup source code

**Production Management**:
1. Use `script-projects-deployments-list` to see all deployments
2. Use `script-projects-deployments-update` to update production configs
3. Use `script-scripts-run` to trigger automated workflows

## 🌐 Test the MCP Server with Postman

The MCP Server (`mcpServer.js`) exposes your automated API tools to MCP-compatible clients, such as Claude Desktop or the Postman Desktop Application. We recommend that you test the server with Postman first and then move on to using it with an LLM.

**Step 1**: Download the latest Postman Desktop Application from [https://www.postman.com/downloads/](https://www.postman.com/downloads/).

**Step 2**: Read the documentation article [here](https://learning.postman.com/docs/postman-ai-agent-builder/mcp-requests/create/) and see how to create an MCP request inside the Postman app.

**Step 3**: Set the type of the MCP request to `STDIO` and set the command to `node <absolute/path/to/mcpServer.js>`. 

**For Windows users**, you can get the full path to node by running:

```powershell
Get-Command node | Select-Object -ExpandProperty Source
```

**For macOS/Linux users**, you can get the full path to node by running:

```bash
which node
```

To check the node version on any platform, run:

```bash
node --version
```

**For Windows users**, to get the absolute path to `mcpServer.js`, run:

```powershell
Get-Location | Select-Object -ExpandProperty Path
```

Then append `\mcpServer.js` to the path.

**For macOS/Linux users**, to get the absolute path to `mcpServer.js`, run:

```bash
realpath mcpServer.js
```

Use the node command followed by the full path to `mcpServer.js` as the command for your new Postman MCP Request. Then click the **Connect** button. You should see a list of tools that you selected before generating the server. You can test that each tool works here before connecting the MCP server to an LLM.

## 🔗 MCP Client Configuration

You can connect your MCP server to various MCP clients. Below are detailed instructions for both Claude Desktop and VS Code.

### 📋 Getting Required Paths

Before configuring any MCP client, you'll need the absolute paths to Node.js and your `mcpServer.js` file.

#### 🪟 Windows Users

**Get Node.js path:**
```powershell
Get-Command node | Select-Object -ExpandProperty Source
```
Example output: `C:\nvm4w\nodejs\node.exe`

**Alternative method if first doesn't work:**
```powershell
where.exe node
```

**Get current directory path:**
```powershell
Get-Location | Select-Object -ExpandProperty Path
```
Example output: `C:\Users\mohal\Downloads\google-appscriot-mcp-server`

**Complete mcpServer.js path:**
```powershell
Join-Path (Get-Location) "mcpServer.js"
```
Example output: `C:\Users\mohal\Downloads\google-appscriot-mcp-server\mcpServer.js`

**Quick copy-paste command to get both paths:**
```powershell
Write-Host "Node.js path: $((Get-Command node).Source)"
Write-Host "mcpServer.js path: $(Join-Path (Get-Location) 'mcpServer.js')"
```

#### 🍎 macOS Users

**Get Node.js path:**
```bash
which node
```
Example output: `/usr/local/bin/node` or `/opt/homebrew/bin/node`

**Get mcpServer.js path:**
```bash
realpath mcpServer.js
```
Example output: `/Users/username/google-apps-script-mcp-server/mcpServer.js`

**Alternative method:**
```bash
echo "$(pwd)/mcpServer.js"
```

**Quick copy-paste command to get both paths:**
```bash
echo "Node.js path: $(which node)"
echo "mcpServer.js path: $(realpath mcpServer.js)"
```

#### 🐧 Linux Users

**Get Node.js path:**
```bash
which node
```
Example output: `/usr/bin/node` or `/usr/local/bin/node`

**Get mcpServer.js path:**
```bash
realpath mcpServer.js
```
Example output: `/home/username/google-apps-script-mcp-server/mcpServer.js`

**Quick copy-paste command to get both paths:**
```bash
echo "Node.js path: $(which node)"
echo "mcpServer.js path: $(realpath mcpServer.js)"
```

#### ✅ Verify Node.js Version

On any platform, verify your Node.js version:
```bash
node --version
```
Ensure it shows `v18.0.0` or higher.

### 🤖 Claude Desktop Setup

**Step 1**: Note the full paths from the previous section.

**Step 2**: Open Claude Desktop and navigate to:
- **Settings** → **Developers** → **Edit Config**

**Step 3**: Add your MCP server configuration:

#### Configuration Template
```json
{
  "mcpServers": {
    "google-apps-script": {
      "command": "<absolute_path_to_node_executable>",
      "args": ["<absolute_path_to_mcpServer.js>"],
      "env": {
        "GOOGLE_APP_SCRIPT_API_CLIENT_ID": "your_client_id_here",
        "GOOGLE_APP_SCRIPT_API_CLIENT_SECRET": "your_client_secret_here"
      }
    }
  }
}
```

#### Windows Example
```json
{
  "mcpServers": {
    "google-apps-script": {
      "command": "C:\\nvm4w\\nodejs\\node.exe",
      "args": ["C:\\Users\\mohal\\Downloads\\google-appscriot-mcp-server\\mcpServer.js"],
      "env": {
        "GOOGLE_APP_SCRIPT_API_CLIENT_ID": "1234567890-abcdefghijk.apps.googleusercontent.com",
        "GOOGLE_APP_SCRIPT_API_CLIENT_SECRET": "GOCSPX-abcdefghijklmnopqrstuvwxyz"
      }
    }
  }
}
```

#### macOS/Linux Example
```json
{
  "mcpServers": {
    "google-apps-script": {
      "command": "/usr/local/bin/node",
      "args": ["/Users/username/google-apps-script-mcp-server/mcpServer.js"],
      "env": {
        "GOOGLE_APP_SCRIPT_API_CLIENT_ID": "1234567890-abcdefghijk.apps.googleusercontent.com",
        "GOOGLE_APP_SCRIPT_API_CLIENT_SECRET": "GOCSPX-abcdefghijklmnopqrstuvwxyz"
      }
    }
  }
}
```

**Step 4**: Replace the OAuth credentials with your actual values from the `.env` file.

**Step 5**: Save the configuration and restart Claude Desktop.

**Step 6**: Verify the connection by checking that the MCP server shows a green circle indicator next to it in Claude Desktop.

### 📝 VS Code Setup (Cline/MCP Extensions)

VS Code can use MCP servers through extensions like **Cline** or other MCP-compatible extensions.

#### Using with Cline Extension

**Step 1**: Install the [Cline extension](https://marketplace.visualstudio.com/items?itemName=saoudrizwan.claude-dev) from the VS Code marketplace.

**Step 2**: Open VS Code settings (`Ctrl+,` on Windows/Linux, `Cmd+,` on macOS).

**Step 3**: Search for "Cline" or "MCP" in the settings.

**Step 4**: Add your MCP server configuration:

#### Method 1: VS Code Settings.json
Add to your VS Code `settings.json` (accessible via `Ctrl+Shift+P` → "Preferences: Open Settings (JSON)"):

```json
{
  "cline.mcpServers": {
    "google-apps-script": {
      "command": "C:\\nvm4w\\nodejs\\node.exe",
      "args": ["C:\\Users\\mohal\\Downloads\\google-appscriot-mcp-server\\mcpServer.js"],
      "env": {
        "GOOGLE_APP_SCRIPT_API_CLIENT_ID": "your_client_id_here",
        "GOOGLE_APP_SCRIPT_API_CLIENT_SECRET": "your_client_secret_here"
      }
    }
  }
}
```

#### Method 2: Workspace Configuration
Create a `.vscode/settings.json` file in your project root:

```json
{
  "cline.mcpServers": {
    "google-apps-script": {
      "command": "node",
      "args": ["./mcpServer.js"],
      "env": {
        "GOOGLE_APP_SCRIPT_API_CLIENT_ID": "your_client_id_here",
        "GOOGLE_APP_SCRIPT_API_CLIENT_SECRET": "your_client_secret_here"
      }
    }
  }
}
```

### 🔧 Configuration File Locations

#### Claude Desktop Config Location:
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Linux**: `~/.config/claude-desktop/claude_desktop_config.json`

#### VS Code Settings Location:
- **Windows**: `%APPDATA%\Code\User\settings.json`
- **macOS**: `~/Library/Application Support/Code/User/settings.json`
- **Linux**: `~/.config/Code/User/settings.json`

### 🎯 Quick Configuration Examples

Replace these paths with your actual system paths:

#### For Current Windows Setup:
```json
{
  "mcpServers": {
    "google-apps-script": {
      "command": "C:\\nvm4w\\nodejs\\node.exe",
      "args": ["C:\\Users\\mohal\\Downloads\\google-appscriot-mcp-server\\mcpServer.js"],
      "env": {
        "GOOGLE_APP_SCRIPT_API_CLIENT_ID": "your_actual_client_id",
        "GOOGLE_APP_SCRIPT_API_CLIENT_SECRET": "your_actual_client_secret"
      }
    }
  }
}
```

#### For macOS Setup:
```json
{
  "mcpServers": {
    "google-apps-script": {
      "command": "/usr/local/bin/node",
      "args": ["/Users/username/google-apps-script-mcp-server/mcpServer.js"],
      "env": {
        "GOOGLE_APP_SCRIPT_API_CLIENT_ID": "your_actual_client_id",
        "GOOGLE_APP_SCRIPT_API_CLIENT_SECRET": "your_actual_client_secret"
      }
    }
  }
}
```

#### For Linux Setup:
```json
{
  "mcpServers": {
    "google-apps-script": {
      "command": "/usr/bin/node",
      "args": ["/home/username/google-apps-script-mcp-server/mcpServer.js"],
      "env": {
        "GOOGLE_APP_SCRIPT_API_CLIENT_ID": "your_actual_client_id",
        "GOOGLE_APP_SCRIPT_API_CLIENT_SECRET": "your_actual_client_secret"
      }
    }
  }
}
```

**🔑 Remember to:**
1. Replace `your_actual_client_id` and `your_actual_client_secret` with your OAuth credentials
2. Update the paths based on your actual system output from the commands above
3. Use your actual username instead of `username` in the paths
4. Ensure you've run `npm run setup-oauth` before configuring MCP clients

## 🔍 Troubleshooting

### Common Issues and Solutions

#### 1. "Command not found" or "Node not found" errors
**Problem**: MCP client can't find Node.js executable
**Solutions**:
- Ensure Node.js is properly installed and in your PATH
- Use absolute paths to the Node.js executable (recommended)
- Verify Node.js version is 18+ using `node --version`
- On Windows, check if multiple Node.js versions are installed

#### 2. "fetch is not defined" errors
**Problem**: Your Node.js version is below 18
**Solutions**:
- **Recommended**: Upgrade to Node.js 18+ 
- **Alternative**: Install `node-fetch` as a dependency:
  ```bash
  npm install node-fetch
  ```
  Then modify each tool file to import fetch:
  ```javascript
  import fetch from 'node-fetch';
  ```

#### 3. OAuth authentication errors
**Problem**: Authentication failures or token issues
**Solutions**:
- Verify your OAuth credentials are correct in the `.env` file
- Ensure environment variables are properly set in the MCP configuration
- Re-run the OAuth setup: `npm run setup-oauth`
- Check that you've followed all steps in the Google Cloud Console setup
- Verify the callback URL is exactly: `http://localhost:3001/oauth/callback`
- Make sure your Google account is added as a test user

#### 4. "Authorization Error: Access blocked" 
**Problem**: Google OAuth consent screen configuration issues
**Solutions**:
- Ensure your app is configured for "External" users
- Add your Gmail address as a test user in OAuth consent screen
- Verify all required scopes are added
- Make sure the OAuth consent screen is properly published

#### 5. MCP server not appearing in Claude Desktop
**Problem**: Configuration file syntax or path issues
**Solutions**:
- Check the configuration file syntax (valid JSON)
- Ensure file paths use proper escaping (double backslashes on Windows)
- Restart Claude Desktop after configuration changes
- Check Claude Desktop logs for error messages
- Verify the config file is in the correct location

#### 6. VS Code/Cline connection issues
**Problem**: Extension not recognizing MCP server
**Solutions**:
- Verify the extension is properly installed and enabled
- Check that the MCP configuration is in the correct settings location
- Reload the VS Code window after configuration changes
- Use workspace-specific settings if global settings don't work

#### 7. "Permission denied" errors (macOS/Linux)
**Problem**: File permission issues
**Solutions**:
- Make the `mcpServer.js` file executable: `chmod +x mcpServer.js`
- Or use the full node command: `node /path/to/mcpServer.js`
- Check file ownership and permissions

#### 8. "EADDRINUSE" or port conflicts
**Problem**: Port 3001 is already in use during OAuth setup
**Solutions**:
- Kill any processes using port 3001:
  ```bash
  # Find process using port 3001
  lsof -i :3001  # macOS/Linux
  netstat -ano | findstr :3001  # Windows
  
  # Kill the process
  kill -9 <PID>  # macOS/Linux
  taskkill /PID <PID> /F  # Windows
  ```
- Or temporarily change the port in `oauth-setup.js`

#### 9. "Token expired" or "Invalid credentials" errors
**Problem**: OAuth tokens have expired or are invalid
**Solutions**:
- Re-run the OAuth setup: `npm run setup-oauth`
- Clear stored tokens and re-authenticate
- Check that your OAuth app credentials haven't changed
- Verify the OAuth app is still active in Google Cloud Console

#### 10. Script execution permission errors
**Problem**: Can't execute scripts or access projects
**Solutions**:
- Ensure your Google account has access to the Apps Script projects
- Verify the script is shared with your account
- Check that the required scopes are granted
- For script execution, ensure the script is deployed and executable

### Testing Your Configuration

#### Test MCP Server Independently
```bash
npm start
```
If it starts without errors, your basic setup is correct.

#### Test OAuth Authentication
```bash
npm run test-oauth
```
This verifies your OAuth setup is working correctly.

#### Test with Debug Logging
```bash
npm run debug
```
This provides detailed logging to help identify issues.

#### Test Individual Tools
```bash
npm run list-tools
```
This lists all available tools and their parameters.

### Log Files and Debugging

#### Enable Debug Logging
Set the `LOG_LEVEL` environment variable:
```bash
# In .env file
LOG_LEVEL=debug

# Or run with debug
npm run debug
```

#### Check OAuth Flow
The OAuth setup process provides detailed output. Watch for:
- Browser opening successfully
- Authorization code capture
- Token exchange success
- Test API call success

#### Common Log Messages

**Success Messages**:
- `OAuth tokens loaded successfully`
- `Server ready to handle MCP requests`
- `Tool executed successfully`

**Warning Messages**:
- `Token refresh required` (normal operation)
- `Retrying API call with refreshed token`

**Error Messages**:
- `OAuth credentials not found` → Check .env file
- `Failed to refresh token` → Re-run OAuth setup
- `API call failed` → Check permissions and quotas

### Getting Help

#### Support Resources
1. **Google Apps Script API Documentation**: [https://developers.google.com/apps-script/api](https://developers.google.com/apps-script/api)
2. **MCP Protocol Documentation**: [https://modelcontextprotocol.io/](https://modelcontextprotocol.io/)
3. **OAuth 2.0 Guide**: [https://developers.google.com/identity/protocols/oauth2](https://developers.google.com/identity/protocols/oauth2)

#### Diagnostic Information to Collect
When seeking help, please provide:
- Node.js version (`node --version`)
- Operating system and version
- Error messages from console/logs
- Steps you followed before the error
- Contents of your `.env` file (without secrets)
- MCP client configuration (without secrets)

## 🚀 Advanced Usage

### Environment Variables

#### Core Configuration
```env
# Required OAuth credentials
GOOGLE_APP_SCRIPT_API_CLIENT_ID=your_client_id
GOOGLE_APP_SCRIPT_API_CLIENT_SECRET=your_client_secret

# Optional configuration
LOG_LEVEL=info                    # debug, info, warn, error
NODE_ENV=development              # development, production
PORT=3001                        # OAuth callback port
```

#### Logging Levels
- `debug`: Detailed debugging information
- `info`: General information messages  
- `warn`: Warning messages
- `error`: Error messages only

### Running in Production

#### Using PM2 Process Manager
```bash
# Install PM2
npm install -g pm2

# Start with PM2
pm2 start mcpServer.js --name "gas-mcp-server"

# Monitor
pm2 status
pm2 logs gas-mcp-server

# Auto-restart on system boot
pm2 startup
pm2 save
```

#### Using Docker

**Build Docker image:**
```bash
docker build -t google-apps-script-mcp .
```

**Run with Docker:**
```bash
docker run -i --rm --env-file=.env google-apps-script-mcp
```

**Docker Compose setup:**
```yaml
version: '3.8'
services:
  gas-mcp:
    build: .
    env_file:
      - .env
    stdin_open: true
    tty: true
```

#### Claude Desktop with Docker
```json
{
  "mcpServers": {
    "google-apps-script": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "--env-file=.env", "google-apps-script-mcp"]
    }
  }
}
```

### Custom Tool Development

#### Adding New Tools

1. **Create a new tool file** in `tools/google-app-script-api/apps-script-api/`:
```javascript
import { getAuthHeaders } from '../../../lib/oauth-helper.js';

const executeFunction = async ({ param1, param2 }) => {
  const baseUrl = 'https://script.googleapis.com';
  
  try {
    const headers = await getAuthHeaders();
    const response = await fetch(`${baseUrl}/v1/your-endpoint`, {
      method: 'POST',
      headers,
      body: JSON.stringify({ param1, param2 })
    });
    
    return await response.json();
  } catch (error) {
    throw new Error(`API call failed: ${error.message}`);
  }
};

export { executeFunction };
```

2. **Add to paths.js**:
```javascript
export const toolPaths = [
  // ...existing paths...
  'google-app-script-api/apps-script-api/your-new-tool.js'
];
```

3. **Update tool descriptions** in your MCP server tool definitions.

#### Tool Template Structure
```javascript
import { getAuthHeaders } from '../../../lib/oauth-helper.js';

/**
 * Tool description and JSDoc comments
 */
const executeFunction = async (args) => {
  const baseUrl = 'https://script.googleapis.com';
  
  try {
    // 1. Validate parameters
    if (!args.requiredParam) {
      throw new Error('requiredParam is required');
    }
    
    // 2. Get authentication headers
    const headers = await getAuthHeaders();
    
    // 3. Make API call
    const response = await fetch(`${baseUrl}/v1/endpoint`, {
      method: 'GET/POST/PUT/DELETE',
      headers,
      body: JSON.stringify(args) // for POST/PUT
    });
    
    // 4. Handle response
    if (!response.ok) {
      throw new Error(`API error: ${response.status} ${response.statusText}`);
    }
    
    return await response.json();
    
  } catch (error) {
    console.error('Tool execution failed:', error);
    throw error;
  }
};

export { executeFunction };
```

### Server-Sent Events (SSE) Mode

For real-time communication with web interfaces:

```bash
npm run start-sse
```

The server will run on HTTP with SSE support for streaming responses.

### Multiple Environment Support

#### Development Environment
```env
NODE_ENV=development
LOG_LEVEL=debug
GOOGLE_APP_SCRIPT_API_CLIENT_ID=dev_client_id
GOOGLE_APP_SCRIPT_API_CLIENT_SECRET=dev_client_secret
```

#### Production Environment
```env
NODE_ENV=production
LOG_LEVEL=info
GOOGLE_APP_SCRIPT_API_CLIENT_ID=prod_client_id
GOOGLE_APP_SCRIPT_API_CLIENT_SECRET=prod_client_secret
```

### Performance Optimization

#### Token Caching
The OAuth helper automatically caches access tokens in memory and refreshes them as needed.

#### Request Batching
For multiple operations, consider batching requests where possible:

```javascript
// Instead of multiple individual calls
const results = await Promise.all([
  tool1(args1),
  tool2(args2),
  tool3(args3)
]);
```

#### Rate Limiting
Google Apps Script API has rate limits. The tools include automatic retry logic with exponential backoff.

### Security Best Practices

#### Credential Management
- Never commit `.env` files to version control
- Use different OAuth apps for development and production
- Regularly rotate OAuth credentials
- Monitor OAuth app usage in Google Cloud Console

#### Access Control
- Use least-privilege OAuth scopes
- Add only necessary test users to your OAuth app
- Monitor script execution logs for unauthorized access
- Implement logging for all API calls

#### Network Security
- Run the MCP server in a secure environment
- Use HTTPS for production deployments
- Implement proper firewall rules
- Monitor network traffic for anomalies

## 🛠️ Additional CLI Commands

### Available npm Scripts

```bash
# Start the MCP server
npm start

# Start with SSE support
npm run start-sse

# Start with debug logging
npm run debug

# Start SSE with debug logging
npm run debug-sse

# List all available tools and their descriptions
npm run list-tools

# Test OAuth authentication
npm run test-oauth

# Set up or refresh OAuth tokens
npm run setup-oauth

# Test logging functionality
npm run test-logging
```

### Tool Information

#### List Available Tools
```bash
npm run list-tools
```

Example output:
```
Available Tools:

Google Apps Script API:
  script-projects-create
    Description: Create a new Google Apps Script project
    Parameters:
      - title (required): The title of the new script project
      - parentId (optional): The ID of the parent project

  script-projects-get
    Description: Get metadata of a Google Apps Script project
    Parameters:
      - scriptId (required): The ID of the script project to retrieve
      - fields (optional): Specific fields to include in response
      [... additional parameters ...]
```

### Adding New Tools from Postman

1. Visit [Postman MCP Generator](https://postman.com/explore/mcp-generator)
2. Select new API requests for Google Apps Script or other APIs
3. Generate a new MCP server
4. Copy new tool files into your existing `tools/` folder
5. Update `tools/paths.js` to include new tool references
6. Restart your MCP server

## 💬 Support and Community

### Getting Help

- **GitHub Issues**: Report bugs and request features
- **Postman Discord**: Join the `#mcp-lab` channel in [Postman Discord](https://discord.gg/HQJWM8YF)
- **Documentation**: Visit [Postman MCP Generator](https://postman.com/explore/mcp-generator) for updates

### Contributing

Contributions are welcome! Please:
1. Fork the repository
2. Create a feature branch
3. Add tests for new functionality
4. Submit a pull request

### License

This project is licensed under the MIT License. See the LICENSE file for details.

```

--------------------------------------------------------------------------------
/test/debug-mcp-deployment.js:
--------------------------------------------------------------------------------

```javascript

```

--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------

```dockerfile
FROM node:22.12-alpine AS builder

WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install

COPY . .

ENTRYPOINT ["node", "mcpServer.js"]
```

--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------

```javascript
import { Command } from "commander";
import { registerToolsCommand } from "./commands/tools.js";

const program = new Command();

// Register commands
registerToolsCommand(program);

program.parse(process.argv);

```

--------------------------------------------------------------------------------
/test/debug-test.js:
--------------------------------------------------------------------------------

```javascript
console.log('🔍 Debug: Script starting...');

import 'dotenv/config';
console.log('🔍 Debug: Dotenv loaded');

import { TokenManager } from './lib/tokenManager.js';
console.log('🔍 Debug: TokenManager imported');

const tokenManager = new TokenManager();
console.log('🔍 Debug: TokenManager instantiated');

const tokenInfo = tokenManager.getTokenInfo();
console.log('🔍 Debug: TokenInfo obtained:', tokenInfo);

console.log('🔍 Debug: Script completed successfully');

```

--------------------------------------------------------------------------------
/test/simple-test.js:
--------------------------------------------------------------------------------

```javascript
import 'dotenv/config';

console.log('🧪 Simple OAuth Test');
console.log('Environment check:');
console.log('- CLIENT_ID exists:', !!process.env.GOOGLE_APP_SCRIPT_API_CLIENT_ID);
console.log('- CLIENT_SECRET exists:', !!process.env.GOOGLE_APP_SCRIPT_API_CLIENT_SECRET);
console.log('- REFRESH_TOKEN exists:', !!process.env.GOOGLE_APP_SCRIPT_API_REFRESH_TOKEN);

// Test OAuth helper import
try {
  const { getAuthHeaders } = await import('./lib/oauth-helper.js');
  console.log('✅ OAuth helper imported successfully');
  
  const headers = await getAuthHeaders();
  console.log('✅ Headers obtained:', Object.keys(headers));
  
} catch (error) {
  console.error('❌ Error:', error.message);
}

```

--------------------------------------------------------------------------------
/test/simple-oauth-test.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

/**
 * Simple OAuth Setup Test
 */

console.log('🔐 OAuth Setup Test');
console.log('==================');

// Test without any imports first
console.log('✅ Console output working');

try {
  console.log('📦 Testing imports...');
  
  // Test basic import
  const { TokenManager } = await import('../lib/tokenManager.js');
  console.log('✅ TokenManager imported successfully');
  
  const tokenManager = new TokenManager();
  console.log('✅ TokenManager instance created');
  
  const tokenInfo = tokenManager.getTokenInfo();
  console.log('📊 Token info:', tokenInfo);
  
} catch (error) {
  console.error('❌ Error:', error.message);
  console.error('Stack:', error.stack);
}

```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "postman-mcp-generator-mcp",
  "version": "1.0.0",
  "description": "A simple MCP server with packaged tools",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "list-tools": "node index.js tools",
    "test-oauth": "node test-oauth.js",
    "setup-oauth": "node oauth-setup.js",
    "test-logging": "node test-logging.js",
    "start": "node mcpServer.js",
    "start-sse": "node mcpServer.js --sse",
    "debug": "LOG_LEVEL=debug node mcpServer.js",
    "debug-sse": "LOG_LEVEL=debug node mcpServer.js --sse"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.9.0",
    "commander": "^13.1.0",
    "dotenv": "^16.4.7",
    "express": "^5.1.0",
    "googleapis": "^149.0.0",
    "open": "^10.1.2"
  },
  "engines": {
    "node": ">=16.0.0"
  },
  "author": "Postman, Inc.",
  "license": "MIT"
}

```

--------------------------------------------------------------------------------
/test/test-mcp-version-fix.js:
--------------------------------------------------------------------------------

```javascript
// Test script to verify MCP version creation works
import { apiTool } from './tools/google-app-script-api/apps-script-api/script-projects-versions-create.js';

const scriptId = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';

async function testVersionCreation() {
  console.log('🧪 Testing MCP version creation...');
  
  try {
    const result = await apiTool.function({
      scriptId: scriptId,
      description: 'Test version creation via MCP tools'
    });
    
    console.log('✅ Version creation result:', JSON.stringify(result, null, 2));
    
    if (result.versionNumber) {
      console.log('🎉 Version created successfully!');
      console.log(`📊 Version Number: ${result.versionNumber}`);
    } else {
      console.log('❌ Version creation failed:', result);
    }
    
  } catch (error) {
    console.error('💥 Error during version creation:', error);
  }
}

testVersionCreation();

```

--------------------------------------------------------------------------------
/helpers/check-head-deployment.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

import { getOAuthAccessToken } from './lib/oauth-helper.js';

async function checkHeadDeployment() {
  const scriptId = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';
  
  try {
    console.log('🔐 Getting OAuth token...');
    const token = await getOAuthAccessToken();
    
    console.log('📋 Checking HEAD deployment...');
    const deployResponse = await fetch(`https://script.googleapis.com/v1/projects/${scriptId}/deployments/HEAD`, {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${token}`
      }
    });
    
    if (!deployResponse.ok) {
      const error = await deployResponse.text();
      console.error('❌ HEAD deployment error:', error);
      return;
    }
    
    const deployment = await deployResponse.json();
    console.log('✅ HEAD deployment:', JSON.stringify(deployment, null, 2));
    
  } catch (error) {
    console.error('💥 Error:', error);
  }
}

checkHeadDeployment();

```

--------------------------------------------------------------------------------
/tools/paths.js:
--------------------------------------------------------------------------------

```javascript
export const toolPaths = [
  'google-app-script-api/apps-script-api/script-projects-deployments-delete.js',
  'google-app-script-api/apps-script-api/script-projects-create.js',
  'google-app-script-api/apps-script-api/script-projects-versions-create.js',
  'google-app-script-api/apps-script-api/script-projects-deployments-create.js',
  'google-app-script-api/apps-script-api/script-projects-deployments-update.js',
  'google-app-script-api/apps-script-api/script-projects-deployments-list.js',
  'google-app-script-api/apps-script-api/script-projects-update-content.js',
  'google-app-script-api/apps-script-api/script-projects-deployments-get.js',
  'google-app-script-api/apps-script-api/script-scripts-run.js',
  'google-app-script-api/apps-script-api/script-projects-get.js',
  'google-app-script-api/apps-script-api/script-processes-list-script-processes.js',
  'google-app-script-api/apps-script-api/script-projects-get-metrics.js',
  'google-app-script-api/apps-script-api/script-projects-get-content.js',
  'google-app-script-api/apps-script-api/script-projects-versions-list.js',
  'google-app-script-api/apps-script-api/script-projects-versions-get.js',
  'google-app-script-api/apps-script-api/script-processes-list.js'
];
```

--------------------------------------------------------------------------------
/test/test-mcp-deployment-fix.js:
--------------------------------------------------------------------------------

```javascript
// Test script to verify MCP deployment creation works
import { apiTool } from './tools/google-app-script-api/apps-script-api/script-projects-deployments-create.js';

const scriptId = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';

async function testDeploymentCreation() {
  console.log('🧪 Testing MCP deployment creation...');
  
  try {
    const result = await apiTool.function({
      scriptId: scriptId,
      manifestFileName: 'appsscript',
      versionNumber: 1,
      description: 'Test deployment via MCP tools'
    });
    
    console.log('✅ Deployment creation result:', JSON.stringify(result, null, 2));
    
    if (result.deploymentId) {
      console.log('🎉 Deployment created successfully!');
      console.log(`📱 Deployment ID: ${result.deploymentId}`);
      if (result.entryPoints && result.entryPoints.length > 0) {
        const webAppEntry = result.entryPoints.find(entry => entry.entryPointType === 'WEB_APP');
        if (webAppEntry) {
          console.log(`🌐 Web App URL: ${webAppEntry.webApp.url}`);
        }
      }
    } else {
      console.log('❌ Deployment creation failed:', result);
    }
    
  } catch (error) {
    console.error('💥 Error during deployment creation:', error);
  }
}

testDeploymentCreation();

```

--------------------------------------------------------------------------------
/test/update-webapp-deployment.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

import { getOAuthAccessToken } from '../lib/oauth-helper.js';

async function updateDeploymentForWebApp() {
  const scriptId = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';
  const deploymentId = 'AKfycbx58SZUlVdfZdlUsfYiJnj94oBrpb_yH7IpbSqu7bhDs8sawIgIXaw40c1NLooxNb2e';
  
  try {
    console.log('🔐 Getting OAuth token...');
    const token = await getOAuthAccessToken();
    
    console.log('🚀 Updating deployment for web app...');
    const updateResponse = await fetch(`https://script.googleapis.com/v1/projects/${scriptId}/deployments/${deploymentId}`, {
      method: 'PUT',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        deploymentConfig: {
          scriptId: scriptId,
          versionNumber: 4,
          manifestFileName: 'appsscript',
          description: 'Web app accessible by anyone',
          access: 'ANYONE',
          executeAs: 'USER_DEPLOYING'
        }
      })
    });
    
    if (!updateResponse.ok) {
      const error = await updateResponse.text();
      console.error('❌ Update deployment error:', error);
      return;
    }
    
    const updatedDeployment = await updateResponse.json();
    console.log('✅ Updated deployment:', JSON.stringify(updatedDeployment, null, 2));
    
  } catch (error) {
    console.error('💥 Error:', error);
  }
}

updateDeploymentForWebApp();

```

--------------------------------------------------------------------------------
/test/test-versions-list.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

import 'dotenv/config';
import { apiTool } from './tools/google-app-script-api/apps-script-api/script-projects-versions-list.js';

async function testVersionsList() {
  const scriptId = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';
  
  console.log('📋 Listing versions for script:', scriptId);
  console.log('═'.repeat(80));
  
  try {
    const result = await apiTool.function({ scriptId });
    
    if (result.error) {
      console.log('❌ Error occurred:');
      console.log(JSON.stringify(result, null, 2));
    } else {
      console.log('✅ Script versions retrieved successfully:');
      console.log(JSON.stringify(result, null, 2));
      
      if (result.versions && result.versions.length > 0) {
        console.log('\n📊 Summary:');
        console.log('Total versions:', result.versions.length);
        console.log('\n📝 Version details:');
        result.versions.forEach((version, index) => {
          console.log(`${index + 1}. Version ${version.versionNumber}`);
          console.log(`   Description: ${version.description || 'No description'}`);
          console.log(`   Created: ${version.createTime || 'Unknown'}`);
          console.log('');
        });
      } else {
        console.log('No versions found for this script.');
      }
    }
  } catch (error) {
    console.error('❌ Unexpected error:', error.message);
    console.error('Stack trace:', error.stack);
  }
}

testVersionsList();

```

--------------------------------------------------------------------------------
/test/debug-content-fetch.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

/**
 * Debug script to test the get-content function directly
 */

import { getOAuthAccessToken } from '../lib/oauth-helper.js';

async function testGetContent() {
  const scriptId = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';
  
  try {
    console.log('🔐 Getting OAuth access token...');
    const token = await getOAuthAccessToken();
    console.log('✅ Got access token:', token.substring(0, 20) + '...');
    
    console.log('🌐 Making API request to get script content...');
    const url = `https://script.googleapis.com/v1/projects/${scriptId}/content`;
    
    const response = await fetch(url, {
      method: 'GET',
      headers: {
        'Accept': 'application/json',
        'Authorization': `Bearer ${token}`
      }
    });
    
    console.log('📡 Response status:', response.status);
    console.log('📡 Response headers:', Object.fromEntries(response.headers.entries()));
    
    if (!response.ok) {
      const errorText = await response.text();
      console.error('❌ API Error Response:', errorText);
      
      // Try to parse as JSON for more details
      try {
        const errorJson = JSON.parse(errorText);
        console.error('❌ Parsed error:', JSON.stringify(errorJson, null, 2));
      } catch (e) {
        console.error('❌ Raw error text:', errorText);
      }
      
      return;
    }
    
    const data = await response.json();
    console.log('✅ Success! Script content:');
    console.log(JSON.stringify(data, null, 2));
    
  } catch (error) {
    console.error('💥 Error:', error);
  }
}

testGetContent();

```

--------------------------------------------------------------------------------
/test/test-mcp-deployment-get.js:
--------------------------------------------------------------------------------

```javascript
// Test script to verify MCP deployment get works
import { apiTool } from './tools/google-app-script-api/apps-script-api/script-projects-deployments-get.js';

const scriptId = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';
const deploymentId = 'AKfycbzfRN3HuD8OsEwqQ9mSAGUbuGQrX3krWJPjewVkgKWEkzi_QpuoQBdDlrHBgAS4MhB4'; // From previous test

async function testDeploymentGet() {
  console.log('🧪 Testing MCP deployment get...');
  
  try {
    const result = await apiTool.function({
      scriptId: scriptId,
      deploymentId: deploymentId
    });
    
    console.log('✅ Deployment get result:', JSON.stringify(result, null, 2));
    
    if (result.deploymentId) {
      console.log('🎉 Deployment retrieved successfully!');
      console.log(`📱 Deployment ID: ${result.deploymentId}`);
      
      if (result.entryPoints && result.entryPoints.length > 0) {
        console.log('🔗 Entry Points:');
        result.entryPoints.forEach((entryPoint, index) => {
          console.log(`  ${index + 1}. Type: ${entryPoint.entryPointType}`);
          if (entryPoint.webApp) {
            console.log(`     🌐 Web App URL: ${entryPoint.webApp.url}`);
            console.log(`     🔒 Access: ${entryPoint.webApp.access}`);
            console.log(`     👤 Execute As: ${entryPoint.webApp.executeAs}`);
          }
        });
      } else {
        console.log('⚠️ No entry points found in deployment');
      }
    } else {
      console.log('❌ Deployment retrieval failed:', result);
    }
    
  } catch (error) {
    console.error('💥 Error during deployment get:', error);
  }
}

testDeploymentGet();

```

--------------------------------------------------------------------------------
/test/update-error-handling.js:
--------------------------------------------------------------------------------

```javascript
// Script to update all MCP tools with enhanced error handling
import fs from 'fs';
import path from 'path';

const toolsDir = './tools/google-app-script-api/apps-script-api';
const files = [
  'script-projects-update-content.js',
  'script-projects-deployments-update.js', 
  'script-projects-deployments-get.js',
  'script-projects-get-metrics.js',
  'script-scripts-run.js',
  'script-projects-deployments-delete.js',
  'script-projects-versions-get.js'
];

const loggerImport = `import { logger } from '../../../lib/logger.js';`;

for (const file of files) {
  const filePath = path.join(toolsDir, file);
  if (fs.existsSync(filePath)) {
    let content = fs.readFileSync(filePath, 'utf8');
    
    // Add logger import if not present
    if (!content.includes("import { logger }")) {
      // Find the first import and add logger import after it
      const firstImportMatch = content.match(/import .+ from .+;/);
      if (firstImportMatch) {
        const firstImport = firstImportMatch[0];
        content = content.replace(firstImport, firstImport + '\n' + loggerImport);
      }
    }
    
    // Replace simple error returns with detailed logging
    const simpleErrorPattern = /return \{ error: '.*\.' \};/g;
    const errorMatches = content.match(simpleErrorPattern);
    
    if (errorMatches) {
      console.log(`Updating ${file}...`);
      
      // This would need custom logic for each file based on its specific structure
      // For now, we'll note which files need manual update
      console.log(`  - Found error patterns: ${errorMatches.length}`);
    }
  }
}

console.log('Script completed. Manual updates still needed for specific error handling patterns.');

```

--------------------------------------------------------------------------------
/helpers/create-webapp-deployment.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

import { getOAuthAccessToken } from './lib/oauth-helper.js';

async function createVersionAndDeploy() {
  const scriptId = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';
  
  try {
    console.log('🔐 Getting OAuth token...');
    const token = await getOAuthAccessToken();
    
    console.log('📋 Creating version...');
    const versionResponse = await fetch(`https://script.googleapis.com/v1/projects/${scriptId}/versions`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ 
        description: 'Version for web app deployment' 
      })
    });
    
    if (!versionResponse.ok) {
      const error = await versionResponse.text();
      console.error('❌ Version creation error:', error);
      return;
    }
    
    const version = await versionResponse.json();
    console.log('✅ Version created:', JSON.stringify(version, null, 2));
      console.log('🚀 Creating deployment...');
    const deployResponse = await fetch(`https://script.googleapis.com/v1/projects/${scriptId}/deployments`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        versionNumber: version.versionNumber,
        description: 'Web app accessible by anyone',
        manifestFileName: 'appsscript'
      })
    });
    
    if (!deployResponse.ok) {
      const error = await deployResponse.text();
      console.error('❌ Deployment creation error:', error);
      return;
    }
    
    const deployment = await deployResponse.json();
    console.log('✅ Deployment created:', JSON.stringify(deployment, null, 2));
    
  } catch (error) {
    console.error('💥 Error:', error);
  }
}

createVersionAndDeploy();

```

--------------------------------------------------------------------------------
/test/test-mcp-tools.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

/**
 * Test script to verify MCP tools work with automatic OAuth
 */

import 'dotenv/config';
import { getAuthHeaders } from './lib/oauth-helper.js';

// Test the script-projects-get tool
async function testScriptProjectGet() {
  console.log('🧪 Testing script-projects-get tool...');
  
  try {
    // Import the tool
    const { apiTool } = await import('./tools/google-app-script-api/apps-script-api/script-projects-get.js');
    
    // Test with a sample script ID (this will likely fail but should show detailed error info)
    const testScriptId = '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms'; // Sample ID
    
    console.log('📋 Testing with script ID:', testScriptId);
    console.log('🔄 Calling tool function...');
    
    const result = await apiTool.function({ scriptId: testScriptId });
    
    console.log('✅ Tool result:', JSON.stringify(result, null, 2));
    
  } catch (error) {
    console.error('❌ Test error:', error);
  }
}

// Test OAuth headers directly
async function testOAuthHeaders() {
  console.log('\n🧪 Testing OAuth headers directly...');
  
  try {
    const headers = await getAuthHeaders();
    console.log('✅ OAuth headers obtained successfully');
    console.log('🔐 Authorization header length:', headers.Authorization?.length || 0);
    
    return true;
  } catch (error) {
    console.error('❌ OAuth error:', error);
    return false;
  }
}

// Main test function
async function runTests() {
  console.log('🚀 Starting MCP Tool Tests...');
  console.log('=====================================');
  
  // Test OAuth headers first
  const oauthWorking = await testOAuthHeaders();
  
  if (!oauthWorking) {
    console.log('❌ OAuth not working, skipping tool test');
    return;
  }
  
  // Test the actual tool
  await testScriptProjectGet();
  
  console.log('\n🎉 Tests completed!');
}

runTests().catch(console.error);

```

--------------------------------------------------------------------------------
/lib/tools.js:
--------------------------------------------------------------------------------

```javascript
import { toolPaths } from "../tools/paths.js";
import { logger, withLogging } from "./logger.js";

/**
 * Discovers and loads available tools from the tools directory
 * @returns {Promise<Array>} Array of tool objects
 */
export async function discoverTools() {
  logger.info('DISCOVERY', `Starting tool discovery for ${toolPaths.length} tool paths`);
  
  const toolPromises = toolPaths.map(async (file) => {
    try {
      logger.debug('DISCOVERY', `Loading tool from: ${file}`);
      const module = await import(`../tools/${file}`);
      
      if (!module.apiTool) {
        logger.warn('DISCOVERY', `Tool file missing apiTool export: ${file}`);
        return null;
      }

      const toolName = module.apiTool.definition?.function?.name;
      if (!toolName) {
        logger.warn('DISCOVERY', `Tool missing function name: ${file}`);
        return null;
      }

      // Wrap the original function with logging
      const originalFunction = module.apiTool.function;
      const wrappedFunction = withLogging(toolName, originalFunction);

      logger.debug('DISCOVERY', `Successfully loaded tool: ${toolName}`, {
        file,
        toolName,
        description: module.apiTool.definition?.function?.description
      });

      return {
        ...module.apiTool,
        function: wrappedFunction,
        path: file,
      };
    } catch (error) {
      logger.error('DISCOVERY', `Failed to load tool: ${file}`, {
        file,
        error: {
          message: error.message,
          stack: error.stack
        }
      });
      return null;
    }
  });
  
  const tools = (await Promise.all(toolPromises)).filter(Boolean);
  
  logger.info('DISCOVERY', `Tool discovery completed`, {
    totalPaths: toolPaths.length,
    successfullyLoaded: tools.length,
    failed: toolPaths.length - tools.length,
    toolNames: tools.map(t => t.definition?.function?.name).filter(Boolean)
  });
  
  return tools;
}

```

--------------------------------------------------------------------------------
/helpers/check-deployments.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

import { getOAuthAccessToken } from './lib/oauth-helper.js';

async function checkDeployments() {
  const scriptId = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';
  
  try {
    console.log('🔐 Getting OAuth token...');
    const token = await getOAuthAccessToken();
    
    console.log('📋 Checking deployments...');
    const deployResponse = await fetch(`https://script.googleapis.com/v1/projects/${scriptId}/deployments`, {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${token}`
      }
    });
    
    if (!deployResponse.ok) {
      const error = await deployResponse.text();
      console.error('❌ Deployments list error:', error);
      return;
    }
    
    const deployments = await deployResponse.json();
    console.log('✅ Deployments:', JSON.stringify(deployments, null, 2));
    
    // For each deployment, get detailed info
    if (deployments.deployments) {
      for (const deployment of deployments.deployments) {
        console.log(`\n📋 Getting details for deployment: ${deployment.deploymentId}`);
        
        const detailResponse = await fetch(`https://script.googleapis.com/v1/projects/${scriptId}/deployments/${deployment.deploymentId}`, {
          method: 'GET',
          headers: {
            'Authorization': `Bearer ${token}`
          }
        });
        
        if (detailResponse.ok) {
          const details = await detailResponse.json();
          console.log('📄 Deployment details:', JSON.stringify(details, null, 2));
          
          // Check if it's a web app and show the URL
          if (details.entryPoints) {
            details.entryPoints.forEach(entry => {
              if (entry.entryPointType === 'WEB_APP') {
                console.log(`🌐 Web App URL: ${entry.webApp.url}`);
              }
            });
          }
        }
      }
    }
    
  } catch (error) {
    console.error('💥 Error:', error);
  }
}

checkDeployments();

```

--------------------------------------------------------------------------------
/test/test-mcp-content.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

/**
 * Test script to verify MCP server tools are working with OAuth
 */

import { discoverTools } from './lib/tools.js';

async function testMCPTools() {
  console.log('🔍 Testing MCP Server Tools with OAuth...');
  console.log('═'.repeat(60));
  
  try {
    // Discover all available tools
    console.log('📋 Step 1: Discovering available tools...');
    const tools = await discoverTools();
    console.log(`✅ Found ${tools.length} tools`);
    
    // Find the get-content tool
    const getContentTool = tools.find(tool => 
      tool.definition.function.name === 'script_projects_get_content'
    );
    
    if (!getContentTool) {
      console.error('❌ script_projects_get_content tool not found!');
      console.log('Available tools:');
      tools.forEach(tool => {
        console.log(`  - ${tool.definition.function.name}`);
      });
      return;
    }
    
    console.log('✅ Found script_projects_get_content tool');
    
    // Test the tool with your script ID
    console.log('📋 Step 2: Testing script content fetch...');
    const scriptId = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';
    
    console.log(`🔍 Fetching content for script: ${scriptId}`);
    const result = await getContentTool.function({ scriptId });
    
    if (result.error) {
      console.error('❌ Error fetching content:', result.error);
    } else {
      console.log('✅ Successfully fetched script content!');
      console.log('📊 Content summary:');
      console.log(`  - Script ID: ${result.scriptId}`);
      console.log(`  - Number of files: ${result.files?.length || 0}`);
      
      if (result.files) {
        result.files.forEach((file, index) => {
          console.log(`  - File ${index + 1}: ${file.name} (${file.type})`);
        });
      }
      
      console.log('\n📄 Full content:');
      console.log(JSON.stringify(result, null, 2));
    }
    
  } catch (error) {
    console.error('💥 Test failed:', error);
  }
}

testMCPTools();

```

--------------------------------------------------------------------------------
/commands/tools.js:
--------------------------------------------------------------------------------

```javascript
import { discoverTools } from "../lib/tools.js";

export function registerToolsCommand(program) {
  program
    .command("tools")
    .description("List all available API tools")
    .action(async () => {
      const tools = await discoverTools();
      if (tools.length === 0) {
        console.log("No tools found. Tools should be organized as:");
        console.log("tools/workspace/collection/request.js\n");
        return;
      }

      console.log("\nAvailable Tools:\n");

      // Group tools by workspace/collection
      const groupedTools = tools.reduce((acc, tool) => {
        // Extract workspace and collection from path
        const parts = tool.path.split("/");
        const workspace = parts[1] || "Unknown Workspace";
        const collection = parts[2] || "Unknown Collection";

        if (!acc[workspace]) acc[workspace] = {};
        if (!acc[workspace][collection]) acc[workspace][collection] = [];

        acc[workspace][collection].push(tool);
        return acc;
      }, {});

      // Print tools in a hierarchical structure
      for (const [workspace, collections] of Object.entries(groupedTools)) {
        console.log(`Workspace: ${workspace}`);
        for (const [collection, tools] of Object.entries(collections)) {
          console.log(`  Collection: ${collection}`);
          tools.forEach(
            ({
              definition: {
                function: { name, description, parameters },
              },
            }) => {
              console.log(`    ${name}`);
              console.log(
                `      Description: ${description || "No description provided"}`
              );
              if (parameters?.properties) {
                console.log("      Parameters:");
                Object.entries(parameters.properties).forEach(
                  ([name, details]) => {
                    console.log(
                      `        - ${name}: ${
                        details.description || "No description"
                      }`
                    );
                  }
                );
              }
              console.log("");
            }
          );
        }
        console.log("");
      }
    });
}
```

--------------------------------------------------------------------------------
/helpers/create-proper-webapp.js:
--------------------------------------------------------------------------------

```javascript
import { getOAuthAccessToken } from './lib/oauth-helper.js';

const scriptId = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';

async function createWebAppWithEntryPoint() {
  try {
    const token = await getOAuthAccessToken();
    
    console.log('Creating web app deployment with entry point...');
    
    // Create deployment with web app entry point configuration
    const deploymentConfig = {
      description: "Hello World Web App - Anyone Access",
      manifestFileName: "appsscript",
      versionNumber: 4,
      entryPoints: [
        {
          entryPointType: "WEB_APP",
          webApp: {
            access: "ANYONE",
            executeAs: "USER_ACCESSING"
          }
        }
      ]
    };

    console.log('Deployment config:', JSON.stringify(deploymentConfig, null, 2));

    const response = await fetch(`https://script.googleapis.com/v1/projects/${scriptId}/deployments`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      },
      body: JSON.stringify(deploymentConfig)
    });

    if (!response.ok) {
      const errorText = await response.text();
      console.error('Error response:', errorText);
      throw new Error(`HTTP ${response.status}: ${errorText}`);
    }

    const data = await response.json();
    console.log('Web app deployment created:', JSON.stringify(data, null, 2));
    
    if (data.entryPoints && data.entryPoints[0] && data.entryPoints[0].webApp) {
      console.log('\n🎉 SUCCESS! Your web app is now deployed and accessible!');
      console.log('Web App URL:', data.entryPoints[0].webApp.url);
      console.log('Access Level:', data.entryPoints[0].webApp.access);
      console.log('Execute As:', data.entryPoints[0].webApp.executeAs);
      console.log('\n📱 You can now access your Hello World app at the URL above!');
    }
    
    return data;
  } catch (error) {
    console.error('Error creating web app:', error);
    return null;
  }
}

async function main() {
  console.log('=== Google Apps Script Web App Deployment ===\n');
  console.log('Creating a deployment configured as a web app...\n');
  
  await createWebAppWithEntryPoint();
}

main().catch(console.error);

```

--------------------------------------------------------------------------------
/tools/google-app-script-api/apps-script-api/script-projects-deployments-get.js:
--------------------------------------------------------------------------------

```javascript
import { getOAuthAccessToken } from '../../../lib/oauth-helper.js';
import { logger } from '../../../lib/logger.js';

/**
 * Function to get a deployment of an Apps Script project.
 *
 * @param {Object} args - Arguments for the deployment retrieval.
 * @param {string} args.scriptId - The ID of the script project.
 * @param {string} args.deploymentId - The ID of the deployment to retrieve.
 * @returns {Promise<Object>} - The result of the deployment retrieval.
 */
const executeFunction = async ({ scriptId, deploymentId }) => {
  const baseUrl = 'https://script.googleapis.com';
  const url = `${baseUrl}/v1/projects/${scriptId}/deployments/${deploymentId}`;

  try {
    // Get OAuth access token
    const token = await getOAuthAccessToken();
    
    // Set up headers for the request
    const headers = {
      'Authorization': `Bearer ${token}`,
      'Accept': 'application/json'
    };

    // Perform the fetch request
    const response = await fetch(url, {
      method: 'GET',
      headers
    });

    // Check if the response was successful
    if (!response.ok) {
      const errorText = await response.text();
      console.error('API Error Response:', errorText);
      throw new Error(`HTTP ${response.status}: ${errorText}`);
    }

    // Parse and return the response data
    const data = await response.json();
    return data;
  } catch (error) {
    const errorDetails = {
      message: error.message,
      stack: error.stack,
      scriptId,
      deploymentId,
      timestamp: new Date().toISOString(),
      errorType: error.name || 'Unknown'
    };

    logger.error('DEPLOYMENT_GET', 'Error retrieving deployment', errorDetails);
    
    console.error('❌ Error retrieving deployment:', errorDetails);
    
    // Return detailed error information for debugging
    return { 
      error: true,
      message: error.message,
      details: errorDetails,
      rawError: {
        name: error.name,
        stack: error.stack
      }
    };
  }
};

/**
 * Tool configuration for getting a deployment of an Apps Script project.
 * @type {Object}
 */
const apiTool = {
  function: executeFunction,
  definition: {
    type: 'function',
    function: {
      name: 'script_projects_deployments_get',
      description: 'Get a deployment of an Apps Script project.',
      parameters: {
        type: 'object',
        properties: {
          scriptId: {
            type: 'string',
            description: 'The ID of the script project.'
          },
          deploymentId: {
            type: 'string',
            description: 'The ID of the deployment to retrieve.'
          }
        },
        required: ['scriptId', 'deploymentId']
      }
    }
  }
};

export { apiTool };
```

--------------------------------------------------------------------------------
/tools/google-app-script-api/apps-script-api/script-projects-deployments-delete.js:
--------------------------------------------------------------------------------

```javascript
import { logger } from '../../../lib/logger.js';

/**
 * Function to delete a deployment of an Apps Script project.
 *
 * @param {Object} args - Arguments for the deletion.
 * @param {string} args.scriptId - The ID of the script project.
 * @param {string} args.deploymentId - The ID of the deployment to delete.
 * @returns {Promise<Object>} - The result of the deletion operation.
 */
const executeFunction = async ({ scriptId, deploymentId }) => {
  const baseUrl = 'https://script.googleapis.com';
  const accessToken = ''; // will be provided by the user
  try {
    // Construct the URL for the DELETE request
    const url = `${baseUrl}/v1/projects/${scriptId}/deployments/${deploymentId}?fields=occaecat dolor eu&alt=json&$.xgafv=1&upload_protocol=occaecat dolor eu&uploadType=occaecat dolor eu&quotaUser=occaecat dolor eu&callback=occaecat dolor eu&prettyPrint=true`;

    // Set up headers for the request
    const headers = {
      'Authorization': `Bearer ${accessToken}`,
      'Accept': 'application/json'
    };

    // Perform the fetch request
    const response = await fetch(url, {
      method: 'DELETE',
      headers
    });

    // Check if the response was successful
    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(errorData);
    }

    // Parse and return the response data
    const data = await response.json();
    return data;
  } catch (error) {
    const errorDetails = {
      message: error.message,
      stack: error.stack,
      scriptId,
      deploymentId,
      timestamp: new Date().toISOString(),
      errorType: error.name || 'Unknown'
    };

    logger.error('DEPLOYMENT_DELETE', 'Error deleting deployment', errorDetails);
    
    console.error('❌ Error deleting deployment:', errorDetails);
    
    // Return detailed error information for debugging
    return { 
      error: true,
      message: error.message,
      details: errorDetails,
      rawError: {
        name: error.name,
        stack: error.stack
      }
    };
  }
};

/**
 * Tool configuration for deleting a deployment of an Apps Script project.
 * @type {Object}
 */
const apiTool = {
  function: executeFunction,
  definition: {
    type: 'function',
    function: {
      name: 'script_projects_deployments_delete',
      description: 'Delete a deployment of an Apps Script project.',
      parameters: {
        type: 'object',
        properties: {
          scriptId: {
            type: 'string',
            description: 'The ID of the script project.'
          },
          deploymentId: {
            type: 'string',
            description: 'The ID of the deployment to delete.'
          }
        },
        required: ['scriptId', 'deploymentId']
      }
    }
  }
};

export { apiTool };
```

--------------------------------------------------------------------------------
/helpers/create-web-app.js:
--------------------------------------------------------------------------------

```javascript
import { getOAuthAccessToken } from './lib/oauth-helper.js';

const scriptId = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';

async function listDeployments() {
  try {
    const token = await getOAuthAccessToken();
    
    console.log('Fetching current deployments...');
    const response = await fetch(`https://script.googleapis.com/v1/projects/${scriptId}/deployments`, {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Accept': 'application/json'
      }
    });

    if (!response.ok) {
      const errorText = await response.text();
      console.error('Error response:', errorText);
      throw new Error(`HTTP ${response.status}: ${errorText}`);
    }

    const data = await response.json();
    console.log('Current deployments:', JSON.stringify(data, null, 2));
    return data;
  } catch (error) {
    console.error('Error listing deployments:', error);
    return null;
  }
}

async function createWebApp() {
  try {
    const token = await getOAuthAccessToken();
    
    console.log('Creating web app deployment...');
    
    const deploymentConfig = {
      description: "Hello World Web App - Public Access",
      manifestFileName: "appsscript.json",
      versionNumber: 4, // Using the latest version we created
      accessConfig: {
        access: "ANYONE",
        executeAs: "USER_ACCESSING"
      }
    };

    console.log('Deployment config:', JSON.stringify(deploymentConfig, null, 2));

    const response = await fetch(`https://script.googleapis.com/v1/projects/${scriptId}/deployments`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      },
      body: JSON.stringify(deploymentConfig)
    });

    if (!response.ok) {
      const errorText = await response.text();
      console.error('Error response:', errorText);
      throw new Error(`HTTP ${response.status}: ${errorText}`);
    }

    const data = await response.json();
    console.log('Web app deployment created:', JSON.stringify(data, null, 2));
    
    if (data.entryPoints && data.entryPoints[0] && data.entryPoints[0].webApp) {
      console.log('\n🎉 SUCCESS! Your web app is now deployed!');
      console.log('Web App URL:', data.entryPoints[0].webApp.url);
      console.log('Access Level:', data.entryPoints[0].webApp.access);
      console.log('Execute As:', data.entryPoints[0].webApp.executeAs);
    }
    
    return data;
  } catch (error) {
    console.error('Error creating web app:', error);
    return null;
  }
}

async function main() {
  console.log('=== Google Apps Script Web App Deployment ===\n');
  
  // First list current deployments
  await listDeployments();
  
  console.log('\n' + '='.repeat(50) + '\n');
  
  // Then create the web app
  await createWebApp();
}

main().catch(console.error);

```

--------------------------------------------------------------------------------
/test/test-logging.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

/**
 * Test script to demonstrate enhanced MCP server logging
 */

import { logger } from './lib/logger.js';
import { discoverTools } from './lib/tools.js';

async function testLogging() {
  console.log('🧪 Testing Enhanced MCP Server Logging\n');
  
  // Test different log levels
  logger.info('TEST', 'Testing different log levels');
  logger.debug('TEST', 'This is a debug message', { detail: 'debug info' });
  logger.warn('TEST', 'This is a warning message');
  logger.error('TEST', 'This is an error message', { error: 'test error' });
  
  console.log('\n📋 Current Log Configuration:');
  console.log(`   - Log Level: ${process.env.LOG_LEVEL || 'info'}`);
  console.log(`   - Enabled Levels: ${logger.enabledLevels.join(', ')}`);
  
  console.log('\n🔍 Discovering Tools with Enhanced Logging:');
  try {
    const tools = await discoverTools();
    console.log(`\n✅ Discovered ${tools.length} tools successfully`);
    
    console.log('\n📊 Tool Summary:');
    tools.forEach((tool, index) => {
      const name = tool.definition?.function?.name || 'Unknown';
      const description = tool.definition?.function?.description || 'No description';
      console.log(`   ${index + 1}. ${name}: ${description.substring(0, 60)}...`);
    });
    
  } catch (error) {
    console.error('❌ Failed to discover tools:', error.message);
  }
  
  console.log('\n🎯 Example Tool Invocation Logging:');
  logger.logToolRequest('example_tool', { param1: 'value1', param2: 'value2' });
  
  // Simulate tool execution
  setTimeout(() => {
    logger.logToolResponse('example_tool', { result: 'success', data: 'sample data' }, 150, 'req_123');
  }, 100);
  
  setTimeout(() => {
    logger.logToolError('failing_tool', new Error('Simulated error'), 300, 'req_124');
  }, 200);
  
  console.log('\n📝 API Call Logging Example:');
  logger.logAPICall('GET', 'https://script.googleapis.com/v1/projects/test123', {
    'Authorization': 'Bearer token123',
    'Content-Type': 'application/json'
  });
  
  setTimeout(() => {
    logger.logAPIResponse('GET', 'https://script.googleapis.com/v1/projects/test123', 200, 250, 1024);
  }, 50);
  
  console.log('\n🔐 Authentication Logging Example:');
  logger.logAuthentication('OAuth', true, { 
    tokenType: 'Bearer',
    scope: 'https://www.googleapis.com/auth/script.projects'
  });
  
  console.log('\n✨ Enhanced logging test completed!');
  console.log('\n💡 Tips for using enhanced logging:');
  console.log('   - Set LOG_LEVEL=debug in .env for more detailed logs');
  console.log('   - Set LOG_LEVEL=error in .env for minimal logs');
  console.log('   - All tool executions now include request/response timing');
  console.log('   - API calls are logged with sanitized headers');
  console.log('   - Authentication events are tracked');
  console.log('   - Error details include stack traces and context');
}

// Run the test
testLogging().catch(console.error);

```

--------------------------------------------------------------------------------
/lib/authHelper.js:
--------------------------------------------------------------------------------

```javascript
/**
 * OAuth Authentication Helper for MCP Tools
 * Provides easy access to OAuth tokens with automatic refresh
 */

import { TokenManager } from './tokenManager.js';

/**
 * Get a valid OAuth access token for Google Apps Script API
 * This function handles token loading, validation, and refresh automatically
 * 
 * @param {string} clientId - OAuth client ID (from environment or config)
 * @param {string} clientSecret - OAuth client secret (from environment or config)
 * @returns {Promise<string>} Valid access token
 * @throws {Error} If no tokens are stored or refresh fails
 */
export async function getOAuthAccessToken(clientId, clientSecret) {
  if (!clientId || !clientSecret) {
    throw new Error('OAuth client ID and client secret are required. Please check your environment variables.');
  }

  const tokenManager = new TokenManager();
  
  try {
    const accessToken = await tokenManager.getValidAccessToken(clientId, clientSecret);
    return accessToken;
  } catch (error) {
    if (error.message.includes('No tokens found')) {
      throw new Error(
        'No OAuth tokens found. Please run the OAuth setup first:\n' +
        '  node oauth-setup.js\n\n' +
        'This will guide you through the OAuth authentication process and securely store your tokens.'
      );
    }
    
    if (error.message.includes('Token refresh failed')) {
      throw new Error(
        'Failed to refresh OAuth token. This might happen if:\n' +
        '  - Your OAuth credentials have been revoked\n' +
        '  - Your client secret has changed\n' +
        '  - There are network connectivity issues\n\n' +
        'Please try running the OAuth setup again:\n' +
        '  node oauth-setup.js --force'
      );
    }
    
    throw error;
  }
}

/**
 * Create Authorization header for Google API requests
 * 
 * @param {string} clientId - OAuth client ID
 * @param {string} clientSecret - OAuth client secret
 * @returns {Promise<Object>} Authorization headers object
 */
export async function getAuthHeaders(clientId, clientSecret) {
  const accessToken = await getOAuthAccessToken(clientId, clientSecret);
  return {
    'Authorization': `Bearer ${accessToken}`,
    'Content-Type': 'application/json'
  };
}

/**
 * Check if OAuth tokens are available and valid
 * 
 * @returns {boolean} True if tokens are available
 */
export function hasOAuthTokens() {
  const tokenManager = new TokenManager();
  return tokenManager.hasStoredTokens();
}

/**
 * Get token information for debugging/status
 * 
 * @returns {Object} Token status information
 */
export function getTokenStatus() {
  const tokenManager = new TokenManager();
  return tokenManager.getTokenInfo();
}

/**
 * Clear stored OAuth tokens (for logout/reset)
 */
export function clearOAuthTokens() {
  const tokenManager = new TokenManager();
  tokenManager.clearTokens();
}

export default {
  getOAuthAccessToken,
  getAuthHeaders,
  hasOAuthTokens,
  getTokenStatus,
  clearOAuthTokens
};

```

--------------------------------------------------------------------------------
/test/test-mcp-deployment-direct.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

/**
 * Test MCP deployment creation using the same approach as deploy-complete-webapp.js
 */

import { getOAuthAccessToken } from './lib/oauth-helper.js';

const scriptId = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';

async function createVersionWithMCPApproach() {
  try {
    const token = await getOAuthAccessToken();
    
    console.log('Creating new version using MCP approach...');
    
    const versionData = {
      description: "New version for MCP deployment test"
    };

    const response = await fetch(`https://script.googleapis.com/v1/projects/${scriptId}/versions`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      },
      body: JSON.stringify(versionData)
    });

    if (!response.ok) {
      const errorText = await response.text();
      console.error('Error response:', errorText);
      throw new Error(`HTTP ${response.status}: ${errorText}`);
    }

    const data = await response.json();
    console.log('✅ New version created:', data.versionNumber);
    
    return data;
  } catch (error) {
    console.error('Error creating version:', error);
    return null;
  }
}

async function createDeploymentWithMCPApproach(versionNumber) {
  try {
    const token = await getOAuthAccessToken();
    
    console.log('Creating deployment using MCP approach...');
    
    const deploymentConfig = {
      description: "MCP Test Web App - Public Access",
      manifestFileName: "appsscript",
      versionNumber: versionNumber
    };

    const response = await fetch(`https://script.googleapis.com/v1/projects/${scriptId}/deployments`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      },
      body: JSON.stringify(deploymentConfig)
    });

    if (!response.ok) {
      const errorText = await response.text();
      console.error('Error response:', errorText);
      throw new Error(`HTTP ${response.status}: ${errorText}`);
    }

    const data = await response.json();
    console.log('✅ Deployment created:', JSON.stringify(data, null, 2));
    
    return data;
  } catch (error) {
    console.error('Error creating deployment:', error);
    return null;
  }
}

async function testMCPDeployment() {
  console.log('=== Testing MCP Deployment Approach ===\n');
  
  // Step 1: Create a new version
  console.log('Step 1: Creating a new version...');
  const versionResult = await createVersionWithMCPApproach();
  if (!versionResult) return;
  
  console.log('\n' + '='.repeat(50) + '\n');
  
  // Step 2: Create deployment with the new version
  console.log('Step 2: Creating deployment...');
  const deploymentResult = await createDeploymentWithMCPApproach(versionResult.versionNumber);
  if (!deploymentResult) return;
  
  // Show web app URL if available
  if (deploymentResult.entryPoints && deploymentResult.entryPoints[0] && deploymentResult.entryPoints[0].webApp) {
    console.log('\n🎉 SUCCESS! Web app deployed via MCP approach!');
    console.log('Web App URL:', deploymentResult.entryPoints[0].webApp.url);
  }
}

testMCPDeployment().catch(console.error);

```

--------------------------------------------------------------------------------
/ERROR_HANDLING_ENHANCEMENT.md:
--------------------------------------------------------------------------------

```markdown
# MCP Tools Error Handling Enhancement - Summary

## Overview
All Google Apps Script MCP tools have been updated to provide detailed error logging and raw API response information instead of generic error messages.

## Files Updated
The following 12 files were enhanced with detailed error handling:

1. `script-projects-versions-list.js` ✅
2. `script-projects-deployments-create.js` ✅
3. `script-processes-list-script-processes.js` ✅
4. `script-projects-get-content.js` ✅
5. `script-projects-versions-create.js` ✅
6. `script-projects-update-content.js` ✅
7. `script-projects-deployments-update.js` ✅
8. `script-projects-deployments-get.js` ✅
9. `script-projects-get-metrics.js` ✅
10. `script-scripts-run.js` ✅
11. `script-projects-deployments-delete.js` ✅
12. `script-projects-versions-get.js` ✅

## Changes Made

### 1. Logger Integration
- Added `import { logger } from '../../../lib/logger.js';` to all tools
- Integrated the existing MCPLogger utility for structured logging

### 2. Enhanced Error Handling
**Before:**
```javascript
} catch (error) {
    console.error('Error listing script versions:', error);
    return { error: 'An error occurred while listing script versions.' };
}
```

**After:**
```javascript
} catch (error) {
    const errorDetails = {
      message: error.message,
      stack: error.stack,
      scriptId,
      duration: Date.now() - startTime,
      timestamp: new Date().toISOString(),
      errorType: error.name || 'Unknown'
    };

    logger.error('SCRIPT_VERSIONS_LIST', 'Error listing script versions', errorDetails);
    
    console.error('❌ Error listing script versions:', errorDetails);
    
    // Return detailed error information for debugging
    return { 
      error: true,
      message: error.message,
      details: errorDetails,
      rawError: {
        name: error.name,
        stack: error.stack
      }
    };
}
```

### 3. API Request/Response Logging
Added comprehensive logging for:
- API call details (method, URL, headers)
- Request timing and performance metrics
- Response status and size
- Detailed error responses with full API error data

### 4. Performance Tracking
- Added timing measurements for all operations
- Logged request duration and response times
- Included performance metrics in error details

## New Error Response Format

All tools now return detailed error objects instead of simple error messages:

```javascript
{
  error: true,
  message: "Specific error message",
  details: {
    scriptId: "actual_script_id",
    duration: 1234,
    timestamp: "2025-06-01T10:30:00.000Z",
    errorType: "Error",
    // Additional context-specific fields
  },
  rawError: {
    name: "Error",
    stack: "Full stack trace..."
  }
}
```

## Benefits

1. **Detailed Debugging**: Full stack traces and error details for troubleshooting
2. **API Transparency**: Raw API responses preserved for analysis
3. **Performance Monitoring**: Request timing and duration tracking
4. **Structured Logging**: Consistent log format across all tools
5. **Error Context**: Relevant parameters included in error details
6. **Visual Indicators**: ❌ and ✅ emojis for better log readability

## Usage

The enhanced error handling is automatic. When an error occurs, you'll now see:
- Detailed console logs with full error context
- Structured error objects with debugging information
- API request/response details for troubleshooting
- Performance metrics for optimization

All tools maintain backward compatibility while providing significantly more debugging information.

```

--------------------------------------------------------------------------------
/tools/google-app-script-api/apps-script-api/script-projects-create.js:
--------------------------------------------------------------------------------

```javascript
import { getAuthHeaders } from '../../../lib/oauth-helper.js';

/**
 * Function to create a new Google Apps Script project.
 * OAuth authentication is handled automatically.
 *
 * @param {Object} args - Arguments for creating the script project.
 * @param {string} args.parentId - The ID of the parent project.
 * @param {string} args.title - The title of the new script project.
 * @returns {Promise<Object>} - The result of the project creation.
 */
const executeFunction = async ({ parentId, title }) => {
  const baseUrl = 'https://script.googleapis.com';

  try {
    console.log('🔨 Creating new Google Apps Script project:', title);
    
    // Validate required parameters
    if (!title) {
      throw new Error('title is required');
    }

    const projectData = {
      title
    };

    // Add parentId if provided
    if (parentId) {
      projectData.parentId = parentId;
    }

    // Construct the URL for the API request
    const url = new URL(`${baseUrl}/v1/projects`);
    console.log('🌐 API URL:', url.toString());

    // Get OAuth headers
    const headers = await getAuthHeaders();
    headers['Content-Type'] = 'application/json';
    console.log('🔐 Authorization headers obtained successfully');

    // Perform the fetch request
    const response = await fetch(url.toString(), {
      method: 'POST',
      headers,
      body: JSON.stringify(projectData)
    });

    console.log('📡 API Response Status:', response.status, response.statusText);

    // Check if the response was successful
    if (!response.ok) {
      const errorText = await response.text();
      let errorData;
      
      try {
        errorData = JSON.parse(errorText);
      } catch (parseError) {
        errorData = { message: errorText };
      }

      const detailedError = {
        status: response.status,
        statusText: response.statusText,
        url: url.toString(),
        error: errorData,
        timestamp: new Date().toISOString()
      };

      console.error('❌ API Error Details:', JSON.stringify(detailedError, null, 2));
      
      throw new Error(`API Error (${response.status}): ${errorData.error?.message || errorData.message || 'Unknown error'}`);
    }

    // Parse and return the response data
    const data = await response.json();
    console.log('✅ Successfully created script project');
    return data;
    
  } catch (error) {
    console.error('❌ Error creating script project:', {
      message: error.message,
      stack: error.stack,
      title,
      parentId,
      timestamp: new Date().toISOString()
    });
    
    // Return detailed error information for debugging
    return { 
      error: true,
      message: error.message,
      details: {
        title,
        parentId,
        timestamp: new Date().toISOString(),
        errorType: error.name || 'Unknown'
      }
    };
  }
};

/**
 * Tool configuration for creating a new Google Apps Script project.
 * @type {Object}
 */
const apiTool = {
  function: executeFunction,
  definition: {
    type: 'function',
    function: {
      name: 'script_projects_create',
      description: 'Create a new Google Apps Script project.',
      parameters: {
        type: 'object',
        properties: {
          parentId: {
            type: 'string',
            description: 'The ID of the parent project.'
          },
          title: {
            type: 'string',
            description: 'The title of the new script project.'
          }
        },
        required: ['parentId', 'title']
      }
    }
  }
};

export { apiTool };
```

--------------------------------------------------------------------------------
/test/test-mcp-processes.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

/**
 * Test script to call MCP server tools and observe enhanced logging
 */

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { discoverTools } from './lib/tools.js';
import { logger } from './lib/logger.js';

async function testMCPTool() {
  console.log('🧪 Testing MCP Server Tool Execution with Enhanced Logging\n');
  
  try {
    // Discover and load tools
    logger.info('TEST', 'Starting MCP tool test');
    const tools = await discoverTools();
    
    // Find the script processes list tool
    const processListTool = tools.find(tool => 
      tool.definition?.function?.name === 'script_processes_list'
    );
    
    if (!processListTool) {
      console.error('❌ script_processes_list tool not found');
      return;
    }
    
    console.log('🔍 Found script_processes_list tool');
    console.log(`📝 Description: ${processListTool.definition.function.description}`);
    console.log(`🔧 Required parameters: ${processListTool.definition.function.parameters.required.join(', ')}`);
    
    // Test 1: Call with missing required parameter (should trigger detailed error logging)
    console.log('\n🧪 Test 1: Calling tool with missing required parameter...');
    try {
      await processListTool.function({});
    } catch (error) {
      console.log('✅ Expected error caught (missing scriptId)');
    }
    
    // Test 2: Call with invalid scriptId (should trigger API error logging)
    console.log('\n🧪 Test 2: Calling tool with invalid scriptId...');
    const testScriptId = 'invalid_script_id_12345';
    
    try {
      const result = await processListTool.function({
        scriptId: testScriptId,
        pageSize: 10
      });
      
      console.log('📊 Tool execution result:');
      console.log(JSON.stringify(result, null, 2));
      
    } catch (error) {
      console.log('✅ Expected error caught (invalid scriptId)');
      console.log(`   Error: ${error.message}`);
    }
    
    // Test 3: Call with a potentially valid scriptId format (will likely fail with auth or not found)
    console.log('\n🧪 Test 3: Calling tool with valid format scriptId...');
    const validFormatScriptId = '1BxKdN9XvlHF8rF9mF8Km4K7Y6nC8XvV9WtE5QdA2B';
    
    try {
      const result = await processListTool.function({
        scriptId: validFormatScriptId,
        pageSize: 5,
        fields: 'processes(processType,functionName,startTime,duration,status)'
      });
      
      console.log('📊 Tool execution result:');
      console.log(JSON.stringify(result, null, 2));
      
    } catch (error) {
      console.log('✅ Expected error caught (script not found or auth issue)');
      console.log(`   Error: ${error.message}`);
    }
    
    console.log('\n✨ MCP Tool Test Completed!');
    console.log('\n📋 What the enhanced logging showed:');
    console.log('   ✓ Tool discovery and loading');
    console.log('   ✓ Tool execution requests with parameters');
    console.log('   ✓ OAuth authentication attempts');
    console.log('   ✓ API calls to Google Apps Script API');
    console.log('   ✓ Response times and error details');
    console.log('   ✓ Detailed error context and stack traces');
    
  } catch (error) {
    logger.error('TEST', 'Test failed with unexpected error', {
      error: {
        message: error.message,
        stack: error.stack
      }
    });
    console.error('❌ Test failed:', error.message);
  }
}

// Run the test
testMCPTool().catch(console.error);

```

--------------------------------------------------------------------------------
/test/test-fields-issue.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

/**
 * Test the specific fields parameter issue found in the error analysis
 */

import { discoverTools } from './lib/tools.js';
import { logger } from './lib/logger.js';

const REAL_SCRIPT_ID = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';

async function testFieldsIssue() {
  console.log('🔍 Testing Specific Fields Parameter Issue\n');
  
  try {
    process.env.LOG_LEVEL = 'trace';
    
    const tools = await discoverTools();
    const processListTool = tools.find(tool => 
      tool.definition?.function?.name === 'script_processes_list'
    );
    
    console.log('🧪 Testing the problematic field that caused 400 error...');
    console.log('❌ This field caused an error: processes(processType,functionName,startTime,duration,status)');
    
    try {
      const result = await processListTool.function({
        scriptId: REAL_SCRIPT_ID,
        fields: 'processes(processType,functionName,startTime,duration,status)',
        pageSize: 3
      });
      console.log('✅ Unexpectedly succeeded!');
      console.log(JSON.stringify(result, null, 2));
    } catch (error) {
      console.log('❌ Confirmed error with "status" field:');
      console.log(`   ${error.message}`);
      
      if (error.message.includes('Cannot find matching fields for path')) {
        console.log('\n🔍 The issue is that "status" is not a valid field name.');
        console.log('📝 Let\'s try the correct field name: "processStatus"');
        
        try {
          const correctedResult = await processListTool.function({
            scriptId: REAL_SCRIPT_ID,
            fields: 'processes(processType,functionName,startTime,duration,processStatus)',
            pageSize: 3
          });
          console.log('✅ SUCCESS with corrected field name!');
          console.log(JSON.stringify(correctedResult, null, 2));
        } catch (correctedError) {
          console.log('❌ Still failed with corrected field name:');
          console.log(`   ${correctedError.message}`);
        }
      }
    }
    
    console.log('\n🔍 Testing other potential field name issues...');
    
    const fieldTests = [
      {
        description: 'All available fields',
        fields: 'processes(projectName,functionName,processType,processStatus,userAccessLevel,startTime,duration,runtimeVersion)'
      },
      {
        description: 'With nextPageToken',
        fields: 'processes,nextPageToken'
      },
      {
        description: 'Invalid field name test',
        fields: 'processes(invalidField)'
      },
      {
        description: 'Mixed valid/invalid fields',
        fields: 'processes(functionName,invalidField,processType)'
      }
    ];
    
    for (const test of fieldTests) {
      console.log(`\n📝 Testing: ${test.description}`);
      console.log(`   Fields: ${test.fields}`);
      
      try {
        const result = await processListTool.function({
          scriptId: REAL_SCRIPT_ID,
          fields: test.fields,
          pageSize: 2
        });
        console.log('   ✅ Success');
        console.log(`   📊 Returned ${Object.keys(result).length} top-level keys`);
        if (result.processes) {
          console.log(`   📊 ${result.processes.length} processes returned`);
          if (result.processes[0]) {
            console.log(`   📊 Process fields: ${Object.keys(result.processes[0]).join(', ')}`);
          }
        }
      } catch (error) {
        console.log('   ❌ Error:');
        console.log(`      ${error.message.substring(0, 100)}...`);
      }
    }
    
  } catch (error) {
    console.error('❌ Test failed:', error.message);
  }
}

testFieldsIssue().catch(console.error);

```

--------------------------------------------------------------------------------
/helpers/create-web-app-fixed.js:
--------------------------------------------------------------------------------

```javascript
import { getOAuthAccessToken } from './lib/oauth-helper.js';

const scriptId = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';

async function createWebAppDeployment() {
  try {
    const token = await getOAuthAccessToken();
    
    console.log('Creating web app deployment...');
    
    // The correct format for creating a web app deployment
    const deploymentConfig = {
      description: "Hello World Web App - Public Access",
      manifestFileName: "appsscript",
      versionNumber: 4
    };

    console.log('Deployment config:', JSON.stringify(deploymentConfig, null, 2));

    const response = await fetch(`https://script.googleapis.com/v1/projects/${scriptId}/deployments`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      },
      body: JSON.stringify(deploymentConfig)
    });

    if (!response.ok) {
      const errorText = await response.text();
      console.error('Error response:', errorText);
      throw new Error(`HTTP ${response.status}: ${errorText}`);
    }

    const data = await response.json();
    console.log('Deployment created:', JSON.stringify(data, null, 2));
    
    return data;
  } catch (error) {
    console.error('Error creating deployment:', error);
    return null;
  }
}

async function getDeploymentDetails(deploymentId) {
  try {
    const token = await getOAuthAccessToken();
    
    console.log(`Getting details for deployment: ${deploymentId}`);
    
    const response = await fetch(`https://script.googleapis.com/v1/projects/${scriptId}/deployments/${deploymentId}`, {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Accept': 'application/json'
      }
    });

    if (!response.ok) {
      const errorText = await response.text();
      console.error('Error response:', errorText);
      throw new Error(`HTTP ${response.status}: ${errorText}`);
    }

    const data = await response.json();
    console.log('Deployment details:', JSON.stringify(data, null, 2));
    
    if (data.entryPoints && data.entryPoints[0] && data.entryPoints[0].webApp) {
      console.log('\n🎉 SUCCESS! Your web app is deployed!');
      console.log('Web App URL:', data.entryPoints[0].webApp.url);
      console.log('Access Level:', data.entryPoints[0].webApp.access);
      console.log('Execute As:', data.entryPoints[0].webApp.executeAs);
    } else {
      console.log('\n⚠️  This deployment doesn\'t seem to be configured as a web app yet.');
      console.log('You may need to manually configure it in the Google Apps Script editor.');
    }
    
    return data;
  } catch (error) {
    console.error('Error getting deployment details:', error);
    return null;
  }
}

async function main() {
  console.log('=== Google Apps Script Web App Deployment ===\n');
  
  // Check existing deployments first
  console.log('Checking existing deployments...');
  
  // Check the latest deployment we created
  const existingDeploymentId = 'AKfycbx58SZUlVdfZdlUsfYiJnj94oBrpb_yH7IpbSqu7bhDs8sawIgIXaw40c1NLooxNb2e';
  const existingDeployment = await getDeploymentDetails(existingDeploymentId);
  
  if (existingDeployment && existingDeployment.entryPoints && existingDeployment.entryPoints[0] && existingDeployment.entryPoints[0].webApp) {
    console.log('✅ Existing deployment is already configured as a web app!');
    return;
  }
  
  console.log('\n' + '='.repeat(50) + '\n');
  
  // Create a new deployment
  const newDeployment = await createWebAppDeployment();
  
  if (newDeployment && newDeployment.deploymentId) {
    console.log('\n' + '='.repeat(50) + '\n');
    await getDeploymentDetails(newDeployment.deploymentId);
  }
}

main().catch(console.error);

```

--------------------------------------------------------------------------------
/test/test-token-management.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

/**
 * Test OAuth Token Management System
 * This script tests the secure token storage and refresh functionality
 */

import 'dotenv/config';
import { TokenManager } from './lib/tokenManager.js';
import { getOAuthAccessToken, hasValidTokens, getTokenInfo } from './lib/oauth-helper.js';

console.log('🧪 Testing OAuth Token Management System');
console.log('=========================================\n');

async function testTokenManagement() {
  try {
    console.log('1. 🔍 Checking environment variables...');
    const clientId = process.env.GOOGLE_APP_SCRIPT_API_CLIENT_ID;
    const clientSecret = process.env.GOOGLE_APP_SCRIPT_API_CLIENT_SECRET;
    
    console.log('   - CLIENT_ID exists:', !!clientId);
    console.log('   - CLIENT_SECRET exists:', !!clientSecret);
    
    if (!clientId || !clientSecret) {
      console.error('\n❌ Missing OAuth credentials in .env file');
      console.log('💡 Please update your .env file with:');
      console.log('   - GOOGLE_APP_SCRIPT_API_CLIENT_ID=your_client_id');
      console.log('   - GOOGLE_APP_SCRIPT_API_CLIENT_SECRET=your_client_secret');
      process.exit(1);
    }
    
    console.log('\n2. 📁 Checking token storage...');
    const tokenManager = new TokenManager();
    const tokenInfo = tokenManager.getTokenInfo();
    
    if (tokenInfo.hasTokens) {
      console.log('   ✅ Tokens found');
      console.log(`   📁 Location: ${tokenInfo.location}`);
      console.log(`   💾 Saved at: ${tokenInfo.savedAt}`);
      console.log(`   ⏰ Expires at: ${tokenInfo.expiresAt}`);
      console.log(`   📊 Status: ${tokenInfo.status}`);
      console.log(`   🔐 Scope: ${tokenInfo.scope || 'Not specified'}`);
    } else {
      console.log('   ❌ No tokens found');
      console.log(`   📁 Expected location: ${tokenInfo.location}`);
      console.log('\n💡 Run "node oauth-setup.js" to set up OAuth tokens');
      process.exit(0);
    }
    
    console.log('\n3. 🔐 Testing token validity...');
    const hasTokens = hasValidTokens();
    console.log('   - Has valid tokens:', hasTokens);
    
    if (hasTokens) {
      console.log('\n4. 🔄 Testing access token retrieval...');
      try {
        const accessToken = await getOAuthAccessToken();
        console.log('   ✅ Access token obtained successfully');
        console.log('   🔑 Token preview:', accessToken.substring(0, 20) + '...');
        
        console.log('\n5. ✅ All tests passed!');
        console.log('   🎯 Your OAuth token management is working correctly');
        
      } catch (error) {
        console.error('\n❌ Failed to get access token:', error.message);
        
        if (error.message.includes('Token refresh failed')) {
          console.log('\n💡 This might happen if:');
          console.log('   - Your OAuth credentials have been revoked');
          console.log('   - Your client secret has changed');
          console.log('   - There are network connectivity issues');
          console.log('\n🔧 Try running: node oauth-setup.js --force');
        }
      }
    } else {
      console.log('\n❌ No valid tokens available');
      console.log('💡 Run "node oauth-setup.js" to set up OAuth tokens');
    }
    
  } catch (error) {
    console.error('\n💥 Test failed with error:', error.message);
    process.exit(1);
  }
}

// Command line help
if (process.argv.includes('--help') || process.argv.includes('-h')) {
  console.log('📖 OAuth Token Management Test');
  console.log('\nUsage:');
  console.log('  node test-token-management.js        # Run all tests');
  console.log('  node test-token-management.js --help # Show this help');
  console.log('\nThis script tests:');
  console.log('  - Environment variable configuration');
  console.log('  - Token storage and retrieval');
  console.log('  - Access token refresh functionality');
  console.log('  - Overall OAuth system health');
  process.exit(0);
}

testTokenManagement().catch((error) => {
  console.error('💥 Unexpected error:', error);
  process.exit(1);
});

```

--------------------------------------------------------------------------------
/tools/google-app-script-api/apps-script-api/script-scripts-run.js:
--------------------------------------------------------------------------------

```javascript
import { getAuthHeaders } from '../../../lib/oauth-helper.js';
import { logger } from '../../../lib/logger.js';

/**
 * Function to run a Google Apps Script.
 *
 * @param {Object} args - Arguments for the script execution.
 * @param {string} args.scriptId - The ID of the script to run.
 * @param {string} [args.fields] - Selector specifying which fields to include in a partial response.
 * @param {string} [args.alt='json'] - Data format for response.
 * @param {string} [args.key] - API key for the project.
 * @param {string} [args.access_token] - OAuth access token.
 * @param {string} [args.oauth_token] - OAuth 2.0 token for the current user.
 * @param {string} [args.quotaUser] - Available to use for quota purposes for server-side applications.
 * @param {boolean} [args.prettyPrint=true] - Returns response with indentations and line breaks.
 * @returns {Promise<Object>} - The result of the script execution.
 */
const executeFunction = async ({ scriptId, fields, alt = 'json', key, access_token, oauth_token, quotaUser, prettyPrint = true }) => {
  const baseUrl = 'https://script.googleapis.com';
  const url = new URL(`${baseUrl}/v1/scripts/${scriptId}:run`);
  
  // Append query parameters to the URL
  const params = new URLSearchParams({
    fields,
    alt,
    key,
    access_token,
    oauth_token,
    quotaUser,
    prettyPrint: prettyPrint.toString(),
    '$.xgafv': '1',
    upload_protocol: 'raw',
    uploadType: 'raw'
  });
  
  url.search = params.toString();

  try {
    // Get OAuth headers
    const headers = await getAuthHeaders();
    headers['Content-Type'] = 'application/json';
    // Perform the fetch request
    const response = await fetch(url.toString(), {
      method: 'POST',
      headers
    });

    // Check if the response was successful
    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(errorData);
    }

    // Parse and return the response data
    const data = await response.json();
    return data;
  } catch (error) {
    const errorDetails = {
      message: error.message,
      stack: error.stack,
      scriptId,
      timestamp: new Date().toISOString(),
      errorType: error.name || 'Unknown'
    };

    logger.error('SCRIPT_RUN', 'Error running the script', errorDetails);
    
    console.error('❌ Error running the script:', errorDetails);
    
    // Return detailed error information for debugging
    return { 
      error: true,
      message: error.message,
      details: errorDetails,
      rawError: {
        name: error.name,
        stack: error.stack
      }
    };
  }
};

/**
 * Tool configuration for running Google Apps Script.
 * @type {Object}
 */
const apiTool = {
  function: executeFunction,
  definition: {
    type: 'function',
    function: {
      name: 'script_run',
      description: 'Run a Google Apps Script.',
      parameters: {
        type: 'object',
        properties: {
          scriptId: {
            type: 'string',
            description: 'The ID of the script to run.'
          },
          fields: {
            type: 'string',
            description: 'Selector specifying which fields to include in a partial response.'
          },
          alt: {
            type: 'string',
            enum: ['json', 'xml'],
            description: 'Data format for response.'
          },
          key: {
            type: 'string',
            description: 'API key for the project.'
          },
          access_token: {
            type: 'string',
            description: 'OAuth access token.'
          },
          oauth_token: {
            type: 'string',
            description: 'OAuth 2.0 token for the current user.'
          },
          quotaUser: {
            type: 'string',
            description: 'Available to use for quota purposes for server-side applications.'
          },
          prettyPrint: {
            type: 'boolean',
            description: 'Returns response with indentations and line breaks.'
          }
        },
        required: ['scriptId']
      }
    }
  }
};

export { apiTool };
```

--------------------------------------------------------------------------------
/test/debug-deployment.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

/**
 * Debug script to test deployment-related API calls
 */

import { getOAuthAccessToken } from '../lib/oauth-helper.js';

async function testDeploymentApis() {
  const scriptId = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';
  
  try {
    console.log('🔐 Getting OAuth access token...');
    const token = await getOAuthAccessToken();
    console.log('✅ Got access token');
    
    // Test versions list
    console.log('\n📋 Testing versions list...');
    let url = `https://script.googleapis.com/v1/projects/${scriptId}/versions`;
    
    let response = await fetch(url, {
      method: 'GET',
      headers: {
        'Accept': 'application/json',
        'Authorization': `Bearer ${token}`
      }
    });
    
    console.log('📡 Versions response status:', response.status);
    
    if (!response.ok) {
      const errorText = await response.text();
      console.error('❌ Versions API Error:', errorText);
    } else {
      const data = await response.json();
      console.log('✅ Versions data:', JSON.stringify(data, null, 2));
    }
    
    // Test deployments list
    console.log('\n📋 Testing deployments list...');
    url = `https://script.googleapis.com/v1/projects/${scriptId}/deployments`;
    
    response = await fetch(url, {
      method: 'GET',
      headers: {
        'Accept': 'application/json',
        'Authorization': `Bearer ${token}`
      }
    });
    
    console.log('📡 Deployments response status:', response.status);
    
    if (!response.ok) {
      const errorText = await response.text();
      console.error('❌ Deployments API Error:', errorText);
    } else {
      const data = await response.json();
      console.log('✅ Deployments data:', JSON.stringify(data, null, 2));
    }
    
    // Test creating a version
    console.log('\n📋 Testing version creation...');
    url = `https://script.googleapis.com/v1/projects/${scriptId}/versions`;
    
    response = await fetch(url, {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        description: 'Version for web app deployment'
      })
    });
    
    console.log('📡 Version creation response status:', response.status);
    
    if (!response.ok) {
      const errorText = await response.text();
      console.error('❌ Version creation API Error:', errorText);
    } else {
      const data = await response.json();
      console.log('✅ Version creation data:', JSON.stringify(data, null, 2));
      
      // If version was created successfully, try to create a deployment
      if (data.versionNumber) {
        console.log('\n📋 Testing deployment creation...');
        url = `https://script.googleapis.com/v1/projects/${scriptId}/deployments`;
        
        response = await fetch(url, {
          method: 'POST',
          headers: {
            'Accept': 'application/json',
            'Authorization': `Bearer ${token}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            versionNumber: data.versionNumber,
            description: 'Web app deployment - accessible by anyone',
            manifestFileName: 'appsscript',
            deploymentConfig: {
              scriptId: scriptId,
              description: 'Web app deployment - accessible by anyone',
              manifestFileName: 'appsscript',
              versionNumber: data.versionNumber
            }
          })
        });
        
        console.log('📡 Deployment creation response status:', response.status);
        
        if (!response.ok) {
          const errorText = await response.text();
          console.error('❌ Deployment creation API Error:', errorText);
        } else {
          const deploymentData = await response.json();
          console.log('✅ Deployment creation data:', JSON.stringify(deploymentData, null, 2));
        }
      }
    }
    
  } catch (error) {
    console.error('💥 Error:', error);
  }
}

testDeploymentApis();

```

--------------------------------------------------------------------------------
/tools/google-app-script-api/apps-script-api/script-projects-versions-create.js:
--------------------------------------------------------------------------------

```javascript
import { getOAuthAccessToken } from '../../../lib/oauth-helper.js';
import { logger } from '../../../lib/logger.js';

/**
 * Function to create a new version of a Google Apps Script project.
 *
 * @param {Object} args - Arguments for creating a new version.
 * @param {string} args.scriptId - The ID of the script project.
 * @param {string} args.description - A description for the new version.
 * @returns {Promise<Object>} - The result of the version creation.
 */
const executeFunction = async ({ scriptId, description }) => {
  const baseUrl = 'https://script.googleapis.com';
  const url = `${baseUrl}/v1/projects/${scriptId}/versions`;
  const startTime = Date.now();

  const body = JSON.stringify({
    description
  });

  try {
    logger.info('VERSION_CREATE', 'Starting version creation', { scriptId, description });

    // Get OAuth access token
    const token = await getOAuthAccessToken();
    
    // Set up headers for the request
    const headers = {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Authorization': `Bearer ${token}`
    };

    logger.logAPICall('POST', url, headers, { description });

    // Perform the fetch request
    const fetchStartTime = Date.now();
    const response = await fetch(url, {
      method: 'POST',
      headers,
      body
    });
    
    const fetchDuration = Date.now() - fetchStartTime;
    const responseSize = response.headers.get('content-length') || 'unknown';
    
    logger.logAPIResponse('POST', url, response.status, fetchDuration, responseSize);

    // Check if the response was successful
    if (!response.ok) {
      const errorText = await response.text();
      let errorData;
      
      try {
        errorData = JSON.parse(errorText);
      } catch (parseError) {
        errorData = { message: errorText };
      }

      const detailedError = {
        status: response.status,
        statusText: response.statusText,
        url,
        errorResponse: errorData,
        duration: Date.now() - startTime,
        scriptId,
        description,
        timestamp: new Date().toISOString()
      };

      logger.error('VERSION_CREATE', 'API request failed', detailedError);
      
      console.error('❌ API Error Details:', JSON.stringify(detailedError, null, 2));
      
      throw new Error(`API Error (${response.status}): ${errorData.error?.message || errorData.message || 'Unknown error'}`);
    }

    // Parse and return the response data
    const data = await response.json();
    
    logger.info('VERSION_CREATE', 'Successfully created version', {
      scriptId,
      versionNumber: data.versionNumber,
      description,
      duration: Date.now() - startTime
    });
    
    console.log('✅ Successfully created version');
    return data;
  } catch (error) {
    const errorDetails = {
      message: error.message,
      stack: error.stack,
      scriptId,
      description,
      duration: Date.now() - startTime,
      timestamp: new Date().toISOString(),
      errorType: error.name || 'Unknown'
    };

    logger.error('VERSION_CREATE', 'Error creating version', errorDetails);
    
    console.error('❌ Error creating version:', errorDetails);
    
    // Return detailed error information for debugging
    return { 
      error: true,
      message: error.message,
      details: errorDetails,
      rawError: {
        name: error.name,
        stack: error.stack
      }
    };
  }
};

/**
 * Tool configuration for creating a new version of a Google Apps Script project.
 * @type {Object}
 */
const apiTool = {
  function: executeFunction,
  definition: {
    type: 'function',
    function: {
      name: 'script_projects_versions_create',
      description: 'Creates a new version of a Google Apps Script project.',
      parameters: {
        type: 'object',
        properties: {
          scriptId: {
            type: 'string',
            description: 'The ID of the script project.'
          },
          description: {
            type: 'string',
            description: 'A description for the new version.'
          }
        },
        required: ['scriptId', 'description']
      }
    }
  }
};

export { apiTool };
```

--------------------------------------------------------------------------------
/lib/logger.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Enhanced logging utility for MCP server tool responses
 */

export class MCPLogger {
  constructor() {
    this.logLevel = process.env.LOG_LEVEL || 'info';
    this.enabledLevels = this.getEnabledLevels();
  }

  getEnabledLevels() {
    const levels = ['error', 'warn', 'info', 'debug', 'trace'];
    const currentIndex = levels.indexOf(this.logLevel);
    return currentIndex >= 0 ? levels.slice(0, currentIndex + 1) : levels;
  }

  shouldLog(level) {
    return this.enabledLevels.includes(level);
  }

  formatMessage(level, category, message, data = null) {
    const timestamp = new Date().toISOString();
    const prefix = `[${timestamp}] [${level.toUpperCase()}] [${category}]`;
    
    if (data) {
      return `${prefix} ${message}\n${JSON.stringify(data, null, 2)}`;
    }
    return `${prefix} ${message}`;
  }

  log(level, category, message, data = null) {
    if (!this.shouldLog(level)) return;
    
    const formattedMessage = this.formatMessage(level, category, message, data);
    
    if (level === 'error') {
      console.error(formattedMessage);
    } else if (level === 'warn') {
      console.warn(formattedMessage);
    } else {
      console.log(formattedMessage);
    }
  }

  // Tool-specific logging methods
  logToolRequest(toolName, args) {
    this.log('info', 'TOOL_REQUEST', `Executing tool: ${toolName}`, {
      tool: toolName,
      arguments: args,
      requestId: this.generateRequestId()
    });
  }

  logToolResponse(toolName, response, duration, requestId) {
    this.log('info', 'TOOL_RESPONSE', `Tool completed: ${toolName}`, {
      tool: toolName,
      duration: `${duration}ms`,
      requestId,
      responseSize: JSON.stringify(response).length,
      success: !response.error
    });
  }

  logToolError(toolName, error, duration, requestId) {
    this.log('error', 'TOOL_ERROR', `Tool failed: ${toolName}`, {
      tool: toolName,
      duration: `${duration}ms`,
      requestId,
      error: {
        message: error.message,
        stack: error.stack,
        name: error.name
      }
    });
  }

  logAPICall(method, url, headers, body = null) {
    this.log('debug', 'API_CALL', `Making API request: ${method} ${url}`, {
      method,
      url,
      headers: this.sanitizeHeaders(headers),
      body: body ? (typeof body === 'string' ? body : JSON.stringify(body)) : null
    });
  }

  logAPIResponse(method, url, status, responseTime, responseSize) {
    this.log('debug', 'API_RESPONSE', `API response: ${method} ${url}`, {
      method,
      url,
      status,
      responseTime: `${responseTime}ms`,
      responseSize: `${responseSize} bytes`
    });
  }

  logAuthentication(type, success, details = {}) {
    this.log('info', 'AUTH', `Authentication ${type}: ${success ? 'SUCCESS' : 'FAILED'}`, {
      type,
      success,
      ...details
    });
  }

  sanitizeHeaders(headers) {
    const sanitized = { ...headers };
    if (sanitized.Authorization) {
      sanitized.Authorization = 'Bearer ***REDACTED***';
    }
    return sanitized;
  }

  generateRequestId() {
    return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }

  // Convenience methods
  error(category, message, data) {
    this.log('error', category, message, data);
  }

  warn(category, message, data) {
    this.log('warn', category, message, data);
  }

  info(category, message, data) {
    this.log('info', category, message, data);
  }

  debug(category, message, data) {
    this.log('debug', category, message, data);
  }

  trace(category, message, data) {
    this.log('trace', category, message, data);
  }
}

// Create a singleton instance
export const logger = new MCPLogger();

// Performance tracking decorator for tool functions
export function withLogging(toolName, originalFunction) {
  return async function(...args) {
    const requestId = logger.generateRequestId();
    const startTime = Date.now();
    
    try {
      logger.logToolRequest(toolName, args[0] || {});
      
      const result = await originalFunction.apply(this, args);
      const duration = Date.now() - startTime;
      
      logger.logToolResponse(toolName, result, duration, requestId);
      
      return result;
    } catch (error) {
      const duration = Date.now() - startTime;
      logger.logToolError(toolName, error, duration, requestId);
      throw error;
    }
  };
}

```

--------------------------------------------------------------------------------
/tools/google-app-script-api/apps-script-api/script-projects-deployments-create.js:
--------------------------------------------------------------------------------

```javascript
import { getAuthHeaders } from '../../../lib/oauth-helper.js';
import { logger } from '../../../lib/logger.js';

/**
 * Function to create a deployment of an Apps Script project.
 *
 * @param {Object} args - Arguments for creating the deployment.
 * @param {string} args.scriptId - The ID of the script to deploy.
 * @param {string} args.manifestFileName - The name of the manifest file.
 * @param {number} args.versionNumber - The version number of the script.
 * @param {string} args.description - A description for the deployment.
 * @returns {Promise<Object>} - The result of the deployment creation.
 */
const executeFunction = async ({ scriptId, manifestFileName, versionNumber, description }) => {
  const baseUrl = 'https://script.googleapis.com';
  const url = `${baseUrl}/v1/projects/${scriptId}/deployments`;
  const startTime = Date.now();

  const body = {
    manifestFileName,
    versionNumber,
    description
  };

  try {
    logger.info('DEPLOYMENT_CREATE', 'Starting deployment creation', { scriptId, versionNumber, description });

    // Get OAuth headers
    const headers = await getAuthHeaders();
    headers['Content-Type'] = 'application/json';

    logger.logAPICall('POST', url, headers, body);

    // Perform the fetch request
    const fetchStartTime = Date.now();
    const response = await fetch(url, {
      method: 'POST',
      headers,
      body: JSON.stringify(body)
    });
    
    const fetchDuration = Date.now() - fetchStartTime;
    const responseSize = response.headers.get('content-length') || 'unknown';
    
    logger.logAPIResponse('POST', url, response.status, fetchDuration, responseSize);

    // Check if the response was successful
    if (!response.ok) {
      const errorText = await response.text();
      let errorData;
      
      try {
        errorData = JSON.parse(errorText);
      } catch (parseError) {
        errorData = { message: errorText };
      }

      const detailedError = {
        status: response.status,
        statusText: response.statusText,
        url,
        errorResponse: errorData,
        duration: Date.now() - startTime,
        scriptId,
        versionNumber,
        timestamp: new Date().toISOString()
      };

      logger.error('DEPLOYMENT_CREATE', 'API request failed', detailedError);
      
      console.error('❌ API Error Details:', JSON.stringify(detailedError, null, 2));
      
      throw new Error(`API Error (${response.status}): ${errorData.error?.message || errorData.message || 'Unknown error'}`);
    }

    // Parse and return the response data
    const data = await response.json();
    
    logger.info('DEPLOYMENT_CREATE', 'Successfully created deployment', {
      scriptId,
      deploymentId: data.deploymentId,
      versionNumber,
      duration: Date.now() - startTime
    });
    
    console.log('✅ Successfully created deployment');
    return data;
  } catch (error) {
    const errorDetails = {
      message: error.message,
      stack: error.stack,
      scriptId,
      versionNumber,
      duration: Date.now() - startTime,
      timestamp: new Date().toISOString(),
      errorType: error.name || 'Unknown'
    };

    logger.error('DEPLOYMENT_CREATE', 'Error creating deployment', errorDetails);
    
    console.error('❌ Error creating deployment:', errorDetails);
    
    // Return detailed error information for debugging
    return { 
      error: true,
      message: error.message,
      details: errorDetails,
      rawError: {
        name: error.name,
        stack: error.stack
      }
    };
  }
};

/**
 * Tool configuration for creating a deployment of an Apps Script project.
 * @type {Object}
 */
const apiTool = {
  function: executeFunction,
  definition: {
    type: 'function',
    function: {
      name: 'script_projects_deployments_create',
      description: 'Creates a deployment of an Apps Script project.',
      parameters: {
        type: 'object',
        properties: {
          scriptId: {
            type: 'string',
            description: 'The ID of the script to deploy.'
          },
          manifestFileName: {
            type: 'string',
            description: 'The name of the manifest file.'
          },
          versionNumber: {
            type: 'number',
            description: 'The version number of the script.'
          },
          description: {
            type: 'string',
            description: 'A description for the deployment.'
          }
        },
        required: ['scriptId', 'manifestFileName', 'versionNumber', 'description']
      }
    }
  }
};

export { apiTool };
```

--------------------------------------------------------------------------------
/tools/google-app-script-api/apps-script-api/script-projects-get.js:
--------------------------------------------------------------------------------

```javascript
import { getAuthHeaders } from '../../../lib/oauth-helper.js';

/**
 * Function to get metadata of a Google Apps Script project.
 * Note: OAuth access token is automatically handled by the OAuth helper.
 *
 * @param {Object} args - Arguments for the request.
 * @param {string} args.scriptId - The ID of the script project to retrieve.
 * @param {string} [args.fields] - Selector specifying which fields to include in a partial response.
 * @param {string} [args.alt='json'] - Data format for response.
 * @param {string} [args.quotaUser] - Arbitrary string assigned to a user for quota purposes.
 * @param {boolean} [args.prettyPrint=true] - Returns response with indentations and line breaks.
 * @returns {Promise<Object>} - The metadata of the script project.
 */
const executeFunction = async ({ scriptId, fields, alt = 'json', quotaUser, prettyPrint = true }) => {
  const baseUrl = 'https://script.googleapis.com';

  try {
    console.log('🔍 Getting script project metadata for:', scriptId);
    
    // Validate required parameters
    if (!scriptId) {
      throw new Error('scriptId is required');
    }

    // Construct the URL with query parameters
    const url = new URL(`${baseUrl}/v1/projects/${scriptId}`);
    
    // Only add parameters that have values
    if (fields) url.searchParams.append('fields', fields);
    if (alt) url.searchParams.append('alt', alt);
    if (quotaUser) url.searchParams.append('quotaUser', quotaUser);
    if (prettyPrint !== undefined) url.searchParams.append('prettyPrint', prettyPrint.toString());

    console.log('🌐 API URL:', url.toString());

    // Get OAuth headers - this automatically handles token refresh
    const headers = await getAuthHeaders();
    console.log('🔐 Authorization headers obtained successfully');

    // Perform the fetch request
    const response = await fetch(url.toString(), {
      method: 'GET',
      headers
    });

    console.log('📡 API Response Status:', response.status, response.statusText);

    // Check if the response was successful
    if (!response.ok) {
      const errorText = await response.text();
      let errorData;
      
      try {
        errorData = JSON.parse(errorText);
      } catch (parseError) {
        errorData = { message: errorText };
      }

      const detailedError = {
        status: response.status,
        statusText: response.statusText,
        url: url.toString(),
        error: errorData,
        timestamp: new Date().toISOString()
      };

      console.error('❌ API Error Details:', JSON.stringify(detailedError, null, 2));
      
      throw new Error(`API Error (${response.status}): ${errorData.error?.message || errorData.message || 'Unknown error'}`);
    }

    // Parse and return the response data
    const data = await response.json();
    console.log('✅ Successfully retrieved script project metadata');
    return data;
    
  } catch (error) {
    console.error('❌ Error getting script project metadata:', {
      message: error.message,
      stack: error.stack,
      scriptId,
      timestamp: new Date().toISOString()
    });
    
    // Return detailed error information for debugging
    return { 
      error: true,
      message: error.message,
      details: {
        scriptId,
        timestamp: new Date().toISOString(),
        errorType: error.name || 'Unknown'
      }
    };
  }
};

/**
 * Tool configuration for getting metadata of a Google Apps Script project.
 * OAuth authentication is handled automatically.
 * @type {Object}
 */
const apiTool = {
  function: executeFunction,
  definition: {
    type: 'function',
    function: {
      name: 'script_projects_get',
      description: 'Get metadata of a Google Apps Script project. OAuth authentication is handled automatically.',
      parameters: {
        type: 'object',
        properties: {
          scriptId: {
            type: 'string',
            description: 'The ID of the script project to retrieve.'
          },
          fields: {
            type: 'string',
            description: 'Selector specifying which fields to include in a partial response.'
          },
          alt: {
            type: 'string',
            enum: ['json'],
            description: 'Data format for response.',
            default: 'json'
          },
          quotaUser: {
            type: 'string',
            description: 'Arbitrary string assigned to a user for quota purposes.'
          },
          prettyPrint: {
            type: 'boolean',
            description: 'Returns response with indentations and line breaks.',
            default: true
          }
        },
        required: ['scriptId']
      }
    }
  }
};

export { apiTool };
```

--------------------------------------------------------------------------------
/tools/google-app-script-api/apps-script-api/script-projects-get-metrics.js:
--------------------------------------------------------------------------------

```javascript
import { logger } from '../../../lib/logger.js';

/**
 * Function to get metrics data for Google Apps Script projects.
 *
 * @param {Object} args - Arguments for the metrics request.
 * @param {string} args.scriptId - The ID of the script project.
 * @param {string} args.deploymentId - The ID of the deployment to filter metrics.
 * @param {string} args.metricsGranularity - The granularity of the metrics data.
 * @param {string} args.fields - Selector specifying which fields to include in a partial response.
 * @param {string} args.key - API key for the request.
 * @param {string} args.access_token - OAuth access token for authorization.
 * @param {string} args.oauth_token - OAuth 2.0 token for the current user.
 * @param {boolean} [args.prettyPrint=true] - Whether to return the response with indentations and line breaks.
 * @returns {Promise<Object>} - The metrics data for the specified script project.
 */
const executeFunction = async ({ scriptId, deploymentId, metricsGranularity, fields, key, access_token, oauth_token, prettyPrint = true }) => {
  const baseUrl = 'https://script.googleapis.com';
  const token = process.env.GOOGLE_APP_SCRIPT_API_API_KEY;

  try {
    // Construct the URL with query parameters
    const url = new URL(`${baseUrl}/v1/projects/${scriptId}/metrics`);
    url.searchParams.append('metricsFilter.deploymentId', deploymentId);
    url.searchParams.append('metricsGranularity', metricsGranularity);
    url.searchParams.append('fields', fields);
    url.searchParams.append('alt', 'json');
    url.searchParams.append('key', key);
    url.searchParams.append('$.xgafv', '1');
    url.searchParams.append('access_token', access_token);
    url.searchParams.append('oauth_token', oauth_token);
    url.searchParams.append('prettyPrint', prettyPrint.toString());

    // Set up headers for the request
    const headers = {
      'Accept': 'application/json'
    };

    // If a token is provided, add it to the Authorization header
    if (token) {
      headers['Authorization'] = `Bearer ${token}`;
    }

    // Perform the fetch request
    const response = await fetch(url.toString(), {
      method: 'GET',
      headers
    });

    // Check if the response was successful
    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(errorData);
    }

    // Parse and return the response data
    const data = await response.json();
    return data;
  } catch (error) {
    const errorDetails = {
      message: error.message,
      stack: error.stack,
      scriptId,
      deploymentId,
      timestamp: new Date().toISOString(),
      errorType: error.name || 'Unknown'
    };

    logger.error('METRICS_GET', 'Error getting metrics data', errorDetails);
    
    console.error('❌ Error getting metrics data:', errorDetails);
    
    // Return detailed error information for debugging
    return { 
      error: true,
      message: error.message,
      details: errorDetails,
      rawError: {
        name: error.name,
        stack: error.stack
      }
    };
  }
};

/**
 * Tool configuration for getting metrics data for Google Apps Script projects.
 * @type {Object}
 */
const apiTool = {
  function: executeFunction,
  definition: {
    type: 'function',
    function: {
      name: 'get_script_metrics',
      description: 'Get metrics data for Google Apps Script projects.',
      parameters: {
        type: 'object',
        properties: {
          scriptId: {
            type: 'string',
            description: 'The ID of the script project.'
          },
          deploymentId: {
            type: 'string',
            description: 'The ID of the deployment to filter metrics.'
          },
          metricsGranularity: {
            type: 'string',
            description: 'The granularity of the metrics data.'
          },
          fields: {
            type: 'string',
            description: 'Selector specifying which fields to include in a partial response.'
          },
          key: {
            type: 'string',
            description: 'API key for the request.'
          },
          access_token: {
            type: 'string',
            description: 'OAuth access token for authorization.'
          },
          oauth_token: {
            type: 'string',
            description: 'OAuth 2.0 token for the current user.'
          },
          prettyPrint: {
            type: 'boolean',
            description: 'Whether to return the response with indentations and line breaks.'
          }
        },
        required: ['scriptId', 'deploymentId', 'metricsGranularity', 'fields', 'key', 'access_token', 'oauth_token']
      }
    }
  }
};

export { apiTool };
```

--------------------------------------------------------------------------------
/tools/google-app-script-api/apps-script-api/script-projects-versions-get.js:
--------------------------------------------------------------------------------

```javascript
import { logger } from '../../../lib/logger.js';

/**
 * Function to get a version of a Google Apps Script project.
 *
 * @param {Object} args - Arguments for the request.
 * @param {string} args.scriptId - The ID of the script project.
 * @param {string} args.versionNumber - The version number of the script project.
 * @param {string} [args.fields] - Selector specifying which fields to include in a partial response.
 * @param {string} [args.alt='json'] - Data format for response.
 * @param {string} [args.key] - API key for the project.
 * @param {string} [args.access_token] - OAuth access token.
 * @param {string} [args.quotaUser] - Available to use for quota purposes for server-side applications.
 * @param {string} [args.oauth_token] - OAuth 2.0 token for the current user.
 * @param {string} [args.callback] - JSONP callback.
 * @param {boolean} [args.prettyPrint=true] - Returns response with indentations and line breaks.
 * @returns {Promise<Object>} - The result of the script version retrieval.
 */
const executeFunction = async ({ scriptId, versionNumber, fields, alt = 'json', key, access_token, quotaUser, oauth_token, callback, prettyPrint = true }) => {
  const baseUrl = 'https://script.googleapis.com';
  const token = process.env.GOOGLE_APP_SCRIPT_API_API_KEY;
  const url = new URL(`${baseUrl}/v1/projects/${scriptId}/versions/${versionNumber}`);

  // Append query parameters
  const params = new URLSearchParams({
    fields,
    alt,
    key,
    access_token,
    quotaUser,
    oauth_token,
    callback,
    prettyPrint: prettyPrint.toString(),
    '$.xgafv': '1',
    upload_protocol: 'raw',
    uploadType: 'media'
  });

  // Set up headers for the request
  const headers = {
    'Accept': 'application/json'
  };

  // If a token is provided, add it to the Authorization header
  if (token) {
    headers['Authorization'] = `Bearer ${token}`;
  }

  // Perform the fetch request
  try {
    const response = await fetch(`${url}?${params.toString()}`, {
      method: 'GET',
      headers
    });

    // Check if the response was successful
    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(errorData);
    }

    // Parse and return the response data
    const data = await response.json();
    return data;
  } catch (error) {
    const errorDetails = {
      message: error.message,
      stack: error.stack,
      scriptId,
      versionNumber,
      timestamp: new Date().toISOString(),
      errorType: error.name || 'Unknown'
    };

    logger.error('VERSION_GET', 'Error retrieving script version', errorDetails);
    
    console.error('❌ Error retrieving script version:', errorDetails);
    
    // Return detailed error information for debugging
    return { 
      error: true,
      message: error.message,
      details: errorDetails,
      rawError: {
        name: error.name,
        stack: error.stack
      }
    };
  }
};

/**
 * Tool configuration for getting a version of a Google Apps Script project.
 * @type {Object}
 */
const apiTool = {
  function: executeFunction,
  definition: {
    type: 'function',
    function: {
      name: 'script_projects_versions_get',
      description: 'Get a version of a Google Apps Script project.',
      parameters: {
        type: 'object',
        properties: {
          scriptId: {
            type: 'string',
            description: 'The ID of the script project.'
          },
          versionNumber: {
            type: 'string',
            description: 'The version number of the script project.'
          },
          fields: {
            type: 'string',
            description: 'Selector specifying which fields to include in a partial response.'
          },
          alt: {
            type: 'string',
            enum: ['json', 'xml'],
            description: 'Data format for response.'
          },
          key: {
            type: 'string',
            description: 'API key for the project.'
          },
          access_token: {
            type: 'string',
            description: 'OAuth access token.'
          },
          quotaUser: {
            type: 'string',
            description: 'Available to use for quota purposes for server-side applications.'
          },
          oauth_token: {
            type: 'string',
            description: 'OAuth 2.0 token for the current user.'
          },
          callback: {
            type: 'string',
            description: 'JSONP callback.'
          },
          prettyPrint: {
            type: 'boolean',
            description: 'Returns response with indentations and line breaks.'
          }
        },
        required: ['scriptId', 'versionNumber']
      }
    }
  }
};

export { apiTool };
```

--------------------------------------------------------------------------------
/helpers/convert-to-oauth.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Files to update
const filesToUpdate = [
  'tools/google-app-script-api/apps-script-api/script-projects-deployments-create.js',
  'tools/google-app-script-api/apps-script-api/script-projects-deployments-get.js',
  'tools/google-app-script-api/apps-script-api/script-projects-deployments-list.js',
  'tools/google-app-script-api/apps-script-api/script-projects-deployments-update.js',
  'tools/google-app-script-api/apps-script-api/script-projects-get-content.js',
  'tools/google-app-script-api/apps-script-api/script-projects-get-metrics.js',
  'tools/google-app-script-api/apps-script-api/script-projects-update-content.js',
  'tools/google-app-script-api/apps-script-api/script-projects-versions-create.js',
  'tools/google-app-script-api/apps-script-api/script-projects-versions-get.js',
  'tools/google-app-script-api/apps-script-api/script-projects-versions-list.js',
  'tools/google-app-script-api/apps-script-api/script-processes-list-script-processes.js'
];

function updateFileForOAuth(filePath) {
  const fullPath = path.join(__dirname, filePath);
  
  if (!fs.existsSync(fullPath)) {
    console.log(`⚠️  File not found: ${filePath}`);
    return;
  }
  
  let content = fs.readFileSync(fullPath, 'utf8');
  
  // Check if already updated
  if (content.includes("import { getAuthHeaders } from '../../../lib/oauth-helper.js';")) {
    console.log(`✅ Already updated: ${filePath}`);
    return;
  }
  
  // Add import at the top
  if (!content.includes("import { getAuthHeaders }")) {
    content = `import { getAuthHeaders } from '../../../lib/oauth-helper.js';\n\n${content}`;
  }
  
  // Remove API key token assignment
  content = content.replace(/\s*const token = process\.env\.GOOGLE_APP_SCRIPT_API_API_KEY;\s*/g, '');
  content = content.replace(/\s*const apiKey = process\.env\.GOOGLE_APP_SCRIPT_API_API_KEY;\s*/g, '');
  
  // Replace header setup
  const headerPatterns = [
    // Pattern 1: Simple headers with token check
    /(\s*)\/\/ Set up headers for the request\s*\n\s*const headers = \{\s*\n\s*['"]Accept['"]:\s*['"]application\/json['"],?\s*\n\s*\};\s*\n\s*\/\/ If a token is provided, add it to the Authorization header\s*\n\s*if \(token\) \{\s*\n\s*headers\[['"]Authorization['"]\] = `Bearer \$\{token\}`;?\s*\n\s*\}/g,
    
    // Pattern 2: Headers with Content-Type
    /(\s*)\/\/ Set up headers for the request\s*\n\s*const headers = \{\s*\n\s*['"]Content-Type['"]:\s*['"]application\/json['"],?\s*\n\s*['"]Accept['"]:\s*['"]application\/json['"],?\s*\n\s*\};\s*\n\s*\/\/ If a token is provided, add it to the Authorization header\s*\n\s*if \(token\) \{\s*\n\s*headers\[['"]Authorization['"]\] = `Bearer \$\{token\}`;?\s*\n\s*\}/g,
    
    // Pattern 3: Authorization-only headers
    /(\s*)\/\/ Set up headers for the request\s*\n\s*const headers = \{\s*\n\s*['"]Authorization['"]:\s*`Bearer \$\{token\}`,?\s*\n\s*['"]Accept['"]:\s*['"]application\/json['"],?\s*\n\s*\}/g
  ];
  
  let headerReplaced = false;
  headerPatterns.forEach(pattern => {
    if (pattern.test(content) && !headerReplaced) {
      content = content.replace(pattern, '$1// Get OAuth headers\n$1const headers = await getAuthHeaders();');
      headerReplaced = true;
    }
  });
  
  // If no pattern matched, try a simpler approach
  if (!headerReplaced) {
    // Replace any Authorization header assignment
    content = content.replace(/headers\[['"]Authorization['"]\]\s*=\s*`Bearer \$\{token\}`;?/g, '');
    
    // Add OAuth headers if we can find where headers are defined
    if (content.includes('const headers = {') && !content.includes('await getAuthHeaders()')) {
      content = content.replace(
        /(const headers = \{[^}]*\});/,
        'const headers = await getAuthHeaders();'
      );
    }
  }
  
  // Wrap the fetch request in try-catch if not already
  if (!content.includes('try {') && content.includes('const response = await fetch')) {
    content = content.replace(
      /(const executeFunction = async \([^}]*\) => \{)/,
      '$1\n  try {'
    );
    content = content.replace(
      /(return data;\s*\}\s*catch)/,
      '$1'
    );
  }
  
  // Write the updated content
  fs.writeFileSync(fullPath, content, 'utf8');
  console.log(`✅ Updated: ${filePath}`);
}

// Update all files
console.log('🔄 Converting Google Apps Script API files to use OAuth authentication...\n');

filesToUpdate.forEach(updateFileForOAuth);

console.log('\n✨ OAuth conversion completed!');
console.log('\n📝 Next steps:');
console.log('1. Update your .env file with OAuth credentials');
console.log('2. Follow the OAUTH_SETUP.md guide to get your credentials');
console.log('3. Test the authentication with one of the tools');

```

--------------------------------------------------------------------------------
/OAUTH_IMPLEMENTATION.md:
--------------------------------------------------------------------------------

```markdown
# Enhanced OAuth Implementation Summary

## What We've Implemented

### 1. **Complete OAuth2 Flow** (`lib/oauth-helper.js`)
- ✅ **Automatic browser opening** for OAuth authorization
- ✅ **Local callback server** to handle OAuth responses
- ✅ **Token management** with automatic refresh
- ✅ **Fallback mechanisms** when refresh tokens expire
- ✅ **Detailed logging** throughout the process
- ✅ **Error handling** with specific troubleshooting guidance

### 2. **Enhanced Test Script** (`test-oauth.js`)
- ✅ **Comprehensive logging** with timestamps and performance metrics
- ✅ **Detailed error information** including stack traces
- ✅ **Environment validation** checking for .env file and credentials
- ✅ **System information** logging for debugging
- ✅ **OAuth credential verification** (without exposing sensitive data)

### 3. **OAuth Setup Script** (`oauth-setup.js`)
- ✅ **Interactive OAuth flow** to obtain refresh tokens
- ✅ **Automatic .env file updates** with new refresh tokens
- ✅ **Credential validation** before starting the flow
- ✅ **User-friendly web interface** for OAuth completion
- ✅ **Comprehensive error handling** and troubleshooting

### 4. **Updated Configuration**
- ✅ **Package.json scripts** for easy access
- ✅ **Environment variables** properly configured
- ✅ **Dependencies installed** (googleapis, open)
- ✅ **Comprehensive setup guide** (OAUTH_SETUP.md)

## Key Features Similar to Your Working App

### 🔐 **OAuth2 Client Creation**
```javascript
const oAuth2Client = new google.auth.OAuth2(clientId, clientSecret, redirectUri);
```

### 🌐 **Local Server for Callback**
```javascript
const server = createServer(async (req, res) => {
  // Handle OAuth callback with detailed logging
});
```

### 🔄 **Token Exchange & Storage**
```javascript
const { tokens: newTokens } = await oAuth2Client.getToken(code);
tokens = newTokens;
```

### 📱 **Browser Automation**
```javascript
open(authUrl).catch(err => {
  console.error('❌ Failed to open browser:', err);
  console.log('🔗 Please manually open this URL in your browser:', authUrl);
});
```

### 🔄 **Automatic Token Refresh**
```javascript
if (refreshToken && refreshToken !== 'your_refresh_token_here') {
  // Use refresh token to get new access token
}
```

## How to Use

### 1. **First Time Setup**
```bash
npm run setup-oauth
```
- Opens browser automatically
- Handles OAuth flow
- Updates .env file with refresh token

### 2. **Test OAuth Setup**
```bash
npm run test-oauth
```
- Validates credentials
- Tests token retrieval
- Shows detailed diagnostic information

### 3. **Use in Your MCP Tools**
The OAuth helper will now:
- ✅ Use refresh token if available
- ✅ Start interactive OAuth flow if needed
- ✅ Handle token expiration automatically
- ✅ Provide detailed error information

## Enhanced Error Logging

### **Success Path Logging:**
- ⏰ Timestamps for all operations
- 📊 Performance metrics
- 🔑 Token information (safely masked)
- 📋 Request/response details

### **Error Path Logging:**
- 🕐 Error timestamps
- 📋 Complete error details (message, stack, status codes)
- 🔍 Environment diagnostics
- 📂 File system checks
- 🔧 Comprehensive troubleshooting steps

### **Example Enhanced Error Output:**
```
❌ OAuth authentication failed!
🕐 Error occurred at: 2025-05-31T10:30:45.123Z

📋 Error Details:
  📄 Message: Failed to refresh token: invalid_grant
  🏷️  Name: Error
  📊 Stack trace:
    Error: Failed to refresh token: invalid_grant
        at getOAuthAccessToken (file:///oauth-helper.js:245:13)
        at testOAuthAuthentication (file:///test-oauth.js:28:31)

🔍 Environment Check:
  📂 Current directory: c:\Users\mohal\Downloads\postman-mcp-server
  🔧 Node.js version: v18.17.0
  📄 .env file exists: true
  🔑 GOOGLE_CLIENT_ID present: true
  🔑 GOOGLE_CLIENT_SECRET present: true
  🔑 GOOGLE_REFRESH_TOKEN present: true

🔧 Troubleshooting steps:
1. Check that your .env file contains valid OAuth credentials
2. Verify your client ID and client secret are correct
3. Ensure your refresh token is valid and not expired
4. Follow the OAUTH_SETUP.md guide to obtain new credentials if needed
5. Make sure the Google Apps Script API is enabled in your GCP project
6. Check your internet connection and firewall settings
7. Verify that the oauth-helper.js file exists and is accessible
```

## Security Features

- 🔐 **No credentials exposed** in logs
- 🔑 **Secure token storage** in environment variables
- 🌐 **Local-only callback server** (port 3001)
- ⏱️ **Automatic server timeout** (5 minutes)
- 🚪 **Clean token cleanup** on logout

## Next Steps

1. **Run the setup**: `npm run setup-oauth`
2. **Test the implementation**: `npm run test-oauth`
3. **Use your MCP tools** with confidence!

The OAuth implementation now matches the robustness and user experience of your working Express app while providing enhanced debugging capabilities for easier troubleshooting.

```

--------------------------------------------------------------------------------
/tools/google-app-script-api/apps-script-api/script-projects-deployments-list.js:
--------------------------------------------------------------------------------

```javascript
import { getOAuthAccessToken } from '../../../lib/oauth-helper.js';
import { logger } from '../../../lib/logger.js';

/**
 * Function to list the deployments of a Google Apps Script project.
 *
 * @param {Object} args - Arguments for the deployment listing.
 * @param {string} args.scriptId - The ID of the script project.
 * @param {number} [args.pageSize=50] - The number of deployments to return per page.
 * @param {string} [args.pageToken] - Token for pagination.
 * @param {string} [args.fields] - Selector specifying which fields to include in a partial response.
 * @param {boolean} [args.prettyPrint=true] - Returns response with indentations and line breaks.
 * @returns {Promise<Object>} - The result of the deployments listing.
 */
const executeFunction = async ({ scriptId, pageSize = 50, pageToken, fields, prettyPrint = true }) => {
  const baseUrl = 'https://script.googleapis.com';
  const startTime = Date.now();

  logger.info('API_CALL', 'Starting deployments list request', {
    scriptId,
    pageSize,
    pageToken: pageToken ? 'provided' : 'none',
    fields: fields || 'all',
    baseUrl
  });

  try {
    // Get OAuth access token
    logger.debug('API_CALL', 'Getting OAuth access token');
    const token = await getOAuthAccessToken();
    logger.debug('API_CALL', 'OAuth token obtained successfully');
    
    // Construct the URL with query parameters
    const url = new URL(`${baseUrl}/v1/projects/${scriptId}/deployments`);
    url.searchParams.append('pageSize', pageSize.toString());
    if (pageToken) url.searchParams.append('pageToken', pageToken);
    if (fields) url.searchParams.append('fields', fields);
    url.searchParams.append('alt', 'json');
    url.searchParams.append('prettyPrint', prettyPrint.toString());

    logger.debug('API_CALL', 'Constructed API URL', {
      url: url.toString(),
      pathSegments: url.pathname.split('/'),
      queryParams: Object.fromEntries(url.searchParams)
    });

    // Set up headers for the request
    const headers = {
      'Accept': 'application/json',
      'Authorization': `Bearer ${token}`
    };

    logger.logAPICall('GET', url.toString(), headers);

    // Perform the fetch request
    const fetchStartTime = Date.now();
    const response = await fetch(url.toString(), {
      method: 'GET',
      headers
    });
    
    const fetchDuration = Date.now() - fetchStartTime;
    const responseSize = response.headers.get('content-length') || 'unknown';
    
    logger.logAPIResponse('GET', url.toString(), response.status, fetchDuration, responseSize);

    // Check if the response was successful
    if (!response.ok) {
      const errorText = await response.text();
      
      logger.error('API_CALL', 'API request failed', {
        status: response.status,
        statusText: response.statusText,
        url: url.toString(),
        errorResponse: errorText,
        duration: Date.now() - startTime
      });
      
      console.error('API Error Response:', errorText);
      throw new Error(`HTTP ${response.status}: ${errorText}`);
    }

    // Parse and return the response data
    const data = await response.json();
    const totalDuration = Date.now() - startTime;
    
    logger.info('API_CALL', 'Deployments list request completed successfully', {
      scriptId,
      deploymentCount: data.deployments ? data.deployments.length : 0,
      hasNextPageToken: !!data.nextPageToken,
      totalDuration: `${totalDuration}ms`,
      responseSize: JSON.stringify(data).length
    });
    
    return data;
  } catch (error) {
    const totalDuration = Date.now() - startTime;
    
    logger.error('API_CALL', 'Deployments list request failed', {
      scriptId,
      error: {
        message: error.message,
        stack: error.stack
      },
      totalDuration: `${totalDuration}ms`
    });
    
    console.error('Error listing deployments:', error);
    return { 
      error: 'An error occurred while listing deployments.',
      details: {
        message: error.message,
        scriptId,
        timestamp: new Date().toISOString()
      }
    };
  }
};

/**
 * Tool configuration for listing deployments of a Google Apps Script project.
 * @type {Object}
 */
const apiTool = {
  function: executeFunction,
  definition: {
    type: 'function',
    function: {
      name: 'script_projects_deployments_list',
      description: 'Lists the deployments of an Apps Script project.',
      parameters: {
        type: 'object',
        properties: {
          scriptId: {
            type: 'string',
            description: 'The ID of the script project.'
          },
          pageSize: {
            type: 'integer',
            description: 'The number of deployments to return per page.'
          },
          pageToken: {
            type: 'string',
            description: 'Token for pagination.'
          },
          fields: {
            type: 'string',
            description: 'Selector specifying which fields to include in a partial response.'
          },
          prettyPrint: {
            type: 'boolean',
            description: 'Returns response with indentations and line breaks.'
          }
        },
        required: ['scriptId']
      }
    }
  }
};

export { apiTool };
```

--------------------------------------------------------------------------------
/test/update-tools.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

/**
 * Script to automatically update all Google Apps Script API tools
 * to use automatic OAuth and enhanced error handling
 */

import { readFileSync, writeFileSync, readdirSync } from 'fs';
import { join } from 'path';

const toolsDir = 'tools/google-app-script-api/apps-script-api';

// Enhanced error handling template
const errorHandlingTemplate = `
  } catch (error) {
    console.error('❌ Error in API call:', {
      message: error.message,
      stack: error.stack,
      timestamp: new Date().toISOString()
    });
    
    // Return detailed error information for debugging
    return { 
      error: true,
      message: error.message,
      details: {
        timestamp: new Date().toISOString(),
        errorType: error.name || 'Unknown'
      }
    };
  }
`;

// Function to remove OAuth parameters from tool definitions
function updateToolDefinition(content) {
  // Remove OAuth-related parameters from the function signature
  content = content.replace(
    /(\{[^}]*?)(key|access_token|oauth_token)[\s\S]*?(,\s*)?/g,
    (match, start, param, comma) => {
      // If this is the last parameter before closing brace, remove the comma
      if (match.includes('}')) {
        return start.replace(/,\s*$/, '');
      }
      return start;
    }
  );

  // Remove OAuth parameters from URL construction
  content = content.replace(/\s*url\.searchParams\.append\([^)]*(?:key|access_token|oauth_token)[^)]*\);?\n?/g, '');

  // Update parameter validation to only require non-OAuth params
  content = content.replace(
    /required:\s*\[[^\]]*(?:key|access_token|oauth_token)[^\]]*\]/g,
    (match) => {
      // Extract non-OAuth required parameters
      const params = match.match(/'([^']+)'/g) || [];
      const nonOAuthParams = params.filter(p => 
        !p.includes('key') && 
        !p.includes('access_token') && 
        !p.includes('oauth_token')
      );
      return `required: [${nonOAuthParams.join(', ')}]`;
    }
  );

  // Remove OAuth parameter definitions from schema
  content = content.replace(/\s*(?:key|access_token|oauth_token):\s*\{[^}]*\},?\n?/g, '');

  // Add OAuth auto-handling note to description
  content = content.replace(
    /(description:\s*')([^']*?)(')/g,
    '$1$2 OAuth authentication is handled automatically.$3'
  );

  return content;
}

// Function to enhance error handling
function enhanceErrorHandling(content) {
  // Replace simple error handling with detailed version
  content = content.replace(
    /if\s*\(\s*!response\.ok\s*\)\s*\{[\s\S]*?throw new Error\([^)]*\);?\s*\}/g,
    `if (!response.ok) {
      const errorText = await response.text();
      let errorData;
      
      try {
        errorData = JSON.parse(errorText);
      } catch (parseError) {
        errorData = { message: errorText };
      }

      const detailedError = {
        status: response.status,
        statusText: response.statusText,
        url: url.toString(),
        error: errorData,
        timestamp: new Date().toISOString()
      };

      console.error('❌ API Error Details:', JSON.stringify(detailedError, null, 2));
      
      throw new Error(\`API Error (\${response.status}): \${errorData.error?.message || errorData.message || 'Unknown error'}\`);
    }`
  );

  // Replace simple catch blocks with detailed error handling
  content = content.replace(
    /catch\s*\([^)]*\)\s*\{[\s\S]*?return\s*\{[^}]*error[^}]*\};?\s*\}/g,
    errorHandlingTemplate.trim()
  );

  return content;
}

// Get all tool files
const toolFiles = readdirSync(toolsDir).filter(file => file.endsWith('.js'));

console.log('🔧 Updating Google Apps Script API tools...');
console.log(`📁 Found ${toolFiles.length} tool files to update`);

let updatedCount = 0;

for (const file of toolFiles) {
  try {
    const filePath = join(toolsDir, file);
    console.log(`🔄 Processing: ${file}`);
    
    let content = readFileSync(filePath, 'utf8');
    
    // Skip if already updated (check for OAuth auto-handling comment)
    if (content.includes('OAuth authentication is handled automatically')) {
      console.log(`✅ ${file} already updated, skipping`);
      continue;
    }
    
    // Apply updates
    content = updateToolDefinition(content);
    content = enhanceErrorHandling(content);
    
    // Add logging for API calls
    if (!content.includes('console.log') && content.includes('fetch(')) {
      content = content.replace(
        /(const url = new URL\([^;]+;)/,
        '$1\n    console.log(\'🌐 API URL:\', url.toString());'
      );
      
      content = content.replace(
        /(const headers = await getAuthHeaders\(\);)/,
        '$1\n    console.log(\'🔐 Authorization headers obtained successfully\');'
      );
      
      content = content.replace(
        /(const response = await fetch\([^;]+;)/,
        '$1\n    console.log(\'📡 API Response Status:\', response.status, response.statusText);'
      );
    }
    
    writeFileSync(filePath, content);
    updatedCount++;
    console.log(`✅ Updated: ${file}`);
    
  } catch (error) {
    console.error(`❌ Error updating ${file}:`, error.message);
  }
}

console.log(`\n🎉 Successfully updated ${updatedCount} out of ${toolFiles.length} files`);
console.log('✅ All tools now use automatic OAuth authentication and enhanced error handling');

```

--------------------------------------------------------------------------------
/tools/google-app-script-api/apps-script-api/script-projects-deployments-update.js:
--------------------------------------------------------------------------------

```javascript
import { logger } from '../../../lib/logger.js';

/**
 * Function to update a deployment of an Apps Script project.
 *
 * @param {Object} args - Arguments for the update.
 * @param {string} args.scriptId - The ID of the script to update.
 * @param {string} args.deploymentId - The ID of the deployment to update.
 * @param {Object} args.deploymentConfig - The configuration for the deployment.
 * @param {string} args.deploymentConfig.manifestFileName - The name of the manifest file.
 * @param {number} args.deploymentConfig.versionNumber - The version number of the deployment.
 * @param {string} args.deploymentConfig.description - A description of the deployment.
 * @returns {Promise<Object>} - The result of the deployment update.
 */
const executeFunction = async ({ scriptId, deploymentId, deploymentConfig }) => {
  const baseUrl = 'https://script.googleapis.com';
  const token = process.env.GOOGLE_APP_SCRIPT_API_API_KEY;
  const apiKey = process.env.GOOGLE_APP_SCRIPT_API_API_KEY;
  const startTime = Date.now();

  try {
    logger.info('DEPLOYMENT_UPDATE', 'Starting deployment update', { 
      scriptId, 
      deploymentId, 
      versionNumber: deploymentConfig?.versionNumber 
    });

    // Construct the URL for the request
    const url = `${baseUrl}/v1/projects/${scriptId}/deployments/${deploymentId}?key=${apiKey}&prettyPrint=true`;

    // Set up headers for the request
    const headers = {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Authorization': `Bearer ${token}`
    };

    // Prepare the body of the request
    const requestBody = { deploymentConfig };
    const body = JSON.stringify(requestBody);

    logger.logAPICall('PUT', url, headers, requestBody);

    // Perform the fetch request
    const fetchStartTime = Date.now();
    const response = await fetch(url, {
      method: 'PUT',
      headers,
      body
    });
    
    const fetchDuration = Date.now() - fetchStartTime;
    const responseSize = response.headers.get('content-length') || 'unknown';
    
    logger.logAPIResponse('PUT', url, response.status, fetchDuration, responseSize);

    // Check if the response was successful
    if (!response.ok) {
      const errorText = await response.text();
      let errorData;
      
      try {
        errorData = JSON.parse(errorText);
      } catch (parseError) {
        errorData = { message: errorText };
      }

      const detailedError = {
        status: response.status,
        statusText: response.statusText,
        url,
        errorResponse: errorData,
        duration: Date.now() - startTime,
        scriptId,
        deploymentId,
        timestamp: new Date().toISOString()
      };

      logger.error('DEPLOYMENT_UPDATE', 'API request failed', detailedError);
      
      console.error('❌ API Error Details:', JSON.stringify(detailedError, null, 2));
      
      throw new Error(`API Error (${response.status}): ${errorData.error?.message || errorData.message || 'Unknown error'}`);
    }

    // Parse and return the response data
    const data = await response.json();
    
    logger.info('DEPLOYMENT_UPDATE', 'Successfully updated deployment', {
      scriptId,
      deploymentId,
      duration: Date.now() - startTime
    });
    
    console.log('✅ Successfully updated deployment');
    return data;
  } catch (error) {
    const errorDetails = {
      message: error.message,
      stack: error.stack,
      scriptId,
      deploymentId,
      duration: Date.now() - startTime,
      timestamp: new Date().toISOString(),
      errorType: error.name || 'Unknown'
    };

    logger.error('DEPLOYMENT_UPDATE', 'Error updating deployment', errorDetails);
    
    console.error('❌ Error updating deployment:', errorDetails);
    
    // Return detailed error information for debugging
    return { 
      error: true,
      message: error.message,
      details: errorDetails,
      rawError: {
        name: error.name,
        stack: error.stack
      }
    };
  }
};

/**
 * Tool configuration for updating a deployment of an Apps Script project.
 * @type {Object}
 */
const apiTool = {
  function: executeFunction,
  definition: {
    type: 'function',
    function: {
      name: 'script_projects_deployments_update',
      description: 'Updates a deployment of an Apps Script project.',
      parameters: {
        type: 'object',
        properties: {
          scriptId: {
            type: 'string',
            description: 'The ID of the script to update.'
          },
          deploymentId: {
            type: 'string',
            description: 'The ID of the deployment to update.'
          },
          deploymentConfig: {
            type: 'object',
            properties: {
              manifestFileName: {
                type: 'string',
                description: 'The name of the manifest file.'
              },
              versionNumber: {
                type: 'integer',
                description: 'The version number of the deployment.'
              },
              description: {
                type: 'string',
                description: 'A description of the deployment.'
              }
            },
            required: ['manifestFileName', 'versionNumber', 'description']
          }
        },
        required: ['scriptId', 'deploymentId', 'deploymentConfig']
      }
    }
  }
};

export { apiTool };
```

--------------------------------------------------------------------------------
/test/test-mcp-fetch-processes.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

/**
 * Simple MCP Server Test - Fetch Script Processes List
 * This test focuses on fetching script processes using the MCP tool to identify errors
 */

import { discoverTools } from './lib/tools.js';
import { logger } from './lib/logger.js';

// Known working script ID from previous tests
const SCRIPT_ID = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';

async function testFetchProcesses() {
  console.log('🔄 Testing MCP Server - Fetch Script Processes List\n');
  
  try {
    // Set logging to capture detailed information
    process.env.LOG_LEVEL = 'debug';
    
    console.log('🔍 Step 1: Discovering MCP tools...');
    const tools = await discoverTools();
    console.log(`✅ Found ${tools.length} tools\n`);
    
    // Find the script processes list tool
    const processListTool = tools.find(tool => 
      tool.definition?.function?.name === 'd94_script_processes_list' ||
      tool.definition?.function?.name === 'script_processes_list'
    );
    
    if (!processListTool) {
      console.error('❌ Script processes list tool not found');
      console.log('Available tools:');
      tools.forEach(tool => {
        console.log(`  - ${tool.definition?.function?.name}`);
      });
      return;
    }
    
    console.log('🎯 Step 2: Found script processes list tool');
    console.log(`   Name: ${processListTool.definition.function.name}`);
    console.log(`   Description: ${processListTool.definition.function.description}`);
    console.log(`   Required params: ${processListTool.definition.function.parameters.required?.join(', ') || 'none'}\n`);
    
    // Test the tool with minimal parameters
    console.log('🚀 Step 3: Calling tool to fetch processes...');
    console.log(`   Script ID: ${SCRIPT_ID}`);
    
    try {
      const startTime = Date.now();
      
      const result = await processListTool.function({
        scriptId: SCRIPT_ID,
        pageSize: 10
      });
      
      const duration = Date.now() - startTime;
      
      console.log(`✅ Success! Call completed in ${duration}ms`);
      console.log('\n📊 RESULT:');
      console.log('=' .repeat(50));
      
      if (result && typeof result === 'object') {
        if (result.processes && Array.isArray(result.processes)) {
          console.log(`Found ${result.processes.length} processes:`);
          result.processes.forEach((process, index) => {
            console.log(`\n  Process ${index + 1}:`);
            console.log(`    Function: ${process.functionName || 'N/A'}`);
            console.log(`    Type: ${process.processType || 'N/A'}`);
            console.log(`    Status: ${process.processStatus || 'N/A'}`);
            console.log(`    Start: ${process.startTime || 'N/A'}`);
            console.log(`    Duration: ${process.duration || 'N/A'}`);
          });
        } else {
          console.log('No processes found in result');
        }
        
        if (result.nextPageToken) {
          console.log(`\nNext page token available: ${result.nextPageToken.substring(0, 20)}...`);
        }
      } else {
        console.log('Unexpected result format:');
        console.log(JSON.stringify(result, null, 2));
      }
      
    } catch (error) {
      console.log('\n❌ ERROR OCCURRED:');
      console.log('=' .repeat(50));
      console.log(`Error Type: ${error.constructor.name}`);
      console.log(`Error Message: ${error.message}`);
      
      if (error.response) {
        console.log(`HTTP Status: ${error.response.status}`);
        console.log(`Response Data: ${JSON.stringify(error.response.data, null, 2)}`);
      }
      
      if (error.stack) {
        console.log('\nStack Trace:');
        console.log(error.stack);
      }
      
      // Log additional context if available
      if (error.config) {
        console.log('\nRequest Config:');
        console.log(`URL: ${error.config.url}`);
        console.log(`Method: ${error.config.method?.toUpperCase()}`);
        console.log(`Headers: ${JSON.stringify(error.config.headers, null, 2)}`);
      }
    }
    
  } catch (setupError) {
    console.log('\n💥 SETUP ERROR:');
    console.log('=' .repeat(50));
    console.log(`Error: ${setupError.message}`);
    console.log(`Stack: ${setupError.stack}`);
  }
  
  console.log('\n🏁 Test completed\n');
}

// Test with problematic fields parameter
async function testProblematicFields() {
  console.log('🔥 Testing Problematic Fields Parameter\n');
  
  try {
    const tools = await discoverTools();
    const processListTool = tools.find(tool => 
      tool.definition?.function?.name === 'd94_script_processes_list' ||
      tool.definition?.function?.name === 'script_processes_list'
    );
    
    if (!processListTool) {
      console.log('❌ Tool not found for fields test');
      return;
    }
    
    console.log('🧪 Testing with known problematic fields parameter...');
    
    try {
      const result = await processListTool.function({
        scriptId: SCRIPT_ID,
        pageSize: 5,
        fields: 'processes(processType,functionName,startTime,duration,status)'
      });
      
      console.log('😮 Unexpected success with problematic fields!');
      console.log(JSON.stringify(result, null, 2));
      
    } catch (error) {
      console.log('✅ Expected error with invalid "status" field:');
      console.log(`   Error: ${error.message}`);
      
      if (error.response?.data) {
        console.log('   API Response:');
        console.log(JSON.stringify(error.response.data, null, 2));
      }
    }
    
  } catch (error) {
    console.log(`❌ Fields test setup error: ${error.message}`);
  }
}

// Run both tests
async function runAllTests() {
  await testFetchProcesses();
  console.log('\n' + '='.repeat(60) + '\n');
  await testProblematicFields();
}

runAllTests().catch(console.error);

```

--------------------------------------------------------------------------------
/tools/google-app-script-api/apps-script-api/script-projects-get-content.js:
--------------------------------------------------------------------------------

```javascript
import { getOAuthAccessToken } from '../../../lib/oauth-helper.js';
import { logger } from '../../../lib/logger.js';

/**
 * Function to get the content of a Google Apps Script project.
 *
 * @param {Object} args - Arguments for the request.
 * @param {string} args.scriptId - The ID of the script project to retrieve content for.
 * @param {string} [args.versionNumber] - The version number of the script project.
 * @param {string} [args.fields] - Selector specifying which fields to include in a partial response.
 * @param {string} [args.alt="json"] - Data format for response.
 * @param {string} [args.key] - API key for the project.
 * @param {string} [args.access_token] - OAuth access token.
 * @param {string} [args.prettyPrint="true"] - Returns response with indentations and line breaks.
 * @returns {Promise<Object>} - The content of the script project.
 */
const executeFunction = async ({ scriptId, versionNumber, fields, alt = "json", key, access_token, prettyPrint = "true" }) => {
  const baseUrl = 'https://script.googleapis.com';
  const startTime = Date.now();
  
  try {
    logger.info('SCRIPT_GET_CONTENT', 'Starting script content retrieval', { scriptId, versionNumber });

    // Get OAuth access token
    const token = await getOAuthAccessToken();
    
    // Construct the URL with query parameters
    const url = new URL(`${baseUrl}/v1/projects/${scriptId}/content`);
    if (versionNumber) url.searchParams.append('versionNumber', versionNumber);
    if (fields) url.searchParams.append('fields', fields);
    url.searchParams.append('alt', alt);
    if (key) url.searchParams.append('key', key);
    if (prettyPrint) url.searchParams.append('prettyPrint', prettyPrint);

    logger.debug('SCRIPT_GET_CONTENT', 'Constructed API URL', {
      url: url.toString(),
      pathSegments: url.pathname.split('/'),
      queryParams: Object.fromEntries(url.searchParams)
    });

    // Set up headers for the request
    const headers = {
      'Accept': 'application/json',
      'Authorization': `Bearer ${token}`
    };

    logger.logAPICall('GET', url.toString(), headers);

    // Perform the fetch request
    const fetchStartTime = Date.now();
    const response = await fetch(url.toString(), {
      method: 'GET',
      headers
    });
    
    const fetchDuration = Date.now() - fetchStartTime;
    const responseSize = response.headers.get('content-length') || 'unknown';
    
    logger.logAPIResponse('GET', url.toString(), response.status, fetchDuration, responseSize);

    // Check if the response was successful
    if (!response.ok) {
      const errorText = await response.text();
      let errorData;
      
      try {
        errorData = JSON.parse(errorText);
      } catch (parseError) {
        errorData = { message: errorText };
      }

      const detailedError = {
        status: response.status,
        statusText: response.statusText,
        url: url.toString(),
        errorResponse: errorData,
        duration: Date.now() - startTime,
        scriptId,
        versionNumber,
        timestamp: new Date().toISOString()
      };

      logger.error('SCRIPT_GET_CONTENT', 'API request failed', detailedError);
      
      console.error('❌ API Error Details:', JSON.stringify(detailedError, null, 2));
      
      throw new Error(`API Error (${response.status}): ${errorData.error?.message || errorData.message || 'Unknown error'}`);
    }

    // Parse and return the response data
    const data = await response.json();
    
    logger.info('SCRIPT_GET_CONTENT', 'Successfully retrieved script content', {
      scriptId,
      versionNumber,
      filesCount: data.files?.length || 0,
      duration: Date.now() - startTime
    });
    
    console.log('✅ Successfully retrieved script content');
    return data;
  } catch (error) {
    const errorDetails = {
      message: error.message,
      stack: error.stack,
      scriptId,
      versionNumber,
      duration: Date.now() - startTime,
      timestamp: new Date().toISOString(),
      errorType: error.name || 'Unknown'
    };

    logger.error('SCRIPT_GET_CONTENT', 'Error getting script project content', errorDetails);
    
    console.error('❌ Error getting script project content:', errorDetails);
    
    // Return detailed error information for debugging
    return { 
      error: true,
      message: error.message,
      details: errorDetails,
      rawError: {
        name: error.name,
        stack: error.stack
      }
    };
  }
};

/**
 * Tool configuration for getting the content of a Google Apps Script project.
 * @type {Object}
 */
const apiTool = {
  function: executeFunction,
  definition: {
    type: 'function',
    function: {
      name: 'script_projects_get_content',
      description: 'Get the content of a Google Apps Script project.',
      parameters: {
        type: 'object',
        properties: {
          scriptId: {
            type: 'string',
            description: 'The ID of the script project to retrieve content for.'
          },
          versionNumber: {
            type: 'string',
            description: 'The version number of the script project.'
          },
          fields: {
            type: 'string',
            description: 'Selector specifying which fields to include in a partial response.'
          },
          alt: {
            type: 'string',
            description: 'Data format for response.'
          },
          key: {
            type: 'string',
            description: 'API key for the project.'
          },
          access_token: {
            type: 'string',
            description: 'OAuth access token.'
          },
          prettyPrint: {
            type: 'string',
            description: 'Returns response with indentations and line breaks.'
          }
        },
        required: ['scriptId']
      }
    }
  }
};

export { apiTool };
```

--------------------------------------------------------------------------------
/test/test-oauth.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

/**
 * Test script to verify OAuth authentication setup
 */

import 'dotenv/config';
import { getOAuthAccessToken, getAuthHeaders } from './lib/oauth-helper.js';

async function testOAuthAuthentication() {
  console.log('🔐 Testing OAuth Authentication for Google Apps Script API...\n');
  console.log('🕐 Test started at:', new Date().toISOString());
  console.log('📂 Working directory:', process.cwd());
  console.log('🔧 Node.js version:', process.version);
  console.log('');
  
  try {
    // Test 1: Get access token
    console.log('📋 Step 1: Getting OAuth access token...');
    console.log('⏳ Attempting to retrieve access token from OAuth helper...');
    
    const startTime = Date.now();
    const accessToken = await getOAuthAccessToken();
    const duration = Date.now() - startTime;
    
    console.log('✅ Successfully obtained access token:', accessToken.substring(0, 20) + '...');
    console.log('⏱️  Token retrieval took:', duration + 'ms');
    console.log('📏 Full token length:', accessToken.length, 'characters');
    console.log('');
    
    // Test 2: Get auth headers
    console.log('📋 Step 2: Creating authorization headers...');
    console.log('⏳ Building authorization headers for API requests...');
    
    const headerStartTime = Date.now();
    const headers = await getAuthHeaders();
    const headerDuration = Date.now() - headerStartTime;
    
    console.log('✅ Successfully created auth headers:', JSON.stringify(headers, null, 2));
    console.log('⏱️  Header creation took:', headerDuration + 'ms');
    console.log('📊 Header keys count:', Object.keys(headers).length);
    console.log('');
    
    // Test 3: Test API call (optional - requires valid script ID)
    console.log('📋 Step 3: Testing API connectivity...');
    console.log('ℹ️  To test a full API call, you would need a valid script ID.');
    console.log('ℹ️  You can test with the script_processes_list tool in your MCP client.\n');
    
    const totalDuration = Date.now() - startTime;
    console.log('🎉 OAuth authentication test completed successfully!');
    console.log('✅ Your OAuth setup is working correctly.');
    console.log('⏱️  Total test duration:', totalDuration + 'ms');
    console.log('🕐 Test completed at:', new Date().toISOString());
    console.log('');
    
    console.log('📝 Next steps:');
    console.log('1. Test one of the tools in your MCP client (Claude Desktop, Postman, etc.)');
    console.log('2. Use a valid Google Apps Script project ID when calling the tools');
    console.log('3. Ensure your OAuth token has the required scopes for the operations you want to perform');
    
  } catch (error) {
    console.error('❌ OAuth authentication failed!');
    console.error('🕐 Error occurred at:', new Date().toISOString());
    console.error('');
    
    // Detailed error logging
    console.error('📋 Error Details:');
    console.error('  📄 Message:', error.message);
    console.error('  🏷️  Name:', error.name);
    console.error('  📊 Stack trace:');
    if (error.stack) {
      console.error(error.stack.split('\n').map(line => '    ' + line).join('\n'));
    } else {
      console.error('    (No stack trace available)');
    }
    console.error('');
    
    // Additional error information
    if (error.code) {
      console.error('  🔢 Error code:', error.code);
    }
    if (error.status) {
      console.error('  📊 HTTP status:', error.status);
    }
    if (error.statusText) {
      console.error('  📝 Status text:', error.statusText);
    }
    if (error.response) {
      console.error('  📬 Response data:', JSON.stringify(error.response, null, 2));
    }
    console.error('');
    
    // Environment check
    console.log('🔍 Environment Check:');
    console.log('  📂 Current directory:', process.cwd());
    console.log('  🔧 Node.js version:', process.version);
    console.log('  💾 Platform:', process.platform);
    console.log('  🏗️  Architecture:', process.arch);
    
    // Check for .env file
    try {
      const fs = await import('fs');
      const envPath = '.env';
      const envExists = fs.existsSync(envPath);
      console.log('  📄 .env file exists:', envExists);
      
      if (envExists) {
        const envContent = fs.readFileSync(envPath, 'utf8');
        const envLines = envContent.split('\n').filter(line => line.trim() && !line.startsWith('#'));
        console.log('  📋 .env file lines count:', envLines.length);
          // Check for required OAuth variables (without showing values)
        const requiredVars = ['GOOGLE_APP_SCRIPT_API_CLIENT_ID', 'GOOGLE_APP_SCRIPT_API_CLIENT_SECRET', 'GOOGLE_APP_SCRIPT_API_REFRESH_TOKEN'];
        requiredVars.forEach(varName => {
          const hasVar = envContent.includes(varName + '=');
          console.log(`  🔑 ${varName} present:`, hasVar);
        });
      }
    } catch (fsError) {
      console.log('  ⚠️  Could not check .env file:', fsError.message);
    }
    console.log('');
    
    console.log('🔧 Troubleshooting steps:');
    console.log('1. Check that your .env file contains valid OAuth credentials');
    console.log('2. Verify your client ID and client secret are correct');
    console.log('3. Ensure your refresh token is valid and not expired');
    console.log('4. Follow the OAUTH_SETUP.md guide to obtain new credentials if needed');
    console.log('5. Make sure the Google Apps Script API is enabled in your GCP project');
    console.log('6. Check your internet connection and firewall settings');
    console.log('7. Verify that the oauth-helper.js file exists and is accessible');
    
    process.exit(1);
  }
}

// Run the test if this script is executed directly
console.log('🔍 Debug: process.argv[1]:', process.argv[1]);
console.log('🔍 Debug: endsWith check:', process.argv[1] && process.argv[1].endsWith('test-oauth.js'));

if (process.argv[1] && process.argv[1].endsWith('test-oauth.js')) {
  console.log('🚀 Starting OAuth test...');
  testOAuthAuthentication();
} else {
  console.log('❌ Script not executed directly, skipping test');
}

```

--------------------------------------------------------------------------------
/tools/google-app-script-api/apps-script-api/script-projects-update-content.js:
--------------------------------------------------------------------------------

```javascript
import { getOAuthAccessToken } from '../../../lib/oauth-helper.js';
import { logger } from '../../../lib/logger.js';

/**
 * Function to update the content of a Google Apps Script project.
 *
 * @param {Object} args - Arguments for the update.
 * @param {string} args.scriptId - The ID of the script project to update.
 * @param {Array<Object>} args.files - The files to be updated in the script project.
 * @returns {Promise<Object>} - The result of the update operation.
 */
const executeFunction = async ({ scriptId, files }) => {
  const baseUrl = 'https://script.googleapis.com';
  const startTime = Date.now();

  try {
    logger.info('SCRIPT_UPDATE_CONTENT', 'Starting script content update', { 
      scriptId, 
      filesCount: files?.length || 0 
    });

    // Get OAuth access token
    const token = await getOAuthAccessToken();
    
    // Construct the URL for the request
    const url = `${baseUrl}/v1/projects/${scriptId}/content`;

    // Set up headers for the request
    const headers = {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json',
      'Accept': 'application/json'
    };

    // Prepare the body of the request
    const requestBody = { scriptId, files };
    const body = JSON.stringify(requestBody);

    logger.logAPICall('PUT', url, headers, requestBody);

    // Perform the fetch request
    const fetchStartTime = Date.now();
    const response = await fetch(url, {
      method: 'PUT',
      headers,
      body
    });
    
    const fetchDuration = Date.now() - fetchStartTime;
    const responseSize = response.headers.get('content-length') || 'unknown';
    
    logger.logAPIResponse('PUT', url, response.status, fetchDuration, responseSize);

    // Check if the response was successful
    if (!response.ok) {
      const errorText = await response.text();
      let errorData;
      
      try {
        errorData = JSON.parse(errorText);
      } catch (parseError) {
        errorData = { message: errorText };
      }

      const detailedError = {
        status: response.status,
        statusText: response.statusText,
        url,
        errorResponse: errorData,
        duration: Date.now() - startTime,
        scriptId,
        filesCount: files?.length || 0,
        timestamp: new Date().toISOString()
      };

      logger.error('SCRIPT_UPDATE_CONTENT', 'API request failed', detailedError);
      
      console.error('❌ API Error Details:', JSON.stringify(detailedError, null, 2));
      
      throw new Error(`API Error (${response.status}): ${errorData.error?.message || errorData.message || 'Unknown error'}`);
    }

    // Parse and return the response data
    const data = await response.json();
    
    logger.info('SCRIPT_UPDATE_CONTENT', 'Successfully updated script content', {
      scriptId,
      filesCount: files?.length || 0,
      duration: Date.now() - startTime
    });
    
    console.log('✅ Successfully updated script content');
    return data;
  } catch (error) {
    const errorDetails = {
      message: error.message,
      stack: error.stack,
      scriptId,
      filesCount: files?.length || 0,
      duration: Date.now() - startTime,
      timestamp: new Date().toISOString(),
      errorType: error.name || 'Unknown'
    };

    logger.error('SCRIPT_UPDATE_CONTENT', 'Error updating script project content', errorDetails);
    
    console.error('❌ Error updating script project content:', errorDetails);
    
    // Return detailed error information for debugging
    return { 
      error: true,
      message: error.message,
      details: errorDetails,
      rawError: {
        name: error.name,
        stack: error.stack
      }
    };
  }
};

/**
 * Tool configuration for updating Google Apps Script project content.
 * @type {Object}
 */
const apiTool = {
  function: executeFunction,
  definition: {
    type: 'function',
    function: {
      name: 'update_script_content',
      description: 'Updates the content of a specified Google Apps Script project.',
      parameters: {
        type: 'object',
        properties: {
          scriptId: {
            type: 'string',
            description: 'The ID of the script project to update.'
          },
          files: {
            type: 'array',
            items: {
              type: 'object',
              properties: {
                name: {
                  type: 'string',
                  description: 'The name of the file.'
                },
                lastModifyUser: {
                  type: 'object',
                  properties: {
                    photoUrl: { type: 'string' },
                    domain: { type: 'string' },
                    name: { type: 'string' },
                    email: { type: 'string' }
                  }
                },
                type: {
                  type: 'string',
                  description: 'The type of the file.'
                },
                updateTime: { type: 'string' },
                source: { type: 'string' },
                createTime: { type: 'string' },
                functionSet: {
                  type: 'object',
                  properties: {
                    values: {
                      type: 'array',
                      items: {
                        type: 'object',
                        properties: {
                          parameters: {
                            type: 'array',
                            items: {
                              type: 'object',
                              properties: {
                                value: { type: 'string' }
                              }
                            }
                          },
                          name: { type: 'string' }
                        }
                      }
                    }
                  }
                }
              }
            },
            description: 'The files to be updated in the script project.'
          }
        },
        required: ['scriptId', 'files']
      }
    }
  }
};

export { apiTool };
```

--------------------------------------------------------------------------------
/tools/google-app-script-api/apps-script-api/script-projects-versions-list.js:
--------------------------------------------------------------------------------

```javascript
import { getOAuthAccessToken } from '../../../lib/oauth-helper.js';
import { logger } from '../../../lib/logger.js';

/**
 * Function to list the versions of a Google Apps Script project.
 *
 * @param {Object} args - Arguments for the request.
 * @param {string} args.scriptId - The ID of the script project.
 * @param {number} [args.pageSize=100] - The number of versions to return per page.
 * @param {string} [args.pageToken] - The token for the next page of results.
 * @param {string} [args.fields] - Selector specifying which fields to include in a partial response.
 * @param {string} [args.alt='json'] - Data format for response.
 * @param {string} [args.key] - API key for the request.
 * @param {string} [args.access_token] - OAuth access token.
 * @param {string} [args.oauth_token] - OAuth 2.0 token for the current user.
 * @param {boolean} [args.prettyPrint=true] - Returns response with indentations and line breaks.
 * @returns {Promise<Object>} - The result of the request containing the versions of the script project.
 */
const executeFunction = async ({ scriptId, pageSize = 100, pageToken, fields, key, access_token, oauth_token, prettyPrint = true }) => {
  const baseUrl = 'https://script.googleapis.com';
  const startTime = Date.now();
  
  try {
    logger.info('SCRIPT_VERSIONS_LIST', 'Starting script versions list request', { scriptId, pageSize, pageToken });
    
    // Get OAuth access token
    const token = await getOAuthAccessToken();
    
    // Construct the URL with query parameters
    const url = new URL(`${baseUrl}/v1/projects/${scriptId}/versions`);
    url.searchParams.append('pageSize', pageSize.toString());
    if (pageToken) url.searchParams.append('pageToken', pageToken);
    if (fields) url.searchParams.append('fields', fields);
    url.searchParams.append('alt', 'json');
    if (key) url.searchParams.append('key', key);
    if (prettyPrint) url.searchParams.append('prettyPrint', prettyPrint.toString());

    logger.debug('SCRIPT_VERSIONS_LIST', 'Constructed API URL', {
      url: url.toString(),
      pathSegments: url.pathname.split('/'),
      queryParams: Object.fromEntries(url.searchParams)
    });

    // Set up headers for the request
    const headers = {
      'Accept': 'application/json',
      'Authorization': `Bearer ${token}`
    };

    logger.logAPICall('GET', url.toString(), headers);

    // Perform the fetch request
    const fetchStartTime = Date.now();
    const response = await fetch(url.toString(), {
      method: 'GET',
      headers
    });
    
    const fetchDuration = Date.now() - fetchStartTime;
    const responseSize = response.headers.get('content-length') || 'unknown';
    
    logger.logAPIResponse('GET', url.toString(), response.status, fetchDuration, responseSize);

    // Check if the response was successful
    if (!response.ok) {
      const errorText = await response.text();
      let errorData;
      
      try {
        errorData = JSON.parse(errorText);
      } catch (parseError) {
        errorData = { message: errorText };
      }

      const detailedError = {
        status: response.status,
        statusText: response.statusText,
        url: url.toString(),
        errorResponse: errorData,
        duration: Date.now() - startTime,
        scriptId,
        timestamp: new Date().toISOString()
      };

      logger.error('SCRIPT_VERSIONS_LIST', 'API request failed', detailedError);
      
      console.error('❌ API Error Details:', JSON.stringify(detailedError, null, 2));
      
      throw new Error(`API Error (${response.status}): ${errorData.error?.message || errorData.message || 'Unknown error'}`);
    }

    // Parse and return the response data
    const data = await response.json();
    
    logger.info('SCRIPT_VERSIONS_LIST', 'Successfully retrieved script versions', {
      scriptId,
      versionsCount: data.versions?.length || 0,
      duration: Date.now() - startTime
    });
    
    console.log('✅ Successfully retrieved script versions');
    return data;
  } catch (error) {
    const errorDetails = {
      message: error.message,
      stack: error.stack,
      scriptId,
      duration: Date.now() - startTime,
      timestamp: new Date().toISOString(),
      errorType: error.name || 'Unknown'
    };

    logger.error('SCRIPT_VERSIONS_LIST', 'Error listing script versions', errorDetails);
    
    console.error('❌ Error listing script versions:', errorDetails);
    
    // Return detailed error information for debugging
    return { 
      error: true,
      message: error.message,
      details: errorDetails,
      rawError: {
        name: error.name,
        stack: error.stack
      }
    };
  }
};

/**
 * Tool configuration for listing versions of a Google Apps Script project.
 * @type {Object}
 */
const apiTool = {
  function: executeFunction,
  definition: {
    type: 'function',
    function: {
      name: 'script_projects_versions_list',
      description: 'List the versions of a Google Apps Script project.',
      parameters: {
        type: 'object',
        properties: {
          scriptId: {
            type: 'string',
            description: 'The ID of the script project.'
          },
          pageSize: {
            type: 'integer',
            description: 'The number of versions to return per page.'
          },
          pageToken: {
            type: 'string',
            description: 'The token for the next page of results.'
          },
          fields: {
            type: 'string',
            description: 'Selector specifying which fields to include in a partial response.'
          },
          alt: {
            type: 'string',
            enum: ['json'],
            description: 'Data format for response.'
          },
          key: {
            type: 'string',
            description: 'API key for the request.'
          },
          access_token: {
            type: 'string',
            description: 'OAuth access token.'
          },
          oauth_token: {
            type: 'string',
            description: 'OAuth 2.0 token for the current user.'
          },
          prettyPrint: {
            type: 'boolean',
            description: 'Returns response with indentations and line breaks.'
          }
        },
        required: ['scriptId']
      }
    }
  }
};

export { apiTool };
```

--------------------------------------------------------------------------------
/test/test-mcp-errors.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

/**
 * Comprehensive MCP Server Error Testing Script
 * Tests the script processes list tool with real script ID to identify specific errors
 */

import { discoverTools } from './lib/tools.js';
import { logger } from './lib/logger.js';

// Real script ID used throughout the codebase
const REAL_SCRIPT_ID = '1fSY7y3Rh84FsgJmrFIMm4AUOV3mPgelLRvZ4Dahrv68zyDzX-cGbeYjn';

async function testMCPErrors() {
  console.log('🚨 MCP Server Error Analysis - Script Processes List\n');
  
  try {
    // Set high verbosity for maximum details
    process.env.LOG_LEVEL = 'trace';
    
    // Discover tools
    logger.info('TEST', 'Starting comprehensive error analysis');
    const tools = await discoverTools();
    
    // Find the script processes list tool
    const processListTool = tools.find(tool => 
      tool.definition?.function?.name === 'script_processes_list'
    );
    
    if (!processListTool) {
      console.error('❌ script_processes_list tool not found');
      return;
    }
    
    console.log('🔍 Found script_processes_list tool');
    console.log(`📝 Description: ${processListTool.definition.function.description}`);
    console.log(`🔧 Required: ${processListTool.definition.function.parameters.required.join(', ')}`);
    console.log(`📋 Properties: ${Object.keys(processListTool.definition.function.parameters.properties).join(', ')}\n`);
    
    // TEST 1: Basic call with real script ID
    console.log('🧪 TEST 1: Basic call with real script ID');
    console.log(`🎯 Using script ID: ${REAL_SCRIPT_ID}`);
    try {
      const result1 = await processListTool.function({
        scriptId: REAL_SCRIPT_ID
      });
      console.log('✅ Success - Basic call worked');
      console.log(`📊 Result type: ${typeof result1}`);
      console.log(`📊 Result content: ${JSON.stringify(result1, null, 2)}`);
    } catch (error) {
      console.log('❌ Error in basic call:');
      console.log(`   Message: ${error.message}`);
      console.log(`   Type: ${error.constructor.name}`);
    }
    
    // TEST 2: Call with minimal valid fields parameter
    console.log('\n🧪 TEST 2: Call with valid fields parameter');
    try {
      const result2 = await processListTool.function({
        scriptId: REAL_SCRIPT_ID,
        fields: 'processes'
      });
      console.log('✅ Success - With fields parameter');
      console.log(`📊 Result: ${JSON.stringify(result2, null, 2)}`);
    } catch (error) {
      console.log('❌ Error with fields parameter:');
      console.log(`   Message: ${error.message}`);
      console.log(`   Type: ${error.constructor.name}`);
    }
    
    // TEST 3: Call with specific valid field selections
    console.log('\n🧪 TEST 3: Call with specific field selections');
    const validFields = [
      'processes(processType,functionName,startTime,duration)',
      'processes(processType,functionName)',
      'processes(startTime)',
      'processes.processType,processes.functionName'
    ];
    
    for (const field of validFields) {
      console.log(`\n   📝 Testing field: ${field}`);
      try {
        const result = await processListTool.function({
          scriptId: REAL_SCRIPT_ID,
          fields: field,
          pageSize: 3
        });
        console.log(`   ✅ Success with field: ${field}`);
        console.log(`   📊 Result: ${JSON.stringify(result, null, 2)}`);
      } catch (error) {
        console.log(`   ❌ Error with field '${field}': ${error.message}`);
      }
    }
    
    // TEST 4: Test different parameter combinations
    console.log('\n🧪 TEST 4: Testing different parameter combinations');
    
    const testCases = [
      { name: 'With pageSize only', params: { scriptId: REAL_SCRIPT_ID, pageSize: 5 } },
      { name: 'With pageToken', params: { scriptId: REAL_SCRIPT_ID, pageToken: 'test_token' } },
      { name: 'With deploymentId filter', params: { scriptId: REAL_SCRIPT_ID, deploymentId: 'test_deployment' } },
      { name: 'With functionName filter', params: { scriptId: REAL_SCRIPT_ID, functionName: 'myFunction' } },
      { name: 'With time filters', params: { 
        scriptId: REAL_SCRIPT_ID, 
        startTime: '2024-01-01T00:00:00Z',
        endTime: '2024-12-31T23:59:59Z'
      }},
    ];
    
    for (const testCase of testCases) {
      console.log(`\n   📝 Testing: ${testCase.name}`);
      try {
        const result = await processListTool.function(testCase.params);
        console.log(`   ✅ Success: ${testCase.name}`);
        console.log(`   📊 Result: ${JSON.stringify(result, null, 2)}`);
      } catch (error) {
        console.log(`   ❌ Error in ${testCase.name}: ${error.message}`);
      }
    }
    
    // TEST 5: Check if the script actually exists by trying to get its metadata
    console.log('\n🧪 TEST 5: Verify script exists by getting metadata');
    const scriptGetTool = tools.find(tool => 
      tool.definition?.function?.name === 'script_projects_get'
    );
    
    if (scriptGetTool) {
      try {
        const metadata = await scriptGetTool.function({
          scriptId: REAL_SCRIPT_ID
        });
        console.log('✅ Script metadata retrieved successfully');
        console.log(`📋 Script title: ${metadata.title || 'No title'}`);
        console.log(`📋 Script ID: ${metadata.scriptId || 'No ID'}`);
        console.log(`📋 Create time: ${metadata.createTime || 'No create time'}`);
      } catch (error) {
        console.log('❌ Error getting script metadata:');
        console.log(`   Message: ${error.message}`);
        console.log('   This might indicate the script doesn\'t exist or access issues');
      }
    }
    
  } catch (error) {
    logger.error('TEST', 'Test failed with unexpected error', {
      error: {
        message: error.message,
        stack: error.stack
      }
    });
    console.error('❌ Test failed:', error.message);
  }
  
  console.log('\n🏁 Error Analysis Complete');
  console.log('\n📋 Summary of Findings:');
  console.log('   • Check the detailed logs above for specific API errors');
  console.log('   • Look for authentication issues, invalid parameters, or API limitations');
  console.log('   • Note which parameter combinations work vs. which fail');
  console.log('   • Verify if the script ID is accessible with current OAuth scopes');
}

// Run the error analysis
testMCPErrors().catch(console.error);

```
Page 1/2FirstPrevNextLast