Claude 2a7dd1c818 fix: resolve SSL certificate chain issues for gogs-mcp communication 4 miesięcy temu
..
src 2a7dd1c818 fix: resolve SSL certificate chain issues for gogs-mcp communication 4 miesięcy temu
.gitignore 37c52fbd75 feat: rewrite issue handler with TypeScript and Claude Agent SDK 9 miesięcy temu
README.md 03115969f5 fix: add global .env file support for client configuration #40 8 miesięcy temu
package-lock.json 37c52fbd75 feat: rewrite issue handler with TypeScript and Claude Agent SDK 9 miesięcy temu
package.json 37c52fbd75 feat: rewrite issue handler with TypeScript and Claude Agent SDK 9 miesięcy temu
tsconfig.json 37c52fbd75 feat: rewrite issue handler with TypeScript and Claude Agent SDK 9 miesięcy temu

README.md

Agent Manager Client

TypeScript-based Claude Agent SDK client for automated issue handling in Gogs repositories.

Overview

This client uses the @anthropic-ai/claude-agent-sdk to provide AI-powered issue automation. It replaces the previous bash-based Claude Code implementation with a more robust, type-safe TypeScript solution.

Features

  • TypeScript Implementation: Fully typed code with compile-time safety
  • MCP Integration: Connects to gogs-mcp server for Gogs API operations
  • Issue Automation: Automatically handles issues assigned to Claude
  • Comment Processing: Responds to issue comments and updates
  • Label-Aware Behavior: Adjusts behavior based on issue labels (question, documentation, bug, enhancement)
  • Environment-Specific Configuration: Supports different gogs-mcp paths via environment variables
  • Per-Repository MCP Configuration: Different repositories can use different MCP servers
  • Dynamic Tool Discovery: Automatically discovers and enables tools from all configured MCP servers
  • Automatic Repository Management: Clones repositories on demand and pulls latest changes
  • Dynamic Git URL Fetching: Retrieves SSH URLs from Gogs API instead of hardcoding
  • Environment Setup: Handles HOME, PATH, and XDG directory configuration automatically
  • Project Memory Support: Reads and includes CLAUDE.md files for project-specific context

Architecture

The client is organized into focused modules with clear responsibilities:

client/
├── src/
│   ├── claude-client.ts       # Main Claude Agent SDK client
│   │                          # - Handles issue automation requests
│   │                          # - Builds prompts with label-aware instructions
│   │                          # - Manages Claude Agent SDK sessions
│   │                          # - Reads and includes CLAUDE.md project memory
│   │
│   ├── config.ts              # Configuration management
│   │                          # - Loads .env files
│   │                          # - Generates MCP configurations
│   │                          # - Manages GOGS_MCP_PATH setting
│   │
│   ├── mcpConfigManager.ts    # MCP configuration loader
│   │                          # - Per-repository config support
│   │                          # - Global default config
│   │                          # - Environment variable substitution
│   │                          # - Security checks (file permissions)
│   │
│   ├── toolDiscovery.ts       # Dynamic tool discovery
│   │                          # - Discovers tools from MCP servers
│   │                          # - Includes built-in Claude Code tools
│   │                          # - Formats tool names (mcp__{server}__{tool})
│   │
│   ├── repository-manager.ts  # Git repository operations
│   │                          # - Clones repositories on demand
│   │                          # - Pulls latest changes
│   │                          # - Environment setup (HOME, PATH, XDG)
│   │                          # - Agent Manager path detection
│   │
│   ├── gogs-helper.ts         # Gogs API helper functions
│   │                          # - Fetches SSH URLs from Gogs API
│   │                          # - Reads existing Git remote URLs
│   │                          # - Direct API access (pre-MCP)
│   │
│   ├── types.ts               # TypeScript type definitions
│   │                          # - IssueData, IssueHandlerResult
│   │                          # - ClaudeClientConfig, MCPServerConfig
│   │                          # - Type-safe interfaces
│   │
│   └── index.ts               # CLI entry point
│                              # - Parses command-line arguments
│                              # - Orchestrates repository management
│                              # - Invokes ClaudeClient
│
├── dist/                      # Compiled JavaScript (generated by tsc)
├── package.json               # Dependencies and scripts
└── tsconfig.json              # TypeScript configuration

Key Components

ClaudeClient (claude-client.ts)

  • Main orchestrator for issue automation
  • Builds context-rich prompts with label-aware behavior
  • Manages Claude Agent SDK query lifecycle
  • Tracks costs, session IDs, and execution metrics

McpConfigManager (mcpConfigManager.ts)

  • Three-tier configuration priority (repo → global → fallback)
  • Secure secret management with environment variables
  • File permission validation
  • Configuration creation and listing utilities

ToolDiscovery (toolDiscovery.ts)

  • Connects to all configured MCP servers
  • Queries each server for available tools
  • Merges with built-in Claude Code tools
  • Returns complete tool list for Agent SDK

RepositoryManager (repository-manager.ts)

  • Automatic Git operations (clone/pull)
  • Environment variable setup for systemd compatibility
  • XDG directory creation and management
  • Multi-location path detection

Installation

cd client
npm install

Building

npm run build

This compiles TypeScript to JavaScript in the dist/ directory.

Usage

Programmatic API

import { ClaudeClient, Config, ToolDiscovery } from './client/dist/index.js';

// Load configuration
Config.load('/path/to/repo');

// Generate MCP config (with dynamic per-repo support)
const mcpConfig = Config.generateMcpConfig('/path/to/repo', 'owner', 'repo');

// Discover available tools automatically
const allowedTools = await ToolDiscovery.discoverTools(mcpConfig);

// Create client
const client = new ClaudeClient({
  workingDirectory: '/path/to/repo',
  mcpConfigPath: '/path/to/repo/.mcp-gogs.json',
  allowedTools,  // Automatically discovered tools
  dangerouslySkipPermissions: true
});

// Handle issue
const result = await client.handleIssue({
  owner: 'username',
  repo: 'repo-name',
  number: 42,
  title: 'Issue title',
  body: 'Issue description',
  action: 'opened',
  pusher: 'username',
  assignee: 'claude'
});

console.log(result);

Command Line

node dist/index.js <owner> <repo> <pusher> <issue_number> <issue_title> <issue_body> <issue_action> [comment_body] [assignee]

Webhook Integration

The client is called directly from commands.json for issue and issue_comment events. The TypeScript client handles all environment setup, repository management, and issue processing.

Configuration

Environment Variables

The client loads environment variables from two locations (in priority order):

  1. Global configuration: ~/.config/agent-manager/.env (shared across all repositories)
  2. Repository-specific configuration: .env in repository root (overrides global)

This allows you to set common values (like GOGS_ACCESS_TOKEN) once in the global file, eliminating the need to duplicate them in every cloned repository.

Global Configuration (~/.config/agent-manager/.env)

Create this file to set global defaults for all repositories:

# Required: Gogs API authentication (applies to all repositories)
GOGS_ACCESS_TOKEN=your-token-here
GOGS_BASE_URL=https://git.smartbotics.ai

# Optional: Path to gogs-mcp server
GOGS_MCP_PATH=/data/gogs-mcp/dist/index.js

Setup:

mkdir -p ~/.config/agent-manager
cp /path/to/agent-manager/examples/global-env.example ~/.config/agent-manager/.env
chmod 600 ~/.config/agent-manager/.env
# Edit the file and add your values

Repository-Specific Configuration (.env in repository)

Optional. Use this to override global values for specific repositories:

# Example: Use a different Gogs token for this specific repository
GOGS_ACCESS_TOKEN=repo-specific-token

# Example: Custom home directory for this repository
HOME=/custom/home/path

Notes:

  • Repository-specific values override global values
  • If a repository doesn't have a .env file, it uses only global values
  • You no longer need to manually create .env files in every cloned repository

Webhook Variables

When called from commands.json, the client receives these variables from webhooks:

  • {{repo_owner}} - Repository owner (e.g., "fszontagh")
  • {{repo}} - Repository name (e.g., "agent-manager")
  • {{pusher}} - Username who triggered the webhook
  • {{issue_number}} - Issue number
  • {{issue_title}} - Issue title
  • {{issue_body}} - Issue description
  • {{issue_action}} - Action (opened, assigned, closed, reopened)
  • {{comment_body}} - Comment text (for issue_comment events)
  • {{issue_assignee}} - Assigned username (e.g., "claude")
  • {{issue_labels}} - Comma-separated label names (e.g., "bug,enhancement")

Dynamic Tool Discovery

The client automatically discovers available tools from all configured MCP servers at runtime. You don't need to manually configure the tool list.

