@aws/run-mcp-servers-with-aws-lambda 0.2.3 → 0.3.0

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.
Files changed (33) hide show
  1. package/dist/client/index.d.ts +2 -27
  2. package/dist/client/index.js +4 -51
  3. package/dist/client/lambdaFunction.d.ts +27 -0
  4. package/dist/client/lambdaFunction.js +51 -0
  5. package/dist/client/streamableHttpWithSigV4.d.ts +88 -0
  6. package/dist/client/streamableHttpWithSigV4.js +116 -0
  7. package/dist/client/streamableHttpWithSigV4.test.js +442 -0
  8. package/dist/handlers/{api_gateway_proxy_event_handler.d.ts → apiGatewayProxyEventHandler.d.ts} +2 -2
  9. package/dist/handlers/{api_gateway_proxy_event_handler.js → apiGatewayProxyEventHandler.js} +1 -1
  10. package/dist/handlers/{api_gateway_proxy_event_v2_handler.d.ts → apiGatewayProxyEventV2Handler.d.ts} +2 -2
  11. package/dist/handlers/{api_gateway_proxy_event_v2_handler.js → apiGatewayProxyEventV2Handler.js} +1 -1
  12. package/dist/handlers/index.d.ts +4 -4
  13. package/dist/handlers/index.js +3 -3
  14. package/dist/handlers/{lambda_function_url_event_handler.d.ts → lambdaFunctionUrlEventHandler.d.ts} +2 -2
  15. package/dist/handlers/{lambda_function_url_event_handler.js → lambdaFunctionUrlEventHandler.js} +1 -1
  16. package/dist/handlers/{streamable_http_handler.d.ts → streamableHttpHandler.d.ts} +1 -1
  17. package/dist/server-adapter/index.d.ts +2 -2
  18. package/dist/server-adapter/index.js +2 -2
  19. package/dist/server-adapter/{stdio_server_adapter.test.js → stdioServerAdapter.test.js} +2 -2
  20. package/dist/server-adapter/{stdio_server_adapter_request_handler.d.ts → stdioServerAdapterRequestHandler.d.ts} +1 -1
  21. package/dist/server-adapter/{stdio_server_adapter_request_handler.js → stdioServerAdapterRequestHandler.js} +1 -1
  22. package/dist/server-adapter/stdioServerAdapterRequestHandler.test.d.ts +1 -0
  23. package/dist/server-adapter/{stdio_server_adapter_request_handler.test.js → stdioServerAdapterRequestHandler.test.js} +53 -53
  24. package/package.json +7 -1
  25. /package/dist/client/{index.test.d.ts → lambdaFunction.test.d.ts} +0 -0
  26. /package/dist/client/{index.test.js → lambdaFunction.test.js} +0 -0
  27. /package/dist/{handlers/request_handler.js → client/streamableHttpWithSigV4.test.d.ts} +0 -0
  28. /package/dist/handlers/{request_handler.d.ts → requestHandler.d.ts} +0 -0
  29. /package/dist/{server-adapter/stdio_server_adapter.test.d.ts → handlers/requestHandler.js} +0 -0
  30. /package/dist/handlers/{streamable_http_handler.js → streamableHttpHandler.js} +0 -0
  31. /package/dist/server-adapter/{stdio_server_adapter.d.ts → stdioServerAdapter.d.ts} +0 -0
  32. /package/dist/server-adapter/{stdio_server_adapter.js → stdioServerAdapter.js} +0 -0
  33. /package/dist/server-adapter/{stdio_server_adapter_request_handler.test.d.ts → stdioServerAdapter.test.d.ts} +0 -0
