Skip to main content
Glama
mohalmah

Google Apps Script MCP Server

by mohalmah

script_projects_create

Create a new Google Apps Script project by specifying a parent project ID and title for the script.

Instructions

Create a new Google Apps Script project.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
parentIdYesThe ID of the parent project.
titleYesThe title of the new script project.

Implementation Reference

  • The core handler function `executeFunction` that implements the tool logic: validates inputs, authenticates with OAuth, makes POST request to Google Apps Script API to create project, handles responses and errors with detailed logging.
    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'
          }
        };
      }
    };
  • The tool schema definition including name 'script_projects_create', description, input parameters schema with properties parentId and title, and required fields.
    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']
          }
        }
      }
    };
  • tools/paths.js:3-3 (registration)
    The tool file path is registered in the toolPaths array, which is used for dynamic discovery and loading of tools.
    'google-app-script-api/apps-script-api/script-projects-create.js',
  • lib/tools.js:8-64 (registration)
    The `discoverTools` function dynamically loads all tools by importing modules from paths in toolPaths, extracting apiTool, wrapping with logging, and returning the list of tools for registration.
    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;
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mohalmah/google-appscript-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server