UNPKG

@atlas-kitchen/atlas-mcp

Version:

Model Context Protocol server for Atlas restaurant management system - enables Claude to interact with restaurant orders, menus, and reports

176 lines 7.79 kB
import { z } from 'zod'; import { saveCache, loadCache, clearCache } from '../token-cache.js'; const SwitchMerchantSchema = z.object({ merchant: z.string(), outletId: z.string().optional(), }); export function createAuthTools(client, authManager, reauthenticate) { return [ { name: 'atlas_switch_merchant', description: 'Switch active merchant context. Accepts a merchant name, identifier, or ID - fuzzy matching is supported. Optionally set an outlet ID for POS operations.', inputSchema: { type: 'object', properties: { merchant: { type: 'string', description: 'Merchant name, identifier, or ID to switch to (fuzzy matched)' }, outletId: { type: 'string', description: 'Outlet ID (optional)' }, }, required: ['merchant'], }, handler: async (input) => { const { merchant, outletId } = SwitchMerchantSchema.parse(input); try { const merchants = await client.getMerchants(); const needle = merchant.toLowerCase(); // Try exact match first (id or identifier), then fuzzy name match const match = merchants.find((m) => m.id === merchant || m.identifier === merchant || m.identifier?.toLowerCase() === needle || m.name?.toLowerCase() === needle) || merchants.find((m) => m.name?.toLowerCase().includes(needle) || m.identifier?.toLowerCase().includes(needle) || m.brandAndEntityNames?.some((b) => b.toLowerCase().includes(needle))); if (!match) { return { success: false, error: `No merchant matching "${merchant}". Available merchants: ${merchants.map((m) => `${m.name} (${m.identifier})`).join(', ')}`, }; } authManager.setMerchantContext(match.identifier, outletId); // Persist context to cache const tokens = authManager.getTokens(); if (tokens) { saveCache({ accessToken: tokens.accessToken, refreshToken: tokens.refreshToken, merchantId: match.identifier, outletId: outletId, }); } return { success: true, message: `Switched to merchant: ${match.name} (${match.identifier})`, context: { merchantId: match.id, merchantName: match.name, merchantIdentifier: match.identifier, outletId: authManager.getOutletId(), }, }; } catch (error) { return { success: false, error: error.message || 'Failed to switch merchant', }; } }, }, { name: 'atlas_list_merchants', description: 'List all merchants the authenticated user can access, showing each merchant\'s name, identifier, and ID. Use this to find the right merchant before calling atlas_switch_merchant.', inputSchema: { type: 'object', properties: {}, }, handler: async () => { try { const merchants = await client.getMerchants(); const currentMerchantId = authManager.getMerchantId(); return { success: true, currentMerchantId, merchants: merchants.map((m) => ({ id: m.id, name: m.name, identifier: m.identifier, brandAndEntityNames: m.brandAndEntityNames, })), }; } catch (error) { return { success: false, error: error.message || 'Failed to list merchants', }; } }, }, { name: 'atlas_list_outlets', description: 'List all outlets for the current merchant, showing each outlet\'s id, identifier, label, archived status, and config. Use this to find outlet IDs for operations that require a specific outlet context.', inputSchema: { type: 'object', properties: {}, }, handler: async () => { try { const outlets = await client.getOutlets(); return { success: true, outlets, }; } catch (error) { return { success: false, error: error.message || 'Failed to list outlets', }; } }, }, { name: 'atlas_reauth', description: 'Force re-authentication by clearing all cached tokens and merchant context, then re-authenticating with the API key. Use this when API calls fail due to stale or expired tokens.', inputSchema: { type: 'object', properties: {}, }, handler: async () => { try { authManager.clear(); clearCache(); const ok = await reauthenticate(); if (ok) { return { success: true, message: 'Re-authenticated successfully. Merchant context was cleared — use atlas_switch_merchant to set it again.', }; } return { success: false, error: 'Re-authentication failed. Check that ATLAS_API_KEY is set and valid.', }; } catch (error) { return { success: false, error: error.message || 'Re-authentication failed', }; } }, }, { name: 'atlas_auth_status', description: 'Show current authentication state, active merchant ID, outlet ID, and whether cached tokens exist. Use this to verify which merchant/outlet context is active before making API calls.', inputSchema: { type: 'object', properties: {}, }, handler: async () => { const authenticated = authManager.isAuthenticated(); const merchantId = authManager.getMerchantId(); const outletId = authManager.getOutletId(); const cached = loadCache(); return { success: true, authenticated, merchantId, outletId, hasCachedTokens: cached !== null, hasCachedContext: cached?.merchantId != null, }; }, }, ]; } //# sourceMappingURL=auth.js.map