Skip to content
  • navigation title: Claude 4×Copilot Complete Implementation Guide: Mastering MCP, CLI, and Agent Mode in Practice [2025 Technical Deep Dive] description: Implementation details for integrating Claude Sonnet 4 and GitHub Copilot. Complete practical guide covering MCP construction, custom CLI command creation, Agent Mode utilization, and team management dashboard development. date: 2025-11-13 tags:
  • Claude-4-Implementation
  • MCP-Protocol
  • Claude-Code-CLI
  • GitHub-Copilot-Agent
  • AI-Development-Practice
  • 2025-Latest
  • claude-4-implementation
  • protocol-deep-dive categories:
  • AI Development & Automation
  • 🤖 AI Development & Automation author: Claude Code status: technical-guide

Claude Code Complete Guide

Claude 4×Copilot Complete Implementation Guide: Mastering MCP, CLI, and Agent Mode in Practice [2025 Technical Deep Dive]

Introduction

This article provides technical implementation details to actually achieve the 5.5x development efficiency improvement introduced in the Claude 4×GitHub Copilot CLI Revolution article.

Beyond conceptual explanations, we provide a complete implementation guide including practical code examples, configuration files, and troubleshooting.

Key Points

  • MCP Server Construction

    Complete implementation of custom Model Context Protocol servers with OAuth 2.0 authentication

  • CLI Extension Development

    Team-specific custom slash commands and workflow automation

  • Agent Mode Utilization

    Building complete automation systems from GitHub Issues to PRs

  • Management Dashboard

    Real-time development metrics visualization and team efficiency optimization

🔧 Complete MCP (Model Context Protocol) Implementation

Basic MCP Server Construction

Node.js MCP Server Implementation

// mcp-server/src/index.ts
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { 
  CallToolRequestSchema,
  ErrorCode,
  ListToolsRequestSchema,
  McpError
} from '@modelcontextprotocol/sdk/types.js';
import { z } from 'zod';

// Tool definition schema
const DatabaseQuerySchema = z.object({
  query: z.string().describe('SQL query to execute'),
  database: z.string().describe('Database name'),
});

const ApiCallSchema = z.object({
  endpoint: z.string().describe('API endpoint URL'),
  method: z.enum(['GET', 'POST', 'PUT', 'DELETE']),
  headers: z.record(z.string()).optional(),
  body: z.any().optional(),
});

class CustomMCPServer {
  private server: Server;
  private dbConnections: Map<string, any> = new Map();

  constructor() {
    this.server = new Server(
      {
        name: 'custom-development-server',
        version: '1.0.0',
      },
      {
        capabilities: {
          tools: {},
          resources: {},
        },
      }
    );

    this.setupHandlers();
  }

  private setupHandlers() {
    // Provide tool list
    this.server.setRequestHandler(ListToolsRequestSchema, async () => {
      return {
        tools: [
          {
            name: 'database_query',
            description: 'Execute SQL queries on connected databases',
            inputSchema: {
              type: 'object',
              properties: {
                query: {
                  type: 'string',
                  description: 'SQL query to execute',
                },
                database: {
                  type: 'string',
                  description: 'Target database name',
                },
              },
              required: ['query', 'database'],
            },
          },
          {
            name: 'api_call',
            description: 'Make HTTP API calls to external services',
            inputSchema: {
              type: 'object',
              properties: {
                endpoint: { type: 'string' },
                method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'DELETE'] },
                headers: { type: 'object' },
                body: { type: 'object' },
              },
              required: ['endpoint', 'method'],
            },
          },
          {
            name: 'deployment_status',
            description: 'Check deployment status across environments',
            inputSchema: {
              type: 'object',
              properties: {
                environment: {
                  type: 'string',
                  enum: ['development', 'staging', 'production'],
                },
                service: { type: 'string' },
              },
              required: ['environment'],
            },
          },
        ],
      };
    });

    // Tool execution handler
    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
      const { name, arguments: args } = request.params;

      try {
        switch (name) {
          case 'database_query':
            return await this.handleDatabaseQuery(args);
          case 'api_call':
            return await this.handleApiCall(args);
          case 'deployment_status':
            return await this.handleDeploymentStatus(args);
          default:
            throw new McpError(
              ErrorCode.MethodNotFound,
              `Tool ${name} not found`
            );
        }
      } catch (error) {
        if (error instanceof McpError) {
          throw error;
        }
        throw new McpError(
          ErrorCode.InternalError,
          `Tool execution failed: ${error}`
        );
      }
    });
  }

  private async handleDatabaseQuery(args: any) {
    const { query, database } = DatabaseQuerySchema.parse(args);

    // Database connection (actual implementation should use connection pooling)
    const connection = await this.getDbConnection(database);
    const results = await connection.query(query);

    return {
      content: [
        {
          type: 'text',
          text: `Query executed successfully on ${database}:\n${JSON.stringify(results, null, 2)}`,
        },
      ],
    };
  }

  private async handleApiCall(args: any) {
    const { endpoint, method, headers = {}, body } = ApiCallSchema.parse(args);

    const response = await fetch(endpoint, {
      method,
      headers: {
        'Content-Type': 'application/json',
        ...headers,
      },
      body: body ? JSON.stringify(body) : undefined,
    });

    const responseData = await response.json();

    return {
      content: [
        {
          type: 'text',
          text: `API call to ${endpoint} completed:\nStatus: ${response.status}\nResponse: ${JSON.stringify(responseData, null, 2)}`,
        },
      ],
    };
  }

  private async handleDeploymentStatus(args: any) {
    const { environment, service } = args;

    // Example integration with Kubernetes API or Docker API
    const deploymentInfo = await this.checkDeploymentStatus(environment, service);

    return {
      content: [
        {
          type: 'text',
          text: `Deployment Status for ${environment}:\n${JSON.stringify(deploymentInfo, null, 2)}`,
        },
      ],
    };
  }

  private async getDbConnection(database: string) {
    // Actual implementation requires connection pooling
    if (!this.dbConnections.has(database)) {
      const { createConnection } = await import('mysql2/promise');
      const connection = await createConnection({
        host: process.env.DB_HOST,
        user: process.env.DB_USER,
        password: process.env.DB_PASSWORD,
        database: database,
      });
      this.dbConnections.set(database, connection);
    }
    return this.dbConnections.get(database);
  }

  private async checkDeploymentStatus(environment: string, service?: string) {
    // Check Kubernetes cluster status
    const k8s = await import('@kubernetes/client-node');
    const kc = new k8s.KubeConfig();
    kc.loadFromDefault();

    const k8sApi = kc.makeApiClient(k8s.AppsV1Api);

    if (service) {
      const deployment = await k8sApi.readNamespacedDeployment(service, environment);
      return {
        name: deployment.body.metadata?.name,
        replicas: deployment.body.status?.replicas,
        readyReplicas: deployment.body.status?.readyReplicas,
        updatedReplicas: deployment.body.status?.updatedReplicas,
      };
    } else {
      const deployments = await k8sApi.listNamespacedDeployment(environment);
      return deployments.body.items.map(d => ({
        name: d.metadata?.name,
        replicas: d.status?.replicas,
        readyReplicas: d.status?.readyReplicas,
      }));
    }
  }

  async start() {
    const transport = new StdioServerTransport();
    await this.server.connect(transport);
    console.log('Custom MCP Server running on stdio');
  }
}

// Start server
const server = new CustomMCPServer();
server.start().catch(console.error);

MCP Configuration File

// ~/.claude/mcp_settings.json
{
  "mcpServers": {
    "custom-development-server": {
      "command": "node",
      "args": ["/path/to/mcp-server/dist/index.js"],
      "env": {
        "DB_HOST": "localhost",
        "DB_USER": "developer",
        "DB_PASSWORD": "${{ secrets.DB_PASSWORD }}",
        "KUBECONFIG": "/home/user/.kube/config"
      }
    },
    "github-integration": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${{ secrets.GITHUB_TOKEN }}"
      }
    }
  },
  "oauth": {
    "enabled": true,
    "providers": {
      "github": {
        "client_id": "${{ vars.GITHUB_CLIENT_ID }}",
        "client_secret": "${{ secrets.GITHUB_CLIENT_SECRET }}",
        "scope": "repo,read:org,workflow"
      }
    }
  }
}

MCP Server with OAuth 2.0 Authentication

// mcp-server/src/auth.ts
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
import express from 'express';
import { OAuth2Server } from 'oauth2-server';

class AuthenticatedMCPServer {
  private app: express.Application;
  private mcpServer: Server;
  private oauth: OAuth2Server;

  constructor() {
    this.app = express();
    this.setupOAuth();
    this.setupMCPServer();
  }

  private setupOAuth() {
    this.oauth = new OAuth2Server({
      model: {
        // OAuth2 server model implementation
        getAccessToken: async (token: string) => {
          // Token validation logic
          const tokenData = await this.validateToken(token);
          return {
            accessToken: token,
            accessTokenExpiresAt: new Date(tokenData.expires),
            user: tokenData.user,
            client: tokenData.client,
          };
        },

        getClient: async (clientId: string, clientSecret: string) => {
          // Client authentication
          return {
            id: clientId,
            redirectUris: ['http://localhost:3000/callback'],
            grants: ['authorization_code', 'refresh_token'],
          };
        },

        saveToken: async (token: any, client: any, user: any) => {
          // Save token
          await this.saveTokenToDatabase(token, client, user);
          return {
            ...token,
            client,
            user,
          };
        },
      },
    });
  }

  private setupMCPServer() {
    this.mcpServer = new Server(
      {
        name: 'authenticated-mcp-server',
        version: '1.0.0',
      },
      {
        capabilities: {
          tools: {},
          resources: {},
        },
      }
    );

    // Implementation of tools requiring authentication
    this.mcpServer.setRequestHandler(CallToolRequestSchema, async (request, { meta }) => {
      // Get authentication info from request metadata
      const authToken = meta?.authorization;
      if (!authToken) {
        throw new McpError(ErrorCode.InvalidRequest, 'Authentication required');
      }

      // Token validation
      const isValid = await this.validateRequestToken(authToken);
      if (!isValid) {
        throw new McpError(ErrorCode.InvalidRequest, 'Invalid authentication token');
      }

      // Normal tool processing
      return await this.executeAuthenticatedTool(request.params);
    });
  }

  private async validateToken(token: string) {
    // JWT verification or database lookup
    // Implementation details depend on environment
    return {
      expires: Date.now() + 3600000, // 1 hour
      user: { id: 'user123', name: 'Developer' },
      client: { id: 'claude-code-cli' },
    };
  }

  private async saveTokenToDatabase(token: any, client: any, user: any) {
    // Save token information to database
    console.log('Token saved:', { token, client, user });
  }

  private async validateRequestToken(token: string): Promise<boolean> {
    try {
      await this.oauth.authenticate(new express.Request() as any);
      return true;
    } catch {
      return false;
    }
  }

  async start(port: number = 3001) {
    // OAuth2 endpoints
    this.app.post('/oauth/token', async (req, res) => {
      try {
        const token = await this.oauth.token(req, res);
        res.json(token);
      } catch (err) {
        res.status(500).json({ error: err.message });
      }
    });

    // MCP SSE endpoint
    this.app.get('/mcp/sse', async (req, res) => {
      // Server-Sent Events implementation
      const transport = new SSEServerTransport(res);
      await this.mcpServer.connect(transport);
    });

    this.app.listen(port, () => {
      console.log(`Authenticated MCP Server running on port ${port}`);
    });
  }
}

// Start authenticated server
const authServer = new AuthenticatedMCPServer();
authServer.start(3001);

🚀 Claude Code CLI Custom Command Implementation

Project-Specific Slash Commands

Deployment Automation Command

# .claude/commands/deploy-stack.md
# Full Stack Deployment

Please deploy the full-stack application following these steps:

## Prerequisites Check
1. Verify Docker Compose file syntax
2. Check existence of environment variable file (.env)
3. Confirm database migration readiness

## Deployment Steps
1. **Frontend Build**
   ```bash
   cd frontend && npm run build:production
   ```

2. **Backend Image Creation**
   ```bash
   docker build -t myapp-backend:latest ./backend
   ```

3. **Database Migration**
   ```bash
   docker-compose exec db mysql -u root -p myapp < migrations/latest.sql
   ```

4. **Service Startup**
   ```bash
   docker-compose up -d --build
   ```

5. **Health Check Execution**
   - Frontend: http://localhost:3000/health
   - Backend API: http://localhost:8000/api/health
   - Database connection verification

## Post-Deployment Verification
- Check all service startup status
- Verify no log errors
- Perform basic functionality tests

After deployment completion, please conduct production environment verification.

Team Development Workflow

# .claude/commands/team-workflow.md
# Team Development Workflow Execution

## Git Workflow Management
Check current branch status and execute the following workflow:

