@reconcrap/boss-recruit-mcp 1.0.17 → 1.0.18
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 +1 -1
- package/src/index.js +77 -21
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -8,11 +8,18 @@ const require = createRequire(import.meta.url);
|
|
|
8
8
|
const { version: SERVER_VERSION } = require("../package.json");
|
|
9
9
|
const TOOL_NAME = "run_recruit_pipeline";
|
|
10
10
|
const SERVER_NAME = "boss-recruit-mcp";
|
|
11
|
+
const FRAMING_UNKNOWN = "unknown";
|
|
12
|
+
const FRAMING_HEADER = "header";
|
|
13
|
+
const FRAMING_LINE = "line";
|
|
11
14
|
|
|
12
|
-
function writeMessage(message) {
|
|
15
|
+
function writeMessage(message, framing = FRAMING_LINE) {
|
|
13
16
|
const body = JSON.stringify(message);
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
if (framing === FRAMING_HEADER) {
|
|
18
|
+
const header = `Content-Length: ${Buffer.byteLength(body, "utf8")}\r\n\r\n`;
|
|
19
|
+
process.stdout.write(header + body);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
process.stdout.write(`${body}\n`);
|
|
16
23
|
}
|
|
17
24
|
|
|
18
25
|
function createJsonRpcError(id, code, message) {
|
|
@@ -178,42 +185,91 @@ export function startServer() {
|
|
|
178
185
|
const mcpRoot = path.resolve(path.dirname(thisFile), "..");
|
|
179
186
|
const workspaceRoot = envRoot ? path.resolve(envRoot) : path.resolve(mcpRoot, "..");
|
|
180
187
|
let buffer = Buffer.alloc(0);
|
|
188
|
+
let framing = FRAMING_UNKNOWN;
|
|
181
189
|
|
|
182
190
|
process.stdin.on("data", async (chunk) => {
|
|
183
191
|
buffer = Buffer.concat([buffer, chunk]);
|
|
192
|
+
if (buffer.length >= 3 && buffer[0] === 0xef && buffer[1] === 0xbb && buffer[2] === 0xbf) {
|
|
193
|
+
buffer = buffer.slice(3);
|
|
194
|
+
}
|
|
184
195
|
|
|
185
196
|
while (true) {
|
|
186
|
-
const
|
|
187
|
-
|
|
197
|
+
const crlfHeaderEnd = buffer.indexOf("\r\n\r\n");
|
|
198
|
+
const lfHeaderEnd = buffer.indexOf("\n\n");
|
|
199
|
+
const crHeaderEnd = buffer.indexOf("\r\r");
|
|
200
|
+
let headerEnd = -1;
|
|
201
|
+
let headerSeparatorLength = 0;
|
|
202
|
+
if (
|
|
203
|
+
crlfHeaderEnd !== -1
|
|
204
|
+
&& (lfHeaderEnd === -1 || crlfHeaderEnd < lfHeaderEnd)
|
|
205
|
+
&& (crHeaderEnd === -1 || crlfHeaderEnd < crHeaderEnd)
|
|
206
|
+
) {
|
|
207
|
+
headerEnd = crlfHeaderEnd;
|
|
208
|
+
headerSeparatorLength = 4;
|
|
209
|
+
} else if (lfHeaderEnd !== -1 && (crHeaderEnd === -1 || lfHeaderEnd < crHeaderEnd)) {
|
|
210
|
+
headerEnd = lfHeaderEnd;
|
|
211
|
+
headerSeparatorLength = 2;
|
|
212
|
+
} else if (crHeaderEnd !== -1) {
|
|
213
|
+
headerEnd = crHeaderEnd;
|
|
214
|
+
headerSeparatorLength = 2;
|
|
215
|
+
}
|
|
216
|
+
if (headerEnd !== -1) {
|
|
217
|
+
const headerText = buffer.slice(0, headerEnd).toString("utf8");
|
|
218
|
+
const contentLengthLine = headerText
|
|
219
|
+
.split(/\r\n|\n|\r/)
|
|
220
|
+
.find((line) => line.toLowerCase().startsWith("content-length:"));
|
|
188
221
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
222
|
+
if (!contentLengthLine) {
|
|
223
|
+
buffer = buffer.slice(headerEnd + headerSeparatorLength);
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const contentLength = Number.parseInt(contentLengthLine.split(":")[1].trim(), 10);
|
|
228
|
+
if (!Number.isFinite(contentLength) || contentLength < 0) {
|
|
229
|
+
buffer = buffer.slice(headerEnd + headerSeparatorLength);
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
193
232
|
|
|
194
|
-
|
|
195
|
-
|
|
233
|
+
const bodyStart = headerEnd + headerSeparatorLength;
|
|
234
|
+
const bodyEnd = bodyStart + contentLength;
|
|
235
|
+
if (buffer.length < bodyEnd) break;
|
|
236
|
+
|
|
237
|
+
const body = buffer.slice(bodyStart, bodyEnd).toString("utf8");
|
|
238
|
+
buffer = buffer.slice(bodyEnd);
|
|
239
|
+
framing = FRAMING_HEADER;
|
|
240
|
+
|
|
241
|
+
let message;
|
|
242
|
+
try {
|
|
243
|
+
message = JSON.parse(body);
|
|
244
|
+
} catch {
|
|
245
|
+
writeMessage(createJsonRpcError(null, -32700, "Parse error"), FRAMING_HEADER);
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const response = await handleRequest(message, workspaceRoot);
|
|
250
|
+
if (response) writeMessage(response, framing);
|
|
196
251
|
continue;
|
|
197
252
|
}
|
|
198
253
|
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
const
|
|
202
|
-
if (
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
|
|
254
|
+
const newlineIndex = buffer.indexOf("\n");
|
|
255
|
+
if (newlineIndex === -1) break;
|
|
256
|
+
const rawLine = buffer.slice(0, newlineIndex).toString("utf8").replace(/\r$/, "");
|
|
257
|
+
if (/^\s*content-length:/i.test(rawLine)) break;
|
|
258
|
+
buffer = buffer.slice(newlineIndex + 1);
|
|
259
|
+
const line = rawLine.trim();
|
|
260
|
+
if (!line) continue;
|
|
261
|
+
framing = FRAMING_LINE;
|
|
206
262
|
|
|
207
263
|
let message;
|
|
208
264
|
try {
|
|
209
|
-
message = JSON.parse(
|
|
265
|
+
message = JSON.parse(line);
|
|
210
266
|
} catch {
|
|
211
|
-
writeMessage(createJsonRpcError(null, -32700, "Parse error"));
|
|
267
|
+
writeMessage(createJsonRpcError(null, -32700, "Parse error"), FRAMING_LINE);
|
|
212
268
|
continue;
|
|
213
269
|
}
|
|
214
270
|
|
|
215
271
|
const response = await handleRequest(message, workspaceRoot);
|
|
216
|
-
if (response) writeMessage(response);
|
|
272
|
+
if (response) writeMessage(response, framing);
|
|
217
273
|
}
|
|
218
274
|
});
|
|
219
275
|
}
|