Skip to content

Commit 3ea255f

Browse files
committed
Use Zod for message validation at transport layer
1 parent cc1f19a commit 3ea255f

File tree

5 files changed

+11
-28
lines changed

5 files changed

+11
-28
lines changed

src/client/sse.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import { validateMessage } from "../shared/message.js";
21
import { Transport } from "../shared/transport.js";
3-
import { JSONRPCMessage } from "../types.js";
2+
import { JSONRPCMessage, JSONRPCMessageSchema } from "../types.js";
43

54
/**
65
* Client transport for SSE: this will connect to a server using Server-Sent Events for receiving
@@ -57,8 +56,7 @@ export class SSEClientTransport implements Transport {
5756
const messageEvent = event as MessageEvent;
5857
let message: JSONRPCMessage;
5958
try {
60-
message = JSON.parse(messageEvent.data);
61-
validateMessage(message);
59+
message = JSONRPCMessageSchema.parse(JSON.parse(messageEvent.data));
6260
} catch (error) {
6361
this.onerror?.(error as Error);
6462
return;

src/client/websocket.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import { validateMessage } from "../shared/message.js";
21
import { Transport } from "../shared/transport.js";
3-
import { JSONRPCMessage } from "../types.js";
2+
import { JSONRPCMessage, JSONRPCMessageSchema } from "../types.js";
43

54
const SUBPROTOCOL = "mcp";
65

@@ -38,8 +37,7 @@ export class WebSocketClientTransport implements Transport {
3837
this._socket.onmessage = (event: MessageEvent) => {
3938
let message: JSONRPCMessage;
4039
try {
41-
message = JSON.parse(event.data);
42-
validateMessage(message);
40+
message = JSONRPCMessageSchema.parse(JSON.parse(event.data));
4341
} catch (error) {
4442
this.onerror?.(error as Error);
4543
return;

src/server/sse.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { randomUUID } from "node:crypto";
22
import { IncomingMessage, ServerResponse } from "node:http";
3-
import { validateMessage } from "../shared/message.js";
43
import { Transport } from "../shared/transport.js";
5-
import { JSONRPCMessage } from "../types.js";
4+
import { JSONRPCMessage, JSONRPCMessageSchema } from "../types.js";
65
import getRawBody from "raw-body";
76
import contentType from "content-type";
87

@@ -101,15 +100,16 @@ export class SSEServerTransport implements Transport {
101100
/**
102101
* 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.
103102
*/
104-
async handleMessage(message: JSONRPCMessage): Promise<void> {
103+
async handleMessage(message: unknown): Promise<void> {
104+
let parsedMessage: JSONRPCMessage;
105105
try {
106-
validateMessage(message);
106+
parsedMessage = JSONRPCMessageSchema.parse(message);
107107
} catch (error) {
108108
this.onerror?.(error as Error);
109109
throw error;
110110
}
111111

112-
this.onmessage?.(message);
112+
this.onmessage?.(parsedMessage);
113113
}
114114

115115
async close(): Promise<void> {

src/shared/message.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/shared/stdio.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { JSONRPCMessage } from "../types.js";
2-
import { validateMessage } from "./message.js";
1+
import { JSONRPCMessage, JSONRPCMessageSchema } from "../types.js";
32

43
/**
54
* Buffers a continuous stdio stream into discrete JSON-RPC messages.
@@ -32,9 +31,7 @@ export class ReadBuffer {
3231
}
3332

3433
export function deserializeMessage(line: string): JSONRPCMessage {
35-
const message = JSON.parse(line) as JSONRPCMessage;
36-
validateMessage(message);
37-
return message;
34+
return JSONRPCMessageSchema.parse(JSON.parse(line));
3835
}
3936

4037
export function serializeMessage(message: JSONRPCMessage): string {

0 commit comments

Comments
 (0)