# Task ID: 21

**Title:** Implement Guided MCP Server Setup Wizard with Credential Flow

**Status:** cancelled

**Dependencies:** None

**Priority:** medium

**Description:** Build an interactive setup wizard that guides users through MCP server configuration, including browser-based OAuth flows, API token generation pages, and step-by-step credential setup with secure storage.

**Details:**

Create src/cli/src/commands/setup/ with guided setup flows:

**Setup Wizard Architecture:**

1. **Setup Command** (setup.ts):
   ```bash
   mcpctl setup <server-type>  # e.g., mcpctl setup slack
   ```
   - Fetches server definition from mcpd (envTemplate, setupGuide)
   - Runs appropriate setup flow based on server type

2. **Setup Flows** (flows/):
   - oauth-flow.ts: For OAuth-based services (Slack, GitHub)
   - api-key-flow.ts: For API key services (Jira, OpenAI)
   - custom-flow.ts: For services with unique setup

3. **OAuth Flow Handler** (flows/oauth-flow.ts):
   ```typescript
   async function runOAuthFlow(serverType: string, config: OAuthConfig): Promise<Credentials> {
     // 1. Start local HTTP server to receive OAuth callback
     const callbackServer = await startCallbackServer(config.callbackPort);
     
     // 2. Open browser to OAuth authorization URL
     const authUrl = buildOAuthUrl(config);
     console.log(`Opening browser to authorize ${serverType}...`);
     await open(authUrl);  // Uses 'open' package
     
     // 3. Wait for callback with auth code
     const authCode = await callbackServer.waitForCode();
     
     // 4. Exchange code for tokens
     const tokens = await exchangeCodeForTokens(authCode, config);
     
     // 5. Securely store tokens via mcpd
     await mcpdClient.storeCredentials(serverType, tokens);
     
     return tokens;
   }
   ```

4. **API Key Flow Handler** (flows/api-key-flow.ts):
   ```typescript
   async function runApiKeyFlow(serverType: string, config: ApiKeyConfig): Promise<Credentials> {
     // 1. Display setup instructions
     console.log(chalk.bold(`\nSetting up ${serverType}...\n`));
     console.log(config.setupGuide);  // Markdown rendered to terminal
     
     // 2. Open browser to API key generation page
     if (config.apiKeyUrl) {
       const shouldOpen = await confirm('Open browser to generate API key?');
       if (shouldOpen) await open(config.apiKeyUrl);
     }
     
     // 3. Prompt for required credentials
     const credentials: Record<string, string> = {};
     for (const envVar of config.requiredEnvVars) {
       credentials[envVar.name] = await password({
         message: `Enter ${envVar.description}:`,
         mask: '*'
       });
     }
     
     // 4. Validate credentials (test API call)
     const valid = await validateCredentials(serverType, credentials);
     if (!valid) throw new Error('Invalid credentials');
     
     // 5. Store securely via mcpd
     await mcpdClient.storeCredentials(serverType, credentials);
     
     return credentials;
   }
   ```

5. **Credential Storage** (src/mcpd/src/services/credentials.ts):
   - Encrypt credentials at rest using AES-256-GCM
   - Master key from environment (MCPCTL_MASTER_KEY) or Vault integration
   - Store encrypted credentials in database (McpServer.encryptedCredentials new field)
   - Never log or expose credentials in API responses

**Server-Specific Setup Guides (seed data):**

- **Slack:**
  - Guide: "1. Go to api.slack.com/apps, 2. Create app, 3. Add OAuth scopes..."
  - OAuth flow with workspace authorization
  - Scopes: channels:read, users:read, chat:write

- **Jira:**
  - Guide: "1. Go to id.atlassian.com/manage-profile/security/api-tokens"
  - API key flow with URL, email, token
  - Test: GET /rest/api/3/myself

- **GitHub:**
  - Guide: "1. Go to github.com/settings/tokens"
  - API key flow OR GitHub App OAuth
  - Scopes: repo, read:org

- **Terraform Docs:**
  - No credentials needed
  - Setup verifies terraform CLI installed

**Profile Creation After Setup:**
```bash
mcpctl setup slack
# After successful setup:
# "Slack configured! Create a profile for this server?"
# > Profile name: slack-readonly
# > Read-only mode? Yes
# Profile 'slack-readonly' created and linked to Slack server.
```

**Test Strategy:**

Unit test each flow handler with mocked external services. Test OAuth callback server starts and receives codes correctly. Test API key validation with mock API responses. Integration test with actual services using test accounts (Slack test workspace, GitHub test token). Test credential encryption/decryption roundtrip. Test setup guide rendering (markdown to terminal). E2E test: run `mcpctl setup slack`, mock browser open, simulate OAuth callback, verify credentials stored and profile created. Test error recovery: invalid credentials, timeout waiting for callback, network failures. Security test: verify credentials never logged, encrypted at rest, not in API responses.
