script_projects_create
Create a new Google Apps Script project by specifying a parent project ID and a title for the script. Enables project management through the Google Apps Script API.
Instructions
Create a new Google Apps Script project.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| parentId | Yes | The ID of the parent project. | |
| title | Yes | The title of the new script project. |
Implementation Reference
- Main handler function `executeFunction` that performs the API call to create a new Google Apps Script project, including OAuth authentication via `getAuthHeaders`, parameter validation, HTTP POST request, error handling, and 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' } }; } };
- Tool schema definition in `apiTool.definition.function`, specifying name, description, input parameters (parentId: string optional in code but listed required, title: string required), and structure for MCP tool registration.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 file path for this tool is explicitly listed in the `toolPaths` export, which is used by `lib/tools.js` for dynamic discovery and loading of the `apiTool` during server startup.'google-app-script-api/apps-script-api/script-projects-create.js',
- lib/tools.js:8-64 (registration)The `discoverTools` function dynamically imports all tool files listed in toolPaths (including this one), extracts the `apiTool`, wraps the handler with logging, and prepares the tool objects for MCP server registration in `mcpServer.js`.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; }
- The tool file exports `apiTool` which bundles the handler function and schema. Imports `getAuthHeaders` helper from lib/oauth-helper.js for authentication.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());