deepseek-mcp-bridge 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +9 -0
- package/server.mjs +198 -0
package/package.json
ADDED
package/server.mjs
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import http from 'http';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import os from 'os';
|
|
6
|
+
import crypto from 'crypto';
|
|
7
|
+
|
|
8
|
+
const PORT = 8787;
|
|
9
|
+
|
|
10
|
+
let cookies, storage;
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
const cookiePath = [
|
|
14
|
+
path.join(os.homedir(), 'cookies.json'),
|
|
15
|
+
path.join(os.homedir(), 'cookie.json')
|
|
16
|
+
].find(fs.existsSync);
|
|
17
|
+
const storagePath = path.join(os.homedir(), 'localStorage.json');
|
|
18
|
+
if (cookiePath && fs.existsSync(storagePath)) {
|
|
19
|
+
cookies = JSON.parse(fs.readFileSync(cookiePath, 'utf8'));
|
|
20
|
+
storage = JSON.parse(fs.readFileSync(storagePath, 'utf8'));
|
|
21
|
+
}
|
|
22
|
+
} catch {}
|
|
23
|
+
|
|
24
|
+
function getCookieString() {
|
|
25
|
+
if (Array.isArray(cookies)) return cookies.map(c => c.name + '=' + c.value).join('; ');
|
|
26
|
+
if (cookies?.cookie) return cookies.cookie;
|
|
27
|
+
return Object.entries(cookies || {}).map(([k,v]) => k + '=' + v).join('; ');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function getBearer() {
|
|
31
|
+
try { return JSON.parse(storage.userToken || '{}').value || ''; } catch { return ''; }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function createPowChallenge(targetPath) {
|
|
35
|
+
const res = await fetch('https://chat.deepseek.com/api/v0/chat/create_pow_challenge', {
|
|
36
|
+
method: 'POST',
|
|
37
|
+
headers: {
|
|
38
|
+
'Cookie': getCookieString(),
|
|
39
|
+
'Content-Type': 'application/json',
|
|
40
|
+
'Authorization': 'Bearer ' + getBearer(),
|
|
41
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
|
42
|
+
'Referer': 'https://chat.deepseek.com/',
|
|
43
|
+
'x-client-platform': 'web',
|
|
44
|
+
'x-client-version': '1.7.0',
|
|
45
|
+
'x-app-version': '20241129.1'
|
|
46
|
+
},
|
|
47
|
+
body: JSON.stringify({ target_path: targetPath })
|
|
48
|
+
});
|
|
49
|
+
const data = await res.json();
|
|
50
|
+
return data.data?.biz_data?.challenge || data.data?.challenge || data.challenge;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function solvePow(challenge) {
|
|
54
|
+
const { algorithm, challenge: target, salt, difficulty } = challenge;
|
|
55
|
+
if (algorithm !== 'sha256') throw new Error('Unsupported PoW algorithm');
|
|
56
|
+
let nonce = 0;
|
|
57
|
+
while (nonce <= 1_000_000) {
|
|
58
|
+
const input = `${salt}${target}${nonce}`;
|
|
59
|
+
const hash = crypto.createHash('sha256').update(input).digest('hex');
|
|
60
|
+
let zeroBits = 0;
|
|
61
|
+
for (const char of hash) {
|
|
62
|
+
const val = parseInt(char, 16);
|
|
63
|
+
if (val === 0) zeroBits += 4;
|
|
64
|
+
else { zeroBits += Math.clz32(val) - 28; break; }
|
|
65
|
+
}
|
|
66
|
+
if (zeroBits >= difficulty) break;
|
|
67
|
+
nonce++;
|
|
68
|
+
}
|
|
69
|
+
return nonce;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function chat(prompt) {
|
|
73
|
+
const targetPath = '/api/v0/chat/completion';
|
|
74
|
+
const challenge = await createPowChallenge(targetPath);
|
|
75
|
+
const answer = await solvePow(challenge);
|
|
76
|
+
const powResponse = Buffer.from(
|
|
77
|
+
JSON.stringify({...challenge, answer, target_path: targetPath})
|
|
78
|
+
).toString('base64');
|
|
79
|
+
|
|
80
|
+
const sessionRes = await fetch('https://chat.deepseek.com/api/v0/chat_session/create', {
|
|
81
|
+
method: 'POST',
|
|
82
|
+
headers: {
|
|
83
|
+
'Cookie': getCookieString(),
|
|
84
|
+
'Content-Type': 'application/json',
|
|
85
|
+
'Authorization': 'Bearer ' + getBearer(),
|
|
86
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
|
87
|
+
'Referer': 'https://chat.deepseek.com/',
|
|
88
|
+
'x-client-platform': 'web',
|
|
89
|
+
'x-client-version': '1.7.0',
|
|
90
|
+
'x-app-version': '20241129.1'
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
const sessionData = await sessionRes.json();
|
|
94
|
+
const sessionId = sessionData.data?.biz_data?.id || sessionData.data?.id || '';
|
|
95
|
+
|
|
96
|
+
const chatRes = await fetch('https://chat.deepseek.com/api/v0/chat/completion', {
|
|
97
|
+
method: 'POST',
|
|
98
|
+
headers: {
|
|
99
|
+
'Cookie': getCookieString(),
|
|
100
|
+
'Content-Type': 'application/json',
|
|
101
|
+
'Authorization': 'Bearer ' + getBearer(),
|
|
102
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
|
103
|
+
'Referer': 'https://chat.deepseek.com/',
|
|
104
|
+
'x-ds-pow-response': powResponse,
|
|
105
|
+
'x-client-platform': 'web',
|
|
106
|
+
'x-client-version': '1.7.0',
|
|
107
|
+
'x-app-version': '20241129.1'
|
|
108
|
+
},
|
|
109
|
+
body: JSON.stringify({
|
|
110
|
+
chat_session_id: sessionId,
|
|
111
|
+
model: 'deepseek-chat',
|
|
112
|
+
prompt,
|
|
113
|
+
stream: true,
|
|
114
|
+
ref_file_ids: [],
|
|
115
|
+
thinking_enabled: false,
|
|
116
|
+
search_enabled: false
|
|
117
|
+
})
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
let fullText = '';
|
|
121
|
+
const body = await chatRes.text();
|
|
122
|
+
const lines = body.split('\n');
|
|
123
|
+
for (const line of lines) {
|
|
124
|
+
if (line.startsWith('data:')) {
|
|
125
|
+
try {
|
|
126
|
+
const d = JSON.parse(line.slice(5).trim());
|
|
127
|
+
if (d.v && typeof d.v === 'string' && !d.p) fullText += d.v;
|
|
128
|
+
else if (Array.isArray(d.v)) {
|
|
129
|
+
for (const item of d.v) {
|
|
130
|
+
if (item.v && typeof item.v === 'string' && !item.p) fullText += item.v;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
} catch {}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return fullText.trim() || 'No response';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const server = http.createServer(async (req, res) => {
|
|
140
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
141
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
142
|
+
if (req.method === 'OPTIONS') { res.writeHead(204); res.end(); return; }
|
|
143
|
+
|
|
144
|
+
if (req.method === 'POST' && req.url === '/mcp') {
|
|
145
|
+
const body = await new Promise(r => { let b=''; req.on('data',c=>b+=c); req.on('end',()=>r(b)); });
|
|
146
|
+
let rpc;
|
|
147
|
+
try { rpc = JSON.parse(body); } catch { res.writeHead(400); res.end('Invalid JSON'); return; }
|
|
148
|
+
const { method, id, params } = rpc;
|
|
149
|
+
|
|
150
|
+
const respond = (result) => {
|
|
151
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
152
|
+
res.end(JSON.stringify({ jsonrpc: '2.0', id, result }));
|
|
153
|
+
};
|
|
154
|
+
const error = (code, message) => {
|
|
155
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
156
|
+
res.end(JSON.stringify({ jsonrpc: '2.0', id, error: { code, message } }));
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
try {
|
|
160
|
+
if (method === 'initialize') {
|
|
161
|
+
respond({
|
|
162
|
+
protocolVersion: '0.1.0',
|
|
163
|
+
serverInfo: { name: 'deepseek-mcp-bridge', version: '1.0.0' },
|
|
164
|
+
capabilities: { tools: true }
|
|
165
|
+
});
|
|
166
|
+
} else if (method === 'tools/list') {
|
|
167
|
+
respond({
|
|
168
|
+
tools: [{
|
|
169
|
+
name: 'chat',
|
|
170
|
+
description: 'Send a prompt to DeepSeek and get a response',
|
|
171
|
+
inputSchema: {
|
|
172
|
+
type: 'object',
|
|
173
|
+
properties: { prompt: { type: 'string' } },
|
|
174
|
+
required: ['prompt']
|
|
175
|
+
}
|
|
176
|
+
}]
|
|
177
|
+
});
|
|
178
|
+
} else if (method === 'tools/call') {
|
|
179
|
+
const { name, arguments: args } = params;
|
|
180
|
+
if (name === 'chat') {
|
|
181
|
+
const text = await chat(args.prompt);
|
|
182
|
+
respond({ content: [{ type: 'text', text }] });
|
|
183
|
+
} else {
|
|
184
|
+
error(-32602, 'Unknown tool');
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
error(-32601, 'Method not found');
|
|
188
|
+
}
|
|
189
|
+
} catch (e) {
|
|
190
|
+
error(-32603, e.message);
|
|
191
|
+
}
|
|
192
|
+
} else {
|
|
193
|
+
res.writeHead(404);
|
|
194
|
+
res.end('Not found');
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
server.listen(PORT, '127.0.0.1', () => console.log(`DeepSeek MCP Bridge: http://127.0.0.1:${PORT}`));
|