UNPKG

@grubtech/integration-agent

Version:

One-command installer that sets up the complete Grubtech Integration Agent (MCP server + AI agent personas) for Claude Code to help developers build restaurant and POS integrations.

331 lines (313 loc) 15.4 kB
import { promises as fs } from 'fs'; import { join, dirname } from 'path'; import { homedir } from 'os'; import { createRequire } from 'module'; import { exec } from 'child_process'; import { promisify } from 'util'; const execAsync = promisify(exec); /** * Initializes the Grubtech Integration Agent * * This command sets up everything needed to use the MCP server with Claude Code: * 1. Verifies Claude Code is installed (exits with error if not found) * 2. Creates cache directory for storing scraped documentation * 3. Registers MCP server using 'claude mcp add' command (requires claude CLI in PATH) * 4. Installs agent persona YAML files to project's .claude/grubtech/agents/ directory as subagents * * Users only need to run this once: npx @grubtech/integration-agent init */ export async function initCommand() { console.log('Initializing Grubtech Integration Agent...\n'); // Step 1: Verify Claude Code is installed console.log('[1/5] Checking for Claude Code installation...'); const claudeConfigPath = getClaudeConfigPath(); try { await fs.access(claudeConfigPath); console.log(' ✓ Claude Code found\n'); } catch { console.error(' ✗ Claude Code is not installed!\n'); console.error('This tool requires Claude Code to be installed on your system.\n'); console.error('Download Claude Code from: https://claude.ai/download\n'); console.error('After installing Claude Code, run this command again:'); console.error(' npx @grubtech/integration-agent init\n'); process.exit(1); } // Step 2: Create cache directory (global) and examples directory (local) // Cache: Global storage for scraped Grubtech documentation (avoids repeated downloads) // Examples: Local project-specific API and webhook examples console.log('[2/5] Creating cache directory...'); const grubtechDir = join(homedir(), '.grubtech'); const cacheDir = join(grubtechDir, 'cache'); await fs.mkdir(join(cacheDir, 'docs'), { recursive: true }); console.log(' ✓ Cache directory created at ~/.grubtech/cache/\n'); // Step 3: Install Grubtech Integration (BMAD-METHOD pattern) console.log('[3/5] Installing Grubtech Integration files...'); const grubtechIntegrationDir = join(process.cwd(), '.grubtech-integration'); await installGrubtechIntegration(grubtechIntegrationDir); // Step 4: Configure MCP server in Claude Code using the claude CLI // This registers the MCP server with identifier 'grubtech-integration-support' // Syntax: claude mcp add --transport stdio <name> -- <command> [args...] console.log('[4/5] Configuring MCP server...'); // First, try to remove existing MCP server (ignore errors if it doesn't exist) try { await execAsync('claude mcp remove grubtech-integration-support'); console.log(' ✓ Removed existing MCP server configuration'); } catch { // Server doesn't exist, that's fine } // Use node to import the package directly (works reliably on all platforms) // This avoids npx bin entry issues on Windows with scoped packages const mcpCommand = `claude mcp add --transport stdio grubtech-integration-support -- node --input-type=module --eval "await import('@grubtech/integration-mcp-server')"`; try { await execAsync(mcpCommand); console.log(' ✓ MCP server registered with Claude Code\n'); } catch (error) { // Check if it's just an "already exists" error if (error.message.includes('already exists')) { console.log(' ⚠ MCP server already configured (skipping)\n'); } else { console.error(' ✗ Failed to register MCP server!\n'); console.error('The "claude" CLI command is not available or failed to execute.\n'); console.error('Please ensure:'); console.error(' 1. Claude Code is running'); console.error(' 2. The "claude" command is available in your PATH'); console.error(' 3. You have the latest version of Claude Code\n'); console.error('Error details:', error.message, '\n'); console.error('For manual setup, see: https://docs.claude.com/en/docs/claude-code/mcp\n'); console.error('Continuing with agent persona installation...\n'); } } // Step 5: Link to Claude Code console.log('[5/5] Linking agents and commands to Claude Code...'); await linkToClaudeCode(process.cwd(), grubtechIntegrationDir); // Step 6: Display success message console.log('\n✓ Setup complete!\n'); console.log('Installed components:'); console.log(' • MCP Server: @grubtech/integration-mcp-server'); console.log(' • Grubtech Integration: ./.grubtech-integration/'); console.log(' - agents/ (3 AI agents: BA, Developer, Assistant)'); console.log(' - examples/ (43 API & webhook examples)'); console.log(' - postman-collections/ (3 collections + guide)'); console.log(' - commands/ (3 slash commands)'); console.log(' - docs/ (getting started guide)'); console.log(' • Claude Code: .claude/agents/ and .claude/commands/ (linked)\n'); console.log('Next steps:'); console.log(' 1. Restart Claude Code'); console.log(' 2. Use slash commands to activate agents:'); console.log(' /grubtech-ba - Business Analyst (planning, requirements)'); console.log(' /grubtech-dev - Developer (technical implementation)'); console.log(' /grubtech-assistant - Integration Assistant (technical support, architecture)'); console.log(' 3. Or ask: "How do I authenticate with Grubtech APIs?"\n'); } /** * Installs Grubtech Integration following BMAD-METHOD pattern * * Creates structured directory: grubtech-integration/ * - agents/ - AI agent personas * - examples/ - API & webhook examples * - commands/ - Slash commands * - docs/ - Documentation */ async function installGrubtechIntegration(baseDir) { try { // Use Node's module resolution to find the integration-personas package const require = createRequire(import.meta.url); const personasPackagePath = require.resolve('@grubtech/integration-personas/package.json'); const personasSourceDir = dirname(personasPackagePath); // Create directory structure await fs.mkdir(join(baseDir, 'agents'), { recursive: true }); await fs.mkdir(join(baseDir, 'examples'), { recursive: true }); await fs.mkdir(join(baseDir, 'postman-collections'), { recursive: true }); await fs.mkdir(join(baseDir, 'commands'), { recursive: true }); await fs.mkdir(join(baseDir, 'docs'), { recursive: true }); // Install agents const agentFiles = [ { source: 'ba-agent.md', target: 'business-analyst.md', name: 'Business Analyst' }, { source: 'developer-agent.md', target: 'developer.md', name: 'Developer' }, { source: 'integration-assistant-agent.md', target: 'integration-assistant.md', name: 'Integration Assistant' }, ]; for (const agent of agentFiles) { await fs.copyFile(join(personasSourceDir, agent.source), join(baseDir, 'agents', agent.target)); } console.log(' ✓ Agents installed (3 files)'); // Install commands const commandFiles = [ { source: 'business-analyst-command.md', target: 'grubtech-ba.md' }, { source: 'developer-command.md', target: 'grubtech-dev.md' }, { source: 'integration-assistant-command.md', target: 'grubtech-assistant.md' }, ]; for (const cmd of commandFiles) { await fs.copyFile(join(personasSourceDir, cmd.source), join(baseDir, 'commands', cmd.target)); } console.log(' ✓ Commands installed (3 files)'); // Install examples const examplesSourceDir = join(personasSourceDir, 'examples'); await copyRecursive(examplesSourceDir, join(baseDir, 'examples')); console.log(' ✓ Examples installed (43 files across 3 API suites)'); // Install Postman collections const postmanSourceDir = join(personasSourceDir, 'postman-collections'); await copyRecursive(postmanSourceDir, join(baseDir, 'postman-collections')); console.log(' ✓ Postman collections installed (3 webhook collections + testing guide)'); // Create README in docs/ const readme = `# Grubtech Integration This directory contains everything you need to integrate with Grubtech APIs. ## Structure - **agents/** - AI agent personas for Claude Code - business-analyst.md - Requirements gathering and planning - developer.md - Code generation and implementation - integration-assistant.md - Technical support and architecture - **examples/** - Complete API & webhook examples (43 total) - order-platform/ - For food aggregators (6 APIs + 9 webhooks) - pos/ - For POS systems (13 APIs + 6 webhooks) - delivery/ - For logistics providers (1 API + 3 webhooks) - README.md - Navigation guide and documentation - **postman-collections/** - Webhook testing collections (RECOMMENDED) - postman-order-platform-webhooks.json - Order Platform webhooks collection - postman-pos-webhooks.json - POS webhooks collection - postman-delivery-webhooks.json - Delivery webhooks collection - README.md - Complete guide for testing webhooks with Postman mock servers - **commands/** - Slash commands for Claude Code - /grubtech-ba - Quick access to Business Analyst - /grubtech-dev - Quick access to Developer - /grubtech-assistant - Quick access to Integration Assistant ## Getting Started 1. **Test Webhooks First** (RECOMMENDED): Use Postman mock servers to see actual webhook payloads - See: postman-collections/README.md for step-by-step guide - Import the collection for your integration type - Create mock server and register URLs in Developer Portal - See exact webhook payloads before writing any code 2. **Use AI Agents**: Restart Claude Code and use slash commands - /grubtech-ba - For planning and requirements - /grubtech-dev - For code generation - /grubtech-assistant - For technical support 3. **Reference Examples**: All APIs and webhooks have complete examples - See examples/ directory for cURL commands and payloads ## Examples All API calls and webhooks have complete examples with: - cURL commands - Request/response payloads - Authentication headers - Implementation notes - Field descriptions See examples/README.md for full documentation. ## Postman Collections Test webhook configurations BEFORE coding using Postman mock servers: - Zero infrastructure required - See real webhook payloads - Validate Developer Portal configuration - Plan database schema based on actual data See postman-collections/README.md for complete testing guide. ## Resources - Developer Portal: https://developer.grubtech.com - API Documentation: https://docs.grubtech.io - Support: support@grubtech.com `; await fs.writeFile(join(baseDir, 'docs', 'README.md'), readme); console.log(' ✓ Documentation created'); // Write version file await fs.writeFile(join(baseDir, '.grubtech-version'), '1.0.0'); console.log(' ✓ Version tracking initialized\n'); } catch (error) { console.error(' ✗ Failed to install Grubtech Integration'); console.error(` Error: ${error.message}\n`); throw error; } } /** * Recursively copies a directory */ async function copyRecursive(source, target) { await fs.mkdir(target, { recursive: true }); const entries = await fs.readdir(source, { withFileTypes: true }); for (const entry of entries) { const sourcePath = join(source, entry.name); const targetPath = join(target, entry.name); if (entry.isDirectory()) { await copyRecursive(sourcePath, targetPath); } else { await fs.copyFile(sourcePath, targetPath); } } } /** * Links Grubtech Integration files to Claude Code directories * * Creates copies in .claude/ directories so Claude Code can access them: * - Agents from grubtech-integration/agents/ -> .claude/agents/ * - Commands from grubtech-integration/commands/ -> .claude/commands/ */ async function linkToClaudeCode(projectPath, grubtechDir) { try { // Create .claude directories const claudeAgentsDir = join(projectPath, '.claude', 'agents'); const claudeCommandsDir = join(projectPath, '.claude', 'commands'); await fs.mkdir(claudeAgentsDir, { recursive: true }); await fs.mkdir(claudeCommandsDir, { recursive: true }); // Link agents const agentMappings = [ { source: 'business-analyst.md', target: 'grubtech-business-analyst.md', name: 'Business Analyst' }, { source: 'developer.md', target: 'grubtech-developer.md', name: 'Developer' }, { source: 'integration-assistant.md', target: 'grubtech-integration-assistant.md', name: 'Integration Assistant' }, ]; for (const agent of agentMappings) { const sourcePath = join(grubtechDir, 'agents', agent.source); const targetPath = join(claudeAgentsDir, agent.target); try { await fs.copyFile(sourcePath, targetPath); console.log(` ✓ ${agent.name} agent`); } catch (error) { console.warn(` ⚠ Failed to link ${agent.name}: ${error.message}`); } } // Link commands const commandMappings = [ { source: 'grubtech-ba.md', name: '/grubtech-ba' }, { source: 'grubtech-dev.md', name: '/grubtech-dev' }, { source: 'grubtech-assistant.md', name: '/grubtech-assistant' }, ]; for (const cmd of commandMappings) { const sourcePath = join(grubtechDir, 'commands', cmd.source); const targetPath = join(claudeCommandsDir, cmd.source); try { await fs.copyFile(sourcePath, targetPath); console.log(` ✓ ${cmd.name}`); } catch (error) { console.warn(` ⚠ Failed to link ${cmd.name}: ${error.message}`); } } console.log(' ✓ All links created successfully\n'); } catch (error) { console.error(' ✗ Failed to link to Claude Code'); console.error(` Error: ${error.message}\n`); throw error; } } /** * Gets the Claude Code configuration directory path * * Different operating systems store Claude config in different locations: * - Windows: %APPDATA%\Claude\config * - macOS: ~/Library/Application Support/Claude/config * - Linux: ~/.config/claude */ function getClaudeConfigPath() { const home = homedir(); switch (process.platform) { case 'win32': return join(home, 'AppData', 'Roaming', 'Claude', 'config'); case 'darwin': return join(home, 'Library', 'Application Support', 'Claude', 'config'); default: return join(home, '.config', 'claude'); } } //# sourceMappingURL=init-command.js.map