Skip to content

Commit fd57924

Browse files
authored
feat: add AWS Lambda and API Gateway deployment infrastructure (#3)
1 parent 99da2a6 commit fd57924

File tree

14 files changed

+2716
-9
lines changed

14 files changed

+2716
-9
lines changed

.github/workflows/e2e.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ jobs:
6363
6464
- name: Start server for HTTP transport test
6565
env:
66-
PORT: 3000
66+
MCP_PORT: 3000
6767
QUIP_TOKEN: ${{ secrets.QUIP_TOKEN }}
6868
QUIP_BASE_URL: ${{ secrets.QUIP_BASE_URL }}
6969
run: |

README.md

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ A Model Context Protocol (MCP) server for interacting with Quip spreadsheets, im
1414
- [Transport Documentation](#transport-documentation)
1515
- [Configure for Claude.app](#configure-for-claudeapp)
1616
- [Command Line Arguments](#command-line-arguments)
17+
- [Deploy to AWS Lambda + API Gateway](#deploy-to-aws-lambda--api-gateway)
1718
- [Available Tools](#available-tools)
1819
- [quip_read_spreadsheet](#quip_read_spreadsheet)
1920
- [Resource URIs](#resource-uris)
@@ -27,6 +28,8 @@ A Model Context Protocol (MCP) server for interacting with Quip spreadsheets, im
2728
- [Local Storage](#local-storage)
2829
- [S3 Storage](#s3-storage)
2930
- [Health Check Endpoint](#health-check-endpoint)
31+
- [Cloud Deployment](#cloud-deployment)
32+
- [AWS Lambda + API Gateway](#aws-lambda--api-gateway)
3033
- [Development](#development)
3134
- [Project Structure](#project-structure)
3235
- [Setting Up a Development Environment](#setting-up-a-development-environment)
@@ -233,6 +236,18 @@ node dist/index.js --mock --storage-path /path/to/storage
233236
node dist/index.js --auth --api-key your_api_key_here
234237
```
235238

239+
### Deploy to AWS Lambda + API Gateway
240+
241+
The Quip MCP server can be deployed to AWS Lambda with API Gateway to create a serverless, scalable HTTP endpoint. This setup is ideal for production environments and provides several benefits:
242+
243+
- **Serverless Operation**: No need to manage servers
244+
- **Auto-scaling**: Handles varying loads automatically
245+
- **High Availability**: Distributed across multiple availability zones
246+
- **Cost-effective**: Pay only for what you use
247+
- **Streamable HTTP Interface**: Works with tools that support HTTP MCP servers
248+
249+
For detailed deployment instructions, see the [Cloud Deployment](#aws-lambda--api-gateway) section.
250+
236251
## Available Tools
237252

238253
### quip_read_spreadsheet
@@ -510,6 +525,33 @@ The endpoint returns a simple JSON response with status "ok" when the server is
510525

511526
This endpoint can be used by monitoring tools or container orchestration systems to check if the server is healthy and ready to handle requests.
512527

528+
## Cloud Deployment
529+
530+
### AWS Lambda + API Gateway
531+
532+
The Quip MCP server can be deployed as a serverless application using AWS Lambda with API Gateway. This provides a scalable, low-maintenance deployment option with a streamable HTTP interface.
533+
534+
The project includes an AWS CDK infrastructure setup that automates the deployment of:
535+
- Lambda function with the Quip MCP server
536+
- API Gateway endpoint
537+
- S3 bucket for storing CSV files
538+
- Secrets Manager for storing sensitive information
539+
540+
For detailed deployment instructions, architecture overview, and usage information, see the [AWS Lambda Deployment Guide](infrastructure/README.md) in the infrastructure directory.
541+
542+
To connect Claude.app to your deployed MCP server, add the following to your Claude settings (after deployment):
543+
544+
```json
545+
"mcpServers": {
546+
"quip-remote": {
547+
"endpointUrl": "https://your-api-gateway-url/mcp",
548+
"headers": {
549+
"X-API-Key": "YOUR_API_KEY_VALUE"
550+
}
551+
}
552+
}
553+
```
554+
513555
## Development
514556

515557
### Project Structure
@@ -531,11 +573,33 @@ quip-mcp-server-typescript/
531573
│ ├── auth.ts # Authentication
532574
│ └── cache.ts # Caching mechanism
533575
├── tests/
534-
│ ├── server.test.ts # Unit tests for server
535-
│ ├── quipClient.test.ts # Unit tests for Quip client
536-
│ ├── tools.test.ts # Unit tests for tools
537-
│ ├── storage.test.ts # Unit tests for storage
576+
│ ├── unit/ # Unit tests
577+
│ │ ├── server.test.ts
578+
│ │ ├── quipClient.test.ts
579+
│ │ ├── tools.test.ts
580+
│ │ ├── storage.test.ts
581+
│ │ └── ...
538582
│ └── e2e/ # End-to-end tests
583+
├── infrastructure/ # AWS deployment resources
584+
│ ├── cdk/ # CDK project
585+
│ │ ├── bin/
586+
│ │ │ └── app.ts # CDK app entry point
587+
│ │ ├── lib/
588+
│ │ │ └── quip-mcp-server-stack.ts # Main CDK stack
589+
│ │ ├── lambda/ # Lambda function code
590+
│ │ │ ├── run.js # Lambda handler
591+
│ │ │ └── package.json
592+
│ │ ├── package.json
593+
│ │ └── tsconfig.json
594+
│ └── README.md # AWS deployment documentation
595+
├── example-client/ # Example MCP client implementation
596+
│ ├── src/
597+
│ │ ├── client-common.ts
598+
│ │ ├── http-client.ts
599+
│ │ ├── stdio-client.ts
600+
│ │ └── index.ts
601+
│ ├── package.json
602+
│ └── README.md
539603
├── dist/ # Compiled JavaScript output
540604
├── .env.example # Example environment variables
541605
├── .gitignore # Git ignore file

example-client/start-http-server.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ fi
7070
echo "Starting Quip MCP server in HTTP mode on port $PORT..."
7171

7272
# Define base command
73-
CMD="QUIP_TOKEN=\"$QUIP_TOKEN\" QUIP_BASE_URL=\"$QUIP_BASE_URL\" PORT=$PORT"
73+
CMD="QUIP_TOKEN=\"$QUIP_TOKEN\" QUIP_BASE_URL=\"$QUIP_BASE_URL\" MCP_PORT=$PORT"
7474

7575
# Add storage type
7676
CMD="$CMD STORAGE_TYPE=$STORAGE_TYPE"

infrastructure/README.md

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
# Quip MCP Server on AWS Lambda
2+
3+
This project contains the AWS CDK infrastructure code to deploy the quip-mcp-server-typescript project on AWS Lambda with API Gateway.
4+
5+
## Architecture Overview
6+
7+
The architecture consists of the following components:
8+
9+
1. **AWS Lambda Function**: Hosts the Quip MCP server using AWS Lambda Web Adapter to convert API Gateway requests to HTTP requests.
10+
2. **API Gateway**: Provides the HTTP endpoint for clients to interact with the MCP server.
11+
3. **S3 Bucket**: Stores the CSV files exported from Quip spreadsheets.
12+
4. **AWS Secrets Manager**: Stores sensitive information like the Quip API token.
13+
14+
## Architecture Diagram
15+
16+
```mermaid
17+
flowchart TB
18+
Client[Client] -->|HTTP Request| APIGW[API Gateway]
19+
APIGW -->|Proxy Request| Lambda[Lambda Function]
20+
Lambda -->|Adapter| WebAdapter[AWS Lambda Web Adapter]
21+
WebAdapter -->|Forward Request| MCP[Quip MCP Server]
22+
MCP -->|Store/Retrieve Files| S3[(S3 Bucket)]
23+
MCP -->|Access Quip API| QuipAPI[Quip API]
24+
Lambda -->|Get Secrets| SecretsManager[Secrets Manager]
25+
26+
subgraph "AWS Cloud"
27+
APIGW
28+
Lambda
29+
WebAdapter
30+
MCP
31+
S3
32+
SecretsManager
33+
end
34+
35+
subgraph "External"
36+
QuipAPI
37+
Client
38+
end
39+
```
40+
41+
## Prerequisites
42+
43+
Before deploying this project, you need to have the following:
44+
45+
1. AWS CLI installed and configured with appropriate credentials
46+
2. Node.js 20.x or later
47+
3. A Quip API token
48+
49+
## Project Structure
50+
51+
```
52+
infrastructure/
53+
├── cdk/ # CDK project
54+
│ ├── bin/
55+
│ │ └── app.ts # CDK app entry point
56+
│ ├── lib/
57+
│ │ └── quip-mcp-server-stack.ts # Main CDK stack
58+
│ ├── lambda/ # Lambda function code
59+
│ │ ├── run.js # Lambda handler
60+
│ │ └── package.json
61+
│ ├── package.json
62+
│ └── tsconfig.json
63+
└── README.md
64+
```
65+
66+
## Deployment Instructions
67+
68+
### 1. Install Dependencies
69+
70+
First, install the dependencies for the CDK project:
71+
72+
```bash
73+
cd infrastructure/cdk
74+
npm install
75+
```
76+
77+
### 2. Bootstrap AWS Environment (First Time Only)
78+
79+
If you haven't used CDK in your AWS account before, you need to bootstrap it:
80+
81+
```bash
82+
npx cdk bootstrap
83+
```
84+
85+
### 3. Configure Secrets
86+
87+
Before deploying, you need to create a secret in AWS Secrets Manager with the following values:
88+
89+
- `QUIP_TOKEN`: Your Quip API token
90+
- `QUIP_BASE_URL`: The base URL for the Quip API (optional, defaults to `https://platform.quip.com/`)
91+
92+
You can create this secret manually in the AWS Console or use the AWS CLI:
93+
94+
```bash
95+
aws secretsmanager create-secret \
96+
--name quip-mcp-server/secrets \
97+
--description "Secrets for Quip MCP Server" \
98+
--secret-string '{"QUIP_TOKEN":"your-quip-api-token","QUIP_BASE_URL":"your-quip-base-url-if-needed"}'
99+
```
100+
101+
### 4. Deploy the CDK Stack
102+
103+
Deploy the CDK stack to your AWS account:
104+
105+
```bash
106+
cd infrastructure/cdk
107+
npx cdk deploy
108+
```
109+
110+
This command will:
111+
1. Synthesize the CloudFormation template
112+
2. Deploy the stack to your AWS account
113+
3. Output the API Gateway URL and API Key ID
114+
115+
### 5. Retrieve the API Key
116+
117+
After deployment, you need to retrieve the API key value from AWS Console or using the AWS CLI:
118+
119+
```bash
120+
aws apigateway get-api-key \
121+
--api-key YOUR_API_KEY_ID \
122+
--include-value
123+
```
124+
125+
Replace `YOUR_API_KEY_ID` with the API Key ID from the CDK output.
126+
127+
## Using the Deployed MCP Server
128+
129+
To use the deployed MCP server, you need to:
130+
131+
1. Use the API Gateway URL from the CDK output
132+
2. Include the API key in the `X-API-Key` header of your requests
133+
3. Send POST requests to the `/mcp` endpoint
134+
135+
Example:
136+
137+
```bash
138+
curl -X POST \
139+
-H "Content-Type: application/json" \
140+
-H "Accept: application/json, text/event-stream" \
141+
-H "X-API-Key: YOUR_API_KEY_VALUE" \
142+
-d '{
143+
"jsonrpc": "2.0",
144+
"id": "1",
145+
"method": "tools/call",
146+
"params": {
147+
"name": "quip_read_spreadsheet",
148+
"arguments": {
149+
"threadId": "YOUR_THREAD_ID"
150+
}
151+
}
152+
}' \
153+
https://your-api-gateway-url/mcp
154+
```
155+
156+
## Monitoring and Troubleshooting
157+
158+
You can monitor your Lambda function and API Gateway using AWS CloudWatch:
159+
160+
1. Lambda logs are available in CloudWatch Logs
161+
2. API Gateway metrics are available in CloudWatch Metrics
162+
3. You can set up CloudWatch Alarms for error rates and latency
163+
164+
## Cleanup
165+
166+
To remove all resources created by this CDK stack:
167+
168+
```bash
169+
cd infrastructure/cdk
170+
npx cdk destroy
171+
```
172+
173+
Note: This will not delete the S3 bucket contents or the Secrets Manager secret due to the retention policy. You need to delete them manually if required.
174+
175+
## Security Considerations
176+
177+
1. The API Gateway is protected with an API key
178+
2. Sensitive information is stored in Secrets Manager
179+
3. The S3 bucket is encrypted with SSE-S3
180+
4. The Lambda function has minimal IAM permissions
181+
182+
## Cost Optimization
183+
184+
1. The Lambda function is configured with 1024MB of memory
185+
2. S3 lifecycle rules delete objects after 180 days
186+
3. Consider using provisioned concurrency for consistent performance if needed

infrastructure/cdk/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
*.d.ts
2+
*.js
3+
!lambda/run.js
4+
cdk.out/

infrastructure/cdk/bin/app.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env node
2+
import 'source-map-support/register';
3+
import * as cdk from 'aws-cdk-lib';
4+
import { QuipMcpServerStack } from '../lib/quip-mcp-server-stack';
5+
6+
const app = new cdk.App();
7+
8+
new QuipMcpServerStack(app, 'QuipMcpServerStack', {
9+
/* If you don't specify 'env', this stack will be environment-agnostic.
10+
* Account/Region-dependent features and context lookups will not work,
11+
* but a single synthesized template can be deployed anywhere. */
12+
13+
/* Uncomment the next line to specialize this stack for the AWS Account
14+
* and Region that are implied by the current CLI configuration. */
15+
// env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
16+
17+
/* Uncomment the next line if you know exactly what Account and Region you
18+
* want to deploy the stack to. */
19+
// env: { account: '123456789012', region: 'us-east-1' },
20+
21+
/* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
22+
});

infrastructure/cdk/cdk.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"app": "npx ts-node -P tsconfig.json --prefer-ts-exts bin/app.ts",
3+
"output": "cdk.out",
4+
"build": "npm run build",
5+
"watch": {
6+
"include": [
7+
"bin/**/*.ts",
8+
"lib/**/*.ts"
9+
],
10+
"exclude": [
11+
"README.md",
12+
"cdk*.json",
13+
"**/*.d.ts",
14+
"**/*.js",
15+
"tsconfig.json",
16+
"package*.json",
17+
"yarn.lock",
18+
"node_modules"
19+
]
20+
}
21+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "quip-mcp-server-lambda",
3+
"version": "1.0.0",
4+
"description": "Lambda handler for quip-mcp-server-typescript",
5+
"main": "lambda-handler.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"keywords": [
10+
"aws",
11+
"lambda",
12+
"quip",
13+
"mcp"
14+
],
15+
"author": "",
16+
"license": "ISC",
17+
"dependencies": {
18+
"@aws-sdk/client-secrets-manager": "^3.806.0"
19+
}
20+
}

0 commit comments

Comments
 (0)