Skip to main content
Glama
andyl25

Google Cloud MCP Server

by andyl25

list-spanner-instances

Retrieve a list of Google Cloud Spanner instances to manage database resources and monitor deployment status.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
_dummyNoNot used, just to ensure parameter compatibility

Implementation Reference

  • The handler function that implements the core logic of listing Spanner instances. It retrieves the project ID from various sources, creates a Spanner client, fetches the list of instances, formats them into a Markdown table with metadata, and includes navigation resource URIs.
    async (_params, _extra) => {
      try {
        // First try to get the project ID from the state manager
        let projectId = stateManager.getCurrentProjectId();
        
        if (projectId) {
          console.log(`Got project ID from state manager: ${projectId}`);
        } else {
          // If not in state manager, try to get it from environment
          const envProjectId = process.env.GOOGLE_CLOUD_PROJECT;
          
          if (envProjectId) {
            projectId = envProjectId;
            console.log(`Got project ID from environment: ${projectId}`);
            // Store in state manager for future use
            await stateManager.setCurrentProjectId(projectId);
          } else {
            // If not in environment, try to get it from our function
            projectId = await getProjectId();
            console.log(`Got project ID from getProjectId: ${projectId}`);
          }
        }
        
        if (!projectId) {
          throw new Error('Project ID could not be determined. Please set a project ID using the set-project-id tool.');
        }
        
        // Create Spanner client with explicit project ID
        const spanner = new (await import('@google-cloud/spanner')).Spanner({
          projectId: projectId
        });
        
        console.log(`Using Spanner client with explicit project ID: ${projectId} for list-spanner-instances`);
        
        const [instances] = await spanner.getInstances();
        
        if (!instances || instances.length === 0) {
          return {
            content: [{
              type: 'text',
              text: `# Spanner Instances\n\nProject: ${projectId}\n\nNo instances found in the project.`
            }]
          };
        }
        
        let markdown = `# Spanner Instances\n\nProject: ${projectId}\n\n`;
        
        // Table header
        markdown += '| Instance ID | State | Config | Nodes |\n';
        markdown += '|-------------|-------|--------|-------|\n';
        
        // Table rows
        for (const instance of instances) {
          const metadata = instance.metadata || {};
          markdown += `| ${instance.id || 'unknown'} | ${metadata.state || 'unknown'} | ${metadata.config?.split('/').pop() || 'unknown'} | ${metadata.nodeCount || 'unknown'} |\n`;
        }
        
        // Add resource links for further exploration
        markdown += '\n## Available Resources\n\n';
        markdown += `- All Instances: \`gcp-spanner://${projectId}/instances\`\n`;
        
        for (const instance of instances) {
          markdown += `- Databases in ${instance.id}: \`gcp-spanner://${projectId}/${instance.id}/databases\`\n`;
        }
        
        return {
          content: [{
            type: 'text',
            text: markdown
          }]
        };
      } catch (error: any) {
        console.error('Error listing Spanner instances:', error);
        throw error;
      }
    }
  • The Zod input schema for the list-spanner-instances tool. It defines an optional dummy string parameter to maintain compatibility with MCP clients that expect an input object.
    // Define an empty schema with a dummy parameter that's optional
    // This ensures compatibility with clients that expect an object parameter
    {
      _dummy: z.string().optional().describe('Not used, just to ensure parameter compatibility')
    },
  • The server.tool() call that registers the 'list-spanner-instances' tool on the MCP server, specifying its name, input schema, and handler function.
    server.tool(
      'list-spanner-instances',
      // Define an empty schema with a dummy parameter that's optional
      // This ensures compatibility with clients that expect an object parameter
      {
        _dummy: z.string().optional().describe('Not used, just to ensure parameter compatibility')
      },
      async (_params, _extra) => {
        try {
          // First try to get the project ID from the state manager
          let projectId = stateManager.getCurrentProjectId();
          
          if (projectId) {
            console.log(`Got project ID from state manager: ${projectId}`);
          } else {
            // If not in state manager, try to get it from environment
            const envProjectId = process.env.GOOGLE_CLOUD_PROJECT;
            
            if (envProjectId) {
              projectId = envProjectId;
              console.log(`Got project ID from environment: ${projectId}`);
              // Store in state manager for future use
              await stateManager.setCurrentProjectId(projectId);
            } else {
              // If not in environment, try to get it from our function
              projectId = await getProjectId();
              console.log(`Got project ID from getProjectId: ${projectId}`);
            }
          }
          
          if (!projectId) {
            throw new Error('Project ID could not be determined. Please set a project ID using the set-project-id tool.');
          }
          
          // Create Spanner client with explicit project ID
          const spanner = new (await import('@google-cloud/spanner')).Spanner({
            projectId: projectId
          });
          
          console.log(`Using Spanner client with explicit project ID: ${projectId} for list-spanner-instances`);
          
          const [instances] = await spanner.getInstances();
          
          if (!instances || instances.length === 0) {
            return {
              content: [{
                type: 'text',
                text: `# Spanner Instances\n\nProject: ${projectId}\n\nNo instances found in the project.`
              }]
            };
          }
          
          let markdown = `# Spanner Instances\n\nProject: ${projectId}\n\n`;
          
          // Table header
          markdown += '| Instance ID | State | Config | Nodes |\n';
          markdown += '|-------------|-------|--------|-------|\n';
          
          // Table rows
          for (const instance of instances) {
            const metadata = instance.metadata || {};
            markdown += `| ${instance.id || 'unknown'} | ${metadata.state || 'unknown'} | ${metadata.config?.split('/').pop() || 'unknown'} | ${metadata.nodeCount || 'unknown'} |\n`;
          }
          
          // Add resource links for further exploration
          markdown += '\n## Available Resources\n\n';
          markdown += `- All Instances: \`gcp-spanner://${projectId}/instances\`\n`;
          
          for (const instance of instances) {
            markdown += `- Databases in ${instance.id}: \`gcp-spanner://${projectId}/${instance.id}/databases\`\n`;
          }
          
          return {
            content: [{
              type: 'text',
              text: markdown
            }]
          };
        } catch (error: any) {
          console.error('Error listing Spanner instances:', error);
          throw error;
        }
      }
    );
  • src/index.ts:140-140 (registration)
    Invocation of registerSpannerTools in the main server initialization, which registers all Spanner tools including list-spanner-instances.
    registerSpannerTools(server);

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/andyl25/googlecloud-mcp'

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