poe-code 3.0.435 → 3.0.437

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poe-code",
3
- "version": "3.0.435",
3
+ "version": "3.0.437",
4
4
  "description": "CLI tool to configure Poe API for developer workflows.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -242,7 +242,9 @@ export function createHttpServer(options) {
242
242
  };
243
243
  };
244
244
  httpServer.handleRequest = async (req, res) => {
245
- if (!(await authorizeHttpRequest(req, res, "/mcp"))) {
245
+ const { baseUrl } = req;
246
+ const protectedResourcePath = typeof baseUrl === "string" && baseUrl.length > 0 ? baseUrl : "/mcp";
247
+ if (!(await authorizeHttpRequest(req, res, protectedResourcePath))) {
246
248
  return;
247
249
  }
248
250
  await transport.handleRequest(req, res);
@@ -14,6 +14,7 @@ export type HttpObservabilityEvent = {
14
14
  statusCode: number;
15
15
  durationMs: number;
16
16
  sessionId?: string;
17
+ reason?: string;
17
18
  } | {
18
19
  type: "request.error";
19
20
  requestId: string;
@@ -103,6 +104,7 @@ export declare class StreamableHttpTransport {
103
104
  private readonly sseEventHistory;
104
105
  private readonly responseRequestIds;
105
106
  private readonly responseOrigins;
107
+ private readonly responseRejectionReasons;
106
108
  private nextNotificationEventId;
107
109
  private nextRequestId;
108
110
  private activeToolCalls;
@@ -154,6 +156,7 @@ export declare class StreamableHttpTransport {
154
156
  private isRequest;
155
157
  private isToolCallOk;
156
158
  private respondWithJsonRpcError;
159
+ private respondWithRejection;
157
160
  private respondWithStatus;
158
161
  private withSessionHeader;
159
162
  private emit;
@@ -43,6 +43,7 @@ export class StreamableHttpTransport {
43
43
  sseEventHistory = new Map();
44
44
  responseRequestIds = new WeakMap();
45
45
  responseOrigins = new WeakMap();
46
+ responseRejectionReasons = new WeakMap();
46
47
  nextNotificationEventId = 1;
47
48
  nextRequestId = 1;
48
49
  activeToolCalls = 0;
@@ -105,11 +106,15 @@ export class StreamableHttpTransport {
105
106
  });
106
107
  try {
107
108
  if (this.closed) {
108
- this.respondWithStatus(res, 503);
109
+ this.respondWithRejection(res, 503, "transport_closed", "The transport is closed; create or use an active transport.");
109
110
  return;
110
111
  }
111
- if (!this.acceptsHost(req) || !this.acceptsOrigin(req)) {
112
- this.respondWithStatus(res, 403);
112
+ if (!this.acceptsHost(req)) {
113
+ this.respondWithRejection(res, 403, "host_not_allowed", `Host ${JSON.stringify(this.readRequestHost(req))} is not allowed; add it to allowedHosts.`);
114
+ return;
115
+ }
116
+ if (!this.acceptsOrigin(req)) {
117
+ this.respondWithRejection(res, 403, "origin_not_allowed", `Origin ${JSON.stringify(this.readOrigin(req) ?? "")} is not allowed; add it to allowedOrigins.`);
113
118
  return;
114
119
  }
115
120
  switch (req.method) {
@@ -155,7 +160,10 @@ export class StreamableHttpTransport {
155
160
  method: req.method ?? "",
156
161
  statusCode: res.statusCode,
157
162
  durationMs: Date.now() - startedAt,
158
- sessionId: this.readSessionId(req)
163
+ sessionId: this.readSessionId(req),
164
+ ...(res.statusCode < 200 || res.statusCode >= 300
165
+ ? { reason: this.responseRejectionReasons.get(res) ?? "http_error" }
166
+ : {})
159
167
  });
160
168
  }
161
169
  }
@@ -184,7 +192,8 @@ export class StreamableHttpTransport {
184
192
  return;
185
193
  }
186
194
  if (!this.acceptsConfiguredResponse(req)) {
187
- this.respondWithStatus(res, 406);
195
+ const expectedType = this.enableJsonResponse ? "application/json" : "text/event-stream";
196
+ this.respondWithRejection(res, 406, "response_type_not_acceptable", `Accept must allow ${expectedType}.`);
188
197
  return;
189
198
  }
190
199
  let classified;
@@ -216,11 +225,11 @@ export class StreamableHttpTransport {
216
225
  const headerSessionId = this.readSessionId(req);
217
226
  if (headerSessionId === undefined) {
218
227
  if (initMessage === undefined) {
219
- this.respondWithStatus(res, 400);
228
+ this.respondWithRejection(res, 400, "session_id_required", "Mcp-Session-Id is required; initialize a session first.");
220
229
  return;
221
230
  }
222
231
  if (this.maxSessions !== undefined && this.sessionCount() >= this.maxSessions) {
223
- this.respondWithStatus(res, 503);
232
+ this.respondWithRejection(res, 503, "session_limit_reached", "The server has reached its session limit; close a session or retry later.");
224
233
  return;
225
234
  }
226
235
  const newSessionId = this.sessionIdGenerator();
@@ -240,14 +249,14 @@ export class StreamableHttpTransport {
240
249
  else {
241
250
  activeSession = this.getActiveSession(headerSessionId, req);
242
251
  if (activeSession === undefined) {
243
- this.respondWithStatus(res, 404);
252
+ this.respondWithRejection(res, 404, "session_not_found", "Session was not found or has expired; reinitialize the session.");
244
253
  return;
245
254
  }
246
255
  sessionId = headerSessionId;
247
256
  this.touchSession(sessionId);
248
257
  if (activeSession.protocolVersion !== undefined &&
249
258
  !this.acceptsProtocolVersion(req, activeSession.protocolVersion)) {
250
- this.respondWithStatus(res, 400);
259
+ this.respondWithRejection(res, 400, "protocol_version_mismatch", `MCP-Protocol-Version must match the session protocol version ${activeSession.protocolVersion}.`);
251
260
  return;
252
261
  }
253
262
  await this.ensureLocalMessageSession(sessionId, activeSession);
@@ -377,30 +386,30 @@ export class StreamableHttpTransport {
377
386
  return;
378
387
  }
379
388
  if (!this.acceptsResponseType(req, "text/event-stream")) {
380
- this.respondWithStatus(res, 406);
389
+ this.respondWithRejection(res, 406, "response_type_not_acceptable", "Accept must allow text/event-stream.");
381
390
  return;
382
391
  }
383
392
  const sessionId = this.readSessionId(req);
384
393
  if (sessionId === undefined) {
385
- this.respondWithStatus(res, 400);
394
+ this.respondWithRejection(res, 400, "session_id_required", "Mcp-Session-Id is required; initialize a session first.");
386
395
  return;
387
396
  }
388
397
  const session = this.getActiveSession(sessionId, req);
389
398
  if (session === undefined) {
390
- this.respondWithStatus(res, 404);
399
+ this.respondWithRejection(res, 404, "session_not_found", "Session was not found or has expired; reinitialize the session.");
391
400
  return;
392
401
  }
393
402
  this.touchSession(sessionId);
394
403
  if (session.initialized &&
395
404
  session.protocolVersion !== undefined &&
396
405
  !this.acceptsProtocolVersion(req, session.protocolVersion)) {
397
- this.respondWithStatus(res, 400);
406
+ this.respondWithRejection(res, 400, "protocol_version_mismatch", `MCP-Protocol-Version must match the session protocol version ${session.protocolVersion}.`);
398
407
  return;
399
408
  }
400
409
  await this.ensureLocalMessageSession(sessionId, session);
401
410
  const existingStreams = this.sseStreams.get(sessionId);
402
411
  if ((existingStreams?.size ?? 0) >= this.maxStreamsPerSession) {
403
- this.respondWithStatus(res, 409);
412
+ this.respondWithRejection(res, 409, "stream_limit_reached", "This session already has the maximum number of streams; close a stream and retry.");
404
413
  return;
405
414
  }
406
415
  let streams = this.sseStreams.get(sessionId);
@@ -454,21 +463,21 @@ export class StreamableHttpTransport {
454
463
  }
455
464
  const sessionId = this.readSessionId(req);
456
465
  if (sessionId === undefined) {
457
- this.respondWithStatus(res, 400);
466
+ this.respondWithRejection(res, 400, "session_id_required", "Mcp-Session-Id is required; initialize a session first.");
458
467
  return;
459
468
  }
460
469
  const session = this.getActiveSession(sessionId, req);
461
470
  if (session === undefined) {
462
- this.respondWithStatus(res, 404);
471
+ this.respondWithRejection(res, 404, "session_not_found", "Session was not found or has expired; reinitialize the session.");
463
472
  return;
464
473
  }
465
474
  if (session.protocolVersion !== undefined &&
466
475
  !this.acceptsProtocolVersion(req, session.protocolVersion)) {
467
- this.respondWithStatus(res, 400);
476
+ this.respondWithRejection(res, 400, "protocol_version_mismatch", `MCP-Protocol-Version must match the session protocol version ${session.protocolVersion}.`);
468
477
  return;
469
478
  }
470
479
  if (!this.deleteSession(sessionId, "client")) {
471
- this.respondWithStatus(res, 404);
480
+ this.respondWithRejection(res, 404, "session_not_found", "Session was not found or has expired; reinitialize the session.");
472
481
  return;
473
482
  }
474
483
  this.respondWithStatus(res, 204);
@@ -841,8 +850,13 @@ export class StreamableHttpTransport {
841
850
  return !(hasOwnProperty(result, "isError") && result.isError === true);
842
851
  }
843
852
  respondWithJsonRpcError(res, statusCode, errorCode, message, id = null) {
853
+ this.responseRejectionReasons.set(res, "json_rpc_error");
844
854
  this.respondWithStatus(res, statusCode, undefined, { "Content-Type": "application/json" }, formatErrorResponse(id, { code: errorCode, message }));
845
855
  }
856
+ respondWithRejection(res, statusCode, reason, message) {
857
+ this.responseRejectionReasons.set(res, reason);
858
+ this.respondWithStatus(res, statusCode, undefined, { "Content-Type": "application/json" }, JSON.stringify({ error: reason, message }));
859
+ }
846
860
  respondWithStatus(res, statusCode, sessionId, headers, body) {
847
861
  res.writeHead(statusCode, this.withSessionHeader(headers, sessionId, res));
848
862
  res.end(body);