# MCP Lambda SAM

Model Context Protocol (MCP) implementation using AWS Lambda and SAM.

## Overview

This project provides a serverless implementation of the Model Context Protocol, with two distinct interfaces:

1. **System Configuration** (Administrative):
   - Registration of MCP tools, resources, and prompts
   - IAM permission management
   - Infrastructure setup and configuration

2. **System Usage** (Client):
   - Establishing SSE connections
   - Sending commands
   - Receiving streaming responses

## Architecture

### Mermaid Diagram

You can visualize the system using this Mermaid syntax:

```mermaid
graph TD
  Client --> MCP[/"MCP Lambda\n(/sse & /message)"/]
  MCP -->|read/write| SessionTable[(Session Table)]
  MCP -->|query| RegistrationTable[(Registration Table)]
  MCP -->|invoke| RegisteredLambda["Registered Lambda Tool"]

  Admin[Administrator] --> RegistrationLambda[/"Registration Lambda\n(/register)"/]
  RegistrationLambda -->|write| RegistrationTable
```

- The **MCP Lambda** reads registrations from the Registration Table on startup and when handling requests.
- It uses the Session Table to persist session state.
- It **invokes registered Lambda tools** dynamically using the ARNs stored in the Registration Table. 

## System Configuration Guide (Administrators)

This section is for system administrators who need to configure and manage the MCP server.

### Deployment

```bash
npx @markvp/mcp-lambda-sam deploy
```

The command will interactively prompt for administrative configuration:
- Stack name (for multiple instances)
- AWS Region
- VPC configuration (optional)

### Permissions Overview

To access MCP endpoints, users and clients must have IAM permission to invoke the relevant Function URLs.

- **Administrators**: must be allowed to invoke the `mcp-registration` function URL
- **Clients**: must be allowed to invoke the `mcp` function URL

You can grant access using either an IAM policy or `aws lambda add-permission` (see below).

### Assigning Permissions via AWS CLI

To grant permission to invoke the **registration function URL**:

```bash
aws lambda add-permission \
  --function-name <registration-function-name> \
  --statement-id allow-registration \
  --action lambda:InvokeFunctionUrl \
  --principal "*" \
  --function-url-auth-type IAM
```

To grant permission to invoke the **MCP function URL** (SSE and message):

```bash
aws lambda add-permission \
  --function-name <mcp-function-name> \
  --statement-id allow-mcp \
  --action lambda:InvokeFunctionUrl \
  --principal "*" \
  --function-url-auth-type IAM
```

Replace `<registration-function-name>` and `<mcp-function-name>` with the actual Lambda function names.

### Registration API

Use these endpoints to manage MCP tools, resources, and prompts:

#### Register a New Tool
```bash
awscurl -X POST ${REGISTRATION_URL}/register \
  --region ap-southeast-2 \
  --service lambda \
  -H "Content-Type: application/json" \
  -d '{
    "type": "tool",
    "name": "example",
    "description": "Example tool",
    "lambdaArn": "arn:aws:lambda:region:account:function:name",
    "parameters": {
      "input": "string"
    }
  }'
```

#### Update Registration
```bash
awscurl -X PUT ${REGISTRATION_URL}/register/{id} \
  --region ap-southeast-2 \
  --service lambda \
  -d '...'
```

#### Delete Registration
```bash
awscurl -X DELETE ${REGISTRATION_URL}/register/{id} \
  --region ap-southeast-2 \
  --service lambda
```

#### List Registrations
```bash
awscurl ${REGISTRATION_URL}/register \
  --region ap-southeast-2 \
  --service lambda
```

### Required IAM Permissions

#### For Administrators
Administrators need these permissions to manage registrations:
```json
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "lambda:InvokeFunctionUrl",
    "Resource": "arn:aws:lambda:${region}:${account}:function:${stack-id}-mcp-registration",
    "Condition": {
      "StringEquals": {
        "lambda:FunctionUrlAuthType": "AWS_IAM"
      }
    }
  }]
}

```

## System Usage Guide (Clients)

This section is for clients who want to use the MCP server.

### Required IAM Permissions

Clients need these permissions to use the MCP server:
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "lambda:InvokeFunctionUrl",
            "Resource": [
                "arn:aws:lambda:${region}:${account}:function:${stack-id}-mcp",
            ],
            "Condition": {
                "StringEquals": {
                    "lambda:FunctionUrlAuthType": "AWS_IAM"
                }
            }
        }
    ]
}
```

### Connecting to the Server

1. **Establish SSE Connection**:
```typescript
const sse = new EventSource(SSE_URL, {
  headers: { 
    Authorization: 'AWS4-HMAC-SHA256 ...', // Must be AWS SigV4 signed
  }
});

sse.onmessage = (event) => {
  console.log(JSON.parse(event.data));
};
```

### Example cURL for SSE

```bash
awscurl -X GET "${MCP_URL}/sse" \
  --region ap-southeast-2 \
  --service lambda
```

The first event will include a `sessionId`. Use this when sending messages.

2. **Send Commands**:
```bash
awscurl -X POST "${MCP_URL}/message?sessionId=session-123" \
  --region ap-southeast-2 \
  --service lambda \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "example",
    "params": {
      "input": "hello"
    }
  }'
```

### Error Handling

#### Common Client Errors
- `401`: Invalid/missing AWS credentials
- `403`: Insufficient permissions
- `404`: Invalid session ID
- `429`: Rate limit exceeded

#### Troubleshooting
1. **Connection Issues**:
   - Verify AWS credentials
   - Check IAM permissions
   - Ensure network connectivity

2. **Command Execution Errors**:
   - Verify session ID is active
   - Check command format matches tool registration
   - Ensure parameters match schema

## Requirements

- AWS CLI installed and configured
- AWS SAM CLI installed
- Node.js 20.x or later
- An AWS account with permissions to create:
  - Lambda functions
  - DynamoDB tables
  - IAM roles
  - SQS queues

## AWS SAM CLI Setup

To deploy this application locally or to AWS using the AWS SAM CLI:

1. Install the AWS SAM CLI: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html
2. Ensure it's available in your PATH:
   ```bash
   sam --version
   ```
3. Build and deploy the application:
   ```bash
   sam build
   sam deploy --guided
   ```
4. Follow the prompts to configure the stack name, region, capabilities, and parameter overrides.

You can rerun `sam deploy` without `--guided` to use saved configuration.

## Installation

You can install and deploy this application in four ways:

### 1. Using AWS Serverless Application Repository (SAR)

The easiest way to deploy the MCP server is through the AWS Serverless Application Repository (SAR):

- Go to the [SAR Console](https://serverlessrepo.aws.amazon.com/applications)
- Search for **mcp-lambda-sam** by Mark Van Proctor
- Click **Deploy**
- Set your parameters:
  - `StackIdentifier`: Unique ID for this MCP server instance
  - `VpcEnabled`: Set to `true` if deploying in a VPC
  - `VpcId` and `SubnetIds`: Provide only if `VpcEnabled` is `true`
- Follow the prompts to deploy

Alternatively, you can deploy from the AWS CLI:
```bash
aws serverlessrepo create-cloud-formation-change-set \
  --application-id arn:aws:serverlessrepo:ap-southeast-2:522814717816:applications/mcp-lambda-sam \
  --stack-name your-stack-name \
  --capabilities CAPABILITY_IAM \
  --parameter-overrides '[{"name":"StackIdentifier","value":"your-stack-id"}]'
```
  
### 2. Using npx (CLI)

```bash
npx @markvp/mcp-lambda-sam deploy
```

The command will interactively prompt for administrative configuration:
- Stack name (for multiple instances)
- AWS Region
- VPC configuration (optional)

### 3. Programmatic Usage with Install
Install the package:

```bash
npm install @markvp/mcp-lambda-sam
```

After installing the package, you can use it programmatically:
```javascript
import { deploy } from '@markvp/mcp-lambda-sam';

// Usage example
deploy();
```

### 4. Local Development and Deployment
Install the package:

```bash
npm install @markvp/mcp-lambda-sam
```

After making development changes, you can deploy it manually:
```bash
npm run deploy
```

## Development
```bash
# Install dependencies
npm install

# Lint
npm run lint

# Run tests
npm test

# Build
npm run build

# Deploy
npm run deploy
```

### Publishing to SAR

If you're contributing to this project and need to publish updates to SAR:

1. Package the application:
```bash
npm run package:sar
```

2. Publish to SAR:
```bash
npm run publish:sar
```

3. Make the application public (one-time setup):
   - Go to AWS Console > Serverless Application Repository
   - Select the application
   - Click "Share" and choose "Public"
   - Apply the following sharing policy:
   ```json
   {
       "Version": "2012-10-17",
       "Statement": [
           {
               "Effect": "Allow",
               "Principal": "*",
               "Action": "serverlessrepo:CreateCloudFormationTemplate",
               "Resource": "arn:aws:serverlessrepo:${region}:${account-id}:applications/mcp-lambda-sam"
           }
       ]
   }
   ```

## License

MIT

## Contributing

1. Fork the repository
2. Create your feature branch
3. Commit your changes
4. Push to the branch
5. Create a new Pull Request