### 1. Current Status Check
```bash
git status
git branch -a
git log --oneline -10

2. Development Branch Cleanup

  • Delete merged branches
  • Sync with remote branches
  • Resolve conflicts if any

3. Pull Request Preparation

  • Review and improve commit messages
  • Check test coverage
  • Apply code review checklist

4. CI/CD Pipeline Status

Check GitHub Actions ${{ workflow.status }}: - Build status - Test results - Deployment status

5. Team Member Notifications

  • Send Slack notifications
  • Create review requests
  • Update progress status

This workflow enhances team development efficiency and quality.

#### Performance Audit Command

```bash
# .claude/commands/performance-audit.md
# Application Performance Audit

## Execution Content
Perform the following comprehensive performance diagnostics:

### 1. Frontend Analysis
```bash
# Lighthouse audit
npx lighthouse http://localhost:3000 --output=json --output-path=./reports/lighthouse.json

# Bundle size analysis
npx webpack-bundle-analyzer build/static/js/*.js

2. Backend Performance Measurement

# API response time measurement
curl -w "@curl-format.txt" -o /dev/null -s http://localhost:8000/api/users

# Database query analysis
mysql -u root -pPASSWORD -e "SHOW PROCESSLIST;" myapp

3. Infrastructure Monitoring

# Docker container resource usage
docker stats --no-stream

# System resource check
htop
iotop

4. Optimization Proposals

Based on diagnostic results, we will provide the following improvement suggestions: - Loading speed improvement - Memory usage optimization - Database query improvement - Cache strategy review

After diagnosis completion, we will provide a detailed report and improvement roadmap.

### CLI Extension Configuration Implementation

```json
// .claude/settings.json
{
  "commands": {
    "deploy-stack": {
      "description": "Complete deployment of full-stack application",
      "file": ".claude/commands/deploy-stack.md",
      "requirements": ["docker", "docker-compose", "npm"],
      "environment_variables": [
        "DB_PASSWORD",
        "API_SECRET_KEY",
        "FRONTEND_BUILD_PATH"
      ]
    },
    "team-workflow": {
      "description": "Team development workflow management",
      "file": ".claude/commands/team-workflow.md",
      "requirements": ["git", "gh"],
      "integrations": ["github", "slack"]
    },
    "performance-audit": {
      "description": "Comprehensive performance diagnostics",
      "file": ".claude/commands/performance-audit.md",
      "requirements": ["lighthouse", "curl", "mysql-client"],
      "output_formats": ["json", "html", "markdown"]
    }
  },
  "hooks": {
    "PreCommand": [
      {
        "name": "Environment Check",
        "condition": {"commands": ["deploy-stack"]},
        "hooks": [
          {"type": "command", "command": "docker --version"},
          {"type": "command", "command": "docker-compose --version"}
        ]
      }
    ],
    "PostCommand": [
      {
        "name": "Cleanup",
        "condition": {"commands": ["performance-audit"]},
        "hooks": [
          {"type": "command", "command": "rm -f /tmp/perf-*.log"}
        ]
      }
    ]
  },
  "integrations": {
    "github": {
      "token": "${{ secrets.GITHUB_TOKEN }}",
      "webhooks": {
        "pull_request": "http://localhost:3000/webhooks/github/pr",
        "deployment": "http://localhost:3000/webhooks/github/deploy"
      }
    },
    "slack": {
      "webhook_url": "${{ secrets.SLACK_WEBHOOK_URL }}",
      "channels": {
        "deployments": "#deployments",
        "alerts": "#alerts",
        "general": "#development"
      }
    }
  }
}

🤖 Complete GitHub Copilot Agent Mode Utilization

Automatic Issue Resolution System

// github-automation/src/agent-orchestrator.ts
import { Octokit } from '@octokit/rest';
import { createAppAuth } from '@octokit/auth-app';

interface IssueAnalysis {
  type: 'bug' | 'feature' | 'enhancement' | 'documentation';
  complexity: 'simple' | 'medium' | 'complex';
  estimatedHours: number;
  requiredSkills: string[];
  dependencies: string[];
}

interface ImplementationPlan {
  steps: ImplementationStep[];
  totalEstimate: number;
  riskFactors: string[];
  testStrategy: string;
}

interface ImplementationStep {
  id: string;
  description: string;
  type: 'analysis' | 'design' | 'implementation' | 'testing' | 'documentation';
  estimatedMinutes: number;
  dependencies: string[];
  output: string;
}

class GitHubAgentOrchestrator {
  private octokit: Octokit;
  private claudeAgent: any; // Claude API client

  constructor() {
    this.octokit = new Octokit({
      authStrategy: createAppAuth,
      auth: {
        appId: process.env.GITHUB_APP_ID,
        privateKey: process.env.GITHUB_PRIVATE_KEY,
        installationId: process.env.GITHUB_INSTALLATION_ID,
      },
    });
  }

  async processIssue(owner: string, repo: string, issueNumber: number) {
    // 1. Get issue information
    const issue = await this.octokit.issues.get({
      owner,
      repo,
      issue_number: issueNumber,
    });

    // 2. Analyze issue
    const analysis = await this.analyzeIssue(issue.data);

    // 3. Generate implementation plan
    const plan = await this.generateImplementationPlan(analysis, issue.data);

    // 4. Execute automated implementation
    const implementation = await this.executeImplementation(plan, {
      owner,
      repo,
      issue: issue.data,
    });

    // 5. Create Pull Request
    const pr = await this.createPullRequest(implementation, {
      owner,
      repo,
      issue: issue.data,
    });

    return {
      analysis,
      plan,
      implementation,
      pullRequest: pr,
    };
  }

  private async analyzeIssue(issue: any): Promise<IssueAnalysis> {
    const prompt = `
Issue Title: ${issue.title}
Issue Body: ${issue.body}
Labels: ${issue.labels.map((l: any) => l.name).join(', ')}

Please analyze this GitHub Issue and provide the following information:
1. Issue type (bug/feature/enhancement/documentation)
2. Complexity level (simple/medium/complex)
3. Estimated implementation time (in hours)
4. Required skills and technologies
5. Dependencies and prerequisites

Respond in JSON format.
`;

    const response = await this.claudeAgent.messages.create({
      model: 'claude-4-sonnet-20250514',
      max_tokens: 1000,
      messages: [{ role: 'user', content: prompt }],
    });

    return JSON.parse(response.content[0].text);
  }

  private async generateImplementationPlan(
    analysis: IssueAnalysis,
    issue: any
  ): Promise<ImplementationPlan> {
    const prompt = `
Issue Analysis Results:
${JSON.stringify(analysis, null, 2)}

Issue Details:
Title: ${issue.title}
Body: ${issue.body}

Based on this analysis, please create a detailed implementation plan.
Respond in JSON format including the following elements:

1. Implementation steps (analysis/design/implementation/testing/documentation)
2. Time estimate for each step
3. Dependencies between steps
4. Risk factors
5. Testing strategy

The implementation should progress incrementally, with each step producing verifiable deliverables.
`;

    const response = await this.claudeAgent.messages.create({
      model: 'claude-4-opus-20250514',
      max_tokens: 2000,
      messages: [{ role: 'user', content: prompt }],
    });

    return JSON.parse(response.content[0].text);
  }

  private async executeImplementation(
    plan: ImplementationPlan,
    context: { owner: string; repo: string; issue: any }
  ) {
    const results = [];

    // Execute sequentially based on implementation plan
    for (const step of plan.steps) {
      console.log(`Executing step: ${step.id} - ${step.description}`);

      const stepResult = await this.executeImplementationStep(step, context);
      results.push({
        step,
        result: stepResult,
        timestamp: new Date(),
      });

      // Pass results from previous step to next step
      context['previousResults'] = results;
    }

    return results;
  }

  private async executeImplementationStep(
    step: ImplementationStep,
    context: any
  ) {
    const stepPrompt = `
Implementation Step: ${step.description}
Step Type: ${step.type}
Estimated Time: ${step.estimatedMinutes} minutes

Context:
- Repository: ${context.owner}/${context.repo}
- Issue: ${context.issue.title}
- Previous Step Results: ${JSON.stringify(context.previousResults || [], null, 2)}

Execute this step and return results in the following format:
- Detailed execution description
- Generated code (if applicable)
- Test results (if applicable)
- Handoff items to next step

If actual file operations or API calls are needed, please provide specific commands and code.
`;

    const response = await this.claudeAgent.messages.create({
      model: 'claude-4-sonnet-20250514',
      max_tokens: 4000,
      messages: [
        {
          role: 'user',
          content: stepPrompt,
        },
      ],
      tools: [
        {
          name: 'file_operations',
          description: 'Read, write, and modify files in the repository',
          input_schema: {
            type: 'object',
            properties: {
              operation: { type: 'string', enum: ['read', 'write', 'modify'] },
              path: { type: 'string' },
              content: { type: 'string' },
            },
          },
        },
        {
          name: 'run_tests',
          description: 'Execute test suites',
          input_schema: {
            type: 'object',
            properties: {
              test_type: { type: 'string', enum: ['unit', 'integration', 'e2e'] },
              target: { type: 'string' },
            },
          },
        },
      ],
    });

    return {
      content: response.content[0].text,
      toolResults: response.tool_calls || [],
    };
  }

  private async createPullRequest(implementation: any, context: any) {
    // Extract file changes from implementation results
    const fileChanges = this.extractFileChanges(implementation);

    // Create branch
    const branchName = `feature/issue-${context.issue.number}-auto-implementation`;

    // Create commit
    const commitMessage = `Auto-implement: ${context.issue.title}

Automated implementation based on issue analysis:
- Issue type: ${implementation[0]?.step?.type}
- Estimated complexity: ${implementation[0]?.result?.complexity}

Generated by Claude Agent Mode
Closes #${context.issue.number}`;

    // Create Pull Request
    const pr = await this.octokit.pulls.create({
      owner: context.owner,
      repo: context.repo,
      title: `[Auto-Generated] ${context.issue.title}`,
      head: branchName,
      base: 'main',
      body: this.generatePRDescription(implementation, context.issue),
    });

    return pr.data;
  }

  private extractFileChanges(implementation: any) {
    // Logic to extract file changes from implementation results
    const changes = [];

    for (const result of implementation) {
      if (result.result.toolResults) {
        for (const toolResult of result.result.toolResults) {
          if (toolResult.name === 'file_operations') {
            changes.push({
              path: toolResult.input.path,
              operation: toolResult.input.operation,
              content: toolResult.input.content,
            });
          }
        }
      }
    }

    return changes;
  }

  private generatePRDescription(implementation: any, issue: any): string {
    return `
## Automatic Implementation Resolution

### Issue Overview
- **Issue**: #${issue.number} - ${issue.title}
- **Type**: ${implementation[0]?.result?.type || 'feature'}
- **Complexity**: ${implementation[0]?.result?.complexity || 'medium'}

### Implementation Details
${implementation.map((step: any, index: number) => `
#### Step ${index + 1}: ${step.step.description}
${step.result.content}
`).join('\n')}

### Test Results
${implementation
  .filter((step: any) => step.step.type === 'testing')
  .map((step: any) => step.result.content)
  .join('\n')}

### Checklist
- [x] Implementation complete
- [x] Unit tests executed
- [x] Integration tests executed
- [ ] Code review (manual verification required)
- [ ] Production deployment approval

### Generation Information
- **Generation Time**: ${new Date().toISOString()}
- **Generation Model**: Claude 4 Agent Mode
- **Automation Level**: Full Automation

---
🤖 This Pull Request was automatically generated by Claude Agent Mode.
Please consider merging after manual review.
`;
  }
}

// Usage example
const orchestrator = new GitHubAgentOrchestrator();

// Webhook processing
export async function handleIssueWebhook(payload: any) {
  if (payload.action === 'opened' || payload.action === 'labeled') {
    const { repository, issue } = payload;

    // Only auto-implement if "auto-implement" label exists
    const hasAutoLabel = issue.labels.some((label: any) => 
      label.name === 'auto-implement'
    );

    if (hasAutoLabel) {
      await orchestrator.processIssue(
        repository.owner.login,
        repository.name,
        issue.number
      );
    }
  }
}

Agent Mode Integration Configuration

# .github/workflows/claude-agent-automation.yml
name: Claude Agent Automation

on:
  issues:
    types: [opened, labeled]
  pull_request:
    types: [opened, synchronize]

env:
  CLAUDE_API_KEY: ${{ secrets.CLAUDE_API_KEY }}
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

jobs:
  auto-implement:
    if: contains(github.event.issue.labels.*.name, 'auto-implement')
    runs-on: ubuntu-latest

    steps:
    - name: Checkout Repository
      uses: actions/checkout@v4
      with:
        token: ${{ secrets.GITHUB_TOKEN }}
        fetch-depth: 0

    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: '20'
        cache: 'npm'

    - name: Install Dependencies
      run: |
        npm install @anthropic-ai/sdk @octokit/rest @octokit/auth-app

    - name: Execute Claude Agent
      id: agent-execution
      run: |
        node -e "
        const { handleIssueWebhook } = require('./github-automation/dist/agent-orchestrator.js');
        const payload = ${{ toJson(github.event) }};
        handleIssueWebhook(payload).then(console.log).catch(console.error);
        "

    - name: Report Results
      if: always()
      uses: actions/github-script@v7
      with:
        script: |
          const issueNumber = context.issue.number;
          const comment = `
          🤖 **Claude Agent Mode Execution Results**

          - **Execution Time**: ${new Date().toISOString()}
          - **Status**: ${{ steps.agent-execution.outcome }}
          - **Execution Log**: [Workflow Details](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})

          ${context.eventName === 'issues' ? 'Automatic implementation started.' : 'Reviewing implementation results.'}
          `;

          await github.rest.issues.createComment({
            owner: context.repo.owner,
            repo: context.repo.repo,
            issue_number: issueNumber,
            body: comment
          });

  quality-check:
    if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest

    steps:
    - name: Checkout PR
      uses: actions/checkout@v4
      with:
        ref: ${{ github.head_ref }}

    - name: Claude Code Quality Review
      run: |
        # Quality check using Claude Code CLI
        claude-code "Analyze the code quality of this PR and provide improvement suggestions" \
          --context "GitHub PR #${{ github.event.number }}" \
          --output-format json > quality-report.json

    - name: Post Quality Report
      uses: actions/github-script@v7
      with:
        script: |
          const fs = require('fs');
          const report = JSON.parse(fs.readFileSync('quality-report.json', 'utf8'));

          const body = `
          ## 📊 Claude Code Quality Report

          ### Overall Assessment
          - **Quality Score**: ${report.qualityScore}/100
          - **Test Coverage**: ${report.testCoverage}%
          - **Performance**: ${report.performance}

          ### Improvement Suggestions
          ${report.suggestions.map(s => `- ${s}`).join('\n')}

          ### Security Check
          ${report.securityIssues.length === 0 ? '✅ No security issues' : 
            '⚠️ Security concerns:\n' + report.securityIssues.map(i => `- ${i}`).join('\n')}
          `;

          await github.rest.pulls.createReview({
            owner: context.repo.owner,
            repo: context.repo.repo,
            pull_number: context.issue.number,
            body: body,
            event: report.qualityScore >= 80 ? 'APPROVE' : 'REQUEST_CHANGES'
          });

📊 Team Management Dashboard Construction

Real-Time Metrics Collection

// dashboard/src/metrics-collector.ts
import { EventEmitter } from 'events';
import { WebSocket } from 'ws';
import { InfluxDB, Point } from '@influxdata/influxdb-client';

interface DeveloperMetrics {
  userId: string;
  sessionId: string;
  timestamp: Date;
  metrics: {
    linesAccepted: number;
    toolUsageCount: number;
    commandsExecuted: number;
    errorsEncountered: number;
    sessionDuration: number;
    productivityScore: number;
  };
}

interface TeamMetrics {
  teamId: string;
  period: 'hour' | 'day' | 'week' | 'month';
  aggregatedData: {
    totalDevelopers: number;
    averageProductivity: number;
    totalLinesGenerated: number;
    toolUsageDistribution: Record<string, number>;
    errorRate: number;
    collaborationScore: number;
  };
}

class MetricsCollector extends EventEmitter {
  private influxDB: InfluxDB;
  private writeClient: any;
  private queryClient: any;
  private wsServer: WebSocket.Server;

  constructor() {
    super();

    // InfluxDB connection configuration
    this.influxDB = new InfluxDB({
      url: process.env.INFLUXDB_URL || 'http://localhost:8086',
      token: process.env.INFLUXDB_TOKEN,
    });

    this.writeClient = this.influxDB.getWriteApi(
      process.env.INFLUXDB_ORG || 'development',
      process.env.INFLUXDB_BUCKET || 'claude-metrics'
    );

    this.queryClient = this.influxDB.getQueryApi(
      process.env.INFLUXDB_ORG || 'development'
    );

    // WebSocket server configuration
    this.wsServer = new WebSocket.Server({ port: 8080 });
    this.setupWebSocketHandlers();
  }

  private setupWebSocketHandlers() {
    this.wsServer.on('connection', (ws, req) => {
      console.log('New metrics client connected');

      ws.on('message', async (data) => {
        try {
          const metrics = JSON.parse(data.toString()) as DeveloperMetrics;
          await this.recordDeveloperMetrics(metrics);

          // Broadcast real-time updates to other clients
          this.broadcastMetricsUpdate(metrics);
        } catch (error) {
          console.error('Error processing metrics:', error);
          ws.send(JSON.stringify({ error: 'Invalid metrics data' }));
        }
      });

      ws.on('close', () => {
        console.log('Metrics client disconnected');
      });
    });
  }

  async recordDeveloperMetrics(metrics: DeveloperMetrics) {
    const point = new Point('developer_metrics')
      .tag('user_id', metrics.userId)
      .tag('session_id', metrics.sessionId)
      .intField('lines_accepted', metrics.metrics.linesAccepted)
      .intField('tool_usage_count', metrics.metrics.toolUsageCount)
      .intField('commands_executed', metrics.metrics.commandsExecuted)
      .intField('errors_encountered', metrics.metrics.errorsEncountered)
      .intField('session_duration', metrics.metrics.sessionDuration)
      .floatField('productivity_score', metrics.metrics.productivityScore)
      .timestamp(metrics.timestamp);

    this.writeClient.writePoint(point);
    await this.writeClient.flush();

    this.emit('metrics_recorded', metrics);
  }

  async generateTeamMetrics(teamId: string, period: string): Promise<TeamMetrics> {
    const timeRange = this.getTimeRange(period);

    const query = `
      from(bucket: "claude-metrics")
        |> range(start: ${timeRange.start}, stop: ${timeRange.end})
        |> filter(fn: (r) => r._measurement == "developer_metrics")
        |> filter(fn: (r) => r.team_id == "${teamId}")
        |> aggregateWindow(every: ${timeRange.window}, fn: mean, createEmpty: false)
    `;

    const result = await this.queryClient.collectRows(query);

    return {
      teamId,
      period: period as any,
      aggregatedData: this.processTeamMetricsData(result),
    };
  }

  private getTimeRange(period: string) {
    const now = new Date();
    switch (period) {
      case 'hour':
        return {
          start: new Date(now.getTime() - 60 * 60 * 1000).toISOString(),
          end: now.toISOString(),
          window: '5m',
        };
      case 'day':
        return {
          start: new Date(now.getTime() - 24 * 60 * 60 * 1000).toISOString(),
          end: now.toISOString(),
          window: '1h',
        };
      case 'week':
        return {
          start: new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000).toISOString(),
          end: now.toISOString(),
          window: '1d',
        };
      case 'month':
        return {
          start: new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000).toISOString(),
          end: now.toISOString(),
          window: '1d',
        };
      default:
        throw new Error(`Unsupported period: ${period}`);
    }
  }

  private processTeamMetricsData(rawData: any[]): TeamMetrics['aggregatedData'] {
    const developers = new Set(rawData.map(row => row.user_id));
    const totalLines = rawData.reduce((sum, row) => sum + (row._value || 0), 0);
    const avgProductivity = rawData.reduce((sum, row) => sum + (row.productivity_score || 0), 0) / rawData.length;

    // Calculate tool usage distribution
    const toolUsage: Record<string, number> = {};
    rawData.forEach(row => {
      if (row.tool_name) {
        toolUsage[row.tool_name] = (toolUsage[row.tool_name] || 0) + 1;
      }
    });

    // Calculate error rate
    const totalCommands = rawData.reduce((sum, row) => sum + (row.commands_executed || 0), 0);
    const totalErrors = rawData.reduce((sum, row) => sum + (row.errors_encountered || 0), 0);
    const errorRate = totalCommands > 0 ? (totalErrors / totalCommands) * 100 : 0;

    return {
      totalDevelopers: developers.size,
      averageProductivity: avgProductivity || 0,
      totalLinesGenerated: totalLines,
      toolUsageDistribution: toolUsage,
      errorRate,
      collaborationScore: this.calculateCollaborationScore(rawData),
    };
  }

  private calculateCollaborationScore(rawData: any[]): number {
    // Collaboration score calculation logic
    // Consider:
    // - Concurrent session count
    // - Shared resource usage
    // - Review participation rate
    // Composite metric

    const sessions = new Set(rawData.map(row => row.session_id));
    const avgSessionLength = rawData.reduce((sum, row) => sum + (row.session_duration || 0), 0) / rawData.length;

    // Simple collaboration score calculation
    return Math.min(100, (sessions.size * 10) + (avgSessionLength / 60));
  }

  private broadcastMetricsUpdate(metrics: DeveloperMetrics) {
    const updateMessage = JSON.stringify({
      type: 'metrics_update',
      data: metrics,
      timestamp: new Date().toISOString(),
    });

    this.wsServer.clients.forEach(client => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(updateMessage);
      }
    });
  }

  // Cost tracking functionality
  async calculateCosts(teamId: string, period: string) {
    const metrics = await this.generateTeamMetrics(teamId, period);

    // Cost calculation based on Claude API usage
    const apiCosts = {
      sonnet4: {
        inputCost: 3.0 / 1000000,  // $3 per million tokens
        outputCost: 15.0 / 1000000, // $15 per million tokens
      },
      opus4: {
        inputCost: 15.0 / 1000000,  // $15 per million tokens
        outputCost: 75.0 / 1000000, // $75 per million tokens
      },
    };

    // Get actual usage data (simplified)
    const usage = await this.getApiUsage(teamId, period);

    const totalCost = 
      (usage.sonnet4.input * apiCosts.sonnet4.inputCost) +
      (usage.sonnet4.output * apiCosts.sonnet4.outputCost) +
      (usage.opus4.input * apiCosts.opus4.inputCost) +
      (usage.opus4.output * apiCosts.opus4.outputCost);

    return {
      totalCost,
      costPerDeveloper: totalCost / metrics.aggregatedData.totalDevelopers,
      costBreakdown: {
        sonnet4: (usage.sonnet4.input * apiCosts.sonnet4.inputCost) + 
                 (usage.sonnet4.output * apiCosts.sonnet4.outputCost),
        opus4: (usage.opus4.input * apiCosts.opus4.inputCost) + 
               (usage.opus4.output * apiCosts.opus4.outputCost),
      },
      usage,
    };
  }

  private async getApiUsage(teamId: string, period: string) {
    // Get API usage (in actual implementation, retrieved from external API)
    const query = `
      from(bucket: "api-usage")
        |> range(start: -${period === 'day' ? '1d' : '7d'})
        |> filter(fn: (r) => r.team_id == "${teamId}")
        |> group(columns: ["model"])
        |> sum()
    `;

    const result = await this.queryClient.collectRows(query);

    return {
      sonnet4: {
        input: result.find(r => r.model === 'sonnet4' && r._field === 'input_tokens')?._value || 0,
        output: result.find(r => r.model === 'sonnet4' && r._field === 'output_tokens')?._value || 0,
      },
      opus4: {
        input: result.find(r => r.model === 'opus4' && r._field === 'input_tokens')?._value || 0,
        output: result.find(r => r.model === 'opus4' && r._field === 'output_tokens')?._value || 0,
      },
    };
  }
}

export { MetricsCollector, DeveloperMetrics, TeamMetrics };

Dashboard Web Application

// dashboard/src/dashboard-app.tsx
import React, { useState, useEffect } from 'react';
import { 
  LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend,
  BarChart, Bar, PieChart, Pie, Cell, ResponsiveContainer
} from 'recharts';
import { MetricsCollector, DeveloperMetrics, TeamMetrics } from './metrics-collector';

interface DashboardProps {
  teamId: string;
  refreshInterval?: number;
}

