air-mcp-server
by eleva
README.md
# air-mcp-server
Template MCP server for AIR s2s agents, deployed on AWS Lambda via API Gateway and provisioned with AWS CDK. It exposes booking and date-utility tools that an AI agent can call over JSON-RPC.
## Tools
| Tool | Description |
|---|---|
| `create_booking` | Saves a booking to DynamoDB and optionally sends a WhatsApp confirmation to the customer |
| `get_current_date` | Returns the current date and time (year, month, day, hour, minute, second, ISO string, timezone) |
| `validate_future_date` | Validates that a `YYYY-MM-DD` date exists in the calendar and checks whether it is in the future |
## Architecture
```
API Gateway POST /mcp
│
▼
Lambda (Node.js 22, ESM)
air-mcp-handler-{stage}
│
├── DynamoDB air-bookings-{stage}
└── WhatsApp Cloud API (optional)
```
The Lambda uses a custom `HttpServerTransport` (no external MCP middleware dependency) that wires JSON-RPC messages directly into `@modelcontextprotocol/sdk`.
## Project structure
```
air-fiori-mcp/
├── __tests__/
│ ├── booking-tool/ # Jest tests for create_booking
│ └── tool-list/ # Snapshot test for the tool list
├── bin/
│ └── cdk-serverless-mcp-server.ts # CDK app entry point
├── lib/
│ └── cdk-serverless-mcp-server-stack.ts # CDK stack (Lambda + DynamoDB + API GW)
├── scripts/
│ ├── dev.sh # Local dev: cdk synth → SAM local start-api
│ └── generate-openapi.ts # Generates openapi.json from tool Zod schemas
├── src/
│ ├── index.ts # Lambda handler + MCP server bootstrap
│ ├── transport.ts # Custom HttpServerTransport
│ └── tool/
│ ├── booking/ # create_booking tool
│ └── date/ # get_current_date, validate_future_date tools
├── .env.example
├── cdk.json
└── package.json
```
## Prerequisites
- Node.js v22+
- AWS CDK v2: `npm install -g aws-cdk`
- AWS SAM CLI (for local dev): [install guide](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)
- Optionally: an AWS profile configured locally
## Environment variables
Copy `.env.example` to `.env` and fill in the values:
```
STAGE_NAME=dev
BOOKINGS_TABLE_NAME=air-bookings-dev
WHATSAPP_ENABLED=0 # set to 1 to enable WhatsApp confirmations
WHATSAPP_API_TOKEN=
WHATSAPP_PHONE_NUMBER_ID=
AWS_REGION=eu-north-1
```
## Getting started
```bash
npm install
```
### Run tests
```bash
npm test
```
### Local development
Starts a local API on `http://localhost:3000` using SAM, pointing at the synthesized CDK template:
```bash
npm run dev
```
### Generate OpenAPI spec
Scans `src/tool/` recursively, converts each tool's Zod schema to JSON Schema, and writes `openapi.json` at the project root. Re-run whenever you add a new tool — no manual changes needed.
```bash
npm run openapi
```
### Deploy
```bash
npm run deploy
```
After deployment the MCP endpoint is at the URL printed by CDK: `https://<api-id>.execute-api.<region>.amazonaws.com/dev/mcp`
## Usage examples
### List tools
```bash
curl -X POST http://127.0.0.1:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
```
### Create a booking
```bash
curl -X POST http://127.0.0.1:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "create_booking",
"arguments": {
"customerName": "Mario Rossi",
"customerPhone": "+39 333 1234567",
"date": "2026-07-15",
"time": "10:00",
"serviceType": "flight",
"notes": "window seat please"
}
}
}'
```
### Get current date
```bash
curl -X POST http://127.0.0.1:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_current_date","arguments":{}}}'
```
### Validate a date
```bash
curl -X POST http://127.0.0.1:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"validate_future_date","arguments":{"date":"2026-07-15"}}}'
```
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing