#
tokens: 8038/50000 8/8 files
lines: on (toggle) GitHub
raw markdown copy reset
# Directory Structure

```
├── .env.example
├── .gitignore
├── Dockerfile
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── smithery.yaml
├── src
│   └── index.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
 1 | # Dependencies
 2 | node_modules/
 3 | 
 4 | # Build output
 5 | build/
 6 | dist/
 7 | 
 8 | # Logs
 9 | *.log
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 | 
14 | # Environment variables
15 | .env
16 | .env.local
17 | .env.*.local
18 | 
19 | # Editor directories and files
20 | .idea/
21 | .vscode/
22 | *.swp
23 | *.swo
24 | *.swn
25 | .DS_Store
26 | 
```

--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------

```
1 | # Required: OpenRouter API key for both DeepSeek and Claude models
2 | OPENROUTER_API_KEY=your_openrouter_api_key_here
3 | 
4 | # Optional: Model configuration (defaults shown below)
5 | DEEPSEEK_MODEL=deepseek/deepseek-r1:free  # DeepSeek model for reasoning
6 | CLAUDE_MODEL=anthropic/claude-3.5-sonnet:beta  # Claude model for responses
7 | 
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Deepseek-Thinking-Claude-3.5-Sonnet-CLINE-MCP
  2 | 
  3 | [![smithery badge](https://smithery.ai/badge/@newideas99/Deepseek-Thinking-Claude-3.5-Sonnet-CLINE-MCP)](https://smithery.ai/server/@newideas99/Deepseek-Thinking-Claude-3.5-Sonnet-CLINE-MCP)
  4 | 
  5 | A Model Context Protocol (MCP) server that combines DeepSeek R1's reasoning capabilities with Claude 3.5 Sonnet's response generation through OpenRouter. This implementation uses a two-stage process where DeepSeek provides structured reasoning which is then incorporated into Claude's response generation.
  6 | 
  7 | ## Features
  8 | 
  9 | - **Two-Stage Processing**:
 10 |   - Uses DeepSeek R1 for initial reasoning (50k character context)
 11 |   - Uses Claude 3.5 Sonnet for final response (600k character context)
 12 |   - Both models accessed through OpenRouter's unified API
 13 |   - Injects DeepSeek's reasoning tokens into Claude's context
 14 | 
 15 | - **Smart Conversation Management**:
 16 |   - Detects active conversations using file modification times
 17 |   - Handles multiple concurrent conversations
 18 |   - Filters out ended conversations automatically
 19 |   - Supports context clearing when needed
 20 | 
 21 | - **Optimized Parameters**:
 22 |   - Model-specific context limits:
 23 |     * DeepSeek: 50,000 characters for focused reasoning
 24 |     * Claude: 600,000 characters for comprehensive responses
 25 |   - Recommended settings:
 26 |     * temperature: 0.7 for balanced creativity
 27 |     * top_p: 1.0 for full probability distribution
 28 |     * repetition_penalty: 1.0 to prevent repetition
 29 | 
 30 | ## Installation
 31 | 
 32 | ### Installing via Smithery
 33 | 
 34 | To install DeepSeek Thinking with Claude 3.5 Sonnet for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@newideas99/Deepseek-Thinking-Claude-3.5-Sonnet-CLINE-MCP):
 35 | 
 36 | ```bash
 37 | npx -y @smithery/cli install @newideas99/Deepseek-Thinking-Claude-3.5-Sonnet-CLINE-MCP --client claude
 38 | ```
 39 | 
 40 | ### Manual Installation
 41 | 1. Clone the repository:
 42 | ```bash
 43 | git clone https://github.com/yourusername/Deepseek-Thinking-Claude-3.5-Sonnet-CLINE-MCP.git
 44 | cd Deepseek-Thinking-Claude-3.5-Sonnet-CLINE-MCP
 45 | ```
 46 | 
 47 | 2. Install dependencies:
 48 | ```bash
 49 | npm install
 50 | ```
 51 | 
 52 | 3. Create a `.env` file with your OpenRouter API key:
 53 | ```env
 54 | # Required: OpenRouter API key for both DeepSeek and Claude models
 55 | OPENROUTER_API_KEY=your_openrouter_api_key_here
 56 | 
 57 | # Optional: Model configuration (defaults shown below)
 58 | DEEPSEEK_MODEL=deepseek/deepseek-r1  # DeepSeek model for reasoning
 59 | CLAUDE_MODEL=anthropic/claude-3.5-sonnet:beta  # Claude model for responses
 60 | ```
 61 | 
 62 | 4. Build the server:
 63 | ```bash
 64 | npm run build
 65 | ```
 66 | 
 67 | ## Usage with Cline
 68 | 
 69 | Add to your Cline MCP settings (usually in `~/.vscode/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`):
 70 | 
 71 | ```json
 72 | {
 73 |   "mcpServers": {
 74 |     "deepseek-claude": {
 75 |       "command": "/path/to/node",
 76 |       "args": ["/path/to/Deepseek-Thinking-Claude-3.5-Sonnet-CLINE-MCP/build/index.js"],
 77 |       "env": {
 78 |         "OPENROUTER_API_KEY": "your_key_here"
 79 |       },
 80 |       "disabled": false,
 81 |       "autoApprove": []
 82 |     }
 83 |   }
 84 | }
 85 | ```
 86 | 
 87 | ## Tool Usage
 88 | 
 89 | The server provides two tools for generating and monitoring responses:
 90 | 
 91 | ### generate_response
 92 | 
 93 | Main tool for generating responses with the following parameters:
 94 | 
 95 | ```typescript
 96 | {
 97 |   "prompt": string,           // Required: The question or prompt
 98 |   "showReasoning"?: boolean, // Optional: Show DeepSeek's reasoning process
 99 |   "clearContext"?: boolean,  // Optional: Clear conversation history
100 |   "includeHistory"?: boolean // Optional: Include Cline conversation history
101 | }
102 | ```
103 | 
104 | ### check_response_status
105 | 
106 | Tool for checking the status of a response generation task:
107 | 
108 | ```typescript
109 | {
110 |   "taskId": string  // Required: The task ID from generate_response
111 | }
112 | ```
113 | 
114 | ### Response Polling
115 | 
116 | The server uses a polling mechanism to handle long-running requests:
117 | 
118 | 1. Initial Request:
119 |    - `generate_response` returns immediately with a task ID
120 |    - Response format: `{"taskId": "uuid-here"}`
121 | 
122 | 2. Status Checking:
123 |    - Use `check_response_status` to poll the task status
124 |    - **Note:** Responses can take up to 60 seconds to complete
125 |    - Status progresses through: pending → reasoning → responding → complete
126 | 
127 | Example usage in Cline:
128 | ```typescript
129 | // Initial request
130 | const result = await use_mcp_tool({
131 |   server_name: "deepseek-claude",
132 |   tool_name: "generate_response",
133 |   arguments: {
134 |     prompt: "What is quantum computing?",
135 |     showReasoning: true
136 |   }
137 | });
138 | 
139 | // Get taskId from result
140 | const taskId = JSON.parse(result.content[0].text).taskId;
141 | 
142 | // Poll for status (may need multiple checks over ~60 seconds)
143 | const status = await use_mcp_tool({
144 |   server_name: "deepseek-claude",
145 |   tool_name: "check_response_status",
146 |   arguments: { taskId }
147 | });
148 | 
149 | // Example status response when complete:
150 | {
151 |   "status": "complete",
152 |   "reasoning": "...",  // If showReasoning was true
153 |   "response": "..."    // The final response
154 | }
155 | ```
156 | 
157 | ## Development
158 | 
159 | For development with auto-rebuild:
160 | ```bash
161 | npm run watch
162 | ```
163 | 
164 | ## How It Works
165 | 
166 | 1. **Reasoning Stage (DeepSeek R1)**:
167 |    - Uses OpenRouter's reasoning tokens feature
168 |    - Prompt is modified to output 'done' while capturing reasoning
169 |    - Reasoning is extracted from response metadata
170 | 
171 | 2. **Response Stage (Claude 3.5 Sonnet)**:
172 |    - Receives the original prompt and DeepSeek's reasoning
173 |    - Generates final response incorporating the reasoning
174 |    - Maintains conversation context and history
175 | 
176 | ## License
177 | 
178 | MIT License - See LICENSE file for details.
179 | 
180 | ## Credits
181 | 
182 | Based on the RAT (Retrieval Augmented Thinking) concept by [Skirano](https://x.com/skirano/status/1881922469411643413), which enhances AI responses through structured reasoning and knowledge retrieval.
183 | 
184 | This implementation specifically combines DeepSeek R1's reasoning capabilities with Claude 3.5 Sonnet's response generation through OpenRouter's unified API.
185 | 
```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2022",
 4 |     "module": "Node16",
 5 |     "moduleResolution": "Node16",
 6 |     "outDir": "./build",
 7 |     "rootDir": "./src",
 8 |     "strict": true,
 9 |     "esModuleInterop": true,
10 |     "skipLibCheck": true,
11 |     "forceConsistentCasingInFileNames": true
12 |   },
13 |   "include": ["src/**/*"],
14 |   "exclude": ["node_modules"]
15 | }
16 | 
```

--------------------------------------------------------------------------------
/smithery.yaml:
--------------------------------------------------------------------------------

```yaml
 1 | # Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml
 2 | 
 3 | startCommand:
 4 |   type: stdio
 5 |   configSchema:
 6 |     # JSON Schema defining the configuration options for the MCP.
 7 |     type: object
 8 |     required:
 9 |       - openrouterApiKey
10 |     properties:
11 |       openrouterApiKey:
12 |         type: string
13 |         description: The API key for accessing the OpenRouter service.
14 |   commandFunction:
15 |     # A function that produces the CLI command to start the MCP on stdio.
16 |     |-
17 |     (config) => ({ command: 'node', args: ['build/index.js'], env: { OPENROUTER_API_KEY: config.openrouterApiKey } })
18 | 
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "deepseek-thinking-claude-3-5-sonnet-cline-mcp",
 3 |   "version": "0.1.0",
 4 |   "description": "MCP server that combines DeepSeek's reasoning with Claude 3.5 Sonnet's response generation through Cline",
 5 |   "private": true,
 6 |   "type": "module",
 7 |   "bin": {
 8 |     "deepseek-thinking-claude-mcp": "./build/index.js"
 9 |   },
10 |   "files": [
11 |     "build"
12 |   ],
13 |   "scripts": {
14 |     "build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
15 |     "prepare": "npm run build",
16 |     "watch": "tsc --watch",
17 |     "inspector": "npx @modelcontextprotocol/inspector build/index.js"
18 |   },
19 |   "dependencies": {
20 |     "@anthropic-ai/sdk": "^0.36.2",
21 |     "@modelcontextprotocol/sdk": "0.6.0",
22 |     "dotenv": "^16.4.7",
23 |     "openai": "^4.80.1",
24 |     "uuid": "^11.0.5"
25 |   },
26 |   "devDependencies": {
27 |     "@types/node": "^20.11.24",
28 |     "@types/uuid": "^10.0.0",
29 |     "typescript": "^5.3.3"
30 |   }
31 | }
32 | 
```

--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------

```dockerfile
 1 | # Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
 2 | # Stage 1: Build the application using Node.js
 3 | FROM node:18-alpine AS builder
 4 | 
 5 | # Set working directory
 6 | WORKDIR /app
 7 | 
 8 | # Copy package.json and package-lock.json to the working directory
 9 | COPY package.json package-lock.json ./
10 | 
11 | # Install dependencies
12 | RUN npm install
13 | 
14 | # Copy source files
15 | COPY src ./src
16 | 
17 | # Build the project
18 | RUN npm run build
19 | 
20 | # Stage 2: Create a lightweight image for production
21 | FROM node:18-alpine
22 | 
23 | # Set working directory
24 | WORKDIR /app
25 | 
26 | # Copy built files from builder
27 | COPY --from=builder /app/build ./build
28 | 
29 | # Copy necessary files
30 | COPY package.json package-lock.json ./
31 | 
32 | # Install only production dependencies
33 | RUN npm install --omit=dev
34 | 
35 | # Environment variables
36 | ENV NODE_ENV=production
37 | 
38 | # Entrypoint command to run the MCP server
39 | ENTRYPOINT ["node", "build/index.js"]
40 | 
41 | # Command to start the server
42 | CMD ["node", "build/index.js"]
43 | 
```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | #!/usr/bin/env node
  2 | import { Server } from '@modelcontextprotocol/sdk/server/index.js';
  3 | import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
  4 | import {
  5 |   CallToolRequestSchema,
  6 |   ErrorCode,
  7 |   ListToolsRequestSchema,
  8 |   McpError,
  9 | } from '@modelcontextprotocol/sdk/types.js';
 10 | import { OpenAI } from 'openai';
 11 | import dotenv from 'dotenv';
 12 | import * as os from 'os';
 13 | import * as path from 'path';
 14 | import * as fs from 'fs/promises';
 15 | import { v4 as uuidv4 } from 'uuid';
 16 | 
 17 | // Load environment variables
 18 | dotenv.config();
 19 | 
 20 | // Debug logging
 21 | const DEBUG = true;
 22 | const log = (...args: any[]) => {
 23 |   if (DEBUG) {
 24 |     console.error('[DEEPSEEK-CLAUDE MCP]', ...args);
 25 |   }
 26 | };
 27 | 
 28 | // Constants
 29 | const DEEPSEEK_MODEL = "deepseek/deepseek-r1";
 30 | const CLAUDE_MODEL = "anthropic/claude-3.5-sonnet:beta";
 31 | 
 32 | interface ConversationEntry {
 33 |   timestamp: number;
 34 |   prompt: string;
 35 |   reasoning: string;
 36 |   response: string;
 37 |   model: string;
 38 | }
 39 | 
 40 | interface ConversationContext {
 41 |   entries: ConversationEntry[];
 42 |   maxEntries: number;
 43 | }
 44 | 
 45 | interface GenerateResponseArgs {
 46 |   prompt: string;
 47 |   showReasoning?: boolean;
 48 |   clearContext?: boolean;
 49 |   includeHistory?: boolean;
 50 | }
 51 | 
 52 | interface CheckResponseStatusArgs {
 53 |   taskId: string;
 54 | }
 55 | 
 56 | interface TaskStatus {
 57 |   status: 'pending' | 'reasoning' | 'responding' | 'complete' | 'error';
 58 |   prompt: string;
 59 |   showReasoning?: boolean;
 60 |   reasoning?: string;
 61 |   response?: string;
 62 |   error?: string;
 63 |   timestamp: number;
 64 | }
 65 | 
 66 | const isValidCheckResponseStatusArgs = (args: any): args is CheckResponseStatusArgs =>
 67 |   typeof args === 'object' &&
 68 |   args !== null &&
 69 |   typeof args.taskId === 'string';
 70 | 
 71 | interface ClaudeMessage {
 72 |   role: 'user' | 'assistant';
 73 |   content: string | { type: string; text: string }[];
 74 | }
 75 | 
 76 | interface UiMessage {
 77 |   ts: number;
 78 |   type: string;
 79 |   say?: string;
 80 |   ask?: string;
 81 |   text: string;
 82 |   conversationHistoryIndex: number;
 83 | }
 84 | 
 85 | const isValidGenerateResponseArgs = (args: any): args is GenerateResponseArgs =>
 86 |   typeof args === 'object' &&
 87 |   args !== null &&
 88 |   typeof args.prompt === 'string' &&
 89 |   (args.showReasoning === undefined || typeof args.showReasoning === 'boolean') &&
 90 |   (args.clearContext === undefined || typeof args.clearContext === 'boolean') &&
 91 |   (args.includeHistory === undefined || typeof args.includeHistory === 'boolean');
 92 | 
 93 | function getClaudePath(): string {
 94 |   const homeDir = os.homedir();
 95 |   switch (process.platform) {
 96 |     case 'win32':
 97 |       return path.join(homeDir, 'AppData', 'Roaming', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'tasks');
 98 |     case 'darwin':
 99 |       return path.join(homeDir, 'Library', 'Application Support', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'tasks');
100 |     default: // linux
101 |       return path.join(homeDir, '.config', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'tasks');
102 |   }
103 | }
104 | 
105 | async function findActiveConversation(): Promise<ClaudeMessage[] | null> {
106 |   try {
107 |     const tasksPath = getClaudePath();
108 |     const dirs = await fs.readdir(tasksPath);
109 |     
110 |     // Get modification time for each api_conversation_history.json
111 |     const dirStats = await Promise.all(
112 |       dirs.map(async (dir) => {
113 |         try {
114 |           const historyPath = path.join(tasksPath, dir, 'api_conversation_history.json');
115 |           const stats = await fs.stat(historyPath);
116 |           const uiPath = path.join(tasksPath, dir, 'ui_messages.json');
117 |           const uiContent = await fs.readFile(uiPath, 'utf8');
118 |           const uiMessages: UiMessage[] = JSON.parse(uiContent);
119 |           const hasEnded = uiMessages.some(m => m.type === 'conversation_ended');
120 |           
121 |           return {
122 |             dir,
123 |             mtime: stats.mtime.getTime(),
124 |             hasEnded
125 |           };
126 |         } catch (error) {
127 |           log('Error checking folder:', dir, error);
128 |           return null;
129 |         }
130 |       })
131 |     );
132 | 
133 |     // Filter out errors and ended conversations, then sort by modification time
134 |     const sortedDirs = dirStats
135 |       .filter((stat): stat is NonNullable<typeof stat> => 
136 |         stat !== null && !stat.hasEnded
137 |       )
138 |       .sort((a, b) => b.mtime - a.mtime);
139 | 
140 |     // Use most recently modified active conversation
141 |     const latest = sortedDirs[0]?.dir;
142 |     if (!latest) {
143 |       log('No active conversations found');
144 |       return null;
145 |     }
146 |     
147 |     const historyPath = path.join(tasksPath, latest, 'api_conversation_history.json');
148 |     const history = await fs.readFile(historyPath, 'utf8');
149 |     return JSON.parse(history);
150 |   } catch (error) {
151 |     log('Error finding active conversation:', error);
152 |     return null;
153 |   }
154 | }
155 | 
156 | function formatHistoryForModel(history: ClaudeMessage[], isDeepSeek: boolean): string {
157 |   const maxLength = isDeepSeek ? 50000 : 600000; // 50k chars for DeepSeek, 600k for Claude
158 |   const formattedMessages = [];
159 |   let totalLength = 0;
160 |   
161 |   // Process messages in reverse chronological order to get most recent first
162 |   for (let i = history.length - 1; i >= 0; i--) {
163 |     const msg = history[i];
164 |     const content = Array.isArray(msg.content)
165 |       ? msg.content.map(c => c.text).join('\n')
166 |       : msg.content;
167 |     
168 |     const formattedMsg = `${msg.role === 'user' ? 'Human' : 'Assistant'}: ${content}`;
169 |     const msgLength = formattedMsg.length;
170 |     
171 |     // Stop adding messages if we'd exceed the limit
172 |     if (totalLength + msgLength > maxLength) {
173 |       break;
174 |     }
175 |     
176 |     formattedMessages.push(formattedMsg); // Add most recent messages first
177 |     totalLength += msgLength;
178 |   }
179 |   
180 |   // Reverse to get chronological order
181 |   return formattedMessages.reverse().join('\n\n');
182 | }
183 | 
184 | class DeepseekClaudeServer {
185 |   private server: Server;
186 |   private openrouterClient: OpenAI;
187 |   private context: ConversationContext = {
188 |     entries: [],
189 |     maxEntries: 10
190 |   };
191 |   private activeTasks: Map<string, TaskStatus> = new Map();
192 | 
193 |   constructor() {
194 |     log('Initializing API clients...');
195 |     
196 |     // Initialize OpenRouter client
197 |     this.openrouterClient = new OpenAI({
198 |       baseURL: "https://openrouter.ai/api/v1",
199 |       apiKey: process.env.OPENROUTER_API_KEY
200 |     });
201 |     log('OpenRouter client initialized');
202 | 
203 |     // Initialize MCP server
204 |     this.server = new Server(
205 |       {
206 |         name: 'deepseek-thinking-claude-mcp',
207 |         version: '0.1.0',
208 |       },
209 |       {
210 |         capabilities: {
211 |           tools: {},
212 |         },
213 |       }
214 |     );
215 | 
216 |     this.setupToolHandlers();
217 |     
218 |     // Error handling
219 |     this.server.onerror = (error) => console.error('[MCP Error]', error);
220 |     process.on('SIGINT', async () => {
221 |       await this.server.close();
222 |       process.exit(0);
223 |     });
224 |   }
225 | 
226 |   private addToContext(entry: ConversationEntry) {
227 |     this.context.entries.push(entry);
228 |     if (this.context.entries.length > this.context.maxEntries) {
229 |       this.context.entries.shift();  // Remove oldest
230 |     }
231 |   }
232 | 
233 |   private formatContextForPrompt(): string {
234 |     return this.context.entries
235 |       .map(entry => `Question: ${entry.prompt}\nReasoning: ${entry.reasoning}\nAnswer: ${entry.response}`)
236 |       .join('\n\n');
237 |   }
238 | 
239 |   private setupToolHandlers() {
240 |     this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
241 |       tools: [
242 |         {
243 |           name: 'generate_response',
244 |           description: 'Generate a response using DeepSeek\'s reasoning and Claude\'s response generation through OpenRouter.',
245 |           inputSchema: {
246 |             type: 'object',
247 |             properties: {
248 |               prompt: {
249 |                 type: 'string',
250 |                 description: 'The user\'s input prompt'
251 |               },
252 |               showReasoning: {
253 |                 type: 'boolean',
254 |                 description: 'Whether to include reasoning in response',
255 |                 default: false
256 |               },
257 |               clearContext: {
258 |                 type: 'boolean',
259 |                 description: 'Clear conversation history before this request',
260 |                 default: false
261 |               },
262 |               includeHistory: {
263 |                 type: 'boolean',
264 |                 description: 'Include Cline conversation history for context',
265 |                 default: true
266 |               }
267 |             },
268 |             required: ['prompt']
269 |           }
270 |         },
271 |         {
272 |           name: 'check_response_status',
273 |           description: 'Check the status of a response generation task',
274 |           inputSchema: {
275 |             type: 'object',
276 |             properties: {
277 |               taskId: {
278 |                 type: 'string',
279 |                 description: 'The task ID returned by generate_response'
280 |               }
281 |             },
282 |             required: ['taskId']
283 |           }
284 |         }
285 |       ]
286 |     }));
287 | 
288 |     this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
289 |       if (request.params.name === 'generate_response') {
290 |         if (!isValidGenerateResponseArgs(request.params.arguments)) {
291 |           throw new McpError(
292 |             ErrorCode.InvalidParams,
293 |             'Invalid generate_response arguments'
294 |           );
295 |         }
296 | 
297 |         const taskId = uuidv4();
298 |         const { prompt, showReasoning, clearContext, includeHistory } = request.params.arguments;
299 | 
300 |         // Initialize task status
301 |         this.activeTasks.set(taskId, {
302 |           status: 'pending',
303 |           prompt,
304 |           showReasoning,
305 |           timestamp: Date.now()
306 |         });
307 | 
308 |         // Start processing in background
309 |         this.processTask(taskId, clearContext, includeHistory).catch(error => {
310 |           log('Error processing task:', error);
311 |           this.activeTasks.set(taskId, {
312 |             ...this.activeTasks.get(taskId)!,
313 |             status: 'error',
314 |             error: error.message
315 |           });
316 |         });
317 | 
318 |         // Return task ID immediately
319 |         return {
320 |           content: [
321 |             {
322 |               type: 'text',
323 |               text: JSON.stringify({ taskId })
324 |             }
325 |           ]
326 |         };
327 |       } else if (request.params.name === 'check_response_status') {
328 |         if (!isValidCheckResponseStatusArgs(request.params.arguments)) {
329 |           throw new McpError(
330 |             ErrorCode.InvalidParams,
331 |             'Invalid check_response_status arguments'
332 |           );
333 |         }
334 | 
335 |         const taskId = request.params.arguments.taskId;
336 |         const task = this.activeTasks.get(taskId);
337 | 
338 |         if (!task) {
339 |           throw new McpError(
340 |             ErrorCode.InvalidRequest,
341 |             `No task found with ID: ${taskId}`
342 |           );
343 |         }
344 | 
345 |         return {
346 |           content: [
347 |             {
348 |               type: 'text',
349 |               text: JSON.stringify({
350 |                 status: task.status,
351 |                 reasoning: task.showReasoning ? task.reasoning : undefined,
352 |                 response: task.status === 'complete' ? task.response : undefined,
353 |                 error: task.error
354 |               })
355 |             }
356 |           ]
357 |         };
358 |       } else {
359 |         throw new McpError(
360 |           ErrorCode.MethodNotFound,
361 |           `Unknown tool: ${request.params.name}`
362 |         );
363 |       }
364 |     });
365 |   }
366 | 
367 |   private async processTask(taskId: string, clearContext?: boolean, includeHistory?: boolean): Promise<void> {
368 |     const task = this.activeTasks.get(taskId);
369 |     if (!task) {
370 |       throw new Error(`No task found with ID: ${taskId}`);
371 |     }
372 |     
373 |     try {
374 |       if (clearContext) {
375 |         this.context.entries = [];
376 |       }
377 | 
378 |       // Update status to reasoning
379 |       this.activeTasks.set(taskId, {
380 |         ...task,
381 |         status: 'reasoning'
382 |       });
383 | 
384 |       // Get Cline conversation history if requested
385 |       let history: ClaudeMessage[] | null = null;
386 |       if (includeHistory !== false) {
387 |         history = await findActiveConversation();
388 |       }
389 | 
390 |       // Get DeepSeek reasoning with limited history
391 |       const reasoningHistory = history ? formatHistoryForModel(history, true) : '';
392 |       const reasoningPrompt = reasoningHistory 
393 |         ? `${reasoningHistory}\n\nNew question: ${task.prompt}`
394 |         : task.prompt;
395 |       const reasoning = await this.getDeepseekReasoning(reasoningPrompt);
396 | 
397 |       // Update status with reasoning
398 |       this.activeTasks.set(taskId, {
399 |         ...task,
400 |         status: 'responding',
401 |         reasoning
402 |       });
403 | 
404 |       // Get final response with full history
405 |       const responseHistory = history ? formatHistoryForModel(history, false) : '';
406 |       const fullPrompt = responseHistory 
407 |         ? `${responseHistory}\n\nCurrent task: ${task.prompt}`
408 |         : task.prompt;
409 |       const response = await this.getFinalResponse(fullPrompt, reasoning);
410 | 
411 |       // Add to context after successful response
412 |       this.addToContext({
413 |         timestamp: Date.now(),
414 |         prompt: task.prompt,
415 |         reasoning,
416 |         response,
417 |         model: CLAUDE_MODEL
418 |       });
419 | 
420 |       // Update status to complete
421 |       this.activeTasks.set(taskId, {
422 |         ...task,
423 |         status: 'complete',
424 |         reasoning,
425 |         response,
426 |         timestamp: Date.now()
427 |       });
428 |     } catch (error) {
429 |       // Update status to error
430 |       this.activeTasks.set(taskId, {
431 |         ...task,
432 |         status: 'error',
433 |         error: error instanceof Error ? error.message : 'Unknown error',
434 |         timestamp: Date.now()
435 |       });
436 |       throw error;
437 |     }
438 |   }
439 | 
440 |   private async getDeepseekReasoning(prompt: string): Promise<string> {
441 |     const contextPrompt = this.context.entries.length > 0
442 |       ? `Previous conversation:\n${this.formatContextForPrompt()}\n\nNew question: ${prompt}`
443 |       : prompt;
444 | 
445 |     try {
446 |       // Get reasoning from DeepSeek
447 |       const response = await this.openrouterClient.chat.completions.create({
448 |         model: DEEPSEEK_MODEL,
449 |         messages: [{ 
450 |           role: "user", 
451 |           content: contextPrompt
452 |         }],
453 |         include_reasoning: true,
454 |         temperature: 0.7,
455 |         top_p: 1
456 |       } as any);
457 | 
458 |       // Get reasoning from response
459 |       const responseData = response as any;
460 |       if (!responseData.choices?.[0]?.message?.reasoning) {
461 |         throw new Error('No reasoning received from DeepSeek');
462 |       }
463 |       return responseData.choices[0].message.reasoning;
464 |     } catch (error) {
465 |       log('Error in getDeepseekReasoning:', error);
466 |       throw error;
467 |     }
468 |   }
469 | 
470 |   private async getFinalResponse(prompt: string, reasoning: string): Promise<string> {
471 |     try {
472 |       // Create messages array with proper structure
473 |       const messages = [
474 |         // First the user's question
475 |         {
476 |           role: "user" as const,
477 |           content: prompt
478 |         },
479 |         // Then the reasoning as assistant's thoughts
480 |         {
481 |           role: "assistant" as const,
482 |           content: `<thinking>${reasoning}</thinking>`
483 |         }
484 |       ];
485 | 
486 |       // If we have context, prepend it as previous turns
487 |       if (this.context.entries.length > 0) {
488 |         const contextMessages = this.context.entries.flatMap(entry => [
489 |           {
490 |             role: "user" as const,
491 |             content: entry.prompt
492 |           },
493 |           {
494 |             role: "assistant" as const,
495 |             content: entry.response
496 |           }
497 |         ]);
498 |         messages.unshift(...contextMessages);
499 |       }
500 | 
501 |       const response = await this.openrouterClient.chat.completions.create({
502 |         model: CLAUDE_MODEL,
503 |         messages: messages,
504 |         temperature: 0.7,
505 |         top_p: 1,
506 |         repetition_penalty: 1
507 |       } as any);
508 |       
509 |       return response.choices[0].message.content || "Error: No response content";
510 |     } catch (error) {
511 |       log('Error in getFinalResponse:', error);
512 |       throw error;
513 |     }
514 |   }
515 | 
516 |   async run() {
517 |     const transport = new StdioServerTransport();
518 |     await this.server.connect(transport);
519 |     console.error('DeepSeek-Claude MCP server running on stdio');
520 |   }
521 | }
522 | 
523 | const server = new DeepseekClaudeServer();
524 | server.run().catch(console.error);
525 | 
```