const Dashboard: React.FC<DashboardProps> = ({ 
  teamId, 
  refreshInterval = 30000 
}) => {
  const [metrics, setMetrics] = useState<TeamMetrics | null>(null);
  const [realTimeData, setRealTimeData] = useState<DeveloperMetrics[]>([]);
  const [costs, setCosts] = useState<any>(null);
  const [loading, setLoading] = useState(true);
  const [selectedPeriod, setSelectedPeriod] = useState<'hour' | 'day' | 'week' | 'month'>('day');

  useEffect(() => {
    const ws = new WebSocket('ws://localhost:8080');

    ws.onmessage = (event) => {
      const message = JSON.parse(event.data);
      if (message.type === 'metrics_update') {
        setRealTimeData(prev => [...prev.slice(-49), message.data]);
      }
    };

    const fetchMetrics = async () => {
      try {
        const [teamMetrics, costData] = await Promise.all([
          fetch(`/api/teams/${teamId}/metrics?period=${selectedPeriod}`).then(r => r.json()),
          fetch(`/api/teams/${teamId}/costs?period=${selectedPeriod}`).then(r => r.json())
        ]);

        setMetrics(teamMetrics);
        setCosts(costData);
        setLoading(false);
      } catch (error) {
        console.error('Failed to fetch metrics:', error);
        setLoading(false);
      }
    };

    fetchMetrics();
    const interval = setInterval(fetchMetrics, refreshInterval);

    return () => {
      ws.close();
      clearInterval(interval);
    };
  }, [teamId, selectedPeriod, refreshInterval]);

  if (loading) {
    return <div className="loading">Loading dashboard...</div>;
  }

  if (!metrics) {
    return <div className="error">Failed to load metrics</div>;
  }

  const productivityData = realTimeData.map((data, index) => ({
    time: new Date(data.timestamp).toLocaleTimeString(),
    productivity: data.metrics.productivityScore,
    linesAccepted: data.metrics.linesAccepted,
    toolUsage: data.metrics.toolUsageCount,
  }));

  const toolUsageData = Object.entries(metrics.aggregatedData.toolUsageDistribution).map(
    ([tool, usage]) => ({
      name: tool,
      value: usage,
      percentage: (usage / Object.values(metrics.aggregatedData.toolUsageDistribution).reduce((a, b) => a + b, 0)) * 100
    })
  );

  const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042', '#8884D8'];

  return (
    <div className="dashboard">
      <header className="dashboard-header">
        <h1>Claude Code Team Dashboard</h1>
        <div className="period-selector">
          {['hour', 'day', 'week', 'month'].map(period => (
            <button
              key={period}
              onClick={() => setSelectedPeriod(period as any)}
              className={selectedPeriod === period ? 'active' : ''}
            >
              {period}
            </button>
          ))}
        </div>
      </header>

      <div className="metrics-grid">
        {/* Key metrics cards */}
        <div className="metric-card">
          <h3>Total Developers</h3>
          <div className="metric-value">{metrics.aggregatedData.totalDevelopers}</div>
        </div>

        <div className="metric-card">
          <h3>Average Productivity Score</h3>
          <div className="metric-value">{metrics.aggregatedData.averageProductivity.toFixed(1)}</div>
        </div>

        <div className="metric-card">
          <h3>Lines of Code Generated</h3>
          <div className="metric-value">{metrics.aggregatedData.totalLinesGenerated.toLocaleString()}</div>
        </div>

        <div className="metric-card">
          <h3>Error Rate</h3>
          <div className="metric-value">{metrics.aggregatedData.errorRate.toFixed(2)}%</div>
        </div>
      </div>

      {/* Real-time productivity chart */}
      <div className="chart-section">
        <h2>Real-Time Productivity</h2>
        <ResponsiveContainer width="100%" height={300}>
          <LineChart data={productivityData}>
            <CartesianGrid strokeDasharray="3 3" />
            <XAxis dataKey="time" />
            <YAxis />
            <Tooltip />
            <Legend />
            <Line 
              type="monotone" 
              dataKey="productivity" 
              stroke="#8884d8" 
              name="Productivity Score" 
            />
            <Line 
              type="monotone" 
              dataKey="linesAccepted" 
              stroke="#82ca9d" 
              name="Lines Accepted" 
            />
          </LineChart>
        </ResponsiveContainer>
      </div>

      {/* Tool usage distribution */}
      <div className="chart-section">
        <h2>Tool Usage Distribution</h2>
        <div className="chart-row">
          <ResponsiveContainer width="50%" height={300}>
            <PieChart>
              <Pie
                data={toolUsageData}
                cx="50%"
                cy="50%"
                labelLine={false}
                label={({ name, percentage }) => `${name}: ${percentage.toFixed(1)}%`}
                outerRadius={80}
                fill="#8884d8"
                dataKey="value"
              >
                {toolUsageData.map((entry, index) => (
                  <Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
                ))}
              </Pie>
              <Tooltip />
            </PieChart>
          </ResponsiveContainer>

          <ResponsiveContainer width="50%" height={300}>
            <BarChart data={toolUsageData}>
              <CartesianGrid strokeDasharray="3 3" />
              <XAxis dataKey="name" />
              <YAxis />
              <Tooltip />
              <Bar dataKey="value" fill="#8884d8" />
            </BarChart>
          </ResponsiveContainer>
        </div>
      </div>

      {/* Cost analysis */}
      {costs && (
        <div className="cost-section">
          <h2>Cost Analysis</h2>
          <div className="cost-grid">
            <div className="cost-card">
              <h3>Total Cost</h3>
              <div className="cost-value">${costs.totalCost.toFixed(2)}</div>
            </div>
            <div className="cost-card">
              <h3>Cost Per Developer</h3>
              <div className="cost-value">${costs.costPerDeveloper.toFixed(2)}</div>
            </div>
            <div className="cost-card">
              <h3>Claude Sonnet 4</h3>
              <div className="cost-value">${costs.costBreakdown.sonnet4.toFixed(2)}</div>
            </div>
            <div className="cost-card">
              <h3>Claude Opus 4</h3>
              <div className="cost-value">${costs.costBreakdown.opus4.toFixed(2)}</div>
            </div>
          </div>

          <div className="usage-details">
            <h3>API Usage Details</h3>
            <table>
              <thead>
                <tr>
                  <th>Model</th>
                  <th>Input Tokens</th>
                  <th>Output Tokens</th>
                  <th>Cost</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td>Claude Sonnet 4</td>
                  <td>{costs.usage.sonnet4.input.toLocaleString()}</td>
                  <td>{costs.usage.sonnet4.output.toLocaleString()}</td>
                  <td>${costs.costBreakdown.sonnet4.toFixed(2)}</td>
                </tr>
                <tr>
                  <td>Claude Opus 4</td>
                  <td>{costs.usage.opus4.input.toLocaleString()}</td>
                  <td>{costs.usage.opus4.output.toLocaleString()}</td>
                  <td>${costs.costBreakdown.opus4.toFixed(2)}</td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      )}

      {/* Alerts and notifications section */}
      <div className="alerts-section">
        <h2>Alerts & Notifications</h2>
        <div className="alert-list">
          {metrics.aggregatedData.errorRate > 5 && (
            <div className="alert alert-warning">
              ⚠️ Error rate exceeds threshold (5%): {metrics.aggregatedData.errorRate.toFixed(2)}%
            </div>
          )}
          {metrics.aggregatedData.averageProductivity < 50 && (
            <div className="alert alert-info">
              ℹ️ Team productivity is declining. Please check tool usage status.
            </div>
          )}
          {costs && costs.totalCost > 1000 && (
            <div className="alert alert-warning">
              💰 Monthly cost may exceed budget ($1000).
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

export default Dashboard;

Dashboard CSS Styles

/* dashboard/src/dashboard.css */
.dashboard {
  max-width: 1400px;
  margin: 0 auto;
  padding: 20px;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

.dashboard-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 30px;
  padding-bottom: 20px;
  border-bottom: 2px solid #e0e0e0;
}

.period-selector {
  display: flex;
  gap: 10px;
}

.period-selector button {
  padding: 8px 16px;
  border: 1px solid #ddd;
  background: white;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s;
}

.period-selector button.active {
  background: #007bff;
  color: white;
  border-color: #007bff;
}

.metrics-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;
  margin-bottom: 30px;
}

.metric-card {
  background: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  text-align: center;
}

.metric-card h3 {
  margin: 0 0 10px 0;
  color: #666;
  font-size: 14px;
  text-transform: uppercase;
}

.metric-value {
  font-size: 2.5em;
  font-weight: bold;
  color: #007bff;
}

.chart-section {
  background: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  margin-bottom: 30px;
}

.chart-row {
  display: flex;
  gap: 20px;
}

.cost-section {
  background: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  margin-bottom: 30px;
}

.cost-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 15px;
  margin-bottom: 20px;
}

.cost-card {
  background: #f8f9fa;
  padding: 15px;
  border-radius: 6px;
  text-align: center;
}

.cost-value {
  font-size: 1.8em;
  font-weight: bold;
  color: #28a745;
}

.usage-details table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 15px;
}

.usage-details th,
.usage-details td {
  padding: 10px;
  text-align: left;
  border-bottom: 1px solid #ddd;
}

.usage-details th {
  background: #f8f9fa;
  font-weight: 600;
}

.alerts-section {
  background: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.alert {
  padding: 12px 16px;
  border-radius: 4px;
  margin-bottom: 10px;
}

.alert-warning {
  background: #fff3cd;
  border-left: 4px solid #ffc107;
  color: #856404;
}

.alert-info {
  background: #d1ecf1;
  border-left: 4px solid #17a2b8;
  color: #0c5460;
}

.loading, .error {
  text-align: center;
  padding: 50px;
  font-size: 1.2em;
}

.error {
  color: #dc3545;
}

⚡ Practical Troubleshooting

Resolving MCP Connection Issues

# MCP diagnostics script
#!/bin/bash
# mcp-diagnostics.sh

echo "=== Claude Code MCP Diagnostics Tool ==="

# 1. Basic configuration check
echo "1. Checking configuration files..."
if [ -f ~/.claude/mcp_settings.json ]; then
    echo "✅ MCP configuration file exists"
    jq . ~/.claude/mcp_settings.json > /dev/null 2>&1
    if [ $? -eq 0 ]; then
        echo "✅ JSON format is valid"
    else
        echo "❌ JSON format error: please check configuration file"
        exit 1
    fi
else
    echo "❌ MCP configuration file not found"
    echo "💡 Please create ~/.claude/mcp_settings.json"
    exit 1
fi

# 2. Server startup check
echo "2. MCP server startup test..."
MCP_SERVERS=$(jq -r '.mcpServers | keys[]' ~/.claude/mcp_settings.json)

for server in $MCP_SERVERS; do
    echo "Testing server: $server"
    COMMAND=$(jq -r ".mcpServers[\"$server\"].command" ~/.claude/mcp_settings.json)
    ARGS=$(jq -r ".mcpServers[\"$server\"].args[]" ~/.claude/mcp_settings.json | tr '\n' ' ')

    # Check server process
    timeout 5s $COMMAND $ARGS --test-connection 2>/dev/null
    if [ $? -eq 0 ]; then
        echo "✅ $server starts successfully"
    else
        echo "❌ $server failed to start"
        echo "💡 Check command: $COMMAND $ARGS"
    fi
done

# 3. Permission check
echo "3. Checking permissions and authentication..."
if [ -n "$GITHUB_TOKEN" ]; then
    echo "✅ GITHUB_TOKEN is configured"
    # Token validity check
    curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user > /dev/null
    if [ $? -eq 0 ]; then
        echo "✅ GitHub token is valid"
    else
        echo "❌ GitHub token is invalid"
    fi
else
    echo "⚠️ GITHUB_TOKEN is not configured"
fi

# 4. Network connection check
echo "4. Checking network connectivity..."
curl -s --connect-timeout 5 https://api.anthropic.com > /dev/null
if [ $? -eq 0 ]; then
    echo "✅ Can connect to Anthropic API"
else
    echo "❌ Failed to connect to Anthropic API"
    echo "💡 Please check proxy settings or firewall"
fi

echo "=== Diagnostics complete ==="

Common Issues and Solutions

# troubleshooting-guide.yml
common_issues:
  connection_failures:
    symptoms:
      - "MCP server connection failed"
      - "Authentication timeout"
      - "Server not responding"

    solutions:
      - check: "Verify MCP server process is running"
        command: "ps aux | grep mcp"

      - check: "Check for port number conflicts"
        command: "netstat -ln | grep :3001"

      - check: "Verify authentication token validity"
        command: "claude-code /mcp status"

  performance_issues:
    symptoms:
      - "Slow response times"
      - "High memory usage"
      - "Tool execution timeout"

    solutions:
      - check: "System resource usage"
        command: "htop"

      - check: "MCP server logs"
        command: "tail -f /var/log/mcp-server.log"

      - optimization: "Implement batch processing"
        description: "Batch multiple tool calls together"

  authentication_errors:
    symptoms:
      - "OAuth 2.0 authentication failed"
      - "Invalid token"
      - "Permission denied"

    solutions:
      - check: "Token expiration"
        command: "jwt-decode ${{ secrets.ACCESS_TOKEN }}"

      - refresh: "Refresh token"
        command: "claude-code /mcp oauth-refresh"

      - verify: "Check permission scopes"
        scopes_required: ["repo", "read:org", "workflow"]

best_practices:
  development:
    - "Separate MCP servers for development and production"
    - "Manage credentials via environment variables"
    - "Set appropriate log levels"
    - "Implement error handling"

  monitoring:
    - "Implement server health checks"
    - "Automate metrics collection"
    - "Set appropriate alert thresholds"
    - "Configure log rotation"

  security:
    - "Principle of least privilege"
    - "Regular token rotation"
    - "Secure communication (HTTPS/WSS)"
    - "Maintain audit logs"

Summary

This article deep-dives into the Claude 4×GitHub Copilot integration introduced in the morning overview article to actual working implementation level:

🎯 Differentiation from Morning Article

Morning Article (Overview)Afternoon Article (Implementation Details)
Feature introduction & possibilitiesComplete implementation code
Configuration examples & simple usageEnterprise-grade production deployment
Theoretical effectivenessPractical troubleshooting
Introduction of 5.5x efficiencySpecific steps to achieve it

🔧 Completed Implementation Items

  • MCP Server: Complete implementation with OAuth 2.0 authentication
  • CLI Customization: Team-specific workflow automation
  • Agent Mode: Issue→PR complete automation system
  • Management Dashboard: Real-time metrics visualization

💡 Next Steps

  1. Environment Setup: Set up local environment using provided code
  2. Phased Deployment: Start pilot operations with small teams
  3. Customization: Extend functionality for organization-specific requirements
  4. Scaling: Full company rollout based on successful case studies

With this implementation guide, complete realization of Claude 4×GitHub Copilot integration from concept to actual operation becomes possible.