@@ -1,27 +1,2 @@
1
- import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
2
- import { JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
3
- export type LambdaFunctionParameters = {
4
- /**
5
- * The name or ARN of the Lambda function, version, or alias.
6
- */
7
- functionName: string;
8
- /**
9
- * The AWS region of the Lambda function.
10
- */
11
- regionName?: string;
12
- };
13
- /**
14
- * Client transport for Lambda functions:
15
- * this will connect to a server by calling the Lambda Invoke API.
16
- */
17
- export declare class LambdaFunctionClientTransport implements Transport {
18
- private _serverParams;
19
- private _lambdaClient;
20
- onclose?: () => void;
21
- onerror?: (error: Error) => void;
22
- onmessage?: (message: JSONRPCMessage) => void;
23
- constructor(server: LambdaFunctionParameters);
24
- start(): Promise<void>;
25
- close(): Promise<void>;
26
- send(message: JSONRPCMessage): Promise<void>;
27
- }
1
+ export * from "./lambdaFunction.js";
2
+ export * from "./streamableHttpWithSigV4.js";
@@ -1,51 +1,4 @@
1
- import { LambdaClient, InvokeCommand } from "@aws-sdk/client-lambda";
2
- /**
3
- * Client transport for Lambda functions:
4
- * this will connect to a server by calling the Lambda Invoke API.
5
- */
6
- export class LambdaFunctionClientTransport {
7
- _serverParams;
8
- _lambdaClient;
9
- onclose;
10
- onerror;
11
- onmessage;
12
- constructor(server) {
13
- this._serverParams = server;
14
- this._lambdaClient = new LambdaClient({
15
- region: this._serverParams.regionName,
16
- });
17
- }
18
- async start() {
19
- // no-op
20
- }
21
- async close() {
22
- // no-op
23
- }
24
- async send(message) {
25
- try {
26
- const invokeCommand = new InvokeCommand({
27
- FunctionName: this._serverParams.functionName,
28
- InvocationType: "RequestResponse",
29
- Payload: JSON.stringify(message),
30
- });
31
- const invokeCommandOutput = await this._lambdaClient.send(invokeCommand);
32
- if (invokeCommandOutput.Payload) {
33
- const responseMessage = Buffer.from(invokeCommandOutput.Payload).toString("utf-8");
34
- if (invokeCommandOutput.FunctionError) {
35
- throw new Error(`${invokeCommandOutput.FunctionError} ${responseMessage}`);
36
- }
37
- if (responseMessage === "{}") {
38
- // Assume we sent a notification and do not expect a response
39
- return;
40
- }
41
- this.onmessage?.(JSON.parse(responseMessage));
42
- }
43
- else {
44
- throw new Error("No payload returned from Lambda function");
45
- }
46
- }
47
- catch (error) {
48
- this.onerror?.(error);
49
- }
50
- }
51
- }
1
+ // Export Lambda function client transport
2
+ export * from "./lambdaFunction.js";
3
+ // Export SigV4 HTTP client transport
4
+ export * from "./streamableHttpWithSigV4.js";
@@ -0,0 +1,27 @@
1
+ import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
2
+ import { JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
3
+ export type LambdaFunctionParameters = {
4
+ /**
5
+ * The name or ARN of the Lambda function, version, or alias.
6
+ */
7
+ functionName: string;
8
+ /**
9
+ * The AWS region of the Lambda function.
10
+ */
11
+ regionName?: string;
12
+ };
13
+ /**
14
+ * Client transport for Lambda functions:
15
+ * this will connect to a server by calling the Lambda Invoke API.
16
+ */
17
+ export declare class LambdaFunctionClientTransport implements Transport {
18
+ private _serverParams;
19
+ private _lambdaClient;
20
+ onclose?: () => void;
21
+ onerror?: (error: Error) => void;
22
+ onmessage?: (message: JSONRPCMessage) => void;
23
+ constructor(server: LambdaFunctionParameters);
24
+ start(): Promise<void>;
25
+ close(): Promise<void>;
26
+ send(message: JSONRPCMessage): Promise<void>;
27
+ }
@@ -0,0 +1,51 @@
1
+ import { LambdaClient, InvokeCommand } from "@aws-sdk/client-lambda";
2
+ /**
3
+ * Client transport for Lambda functions:
4
+ * this will connect to a server by calling the Lambda Invoke API.
5
+ */
6
+ export class LambdaFunctionClientTransport {
7
+ _serverParams;
8
+ _lambdaClient;
9
+ onclose;
10
+ onerror;
11
+ onmessage;
12
+ constructor(server) {
13
+ this._serverParams = server;
14
+ this._lambdaClient = new LambdaClient({
15
+ region: this._serverParams.regionName,
16
+ });
17
+ }
18
+ async start() {
19
+ // no-op
20
+ }
21
+ async close() {
22
+ // no-op
23
+ }
24
+ async send(message) {
25
+ try {
26
+ const invokeCommand = new InvokeCommand({
27
+ FunctionName: this._serverParams.functionName,
28
+ InvocationType: "RequestResponse",
29
+ Payload: JSON.stringify(message),
30
+ });
31
+ const invokeCommandOutput = await this._lambdaClient.send(invokeCommand);
32
+ if (invokeCommandOutput.Payload) {
33
+ const responseMessage = Buffer.from(invokeCommandOutput.Payload).toString("utf-8");
34
+ if (invokeCommandOutput.FunctionError) {
35
+ throw new Error(`${invokeCommandOutput.FunctionError} ${responseMessage}`);
36
+ }
37
+ if (responseMessage === "{}") {
38
+ // Assume we sent a notification and do not expect a response
39
+ return;
40
+ }
41
+ this.onmessage?.(JSON.parse(responseMessage));
42
+ }
43
+ else {
44
+ throw new Error("No payload returned from Lambda function");
45
+ }
46
+ }
47
+ catch (error) {
48
+ this.onerror?.(error);
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,88 @@
1
+ import { StreamableHTTPClientTransport, StreamableHTTPClientTransportOptions } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
2
+ import { FetchLike } from "@modelcontextprotocol/sdk/shared/transport.js";
3
+ import { AwsCredentialIdentity, Provider } from "@aws-sdk/types";
4
+ /**
5
+ * Configuration options for SigV4FetchLike
6
+ */
7
+ export interface SigV4FetchLikeOptions {
8
+ /**
9
+ * AWS credentials (provider), if not provided, default provider will be used
10
+ */
11
+ credentials?: AwsCredentialIdentity | Provider<AwsCredentialIdentity>;
12
+ /**
13
+ * AWS region for signing requests
14
+ */
15
+ region: string;
16
+ /**
17
+ * AWS service name for signing requests (e.g., 'lambda', 'execute-api')
18
+ */
19
+ service: string;
20
+ /**
21
+ * Base fetch implementation to use for actual HTTP requests
22
+ * If not provided, the global fetch will be used
23
+ */
24
+ baseFetch?: FetchLike;
25
+ }
26
+ /**
27
+ * A FetchLike implementation that signs HTTP requests using AWS Signature Version 4.
28
+ *
29
+ * This class can be passed to any transport that accepts a FetchLike parameter.
30
+ * It wraps a base fetch implementation and automatically signs all requests with AWS SigV4.
31
+ */
32
+ export declare class SigV4FetchLike {
33
+ private _signer;
34
+ private _baseFetch;
35
+ constructor(options: SigV4FetchLikeOptions);
36
+ /**
37
+ * Fetch implementation that signs requests with AWS SigV4
38
+ */
39
+ fetch(url: string | URL, init?: RequestInit): Promise<Response>;
40
+ }
41
+ /**
42
+ * Creates a FetchLike function that signs HTTP requests using AWS Signature Version 4.
43
+ *
44
+ * This function can be passed to any transport that accepts a FetchLike parameter,
45
+ * such as StreamableHTTPClientTransport.
46
+ *
47
+ * @param options Configuration options for AWS SigV4 signing
48
+ * @returns A FetchLike function that automatically signs requests
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * const sigV4Fetch = createSigV4Fetch({
53
+ * region: 'us-east-1',
54
+ * service: 'lambda'
55
+ * });
56
+ *
57
+ * const transport = new StreamableHTTPClientTransport(url, {
58
+ * fetch: sigV4Fetch
59
+ * });
60
+ * ```
61
+ */
62
+ export declare function createSigV4Fetch(options: SigV4FetchLikeOptions): FetchLike;
63
+ /**
64
+ * Extended options for StreamableHTTPClientWithSigV4Transport
65
+ */
66
+ export interface StreamableHTTPClientWithSigV4TransportOptions extends StreamableHTTPClientTransportOptions {
67
+ /**
68
+ * AWS credentials (provider), if not provided, default provider will be used
69
+ */
70
+ credentials?: AwsCredentialIdentity | Provider<AwsCredentialIdentity>;
71
+ /**
72
+ * AWS region for signing requests
73
+ */
74
+ region: string;
75
+ /**
76
+ * AWS service name for signing requests (e.g., 'lambda', 'execute-api')
77
+ */
78
+ service: string;
79
+ }
80
+ /**
81
+ * Streamable HTTP client transport with AWS SigV4 signing support.
82
+ *
83
+ * This transport enables communication with MCP servers that authenticate using AWS IAM,
84
+ * such as servers behind a Lambda function URL or API Gateway.
85
+ */
86
+ export declare class StreamableHTTPClientWithSigV4Transport extends StreamableHTTPClientTransport {
87
+ constructor(url: URL, options: StreamableHTTPClientWithSigV4TransportOptions);
88
+ }
@@ -0,0 +1,116 @@
1
+ import { StreamableHTTPClientTransport, } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
2
+ import { SignatureV4 } from "@smithy/signature-v4";
3
+ import { defaultProvider } from "@aws-sdk/credential-provider-node";
4
+ import { Sha256 } from "@aws-crypto/sha256-js";
5
+ import { HttpRequest } from "@aws-sdk/protocol-http";
6
+ /**
7
+ * A FetchLike implementation that signs HTTP requests using AWS Signature Version 4.
8
+ *
9
+ * This class can be passed to any transport that accepts a FetchLike parameter.
10
+ * It wraps a base fetch implementation and automatically signs all requests with AWS SigV4.
11
+ */
12
+ export class SigV4FetchLike {
13
+ _signer;
14
+ _baseFetch;
15
+ constructor(options) {
16
+ this._baseFetch = options.baseFetch ?? fetch;
17
+ this._signer = new SignatureV4({
18
+ service: options.service,
19
+ region: options.region,
20
+ credentials: options.credentials ?? defaultProvider(),
21
+ sha256: Sha256,
22
+ });
23
+ }
24
+ /**
25
+ * Fetch implementation that signs requests with AWS SigV4
26
+ */
27
+ async fetch(url, init) {
28
+ const urlObj = typeof url === "string" ? new URL(url) : url;
29
+ const requestInit = init || {};
30
+ // Convert fetch RequestInit to HttpRequest for signing
31
+ const headers = {
32
+ host: urlObj.hostname,
33
+ };
34
+ if (requestInit.headers) {
35
+ if (requestInit.headers instanceof Headers) {
36
+ requestInit.headers.forEach((value, key) => {
37
+ headers[key.toLowerCase()] = value;
38
+ });
39
+ }
40
+ else if (Array.isArray(requestInit.headers)) {
41
+ requestInit.headers.forEach(([key, value]) => {
42
+ headers[key.toLowerCase()] = value;
43
+ });
44
+ }
45
+ else {
46
+ Object.entries(requestInit.headers).forEach(([key, value]) => {
47
+ headers[key.toLowerCase()] = value;
48
+ });
49
+ }
50
+ }
51
+ const unsignedRequest = new HttpRequest({
52
+ method: requestInit.method || "GET",
53
+ protocol: urlObj.protocol,
54
+ hostname: urlObj.hostname,
55
+ port: urlObj.port ? parseInt(urlObj.port) : undefined,
56
+ path: urlObj.pathname + urlObj.search,
57
+ headers,
58
+ body: requestInit.body,
59
+ });
60
+ // Sign the request
61
+ const signedRequest = await this._signer.sign(unsignedRequest);
62
+ // Convert signed request back to fetch format
63
+ const signedInit = {
64
+ ...requestInit,
65
+ method: signedRequest.method,
66
+ headers: signedRequest.headers,
67
+ body: signedRequest.body,
68
+ };
69
+ return this._baseFetch(urlObj, signedInit);
70
+ }
71
+ }
72
+ /**
73
+ * Creates a FetchLike function that signs HTTP requests using AWS Signature Version 4.
74
+ *
75
+ * This function can be passed to any transport that accepts a FetchLike parameter,
76
+ * such as StreamableHTTPClientTransport.
77
+ *
78
+ * @param options Configuration options for AWS SigV4 signing
79
+ * @returns A FetchLike function that automatically signs requests
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * const sigV4Fetch = createSigV4Fetch({
84
+ * region: 'us-east-1',
85
+ * service: 'lambda'
86
+ * });
87
+ *
88
+ * const transport = new StreamableHTTPClientTransport(url, {
89
+ * fetch: sigV4Fetch
90
+ * });
91
+ * ```
92
+ */
93
+ export function createSigV4Fetch(options) {
94
+ const sigV4Fetch = new SigV4FetchLike(options);
95
+ return sigV4Fetch.fetch.bind(sigV4Fetch);
96
+ }
97
+ /**
98
+ * Streamable HTTP client transport with AWS SigV4 signing support.
99
+ *
100
+ * This transport enables communication with MCP servers that authenticate using AWS IAM,
101
+ * such as servers behind a Lambda function URL or API Gateway.
102
+ */
103
+ export class StreamableHTTPClientWithSigV4Transport extends StreamableHTTPClientTransport {
104
+ constructor(url, options) {
105
+ const sigV4Fetch = createSigV4Fetch({
106
+ credentials: options.credentials,
107
+ region: options.region,
108
+ service: options.service,
109
+ baseFetch: options.fetch,
110
+ });
111
+ super(url, {
112
+ ...options,
113
+ fetch: sigV4Fetch,
114
+ });
115
+ }
116
+ }
@@ -0,0 +1,442 @@
1
+ import { SignatureV4 } from "@smithy/signature-v4";
2
+ import { defaultProvider } from "@aws-sdk/credential-provider-node";
3
+ import { HttpRequest } from "@aws-sdk/protocol-http";
4
+ import { StreamableHTTPClientWithSigV4Transport, SigV4FetchLike, createSigV4Fetch, } from "./streamableHttpWithSigV4.js";
5
+ // Mock dependencies
6
+ jest.mock("@smithy/signature-v4");
7
+ jest.mock("@aws-sdk/credential-provider-node");
8
+ jest.mock("@aws-sdk/protocol-http");
9
+ jest.mock("@modelcontextprotocol/sdk/client/streamableHttp.js");
10
+ describe("StreamableHTTPClientWithSigV4Transport", () => {
11
+ const mockSign = jest.fn();
12
+ const mockDefaultProvider = jest.fn();
13
+ const mockCredentials = {
14
+ accessKeyId: "test-access-key",
15
+ secretAccessKey: "test-secret-key",
16
+ };
17
+ beforeEach(() => {
18
+ jest.clearAllMocks();
19
+ // Mock SignatureV4
20
+ SignatureV4.mockImplementation(() => ({
21
+ sign: mockSign,
22
+ }));
23
+ // Mock defaultProvider
24
+ defaultProvider.mockReturnValue(mockDefaultProvider);
25
+ mockDefaultProvider.mockResolvedValue(mockCredentials);
26
+ });
27
+ describe("constructor", () => {
28
+ test("should initialize with required options", () => {
29
+ const url = new URL("https://example.com/mcp");
30
+ const options = {
31
+ region: "us-east-1",
32
+ service: "lambda",
33
+ };
34
+ new StreamableHTTPClientWithSigV4Transport(url, options);
35
+ expect(SignatureV4).toHaveBeenCalledWith({
36
+ service: "lambda",
37
+ region: "us-east-1",
38
+ credentials: mockDefaultProvider,
39
+ sha256: expect.any(Function),
40
+ });
41
+ });
42
+ test("should use provided credentials instead of default provider", () => {
43
+ const url = new URL("https://example.com/mcp");
44
+ const customCredentials = {
45
+ accessKeyId: "custom-access-key",
46
+ secretAccessKey: "custom-secret-key",
47
+ };
48
+ const options = {
49
+ region: "us-west-2",
50
+ service: "execute-api",
51
+ credentials: customCredentials,
52
+ };
53
+ new StreamableHTTPClientWithSigV4Transport(url, options);
54
+ expect(SignatureV4).toHaveBeenCalledWith({
55
+ service: "execute-api",
56
+ region: "us-west-2",
57
+ credentials: customCredentials,
58
+ sha256: expect.any(Function),
59
+ });
60
+ expect(defaultProvider).not.toHaveBeenCalled();
61
+ });
62
+ test("should use provided fetch function", () => {
63
+ const url = new URL("https://example.com/mcp");
64
+ const customFetch = jest.fn();
65
+ const options = {
66
+ region: "us-east-1",
67
+ service: "lambda",
68
+ fetch: customFetch,
69
+ };
70
+ new StreamableHTTPClientWithSigV4Transport(url, options);
71
+ // The custom fetch should be passed to the SigV4FetchLike as baseFetch
72
+ expect(customFetch).not.toHaveBeenCalled();
73
+ });
74
+ });
75
+ describe("SigV4FetchLike", () => {
76
+ let mockFetch;
77
+ beforeEach(() => {
78
+ mockFetch = jest.fn();
79
+ });
80
+ it("should sign and execute GET request", async () => {
81
+ const testUrl = "https://example.com/test";
82
+ const signedHeaders = {
83
+ authorization: "AWS4-HMAC-SHA256 ...",
84
+ "x-amz-date": "20231201T120000Z",
85
+ };
86
+ mockSign.mockResolvedValue({
87
+ method: "GET",
88
+ headers: signedHeaders,
89
+ body: undefined,
90
+ });
91
+ const mockResponse = new Response("test response");
92
+ mockFetch.mockResolvedValue(mockResponse);
93
+ const options = {
94
+ region: "us-east-1",
95
+ service: "lambda",
96
+ baseFetch: mockFetch,
97
+ };
98
+ const sigV4Fetch = new SigV4FetchLike(options);
99
+ const result = await sigV4Fetch.fetch(testUrl, undefined);
100
+ expect(HttpRequest).toHaveBeenCalledWith({
101
+ method: "GET",
102
+ protocol: "https:",
103
+ hostname: "example.com",
104
+ path: "/test",
105
+ headers: {
106
+ host: "example.com",
107
+ },
108
+ body: undefined,
109
+ });
110
+ expect(mockSign).toHaveBeenCalledWith(expect.any(HttpRequest));
111
+ expect(mockFetch).toHaveBeenCalledWith(new URL(testUrl), {
112
+ method: "GET",
113
+ headers: signedHeaders,
114
+ body: undefined,
115
+ });
116
+ expect(result).toBe(mockResponse);
117
+ });
118
+ it("should sign and execute POST request with body", async () => {
119
+ const testUrl = "https://example.com/api";
120
+ const requestInit = {
121
+ method: "POST",
122
+ headers: {
123
+ "content-type": "application/json",
124
+ },
125
+ body: JSON.stringify({ test: "data" }),
126
+ };
127
+ const signedHeaders = {
128
+ authorization: "AWS4-HMAC-SHA256 ...",
129
+ "x-amz-date": "20231201T120000Z",
130
+ "content-type": "application/json",
131
+ };
132
+ mockSign.mockResolvedValue({
133
+ method: "POST",
134
+ headers: signedHeaders,
135
+ body: requestInit.body,
136
+ });
137
+ const mockResponse = new Response("success");
138
+ mockFetch.mockResolvedValue(mockResponse);
139
+ const options = {
140
+ region: "us-east-1",
141
+ service: "lambda",
142
+ baseFetch: mockFetch,
143
+ };
144
+ const sigV4Fetch = new SigV4FetchLike(options);
145
+ const result = await sigV4Fetch.fetch(testUrl, requestInit);
146
+ expect(HttpRequest).toHaveBeenCalledWith({
147
+ method: "POST",
148
+ protocol: "https:",
149
+ hostname: "example.com",
150
+ path: "/api",
151
+ headers: {
152
+ host: "example.com",
153
+ "content-type": "application/json",
154
+ },
155
+ body: requestInit.body,
156
+ });
157
+ expect(mockSign).toHaveBeenCalledWith(expect.any(HttpRequest));
158
+ expect(mockFetch).toHaveBeenCalledWith(new URL(testUrl), {
159
+ method: "POST",
160
+ headers: signedHeaders,
161
+ body: requestInit.body,
162
+ });
163
+ expect(result).toBe(mockResponse);
164
+ });
165
+ it("should handle URL with port and query parameters", async () => {
166
+ const testUrl = "https://example.com:8443/path?param=value";
167
+ mockSign.mockResolvedValue({
168
+ method: "GET",
169
+ headers: { authorization: "AWS4-HMAC-SHA256 ..." },
170
+ body: undefined,
171
+ });
172
+ mockFetch.mockResolvedValue(new Response("test"));
173
+ const options = {
174
+ region: "us-east-1",
175
+ service: "lambda",
176
+ baseFetch: mockFetch,
177
+ };
178
+ const sigV4Fetch = new SigV4FetchLike(options);
179
+ await sigV4Fetch.fetch(testUrl, undefined);
180
+ expect(HttpRequest).toHaveBeenCalledWith({
181
+ method: "GET",
182
+ protocol: "https:",
183
+ hostname: "example.com",
184
+ port: 8443,
185
+ path: "/path?param=value",
186
+ headers: {
187
+ host: "example.com",
188
+ },
189
+ body: undefined,
190
+ });
191
+ });
192
+ it("should handle Headers object in request init", async () => {
193
+ const testUrl = "https://example.com/test";
194
+ const headers = new Headers();
195
+ headers.set("Content-Type", "application/json");
196
+ headers.set("X-Custom-Header", "custom-value");
197
+ const requestInit = {
198
+ method: "POST",
199
+ headers,
200
+ body: "test body",
201
+ };
202
+ mockSign.mockResolvedValue({
203
+ method: "POST",
204
+ headers: { authorization: "AWS4-HMAC-SHA256 ..." },
205
+ body: "test body",
206
+ });
207
+ mockFetch.mockResolvedValue(new Response("test"));
208
+ const options = {
209
+ region: "us-east-1",
210
+ service: "lambda",
211
+ baseFetch: mockFetch,
212
+ };
213
+ const sigV4Fetch = new SigV4FetchLike(options);
214
+ await sigV4Fetch.fetch(testUrl, requestInit);
215
+ expect(HttpRequest).toHaveBeenCalledWith({
216
+ method: "POST",
217
+ protocol: "https:",
218
+ hostname: "example.com",
219
+ path: "/test",
220
+ headers: {
221
+ host: "example.com",
222
+ "content-type": "application/json",
223
+ "x-custom-header": "custom-value",
224
+ },
225
+ body: "test body",
226
+ });
227
+ });
228
+ it("should handle array headers in request init", async () => {
229
+ const testUrl = "https://example.com/test";
230
+ const requestInit = {
231
+ method: "POST",
232
+ headers: [
233
+ ["Content-Type", "application/json"],
234
+ ["X-Custom-Header", "custom-value"],
235
+ ],
236
+ body: "test body",
237
+ };
238
+ mockSign.mockResolvedValue({
239
+ method: "POST",
240
+ headers: { authorization: "AWS4-HMAC-SHA256 ..." },
241
+ body: "test body",
242
+ });
243
+ mockFetch.mockResolvedValue(new Response("test"));
244
+ const options = {
245
+ region: "us-east-1",
246
+ service: "lambda",
247
+ baseFetch: mockFetch,
248
+ };
249
+ const sigV4Fetch = new SigV4FetchLike(options);
250
+ await sigV4Fetch.fetch(testUrl, requestInit);
251
+ expect(HttpRequest).toHaveBeenCalledWith({
252
+ method: "POST",
253
+ protocol: "https:",
254
+ hostname: "example.com",
255
+ path: "/test",
256
+ headers: {
257
+ host: "example.com",
258
+ "content-type": "application/json",
259
+ "x-custom-header": "custom-value",
260
+ },
261
+ body: "test body",
262
+ });
263
+ });
264
+ it("should handle URL object as input", async () => {
265
+ const testUrl = new URL("https://example.com/test");
266
+ mockSign.mockResolvedValue({
267
+ method: "GET",
268
+ headers: { authorization: "AWS4-HMAC-SHA256 ..." },
269
+ body: undefined,
270
+ });
271
+ mockFetch.mockResolvedValue(new Response("test"));
272
+ const options = {
273
+ region: "us-east-1",
274
+ service: "lambda",
275
+ baseFetch: mockFetch,
276
+ };
277
+ const sigV4Fetch = new SigV4FetchLike(options);
278
+ await sigV4Fetch.fetch(testUrl, undefined);
279
+ expect(HttpRequest).toHaveBeenCalledWith({
280
+ method: "GET",
281
+ protocol: "https:",
282
+ hostname: "example.com",
283
+ path: "/test",
284
+ headers: {
285
+ host: "example.com",
286
+ },
287
+ body: undefined,
288
+ });
289
+ });
290
+ it("should propagate signing errors", async () => {
291
+ const testUrl = "https://example.com/test";
292
+ mockSign.mockRejectedValue(new Error("Signing failed"));
293
+ const options = {
294
+ region: "us-east-1",
295
+ service: "lambda",
296
+ baseFetch: mockFetch,
297
+ };
298
+ const sigV4Fetch = new SigV4FetchLike(options);
299
+ await expect(sigV4Fetch.fetch(testUrl, undefined)).rejects.toThrow("Signing failed");
300
+ expect(mockFetch).not.toHaveBeenCalled();
301
+ });
302
+ it("should propagate fetch errors", async () => {
303
+ const testUrl = "https://example.com/test";
304
+ mockSign.mockResolvedValue({
305
+ method: "GET",
306
+ headers: { authorization: "AWS4-HMAC-SHA256 ..." },
307
+ body: undefined,
308
+ });
309
+ mockFetch.mockRejectedValue(new Error("Network error"));
310
+ const options = {
311
+ region: "us-east-1",
312
+ service: "lambda",
313
+ baseFetch: mockFetch,
314
+ };
315
+ const sigV4Fetch = new SigV4FetchLike(options);
316
+ await expect(sigV4Fetch.fetch(testUrl, undefined)).rejects.toThrow("Network error");
317
+ });
318
+ });
319
+ describe("createSigV4Fetch", () => {
320
+ let mockFetch;
321
+ beforeEach(() => {
322
+ mockFetch = jest.fn();
323
+ });
324
+ it("should create a FetchLike function that signs requests", async () => {
325
+ const testUrl = "https://example.com/test";
326
+ const signedHeaders = {
327
+ authorization: "AWS4-HMAC-SHA256 ...",
328
+ "x-amz-date": "20231201T120000Z",
329
+ };
330
+ mockSign.mockResolvedValue({
331
+ method: "GET",
332
+ headers: signedHeaders,
333
+ body: undefined,
334
+ });
335
+ const mockResponse = new Response("test response");
336
+ mockFetch.mockResolvedValue(mockResponse);
337
+ const options = {
338
+ region: "us-east-1",
339
+ service: "lambda",
340
+ baseFetch: mockFetch,
341
+ };
342
+ const sigV4Fetch = createSigV4Fetch(options);
343
+ const result = await sigV4Fetch(testUrl, undefined);
344
+ expect(HttpRequest).toHaveBeenCalledWith({
345
+ method: "GET",
346
+ protocol: "https:",
347
+ hostname: "example.com",
348
+ path: "/test",
349
+ headers: {
350
+ host: "example.com",
351
+ },
352
+ body: undefined,
353
+ });
354
+ expect(mockSign).toHaveBeenCalledWith(expect.any(HttpRequest));
355
+ expect(mockFetch).toHaveBeenCalledWith(new URL(testUrl), {
356
+ method: "GET",
357
+ headers: signedHeaders,
358
+ body: undefined,
359
+ });
360
+ expect(result).toBe(mockResponse);
361
+ });
362
+ it("should work with StreamableHTTPClientTransport", async () => {
363
+ const testUrl = "https://example.com/test";
364
+ const signedHeaders = {
365
+ authorization: "AWS4-HMAC-SHA256 ...",
366
+ "x-amz-date": "20231201T120000Z",
367
+ };
368
+ mockSign.mockResolvedValue({
369
+ method: "GET",
370
+ headers: signedHeaders,
371
+ body: undefined,
372
+ });
373
+ const mockResponse = new Response("test response");
374
+ mockFetch.mockResolvedValue(mockResponse);
375
+ const options = {
376
+ region: "us-east-1",
377
+ service: "lambda",
378
+ baseFetch: mockFetch,
379
+ };
380
+ const sigV4Fetch = createSigV4Fetch(options);
381
+ // This demonstrates how users can now use the SigV4 fetch with any transport
382
+ const result = await sigV4Fetch(testUrl, { method: "GET" });
383
+ expect(result).toBe(mockResponse);
384
+ expect(mockSign).toHaveBeenCalled();
385
+ expect(mockFetch).toHaveBeenCalled();
386
+ });
387
+ });
388
+ describe("credential provider integration", () => {
389
+ test("should use default provider when no credentials provided", () => {
390
+ const url = new URL("https://example.com/mcp");
391
+ const options = {
392
+ region: "us-east-1",
393
+ service: "lambda",
394
+ };
395
+ new StreamableHTTPClientWithSigV4Transport(url, options);
396
+ expect(defaultProvider).toHaveBeenCalled();
397
+ expect(SignatureV4).toHaveBeenCalledWith({
398
+ service: "lambda",
399
+ region: "us-east-1",
400
+ credentials: mockDefaultProvider,
401
+ sha256: expect.any(Function),
402
+ });
403
+ });
404
+ test("should use provided credential provider function", () => {
405
+ const url = new URL("https://example.com/mcp");
406
+ const customProvider = jest.fn().mockResolvedValue(mockCredentials);
407
+ const options = {
408
+ region: "us-east-1",
409
+ service: "lambda",
410
+ credentials: customProvider,
411
+ };
412
+ new StreamableHTTPClientWithSigV4Transport(url, options);
413
+ expect(SignatureV4).toHaveBeenCalledWith({
414
+ service: "lambda",
415
+ region: "us-east-1",
416
+ credentials: customProvider,
417
+ sha256: expect.any(Function),
418
+ });
419
+ expect(defaultProvider).not.toHaveBeenCalled();
420
+ });
421
+ test("should use provided static credentials", () => {
422
+ const url = new URL("https://example.com/mcp");
423
+ const staticCredentials = {
424
+ accessKeyId: "static-key",
425
+ secretAccessKey: "static-secret",
426
+ };
427
+ const options = {
428
+ region: "us-east-1",
429
+ service: "lambda",
430
+ credentials: staticCredentials,
431
+ };
432
+ new StreamableHTTPClientWithSigV4Transport(url, options);
433
+ expect(SignatureV4).toHaveBeenCalledWith({
434
+ service: "lambda",
435
+ region: "us-east-1",
436
+ credentials: staticCredentials,
437
+ sha256: expect.any(Function),
438
+ });
439
+ expect(defaultProvider).not.toHaveBeenCalled();
440
+ });
441
+ });
442
+ });
@@ -1,6 +1,6 @@
1
1
  import { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";
2
- import { StreamableHttpHandler, ParsedHttpRequest, HttpResponse } from "./streamable_http_handler.js";
3
- import { RequestHandler } from "./request_handler.js";
2
+ import { StreamableHttpHandler, ParsedHttpRequest, HttpResponse } from "./streamableHttpHandler.js";
3
+ import { RequestHandler } from "./requestHandler.js";
4
4
  /**
5
5
  * Handler for API Gateway V1 events (REST APIs)
6
6
  *
@@ -1,4 +1,4 @@
1
- import { StreamableHttpHandler, } from "./streamable_http_handler.js";
1
+ import { StreamableHttpHandler, } from "./streamableHttpHandler.js";
2
2
  /**
3
3
  * Handler for API Gateway V1 events (REST APIs)
4
4
  *
@@ -1,6 +1,6 @@
1
1
  import { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from "aws-lambda";
2
- import { StreamableHttpHandler, ParsedHttpRequest, HttpResponse } from "./streamable_http_handler.js";
3
- import { RequestHandler } from "./request_handler.js";
2
+ import { StreamableHttpHandler, ParsedHttpRequest, HttpResponse } from "./streamableHttpHandler.js";
3
+ import { RequestHandler } from "./requestHandler.js";
4
4
  /**
5
5
  * Handler for API Gateway V2 events (HTTP APIs)
6
6
  *
@@ -1,4 +1,4 @@
1
- import { StreamableHttpHandler, } from "./streamable_http_handler.js";
1
+ import { StreamableHttpHandler, } from "./streamableHttpHandler.js";
2
2
  /**
3
3
  * Handler for API Gateway V2 events (HTTP APIs)
4
4
  *
@@ -1,4 +1,4 @@
1
- export { RequestHandler } from "./request_handler.js";
2
- export { APIGatewayProxyEventHandler } from "./api_gateway_proxy_event_handler.js";
3
- export { APIGatewayProxyEventV2Handler } from "./api_gateway_proxy_event_v2_handler.js";
4
- export { LambdaFunctionURLEventHandler } from "./lambda_function_url_event_handler.js";
1
+ export { RequestHandler } from "./requestHandler.js";
2
+ export { APIGatewayProxyEventHandler } from "./apiGatewayProxyEventHandler.js";
3
+ export { APIGatewayProxyEventV2Handler } from "./apiGatewayProxyEventV2Handler.js";
4
+ export { LambdaFunctionURLEventHandler } from "./lambdaFunctionUrlEventHandler.js";
@@ -1,3 +1,3 @@
1
- export { APIGatewayProxyEventHandler } from "./api_gateway_proxy_event_handler.js";
2
- export { APIGatewayProxyEventV2Handler } from "./api_gateway_proxy_event_v2_handler.js";
3
- export { LambdaFunctionURLEventHandler } from "./lambda_function_url_event_handler.js";
1
+ export { APIGatewayProxyEventHandler } from "./apiGatewayProxyEventHandler.js";
2
+ export { APIGatewayProxyEventV2Handler } from "./apiGatewayProxyEventV2Handler.js";
3
+ export { LambdaFunctionURLEventHandler } from "./lambdaFunctionUrlEventHandler.js";
@@ -1,6 +1,6 @@
1
1
  import { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from "aws-lambda";
2
- import { StreamableHttpHandler, ParsedHttpRequest, HttpResponse } from "./streamable_http_handler.js";
3
- import { RequestHandler } from "./request_handler.js";
2
+ import { StreamableHttpHandler, ParsedHttpRequest, HttpResponse } from "./streamableHttpHandler.js";
3
+ import { RequestHandler } from "./requestHandler.js";
4
4
  /**
5
5
  * Handler for Lambda Function URL requests
6
6
  *
@@ -1,4 +1,4 @@
1
- import { StreamableHttpHandler, } from "./streamable_http_handler.js";
1
+ import { StreamableHttpHandler, } from "./streamableHttpHandler.js";
2
2
  /**
3
3
  * Handler for Lambda Function URL requests
4
4
  *
@@ -1,6 +1,6 @@
1
1
  import { Context } from "aws-lambda";
2
2
  import { ErrorCode } from "@modelcontextprotocol/sdk/types.js";
3
- import { RequestHandler } from "./request_handler.js";
3
+ import { RequestHandler } from "./requestHandler.js";
4
4
  /**
5
5
  * Parsed HTTP request data extracted from various Lambda event types
6
6
  */
@@ -1,2 +1,2 @@
1
- export { stdioServerAdapter } from "./stdio_server_adapter.js";
2
- export { StdioServerAdapterRequestHandler } from "./stdio_server_adapter_request_handler.js";
1
+ export { stdioServerAdapter } from "./stdioServerAdapter.js";
2
+ export { StdioServerAdapterRequestHandler } from "./stdioServerAdapterRequestHandler.js";
@@ -1,2 +1,2 @@
1
- export { stdioServerAdapter } from "./stdio_server_adapter.js";
2
- export { StdioServerAdapterRequestHandler } from "./stdio_server_adapter_request_handler.js";
1
+ export { stdioServerAdapter } from "./stdioServerAdapter.js";
2
+ export { StdioServerAdapterRequestHandler } from "./stdioServerAdapterRequestHandler.js";
@@ -1,8 +1,8 @@
1
1
  import { ErrorCode, } from '@modelcontextprotocol/sdk/types.js';
2
- import { stdioServerAdapter } from './stdio_server_adapter.js';
2
+ import { stdioServerAdapter } from './stdioServerAdapter.js';
3
3
  const serverParameters = {
4
4
  command: 'npx',
5
- args: ['tsx', 'test-stdio-server/echo_server.ts'],
5
+ args: ['tsx', 'test-stdio-server/echoServer.ts'],
6
6
  };
7
7
  const mockContext = {
8
8
  callbackWaitsForEmptyEventLoop: true,
@@ -1,7 +1,7 @@
1
1
  import { Context } from 'aws-lambda';
2
2
  import { StdioServerParameters } from '@modelcontextprotocol/sdk/client/stdio.js';
3
3
  import { JSONRPCRequest, JSONRPCResponse, JSONRPCError } from '@modelcontextprotocol/sdk/types.js';
4
- import { RequestHandler } from '../handlers/request_handler.js';
4
+ import { RequestHandler } from '../handlers/requestHandler.js';
5
5
  /**
6
6
  * Generic Request Handler for MCP Stdio Server Adapter
7
7
  *
@@ -1,6 +1,6 @@
1
1
  import { isJSONRPCResponse, isJSONRPCError, ErrorCode, } from '@modelcontextprotocol/sdk/types.js';
2
2
  import { createLogger, format, transports } from 'winston';
3
- import { stdioServerAdapter } from './stdio_server_adapter.js';
3
+ import { stdioServerAdapter } from './stdioServerAdapter.js';
4
4
  const logger = createLogger({
5
5
  level: process.env.LOG_LEVEL?.toLowerCase() || 'info',
6
6
  format: format.simple(),
@@ -1,45 +1,45 @@
1
- import { ErrorCode, } from '@modelcontextprotocol/sdk/types.js';
2
- import { StdioServerAdapterRequestHandler } from './stdio_server_adapter_request_handler.js';
3
- import * as stdioServerAdapter from './stdio_server_adapter.js';
1
+ import { ErrorCode, } from "@modelcontextprotocol/sdk/types.js";
2
+ import { StdioServerAdapterRequestHandler } from "./stdioServerAdapterRequestHandler.js";
3
+ import * as stdioServerAdapter from "./stdioServerAdapter.js";
4
4
  // Mock the stdioServerAdapter function
5
- jest.mock('./stdio_server_adapter.js', () => ({
5
+ jest.mock("./stdioServerAdapter.js", () => ({
6
6
  stdioServerAdapter: jest.fn(),
7
7
  }));
8
8
  const mockStdioServerAdapter = stdioServerAdapter.stdioServerAdapter;
9
9
  const mockServerParams = {
10
- command: 'node',
11
- args: ['test-server.js'],
10
+ command: "node",
11
+ args: ["test-server.js"],
12
12
  };
13
13
  const mockContext = {
14
14
  callbackWaitsForEmptyEventLoop: true,
15
- functionName: 'test-function',
16
- functionVersion: '1',
17
- invokedFunctionArn: 'test-arn',
18
- memoryLimitInMB: '128',
19
- awsRequestId: 'test-id',
20
- logGroupName: 'test-group',
21
- logStreamName: 'test-stream',
15
+ functionName: "test-function",
16
+ functionVersion: "1",
17
+ invokedFunctionArn: "test-arn",
18
+ memoryLimitInMB: "128",
19
+ awsRequestId: "test-id",
20
+ logGroupName: "test-group",
21
+ logStreamName: "test-stream",
22
22
  getRemainingTimeInMillis: () => 1000,
23
23
  done: () => { },
24
24
  fail: () => { },
25
25
  succeed: () => { },
26
26
  };
27
- describe('StdioServerAdapterRequestHandler', () => {
27
+ describe("StdioServerAdapterRequestHandler", () => {
28
28
  let handler;
29
29
  beforeEach(() => {
30
30
  handler = new StdioServerAdapterRequestHandler(mockServerParams);
31
31
  jest.clearAllMocks();
32
32
  });
33
- describe('handleRequest', () => {
34
- test('should return JSONRPCResponse when stdioServerAdapter returns valid response', async () => {
33
+ describe("handleRequest", () => {
34
+ test("should return JSONRPCResponse when stdioServerAdapter returns valid response", async () => {
35
35
  const request = {
36
- jsonrpc: '2.0',
36
+ jsonrpc: "2.0",
37
37
  id: 1,
38
- method: 'test',
39
- params: { arg: 'value' },
38
+ method: "test",
39
+ params: { arg: "value" },
40
40
  };
41
41
  const expectedResponse = {
42
- jsonrpc: '2.0',
42
+ jsonrpc: "2.0",
43
43
  id: 1,
44
44
  result: { success: true },
45
45
  };
@@ -48,17 +48,17 @@ describe('StdioServerAdapterRequestHandler', () => {
48
48
  expect(mockStdioServerAdapter).toHaveBeenCalledWith(mockServerParams, request, mockContext);
49
49
  expect(result).toEqual(expectedResponse);
50
50
  });
51
- test('should return JSONRPCError when stdioServerAdapter returns error', async () => {
51
+ test("should return JSONRPCError when stdioServerAdapter returns error", async () => {
52
52
  const request = {
53
- jsonrpc: '2.0',
53
+ jsonrpc: "2.0",
54
54
  id: 1,
55
- method: 'test',
55
+ method: "test",
56
56
  };
57
57
  const expectedError = {
58
- jsonrpc: '2.0',
58
+ jsonrpc: "2.0",
59
59
  error: {
60
60
  code: ErrorCode.MethodNotFound,
61
- message: 'Method not found',
61
+ message: "Method not found",
62
62
  },
63
63
  id: 1,
64
64
  };
@@ -67,76 +67,76 @@ describe('StdioServerAdapterRequestHandler', () => {
67
67
  expect(mockStdioServerAdapter).toHaveBeenCalledWith(mockServerParams, request, mockContext);
68
68
  expect(result).toEqual(expectedError);
69
69
  });
70
- test('should return internal error when stdioServerAdapter returns unexpected format', async () => {
70
+ test("should return internal error when stdioServerAdapter returns unexpected format", async () => {
71
71
  const request = {
72
- jsonrpc: '2.0',
72
+ jsonrpc: "2.0",
73
73
  id: 1,
74
- method: 'test',
74
+ method: "test",
75
75
  };
76
- const unexpectedResponse = { invalid: 'response' };
76
+ const unexpectedResponse = { invalid: "response" };
77
77
  mockStdioServerAdapter.mockResolvedValue(unexpectedResponse);
78
78
  const result = await handler.handleRequest(request, mockContext);
79
79
  expect(result).toEqual({
80
- jsonrpc: '2.0',
80
+ jsonrpc: "2.0",
81
81
  error: {
82
82
  code: ErrorCode.InternalError,
83
- message: 'Internal error: Unexpected response format from MCP server',
84
- data: 'Expected JSONRPCResponse or JSONRPCError',
83
+ message: "Internal error: Unexpected response format from MCP server",
84
+ data: "Expected JSONRPCResponse or JSONRPCError",
85
85
  },
86
86
  id: 1,
87
87
  });
88
88
  });
89
- test('should return internal error when stdioServerAdapter throws exception', async () => {
89
+ test("should return internal error when stdioServerAdapter throws exception", async () => {
90
90
  const request = {
91
- jsonrpc: '2.0',
91
+ jsonrpc: "2.0",
92
92
  id: 1,
93
- method: 'test',
93
+ method: "test",
94
94
  };
95
- const error = new Error('Connection failed');
95
+ const error = new Error("Connection failed");
96
96
  mockStdioServerAdapter.mockRejectedValue(error);
97
97
  const result = await handler.handleRequest(request, mockContext);
98
98
  expect(result).toEqual({
99
- jsonrpc: '2.0',
99
+ jsonrpc: "2.0",
100
100
  error: {
101
101
  code: ErrorCode.InternalError,
102
- message: 'Internal error',
103
- data: 'Connection failed',
102
+ message: "Internal error",
103
+ data: "Connection failed",
104
104
  },
105
105
  id: 1,
106
106
  });
107
107
  });
108
- test('should handle non-Error exceptions', async () => {
108
+ test("should handle non-Error exceptions", async () => {
109
109
  const request = {
110
- jsonrpc: '2.0',
110
+ jsonrpc: "2.0",
111
111
  id: 1,
112
- method: 'test',
112
+ method: "test",
113
113
  };
114
- mockStdioServerAdapter.mockRejectedValue('String error');
114
+ mockStdioServerAdapter.mockRejectedValue("String error");
115
115
  const result = await handler.handleRequest(request, mockContext);
116
116
  expect(result).toEqual({
117
- jsonrpc: '2.0',
117
+ jsonrpc: "2.0",
118
118
  error: {
119
119
  code: ErrorCode.InternalError,
120
- message: 'Internal error',
121
- data: 'Unknown error',
120
+ message: "Internal error",
121
+ data: "Unknown error",
122
122
  },
123
123
  id: 1,
124
124
  });
125
125
  });
126
- test('should pass server parameters correctly to stdioServerAdapter', async () => {
126
+ test("should pass server parameters correctly to stdioServerAdapter", async () => {
127
127
  const customServerParams = {
128
- command: 'python',
129
- args: ['custom-server.py', '--port', '8080'],
130
- env: { NODE_ENV: 'test' },
128
+ command: "python",
129
+ args: ["custom-server.py", "--port", "8080"],
130
+ env: { hello: "world" },
131
131
  };
132
132
  const customHandler = new StdioServerAdapterRequestHandler(customServerParams);
133
133
  const request = {
134
- jsonrpc: '2.0',
134
+ jsonrpc: "2.0",
135
135
  id: 1,
136
- method: 'test',
136
+ method: "test",
137
137
  };
138
138
  const response = {
139
- jsonrpc: '2.0',
139
+ jsonrpc: "2.0",
140
140
  id: 1,
141
141
  result: {},
142
142
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@aws/run-mcp-servers-with-aws-lambda",
3
3
  "description": "Run Model Context Protocol (MCP) servers with AWS Lambda",
4
- "version": "0.2.3",
4
+ "version": "0.3.0",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
7
7
  "author": {
@@ -46,6 +46,7 @@
46
46
  "aws-sdk-client-mock": "^4.1.0",
47
47
  "aws-sdk-client-mock-jest": "^4.1.0",
48
48
  "eslint": "^9.30.1",
49
+ "eslint-plugin-check-file": "^3.3.0",
49
50
  "jest": "^30.0.4",
50
51
  "ts-jest": "^29.4.0",
51
52
  "tsx": "^4.20.3",
@@ -53,8 +54,13 @@
53
54
  "typescript-eslint": "^8.35.1"
54
55
  },
55
56
  "dependencies": {
57
+ "@aws-crypto/sha256-js": "^5.2.0",
56
58
  "@aws-sdk/client-lambda": "^3.840.0",
59
+ "@aws-sdk/credential-provider-node": "^3.840.0",
60
+ "@aws-sdk/protocol-http": "^3.370.0",
61
+ "@aws-sdk/types": "^3.840.0",
57
62
  "@modelcontextprotocol/sdk": "^1.15.0",
63
+ "@smithy/signature-v4": "^5.1.2",
58
64
  "@types/aws-lambda": "^8.10.149",
59
65
  "winston": "^3.17.0"
60
66
  }