Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
"express": "^5.0.1",
"express-rate-limit": "^7.5.0",
"pkce-challenge": "^5.0.0",
"raw-body": "^3.0.0",
"zod": "^3.23.8",
"zod-to-json-schema": "^3.24.1"
},
Expand Down Expand Up @@ -100,4 +99,4 @@
"resolutions": {
"strip-ansi": "6.0.1"
}
}
}
29 changes: 26 additions & 3 deletions src/server/sse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import { randomUUID } from "node:crypto";
import { IncomingMessage, ServerResponse } from "node:http";
import { Transport } from "../shared/transport.js";
import { JSONRPCMessage, JSONRPCMessageSchema, MessageExtraInfo, RequestInfo } from "../types.js";
import getRawBody from "raw-body";
import contentType from "content-type";
import { AuthInfo } from "./auth/types.js";
import { URL } from 'url';

const MAXIMUM_MESSAGE_SIZE = "4mb";
const MAXIMUM_MESSAGE_SIZE = 4 * 1024 * 1024; // 4MB

/**
* Configuration options for SSEServerTransport.
Expand Down Expand Up @@ -161,7 +160,7 @@ export class SSEServerTransport implements Transport {

body = parsedBody ?? await getRawBody(req, {
limit: MAXIMUM_MESSAGE_SIZE,
encoding: ct.parameters.charset ?? "utf-8",
encoding: (ct.parameters.charset as BufferEncoding) ?? "utf-8",
});
} catch (error) {
res.writeHead(400).end(String(error));
Expand Down Expand Up @@ -219,3 +218,27 @@ export class SSEServerTransport implements Transport {
return this._sessionId;
}
}

export function getRawBody(req: IncomingMessage, { limit, encoding }: { limit: number, encoding: BufferEncoding }) {
return new Promise<string>((resolve, reject) => {
let received = 0;

const chunks: Buffer[] = [];
req.on("data", (chunk: Buffer) => {
received += chunk.length;
if (received > limit)
return reject(new Error(`Message size exceeds limit of ${limit} bytes`));
chunks.push(chunk);
});
req.on('end', () => {
try {
resolve(Buffer.concat(chunks).toString(encoding));
} catch (error) {
reject(error);
}
});
req.on('error', (error) => {
reject(error);
});
});
}
8 changes: 4 additions & 4 deletions src/server/streamableHttp.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { IncomingMessage, ServerResponse } from "node:http";
import { Transport } from "../shared/transport.js";
import { MessageExtraInfo, RequestInfo, isInitializeRequest, isJSONRPCError, isJSONRPCRequest, isJSONRPCResponse, JSONRPCMessage, JSONRPCMessageSchema, RequestId, SUPPORTED_PROTOCOL_VERSIONS, DEFAULT_NEGOTIATED_PROTOCOL_VERSION } from "../types.js";
import getRawBody from "raw-body";
import contentType from "content-type";
import { randomUUID } from "node:crypto";
import { AuthInfo } from "./auth/types.js";
import { getRawBody } from "./sse.js";

const MAXIMUM_MESSAGE_SIZE = "4mb";
const MAXIMUM_MESSAGE_SIZE = 4 * 1024 * 1024; // 4MB

export type StreamId = string;
export type EventId = string;
Expand Down Expand Up @@ -412,9 +412,9 @@ export class StreamableHTTPServerTransport implements Transport {
const parsedCt = contentType.parse(ct);
const body = await getRawBody(req, {
limit: MAXIMUM_MESSAGE_SIZE,
encoding: parsedCt.parameters.charset ?? "utf-8",
encoding: (parsedCt.parameters.charset as BufferEncoding) ?? "utf-8",
});
rawMessage = JSON.parse(body.toString());
rawMessage = JSON.parse(body);
}

let messages: JSONRPCMessage[];
Expand Down