Skip to main content
Glama

project_close

Close a project TCP server and optionally save its state before termination to manage resources and preserve work.

Instructions

Close a project TCP server with optional save

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
projectIdYesProject ID to close
saveNoSave project before closing (default: false)

Implementation Reference

  • Core handler method that closes the Visum project TCP server: checks existence, optionally saves, sends shutdown command via TCP, removes from active servers registry.
    async closeProject(projectId: string, save: boolean = false): Promise<any> {
      const serverInfo = this.activeServers.get(projectId);
      if (!serverInfo) {
        return {
          success: false,
          message: 'Progetto non trovato'
        };
      }
    
      console.error(`CLOSING: Chiusura progetto: ${serverInfo.projectName}`);
    
      try {
        // Salva se richiesto
        if (save) {
          console.error('SAVING: Salvataggio progetto...');
          await this.saveProject(projectId);
        }
    
        // Invia comando di shutdown al server
        await this.sendCommandToServer(projectId, { type: 'shutdown' });
    
        // Rimuovi dal registry
        this.activeServers.delete(projectId);
        this.saveRegistry();
    
        return {
          success: true,
          message: `Progetto ${serverInfo.projectName} chiuso${save ? ' e salvato' : ''}`
        };
      } catch (error) {
        return {
          success: false,
          message: `Errore chiusura progetto: ${(error as Error).message}`
        };
      }
    }
  • MCP tool registration for 'project_close' including schema (projectId, optional save) and thin wrapper handler that calls ProjectServerManager.closeProject and formats MCP response.
    server.tool(
      "project_close",
      "Close a project TCP server with optional save",
      {
        projectId: z.string().describe("Project ID to close"),
        save: z.boolean().optional().describe("Save project before closing (default: false)")
      },
      async ({ projectId, save }) => {
        try {
          const result = await serverManager.closeProject(projectId, save || false);
          
          if (result.success) {
            return {
              content: [
                {
                  type: "text",
                  text: `๐Ÿ”š **Progetto Chiuso**\n\nโœ… ${result.message}`
                }
              ]
            };
          } else {
            return {
              content: [
                {
                  type: "text",
                  text: `โŒ **Errore Chiusura**\n\n${result.message}`
                }
              ]
            };
          }
        } catch (error) {
          return {
            content: [
              {
                type: "text",
                text: `โŒ **Errore:** ${error instanceof Error ? error.message : String(error)}`
              }
            ]
          };
        }
      }
    );
  • Zod schema defining input parameters for the project_close tool.
      projectId: z.string().describe("Project ID to close"),
      save: z.boolean().optional().describe("Save project before closing (default: false)")
    },
  • Helper method used by closeProject to send the shutdown command over TCP to the project server.
    async sendCommandToServer(projectId: string, command: any): Promise<any> {
      const serverInfo = this.activeServers.get(projectId);
      if (!serverInfo) {
        throw new Error('Server progetto non trovato');
      }
    
      return new Promise((resolve, reject) => {
        const client = createConnection(serverInfo.port, 'localhost');
        let buffer = '';
        
        client.on('connect', () => {
          const message = JSON.stringify({ ...command, requestId: Date.now() });
          client.write(message + '\n');
        });
    
        client.on('data', (data: any) => {
          buffer += data.toString();
          
          // Dividi per newlines per separare i messaggi
          const messages = buffer.split('\n');
          buffer = messages.pop() || ''; // Mantieni l'ultimo pezzo (potrebbe essere incompleto)
          
          for (const message of messages) {
            if (message.trim()) {
              try {
                // Rimuovi backslash-n letterali che il server TCP Python aggiunge
                const cleanedResponse = message.replace(/\\n$/g, '');
                const response = JSON.parse(cleanedResponse);
                
                // Ignora il messaggio di welcome, aspetta la risposta vera
                if (response.type === 'project_welcome') {
                  continue;
                }
                
                // Risposta al comando ricevuta (query_result, save_result, error, etc.)
                if (response.type === 'query_result' || response.type === 'save_result' || 
                    response.type === 'error' || response.type === 'shutdown_ack' ||
                    response.result !== undefined) {
                  client.end();
                  resolve(response);
                  return;
                }
              } catch (error) {
                // Ignora messaggi malformati, continua ad aspettare
                console.error('WARN: Messaggio TCP non parsabile:', message);
              }
            }
          }
        });
    
        client.on('error', (error: any) => {
          reject(error);
        });
    
        setTimeout(() => {
          client.end();
          reject(new Error('Timeout comando server'));
        }, 300000); // 5 minuti timeout per operazioni pesanti su reti grandi
      });
    }

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/multiluca2020/visum-thinker-mcp-server'

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