How It Works

  1. The client loads the MCP configuration for the repository
  2. ToolDiscovery connects to each configured MCP server
  3. It queries each server for available tools using the MCP protocol
  4. Tools are formatted as mcp__{server-name}__{tool-name}
  5. Built-in Claude Code tools are added automatically
  6. The complete list is passed to the Claude Agent SDK

Built-in Tools (Always Available)

  • File Operations: Read, Write, Edit
  • Shell Operations: Bash, Grep, Glob
  • Task Management: TodoWrite, Task
  • Web Access: WebFetch, WebSearch
  • Advanced: NotebookEdit, BashOutput, KillShell, Skill, SlashCommand

Default MCP Tools (from gogs-mcp)

When using the default gogs-mcp server, these tools are automatically discovered:

User Tools:

  • mcp__gogs__get_current_user, mcp__gogs__get_user, mcp__gogs__search_users

Repository Tools:

  • mcp__gogs__list_user_repositories, mcp__gogs__search_repositories, mcp__gogs__get_repository
  • mcp__gogs__create_repository, mcp__gogs__delete_repository

Content Tools:

  • mcp__gogs__get_contents, mcp__gogs__get_raw_content
  • mcp__gogs__list_branches, mcp__gogs__get_commits

Issue Tools:

  • mcp__gogs__list_issues, mcp__gogs__get_issue, mcp__gogs__create_issue, mcp__gogs__update_issue
  • mcp__gogs__list_issue_comments, mcp__gogs__create_issue_comment, mcp__gogs__update_issue_comment

Custom MCP Servers

When you add a custom MCP server to your repository configuration, its tools are automatically discovered and available to Claude. No additional configuration needed!

For example, if you configure a "github" MCP server with tools like "create_pr" and "list_repos", they will automatically be available as mcp__github__create_pr and mcp__github__list_repos.

Label-Aware Behavior

The Claude agent automatically adjusts its behavior based on issue labels. Labels are extracted from webhook payloads and influence how Claude approaches the task.

Supported Labels

🔴 "question" Label

  • Behavior: DO NOT implement code changes
  • Purpose: Provide information, guidance, and answers only
  • Actions: May read code for context but won't modify files
  • Focus: Helpful explanations, suggestions, and clarifications

📚 "documentation" Label

  • Behavior: Focus on documentation files only
  • Purpose: Create, update, or improve documentation
  • Acceptable Changes: README.md, CLAUDE.md, other .md files, code comments
  • Restrictions: Avoid implementation changes unless needed for examples

🐛 "bug" Label

  • Behavior: Identify and fix the root cause
  • Purpose: Resolve bugs and defects
  • Actions: Implement minimal changes to fix the bug
  • Best Practice: Add tests to prevent regression when appropriate

✨ "enhancement" Label

  • Behavior: May implement code changes as requested
  • Purpose: Add new features or improvements
  • Guidelines: Follow existing patterns, consider backward compatibility

How It Works

  1. When an issue is assigned or commented on, the webhook includes label information
  2. The claude-client.ts parses labels from the {{issue_labels}} variable
  3. Based on detected labels, specific instructions are injected into the prompt
  4. Claude receives clear guidance on expected behavior for the issue type

Example

If an issue is labeled with "question":

⚠️ QUESTION LABEL DETECTED:
- This issue is labeled as "question"
- DO NOT implement any code changes or features
- Your role is to provide information, guidance, and answers only
- You may read code to understand context, but do not modify files
- Respond with helpful explanations, suggestions, or clarifications

MCP Configuration System

The client supports flexible MCP server configuration with three priority levels. This allows different repositories to use different MCP servers and tools.

Configuration Priority

  1. Repository-specific config: ~/.config/agent-manager/mcp/{owner}/{repo}.json
  2. Global default config: ~/.config/agent-manager/mcp/default.json
  3. Hardcoded fallback: Built-in gogs-mcp configuration (automatic)

Configuration File Format

{
  "mcpServers": {
    "gogs": {
      "type": "stdio",
      "command": "node",
      "args": ["/data/gogs-mcp/dist/index.js"],
      "env": {}
    },
    "custom-server": {
      "type": "stdio",
      "command": "node",
      "args": ["/path/to/custom-mcp/dist/index.js"],
      "env": {
        "API_KEY": "${MY_API_KEY}"
      }
    }
  }
}

Environment Variable Substitution

Configuration files support ${VAR_NAME} syntax for secure secret management:

{
  "mcpServers": {
    "api-service": {
      "type": "stdio",
      "command": "node",
      "args": ["/path/to/api-mcp/dist/index.js"],
      "env": {
        "API_KEY": "${MY_API_KEY}",
        "JWT_TOKEN": "${JWT_TOKEN}"
      }
    }
  }
}

Variables are resolved from the process environment at runtime.

Security

  • File Permissions: Configuration files should have mode 600 (owner read/write only)
  • Directory Permissions: Config directory should have mode 700
  • Secret Management: Never hardcode secrets; always use environment variable substitution
  • Storage Location: Files are stored in ~/.config/agent-manager/mcp/ outside repository directories

Examples

For detailed configuration examples and setup instructions, see:

Automatic Repository Management

The client automatically manages Git repositories for issue handling:

Features

Automatic Cloning

  • When an issue is assigned for a repository that doesn't exist locally
  • Clones the repository to /home/claude/{owner}/{repo}
  • Uses SSH URL fetched dynamically from Gogs API

Automatic Updates

  • If repository already exists, pulls latest changes
  • Ensures Claude always works with current code

Dynamic Git URL Fetching

  • Fetches SSH URL from Gogs API using fetchRepositorySshUrl()
  • No hardcoded repository URLs
  • Works with any repository accessible via Gogs API

Environment Setup

  • Automatically configures HOME directory
  • Sets up PATH to include ~/.local/bin
  • Creates and configures XDG directories (cache, config, data, state)
  • Ensures proper environment even when running as systemd service

Implementation

Repository management is handled by repository-manager.ts:

// Clone repository if it doesn't exist
cloneRepository(sshUrl, targetPath);

// Pull latest changes if repository exists
pullRepository(repoPath);

// Setup environment variables
setupEnvironment();

// Detect agent-manager installation path
detectAgentManagerPath();

Project Memory (CLAUDE.md)

The client automatically reads and includes the CLAUDE.md file from the repository root if it exists. This provides Claude with:

  • Project-specific guidelines and conventions
  • Architecture details and module structure
  • Development patterns and best practices
  • Important context about the codebase

When processing an issue, the CLAUDE.md content is injected into the prompt, ensuring Claude has full context about the project.

Development

Watch Mode

npm run watch

Clean Build

npm run clean
npm run build

Requirements

Dependencies

The client has minimal production dependencies:

{
  "dependencies": {
    "@anthropic-ai/claude-agent-sdk": "^0.1.28",
    "@modelcontextprotocol/sdk": "^1.0.4"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "typescript": "^5.3.0"
  }
}

Integration with Agent Manager

The client integrates seamlessly with the main Agent Manager webhook server through commands.json:

{
  "commands": {
    "issues": [
      {
        "name": "handle-issue-assigned",
        "description": "Handle issues assigned to Claude",
        "type": "node",
        "command": "client/dist/index.js",
        "args": [
          "{{repo_owner}}",
          "{{repo}}",
          "{{pusher}}",
          "{{issue_number}}",
          "{{issue_title}}",
          "{{issue_body}}",
          "{{issue_action}}",
          "",
          "{{issue_assignee}}",
          "{{issue_labels}}"
        ],
        "filterActions": ["assigned"],
        "filterAssignee": "claude"
      }
    ],
    "issue_comment": [
      {
        "name": "handle-issue-comment",
        "description": "Handle comments on issues assigned to Claude",
        "type": "node",
        "command": "client/dist/index.js",
        "args": [
          "{{repo_owner}}",
          "{{repo}}",
          "{{pusher}}",
          "{{issue_number}}",
          "{{issue_title}}",
          "{{issue_body}}",
          "{{issue_action}}",
          "{{comment_body}}",
          "{{issue_assignee}}",
          "{{issue_labels}}"
        ],
        "filterAssignee": "claude"
      }
    ]
  }
}

Troubleshooting

Issue: Repository clone fails

Solution: Ensure SSH keys are configured and GOGS_ACCESS_TOKEN is set

Issue: MCP tools not discovered

Solution: Check that MCP configuration exists and servers are accessible. Review logs for connection errors.

Issue: Permission denied errors

Solution: Verify HOME, XDG directories exist and have correct permissions (700 for directories, 600 for config files)

Issue: Label-aware behavior not working

Solution: Ensure {{issue_labels}} variable is passed from commands.json and labels are set on the issue in Gogs

Issue: CLAUDE.md not loaded

Solution: Verify CLAUDE.md exists in repository root and is readable by the claude user

License

ISC