Skip to content

[v2] AWS Lambda + API Gateway Example #2409

Description

@microadam

Attempting to build a fresh MCP server, v2 is obviously the future, so trying to get it running using that. Is there a simple example that could be shown on how to get this running with streaming on AWS with API gateway and lambda?

I had it working without any streaming, but trying to use streamifyResponse and then everything just stops working. A simple working example would be very handy.

Many thanks

Code example:

import type { APIGatewayProxyEvent, StreamifyHandler } from "aws-lambda";
import { Readable } from "node:stream";
import { pipeline } from "node:stream/promises";

function buildQueryString(
  params: APIGatewayProxyEvent["queryStringParameters"]
): string {
  if (!params) {
    return "";
  }

  const search = new URLSearchParams();
  for (const [key, value] of Object.entries(params)) {
    if (value !== undefined) {
      search.set(key, value);
    }
  }

  const query = search.toString();
  return query ? `?${query}` : "";
}

function toFetchRequest(event: APIGatewayProxyEvent): Request {
  const domain = event.requestContext.domainName;
  const query = buildQueryString(event.queryStringParameters);
  const url = `https://${domain}${event.path}${query}`;

  const headers = new Headers();
  if (event.headers) {
    for (const [key, value] of Object.entries(event.headers)) {
      if (value !== undefined) {
        headers.set(key, value);
      }
    }
  }

  let body: string | undefined;
  if (event.body) {
    body = event.isBase64Encoded
      ? Buffer.from(event.body, "base64").toString("utf8")
      : event.body;
  }

  return new Request(url, {
    method: event.httpMethod,
    headers,
    body: body && event.httpMethod !== "GET" ? body : undefined
  });
}


export const handler: StreamifyHandler<APIGatewayProxyEvent, void> =
  awslambda.streamifyResponse(async (event, responseStream) => {
    const request = toFetchRequest(event);
    const response = await mcpHandler.fetch(request);

    const httpResponseStream = awslambda.HttpResponseStream.from(
      responseStream,
      {
        statusCode: response.status,
        headers: Object.fromEntries(response.headers)
      }
    );

    if (response.body) {
      await pipeline(Readable.fromWeb(response.body), httpResponseStream);
    } else {
      httpResponseStream.end();
    }
  });

NOTE: mcpHandler is omitted here. Its just the basic response of createMcpHandler from the server package

In terms of API Gateway and the lambda config, the "responseTransferMode" is set to "STREAM" on ApiGateway and the lambda is being invoked via its streaming method

Metadata

Metadata

Assignees

No one assigned

    Labels

    v2Ideas, requests and plans for v2 of the SDK which will incorporate major changes and fixes

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions