修改后台权限
This commit is contained in:
172
node_modules/@modelcontextprotocol/sdk/dist/cjs/server/sse.js
generated
vendored
Normal file
172
node_modules/@modelcontextprotocol/sdk/dist/cjs/server/sse.js
generated
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SSEServerTransport = void 0;
|
||||
const node_crypto_1 = require("node:crypto");
|
||||
const node_tls_1 = require("node:tls");
|
||||
const types_js_1 = require("../types.js");
|
||||
const raw_body_1 = __importDefault(require("raw-body"));
|
||||
const content_type_1 = __importDefault(require("content-type"));
|
||||
const node_url_1 = require("node:url");
|
||||
const MAXIMUM_MESSAGE_SIZE = '4mb';
|
||||
/**
|
||||
* Server transport for SSE: this will send messages over an SSE connection and receive messages from HTTP POST requests.
|
||||
*
|
||||
* This transport is only available in Node.js environments.
|
||||
* @deprecated SSEServerTransport is deprecated. Use StreamableHTTPServerTransport instead.
|
||||
*/
|
||||
class SSEServerTransport {
|
||||
/**
|
||||
* Creates a new SSE server transport, which will direct the client to POST messages to the relative or absolute URL identified by `_endpoint`.
|
||||
*/
|
||||
constructor(_endpoint, res, options) {
|
||||
this._endpoint = _endpoint;
|
||||
this.res = res;
|
||||
this._sessionId = (0, node_crypto_1.randomUUID)();
|
||||
this._options = options || { enableDnsRebindingProtection: false };
|
||||
}
|
||||
/**
|
||||
* Validates request headers for DNS rebinding protection.
|
||||
* @returns Error message if validation fails, undefined if validation passes.
|
||||
*/
|
||||
validateRequestHeaders(req) {
|
||||
// Skip validation if protection is not enabled
|
||||
if (!this._options.enableDnsRebindingProtection) {
|
||||
return undefined;
|
||||
}
|
||||
// Validate Host header if allowedHosts is configured
|
||||
if (this._options.allowedHosts && this._options.allowedHosts.length > 0) {
|
||||
const hostHeader = req.headers.host;
|
||||
if (!hostHeader || !this._options.allowedHosts.includes(hostHeader)) {
|
||||
return `Invalid Host header: ${hostHeader}`;
|
||||
}
|
||||
}
|
||||
// Validate Origin header if allowedOrigins is configured
|
||||
if (this._options.allowedOrigins && this._options.allowedOrigins.length > 0) {
|
||||
const originHeader = req.headers.origin;
|
||||
if (originHeader && !this._options.allowedOrigins.includes(originHeader)) {
|
||||
return `Invalid Origin header: ${originHeader}`;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
/**
|
||||
* Handles the initial SSE connection request.
|
||||
*
|
||||
* This should be called when a GET request is made to establish the SSE stream.
|
||||
*/
|
||||
async start() {
|
||||
if (this._sseResponse) {
|
||||
throw new Error('SSEServerTransport already started! If using Server class, note that connect() calls start() automatically.');
|
||||
}
|
||||
this.res.writeHead(200, {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Cache-Control': 'no-cache, no-transform',
|
||||
Connection: 'keep-alive'
|
||||
});
|
||||
// Send the endpoint event
|
||||
// Use a dummy base URL because this._endpoint is relative.
|
||||
// This allows using URL/URLSearchParams for robust parameter handling.
|
||||
const dummyBase = 'http://localhost'; // Any valid base works
|
||||
const endpointUrl = new node_url_1.URL(this._endpoint, dummyBase);
|
||||
endpointUrl.searchParams.set('sessionId', this._sessionId);
|
||||
// Reconstruct the relative URL string (pathname + search + hash)
|
||||
const relativeUrlWithSession = endpointUrl.pathname + endpointUrl.search + endpointUrl.hash;
|
||||
this.res.write(`event: endpoint\ndata: ${relativeUrlWithSession}\n\n`);
|
||||
this._sseResponse = this.res;
|
||||
this.res.on('close', () => {
|
||||
this._sseResponse = undefined;
|
||||
this.onclose?.();
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Handles incoming POST messages.
|
||||
*
|
||||
* This should be called when a POST request is made to send a message to the server.
|
||||
*/
|
||||
async handlePostMessage(req, res, parsedBody) {
|
||||
if (!this._sseResponse) {
|
||||
const message = 'SSE connection not established';
|
||||
res.writeHead(500).end(message);
|
||||
throw new Error(message);
|
||||
}
|
||||
// Validate request headers for DNS rebinding protection
|
||||
const validationError = this.validateRequestHeaders(req);
|
||||
if (validationError) {
|
||||
res.writeHead(403).end(validationError);
|
||||
this.onerror?.(new Error(validationError));
|
||||
return;
|
||||
}
|
||||
const authInfo = req.auth;
|
||||
const host = req.headers.host;
|
||||
const protocol = req.socket instanceof node_tls_1.TLSSocket ? 'https' : 'http';
|
||||
const fullUrl = host && req.url ? new node_url_1.URL(req.url, `${protocol}://${host}`) : undefined;
|
||||
const requestInfo = {
|
||||
headers: req.headers,
|
||||
url: fullUrl
|
||||
};
|
||||
let body;
|
||||
try {
|
||||
const ct = content_type_1.default.parse(req.headers['content-type'] ?? '');
|
||||
if (ct.type !== 'application/json') {
|
||||
throw new Error(`Unsupported content-type: ${ct.type}`);
|
||||
}
|
||||
body =
|
||||
parsedBody ??
|
||||
(await (0, raw_body_1.default)(req, {
|
||||
limit: MAXIMUM_MESSAGE_SIZE,
|
||||
encoding: ct.parameters.charset ?? 'utf-8'
|
||||
}));
|
||||
}
|
||||
catch (error) {
|
||||
res.writeHead(400).end(String(error));
|
||||
this.onerror?.(error);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await this.handleMessage(typeof body === 'string' ? JSON.parse(body) : body, { requestInfo, authInfo });
|
||||
}
|
||||
catch {
|
||||
res.writeHead(400).end(`Invalid message: ${body}`);
|
||||
return;
|
||||
}
|
||||
res.writeHead(202).end('Accepted');
|
||||
}
|
||||
/**
|
||||
* Handle a client message, regardless of how it arrived. This can be used to inform the server of messages that arrive via a means different than HTTP POST.
|
||||
*/
|
||||
async handleMessage(message, extra) {
|
||||
let parsedMessage;
|
||||
try {
|
||||
parsedMessage = types_js_1.JSONRPCMessageSchema.parse(message);
|
||||
}
|
||||
catch (error) {
|
||||
this.onerror?.(error);
|
||||
throw error;
|
||||
}
|
||||
this.onmessage?.(parsedMessage, extra);
|
||||
}
|
||||
async close() {
|
||||
this._sseResponse?.end();
|
||||
this._sseResponse = undefined;
|
||||
this.onclose?.();
|
||||
}
|
||||
async send(message) {
|
||||
if (!this._sseResponse) {
|
||||
throw new Error('Not connected');
|
||||
}
|
||||
this._sseResponse.write(`event: message\ndata: ${JSON.stringify(message)}\n\n`);
|
||||
}
|
||||
/**
|
||||
* Returns the session ID for this transport.
|
||||
*
|
||||
* This can be used to route incoming POST requests.
|
||||
*/
|
||||
get sessionId() {
|
||||
return this._sessionId;
|
||||
}
|
||||
}
|
||||
exports.SSEServerTransport = SSEServerTransport;
|
||||
//# sourceMappingURL=sse.js.map
|
||||
Reference in New Issue
Block a user