Skip to main content
Glama
systempromptio

SystemPrompt Coding Agent

Official
claude-code-integration.md8.99 kB
# Claude Code Integration ## Overview The Claude Code Integration is a sophisticated service that bridges the MCP server with Anthropic's Claude CLI tool, enabling AI-powered coding assistance. It manages sessions, executes queries, streams responses, and parses structured events from Claude's output. ## Architecture ``` MCP Server (Docker) Host Machine ┌─────────────────┐ ┌──────────────┐ │ Claude Code │ TCP │ Host Bridge │ │ Service │ ──────> │ Daemon │ ├─────────────────┤ :9876 ├──────────────┤ │ Session Manager │ │ Claude CLI │ │ Query Executor │ │ Process │ │ Event Parser │ └──────────────┘ └─────────────────┘ ``` ## Core Components ### 1. Claude Code Service (`claude-code-service.ts`) The main service that orchestrates all Claude interactions: ```typescript class ClaudeCodeService extends EventEmitter { // Singleton instance static getInstance(): ClaudeCodeService // Session management createSession(options: ClaudeCodeOptions): Promise<string> findSession(sessionId: string): ClaudeCodeSession | undefined // Query execution querySync(sessionId: string, prompt: string): Promise<string> // Task integration setTaskId(sessionId: string, taskId: string): void setMcpSessionId(sessionId: string, mcpSessionId: string): void } ``` #### Key Features: - **Singleton Pattern**: Ensures single instance across the application - **Event Emission**: Broadcasts session and task events - **Dual Execution Modes**: SDK mode (with API key) or Host Proxy mode - **Session Isolation**: Each query runs in its own session context ### 2. Session Manager (`session-manager.ts`) Manages Claude Code sessions with lifecycle control: ```typescript interface ClaudeCodeSession { id: string; status: 'initializing' | 'ready' | 'busy' | 'error' | 'terminated'; workingDirectory: string; taskId?: string; mcpSessionId?: string; streamBuffer: string[]; errorBuffer: string[]; } ``` #### Session States: - `initializing`: Session being created - `ready`: Available for queries - `busy`: Currently executing a query - `error`: Encountered an error - `terminated`: Session ended ### 3. Host Proxy Client (`host-proxy-client.ts`) Communicates with the daemon for Claude execution: ```typescript class HostProxyClient { execute( prompt: string, workingDirectory: string, onStream?: (data: string) => void, env?: Record<string, string>, sessionId?: string, taskId?: string, onEvent?: (event: ClaudeEvent) => void ): Promise<string> } ``` #### Key Responsibilities: - **Path Mapping**: Converts Docker paths to host paths - **TCP Communication**: Manages socket connection to daemon - **Stream Processing**: Handles real-time output streaming - **Event Integration**: Parses and emits Claude events ### 4. Event Parser (`event-parser.ts`) Extracts structured events from Claude's output stream: ```typescript class ClaudeEventParser { parseLine(line: string, streamType: 'stdout' | 'stderr'): ClaudeEvent[] } ``` #### Detected Event Types: - **Tool Usage**: Start/end of tool executions - **Messages**: Assistant explanations and thinking - **Errors**: Error messages and stack traces - **Stream Data**: Raw output for logging ## Event System ### Event Types ```typescript // Tool usage events { type: 'tool:start', toolName: 'bash', toolId: 'tool_123', parameters: { command: 'npm test' } } { type: 'tool:end', toolName: 'bash', toolId: 'tool_123', duration: 1234, success: true } // Message events { type: 'message', content: "I'll run the tests now", messageType: 'thinking' } // Process events { type: 'process:start', pid: 12345, command: 'claude', workingDirectory: '/project' } ``` ### Event Flow 1. Claude outputs to stdout/stderr 2. Daemon captures and streams to Docker 3. Event parser extracts structured events 4. Service emits events to listeners 5. Task store logs events for persistence ## Query Execution ### Execution Flow ``` 1. Client calls querySync(sessionId, prompt) ↓ 2. Service validates session state ↓ 3. Determines execution mode (SDK vs Host Proxy) ↓ 4. For Host Proxy: a. Maps Docker paths to host paths b. Sends request to daemon via TCP c. Daemon spawns Claude process d. Streams output back ↓ 5. Parses events and updates task progress ↓ 6. Returns final response ``` ### Command Building For Claude CLI execution: ```bash claude \ -p \ --output-format json \ --dangerously-skip-permissions \ --max-turns 5 \ "Your prompt here" ``` ## Progress Tracking The service integrates with task management for progress tracking: ```typescript class ProgressTracker { // Logs assistant messages to task logAssistantMessage(taskId: string, content: string): Promise<void> // Parses progress from stream parseProgressFromStream(session: ClaudeCodeSession, data: string): Promise<void> } ``` ## Configuration ### Environment Variables | Variable | Description | Default | |----------|-------------|---------| | `ANTHROPIC_API_KEY` | API key for SDK mode | None | | `CLAUDE_PROXY_HOST` | Daemon hostname | `host.docker.internal` | | `CLAUDE_PROXY_PORT` | Daemon port | `9876` | | `HOST_FILE_ROOT` | Host project root | `/var/www/html/systemprompt-coding-agent` | ### Options ```typescript interface ClaudeCodeOptions { workingDirectory?: string; env?: Record<string, string>; timeout?: number; maxTurns?: number; } ``` ## Error Handling ### Error Types 1. **SessionNotReadyError**: Session not in ready state 2. **HostProxyConnectionError**: Cannot connect to daemon 3. **HostProxyTimeoutError**: Command execution timeout 4. **HostProxyError**: General proxy errors ### Error Recovery ```typescript try { const result = await service.querySync(sessionId, prompt); } catch (error) { if (error instanceof SessionNotReadyError) { // Wait for session to be ready } else if (error instanceof HostProxyConnectionError) { // Check daemon is running } } ``` ## Integration Points ### With Agent Manager ```typescript // Link Claude session to agent session const agentSession = agentManager.findSessionByTaskId(taskId); if (agentSession) { env.CLAUDE_SESSION_ID = agentSession.id; } ``` ### With Task Store ```typescript // Update task with Claude events taskStore.updateTask(taskId, { logs: [...events], lastActivity: new Date() }); ``` ### With MCP Handler ```typescript // Create Claude session for MCP tool execution const sessionId = await claudeService.createSession({ workingDirectory: '/workspace' }); claudeService.setTaskId(sessionId, task.id); ``` ## Best Practices ### Session Management 1. **Create per-task sessions**: Each task should have its own session 2. **Set working directory**: Always specify the correct working directory 3. **Clean up sessions**: Terminate sessions when tasks complete 4. **Handle session states**: Check session state before queries ### Event Handling 1. **Subscribe early**: Set up event listeners before execution 2. **Parse all events**: Don't ignore stream events 3. **Log structured events**: Store events for debugging 4. **Handle errors gracefully**: Expect and handle parsing errors ### Performance 1. **Stream processing**: Process streams incrementally 2. **Event batching**: Batch events for storage 3. **Connection pooling**: Reuse TCP connections 4. **Timeout handling**: Set appropriate timeouts ## Troubleshooting ### Common Issues 1. **"Tool 'claude' is not available"** - Check CLAUDE_PATH environment variable - Verify Claude CLI is installed on host - Ensure daemon has execute permissions 2. **Connection Refused** - Verify daemon is running - Check port configuration - Ensure Docker networking is correct 3. **Path Not Found** - Verify path mapping configuration - Check HOST_FILE_ROOT environment variable - Ensure volumes are mounted correctly ### Debug Logging Enable verbose logging: ```typescript // In your code logger.debug('Claude query', { sessionId, prompt: prompt.substring(0, 100), workingDirectory }); ``` ### Testing Claude Integration ```bash # Test daemon connection nc -zv host.docker.internal 9876 # Test Claude execution docker exec mcp-server \ node -e " const service = require('./build/services/claude-code').ClaudeCodeService.getInstance(); service.createSession().then(async (id) => { const result = await service.querySync(id, 'echo Hello'); console.log(result); }); " ``` This integration provides a robust bridge between the MCP protocol and Claude's powerful coding capabilities, enabling sophisticated AI-assisted development workflows.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systempromptio/systemprompt-code-orchestrator'

If you have feedback or need assistance with the MCP directory API, please join our Discord server