Skip to main content
Glama

switch_project

Change the active project context in multi-project Optimizely DXP setups to set default credentials and project ID for all subsequent operations. Use before managing multiple projects to ensure commands target the correct environment.

Instructions

🔄 Switch active project context for multi-project setups. INSTANT: <1s. Changes default credentials and project ID for all subsequent tool calls. Use this before operations when managing multiple Optimizely projects. Project context persists for entire session. Required: projectName. Returns new active project details. Use list_projects() to see available projects.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
projectNameYesName of the project to switch to

Implementation Reference

  • Main handler function that executes the switch_project tool logic: validates input, lists projects, calls ProjectTools.switchProject, handles errors with fuzzy matching suggestions, and returns structured success/error responses.
    static async handleSwitchProject(args: ProjectSwitchArgs): Promise<any> { const { projectName } = args; if (!projectName) { return ResponseBuilder.error( '❌ Project name is required', { error: 'Missing projectName parameter' } ); } try { // DXP-36: Improved error handling for project switching // First, try to get available projects with error handling let projects; try { projects = ProjectTools.getConfiguredProjects(); } catch (configError: any) { return ResponseBuilder.error( '❌ **Configuration Error**\n\n' + 'Unable to load project configurations. This might be due to:\n' + '• Malformed environment variables\n' + '• Invalid project configuration format\n' + '• Missing required configuration fields\n\n' + `**Error details**: ${configError.message}\n\n` + '💡 **Next steps**:\n' + '1. Check your environment variables for proper format\n' + '2. Use `list_projects` to see current configuration status\n' + '3. Refer to setup documentation for correct format', { error: 'Configuration load failed', details: configError.message, requestedProject: projectName } ); } if (!projects || projects.length === 0) { return ResponseBuilder.error( '❌ **No Projects Configured**\n\n' + 'No projects are currently configured in your environment.\n\n' + '💡 **To configure a project**, add an environment variable like:\n' + '```\n' + 'MYPROJECT="id=your-project-id;key=your-api-key;secret=your-secret"\n' + '```\n\n' + 'Or see the setup guide for detailed instructions.', { error: 'No projects configured', requestedProject: projectName, availableProjects: [] } ); } // Attempt to switch project const result = ProjectTools.switchProject(projectName); if (!result.success) { // DXP-36: Enhanced error message with fuzzy matching and better suggestions const projectNames = projects.map((p: any) => p.name).filter(Boolean); // Find closest matches using simple string similarity const closeMatches = this.findSimilarProjectNames(projectName, projectNames); let errorMessage = `❌ **Project "${projectName}" not found**\n\n`; if (closeMatches.length > 0) { errorMessage += `🔍 **Did you mean?**\n${closeMatches.map(name => ` • ${name}`).join('\n')}\n\n`; } errorMessage += `📋 **Available projects** (${projectNames.length}):\n`; if (projectNames.length <= 10) { errorMessage += `${projectNames.map((n: string) => ` • ${n}`).join('\n')}\n\n`; } else { errorMessage += `${projectNames.slice(0, 8).map((n: string) => ` • ${n}`).join('\n')}\n • ... and ${projectNames.length - 8} more\n\n`; errorMessage += `💡 Use \`list_projects\` to see all projects\n\n`; } errorMessage += `💡 **Tips**:\n`; errorMessage += `• Project names are case-insensitive\n`; errorMessage += `• You can use partial names if unique\n`; errorMessage += `• Check for typos in the project name`; return ResponseBuilder.error( errorMessage, { requestedProject: projectName, availableProjects: projectNames, suggestions: closeMatches, totalProjects: projectNames.length } ); } // Success! Set as last used project for session persistence ProjectTools.setLastUsedProject(projectName); // Get project details for confirmation const project = result.project!; return ResponseBuilder.successWithStructuredData( { projectName: project.name, projectId: project.projectId, isDefault: project.isDefault || false }, `✅ **Switched to ${project.name}**\n\n` + `**Project Details**:\n` + `• Project ID: ${project.projectId}\n` + `• Environments: ${project.environments!.join(', ')}\n` + `• Status: Active\n\n` + `📌 All subsequent commands will use this project until you switch again.\n\n` + `💡 **Tip**: You can also include the project name in any command:\n` + ` Example: \`list_deployments --project "${project.name}"\`` ); } catch (switchError: any) { // DXP-36: Handle unexpected errors during project switching return ResponseBuilder.error( '❌ **Unexpected Error During Project Switch**\n\n' + `An unexpected error occurred while switching to project "${projectName}".\n\n` + `**Error details**: ${switchError.message}\n\n` + '💡 **Troubleshooting**:\n' + '1. Check if the project configuration is valid\n' + '2. Verify environment variables are properly set\n' + '3. Try switching to a different project first\n' + '4. Contact support if the issue persists', { error: 'Unexpected switch error', details: switchError.message, requestedProject: projectName } ); } }
  • TypeScript interface defining the input arguments for the switch_project tool.
    interface ProjectSwitchArgs { projectName?: string; }
  • Core helper method that performs the actual project switching: finds project by name/ID (case-insensitive), returns credentials and project info, or error if not found. Used by the handler.
    static switchProject(projectIdentifier: string | { projectName?: string; project?: string; projectId?: string }): SwitchResult { // Handle both string and object input const identifier = typeof projectIdentifier === 'object' ? (projectIdentifier.projectName || projectIdentifier.project || projectIdentifier.projectId) : projectIdentifier; if (!identifier) { return { success: false, message: 'No project identifier provided', credentials: null }; } const projects = this.getConfiguredProjects(); const project = projects.find(p => p.projectId === identifier || p.name === identifier || p.name.toLowerCase() === identifier.toLowerCase() ); if (!project) { return { success: false, message: `Project '${projectIdentifier}' not found`, credentials: null }; } return { success: true, message: `Switched to project: ${project.name}`, credentials: { projectId: project.projectId, apiKey: project.apiKey, apiSecret: project.apiSecret }, project: project }; }
  • Fuzzy matching helper for suggesting similar project names when exact match fails, used in error handling.
    static findSimilarProjectNames(input: string, projectNames: string[], maxSuggestions: number = 3): string[] { if (!input || !projectNames || projectNames.length === 0) { return []; } const inputLower = input.toLowerCase(); const suggestions: SimilaritySuggestion[] = []; for (const name of projectNames) { const nameLower = name.toLowerCase(); let score = 0; // Exact match (shouldn't happen, but just in case) if (nameLower === inputLower) { continue; } // Starts with input if (nameLower.startsWith(inputLower)) { score = 90; } // Contains input else if (nameLower.includes(inputLower)) { score = 70; } // Input contains project name (partial) else if (inputLower.includes(nameLower)) { score = 60; } // Check if input is close to start of project name (abbreviation-like) else if (inputLower.length <= 4 && nameLower.length >= inputLower.length) { // Check if most characters of input match start of name let matches = 0; for (let i = 0; i < Math.min(inputLower.length, nameLower.length); i++) { if (inputLower[i] === nameLower[i]) { matches++; } } if (matches >= inputLower.length - 1) { // Allow 1 mismatch score = 50; } } // Levenshtein-like simple distance else { const distance = this.simpleEditDistance(inputLower, nameLower); const maxLen = Math.max(inputLower.length, nameLower.length); const similarity = Math.max(0, (maxLen - distance) / maxLen); // Be more lenient with shorter inputs - they often are abbreviations const threshold = inputLower.length <= 4 ? 0.4 : 0.5; if (similarity > threshold) { score = Math.floor(similarity * 50); } } if (score > 0) { suggestions.push({ name, score }); } } // Sort by score (highest first) and return top suggestions return suggestions .sort((a, b) => b.score - a.score) .slice(0, maxSuggestions) .map(s => s.name); }
  • NLP pattern registration that maps natural language like 'switch to project X' to the 'switch_project' tool.
    { pattern: /^(switch|change|use).*(project|client|api)/i, tool: 'switch_project', category: 'setup' },

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/JaxonDigital/optimizely-dxp-mcp'

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