lemonsqueezy-mcp-server 1.0.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.
- package/ENV_EXAMPLE.md +83 -0
- package/LICENSE +21 -0
- package/README.md +141 -0
- package/SETUP.md +244 -0
- package/dist/config.d.ts +25 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +80 -0
- package/dist/config.js.map +1 -0
- package/dist/config.test.d.ts +2 -0
- package/dist/config.test.d.ts.map +1 -0
- package/dist/config.test.js +55 -0
- package/dist/config.test.js.map +1 -0
- package/dist/connections/firebase.d.ts +3 -0
- package/dist/connections/firebase.d.ts.map +1 -0
- package/dist/connections/firebase.js +62 -0
- package/dist/connections/firebase.js.map +1 -0
- package/dist/connections/salesforce.d.ts +3 -0
- package/dist/connections/salesforce.d.ts.map +1 -0
- package/dist/connections/salesforce.js +307 -0
- package/dist/connections/salesforce.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +101 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/payment-context.d.ts +14 -0
- package/dist/resources/payment-context.d.ts.map +1 -0
- package/dist/resources/payment-context.js +111 -0
- package/dist/resources/payment-context.js.map +1 -0
- package/dist/server.d.ts +36 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +14 -0
- package/dist/server.js.map +1 -0
- package/dist/sync-last-purchase.d.ts +3 -0
- package/dist/sync-last-purchase.d.ts.map +1 -0
- package/dist/sync-last-purchase.js +113 -0
- package/dist/sync-last-purchase.js.map +1 -0
- package/dist/tools/definitions.d.ts +3768 -0
- package/dist/tools/definitions.d.ts.map +1 -0
- package/dist/tools/definitions.js +753 -0
- package/dist/tools/definitions.js.map +1 -0
- package/dist/tools/handlers/analytics.d.ts +21 -0
- package/dist/tools/handlers/analytics.d.ts.map +1 -0
- package/dist/tools/handlers/analytics.js +398 -0
- package/dist/tools/handlers/analytics.js.map +1 -0
- package/dist/tools/handlers/lemonsqueezy.d.ts +436 -0
- package/dist/tools/handlers/lemonsqueezy.d.ts.map +1 -0
- package/dist/tools/handlers/lemonsqueezy.js +481 -0
- package/dist/tools/handlers/lemonsqueezy.js.map +1 -0
- package/dist/tools/handlers/salesforce.d.ts +13 -0
- package/dist/tools/handlers/salesforce.d.ts.map +1 -0
- package/dist/tools/handlers/salesforce.js +54 -0
- package/dist/tools/handlers/salesforce.js.map +1 -0
- package/dist/tools/handlers/vos.d.ts +26 -0
- package/dist/tools/handlers/vos.d.ts.map +1 -0
- package/dist/tools/handlers/vos.js +207 -0
- package/dist/tools/handlers/vos.js.map +1 -0
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +202 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/types.d.ts +24 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/logger.d.ts +3 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +8 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/response.d.ts +14 -0
- package/dist/utils/response.d.ts.map +1 -0
- package/dist/utils/response.js +17 -0
- package/dist/utils/response.js.map +1 -0
- package/dist/utils/retry.d.ts +11 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +36 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/secrets/provider.d.ts +30 -0
- package/dist/utils/secrets/provider.d.ts.map +1 -0
- package/dist/utils/secrets/provider.js +51 -0
- package/dist/utils/secrets/provider.js.map +1 -0
- package/dist/utils/secrets.d.ts +7 -0
- package/dist/utils/secrets.d.ts.map +1 -0
- package/dist/utils/secrets.js +16 -0
- package/dist/utils/secrets.js.map +1 -0
- package/dist/utils/validation.d.ts +580 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +250 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/webhooks/listener.d.ts +17 -0
- package/dist/webhooks/listener.d.ts.map +1 -0
- package/dist/webhooks/listener.js +140 -0
- package/dist/webhooks/listener.js.map +1 -0
- package/dist/webhooks/ngrok.d.ts +8 -0
- package/dist/webhooks/ngrok.d.ts.map +1 -0
- package/dist/webhooks/ngrok.js +50 -0
- package/dist/webhooks/ngrok.js.map +1 -0
- package/package.json +68 -0
package/ENV_EXAMPLE.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Environment Variables Example
|
|
2
|
+
|
|
3
|
+
Create a `.env` file in the project root with the following variables:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
# Lemon Squeezy API Keys
|
|
7
|
+
# Get your API keys from: https://app.lemonsqueezy.com/settings/api
|
|
8
|
+
#
|
|
9
|
+
# For testing (recommended to start):
|
|
10
|
+
LEMONSQUEEZY_TEST_API_KEY=your_test_api_key_here
|
|
11
|
+
#
|
|
12
|
+
# For production (use when ready):
|
|
13
|
+
# LEMONSQUEEZY_API_KEY=your_production_api_key_here
|
|
14
|
+
#
|
|
15
|
+
# Note: If both are set, production key takes priority
|
|
16
|
+
|
|
17
|
+
# Salesforce Integration (Optional - Bonus Feature)
|
|
18
|
+
# Get your credentials from: https://help.salesforce.com/s/articleView?id=sf.user_security_token.htm
|
|
19
|
+
#
|
|
20
|
+
# Option 1: AWS Secrets Manager (Recommended for Production)
|
|
21
|
+
# Store your Salesforce credentials in AWS Secrets Manager as a JSON secret:
|
|
22
|
+
# {
|
|
23
|
+
# "username": "your_salesforce_username@example.com",
|
|
24
|
+
# "password": "your_salesforce_password",
|
|
25
|
+
# "securityToken": "your_security_token"
|
|
26
|
+
# }
|
|
27
|
+
# Or for JWT authentication:
|
|
28
|
+
# {
|
|
29
|
+
# "client_id": "your_connected_app_client_id",
|
|
30
|
+
# "username": "your_username@example.com",
|
|
31
|
+
# "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
|
|
32
|
+
# }
|
|
33
|
+
# Or as plain text key=value pairs:
|
|
34
|
+
# username=your_salesforce_username@example.com
|
|
35
|
+
# password=your_salesforce_password
|
|
36
|
+
# securityToken=your_security_token
|
|
37
|
+
#
|
|
38
|
+
# Example configuration:
|
|
39
|
+
# AWS_SALESFORCE_SECRET_NAME=your-project/salesforce-credentials
|
|
40
|
+
# AWS_REGION=us-west-2 # Your AWS region (us-east-1, us-west-2, eu-west-1, etc.)
|
|
41
|
+
#
|
|
42
|
+
# SECURITY BEST PRACTICE: Do NOT set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY here.
|
|
43
|
+
# Instead, use AWS CLI to configure credentials: `aws configure`
|
|
44
|
+
# This stores credentials securely in ~/.aws/credentials (encrypted by OS).
|
|
45
|
+
# See README.md for full instructions.
|
|
46
|
+
#
|
|
47
|
+
# Note: Use your own secret name and region. The secret name should match
|
|
48
|
+
# exactly what you created in AWS Secrets Manager.
|
|
49
|
+
#
|
|
50
|
+
# Option 2: Environment Variables (For Local Development)
|
|
51
|
+
# SALESFORCE_USERNAME=your_salesforce_username@example.com
|
|
52
|
+
# SALESFORCE_PASSWORD=your_salesforce_password
|
|
53
|
+
# SALESFORCE_TOKEN=your_security_token
|
|
54
|
+
#
|
|
55
|
+
# Optional: Custom login URL (defaults to https://login.salesforce.com)
|
|
56
|
+
# SALESFORCE_LOGIN_URL=https://login.salesforce.com
|
|
57
|
+
#
|
|
58
|
+
# Note: Salesforce integration is optional. The server works perfectly without it.
|
|
59
|
+
# If AWS_SALESFORCE_SECRET_NAME is set, it will use AWS Secrets Manager.
|
|
60
|
+
# Otherwise, it falls back to environment variables.
|
|
61
|
+
|
|
62
|
+
# Proactive Context (Optional - Advanced Feature)
|
|
63
|
+
# Enable Resources capability for proactive AI context
|
|
64
|
+
#
|
|
65
|
+
# ENABLE_RESOURCES=true
|
|
66
|
+
# POLL_FAILED_PAYMENTS=true
|
|
67
|
+
# POLL_INTERVAL_MINUTES=5
|
|
68
|
+
# WEBHOOK_LOG_PATH=/path/to/webhook.log
|
|
69
|
+
|
|
70
|
+
# Webhook Listener (Sprint 2 - Event Engine)
|
|
71
|
+
# Real-time webhook processing replaces file watching
|
|
72
|
+
#
|
|
73
|
+
# WEBHOOK_PORT=3000
|
|
74
|
+
# LEMONSQUEEZY_WEBHOOK_SECRET=your_webhook_signing_secret_here
|
|
75
|
+
# ENABLE_NGROK=true
|
|
76
|
+
#
|
|
77
|
+
# Note: If ENABLE_NGROK=true, ngrok will create a public tunnel.
|
|
78
|
+
# The public URL will be logged on startup - use it to configure your Lemon Squeezy webhook.
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Note:** Copy this content to a `.env` file (not `.env.example`) for local development. The `.env` file is already in `.gitignore` and won't be committed.
|
|
82
|
+
|
|
83
|
+
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Lemon Squeezy MCP Server
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
## 📖 About
|
|
6
|
+
**Give your AI assistant direct access to your payment and subscription data.**
|
|
7
|
+
|
|
8
|
+
This server acts as a bridge between your AI assistant (like VS Code, Claude Desktop, or any MCP-compatible client) and your Lemon Squeezy account. Instead of manually logging into dashboards, searching for orders, and copy-pasting details, you can simply ask your AI questions like:
|
|
9
|
+
- *"What was the last sale?"*
|
|
10
|
+
- *"Is subscription #12345 still active?"*
|
|
11
|
+
- *"Find all customers named 'Alice'"*
|
|
12
|
+
|
|
13
|
+
Your AI will query the data securely and give you an instant answer, right in your code editor.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 🌱 Beginner Level: Getting Started
|
|
18
|
+
|
|
19
|
+
**Who is this for?** You are new to CLI tools or just want to get this running quickly with minimal fuss.
|
|
20
|
+
|
|
21
|
+
### 1. Prerequisites
|
|
22
|
+
Before you start, make sure you have these two things installed on your computer:
|
|
23
|
+
* **Node.js (Version 18 or higher):** This is the software that runs the server. [Download Node.js here](https://nodejs.org/).
|
|
24
|
+
* **A Lemon Squeezy Account:** You need an account to get the data. [Sign up here](https://lemonsqueezy.com).
|
|
25
|
+
|
|
26
|
+
### 2. Get Your API Key
|
|
27
|
+
Think of this as your password for the server.
|
|
28
|
+
1. Log in to your [Lemon Squeezy Dashboard](https://app.lemonsqueezy.com/settings/api).
|
|
29
|
+
2. Go to **Settings** -> **API**.
|
|
30
|
+
3. Click **Create API Key**.
|
|
31
|
+
4. Copy the key (it starts with `ls_...`). **Keep this safe!**
|
|
32
|
+
|
|
33
|
+
### 3. Quick Installation
|
|
34
|
+
Open your terminal (Command Prompt on Windows, Terminal on Mac) and run these commands one by one:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# 1. Download the project
|
|
38
|
+
git clone https://github.com/MichaelWeed/lemonsqueezy-mcp-server.git
|
|
39
|
+
cd lemonsqueezy-mcp-server
|
|
40
|
+
|
|
41
|
+
# 2. Install the necessary files
|
|
42
|
+
npm install
|
|
43
|
+
|
|
44
|
+
# 3. Build the server
|
|
45
|
+
npm run build
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 4. Connect to Your AI Editor
|
|
49
|
+
The exact steps depend on which AI editor you're using. Here are the most common:
|
|
50
|
+
|
|
51
|
+
**One-copy-paste setup (Claude Desktop / Cursor / npx):**
|
|
52
|
+
Add this to your MCP config file (e.g. `claude_desktop_config.json` or Cursor MCP settings). Replace `YOUR_KEY_HERE` with your Lemon Squeezy API key.
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
"mcpServers": {
|
|
56
|
+
"lemonsqueezy": {
|
|
57
|
+
"command": "npx",
|
|
58
|
+
"args": ["-y", "lemonsqueezy-mcp-server"],
|
|
59
|
+
"env": {
|
|
60
|
+
"LEMONSQUEEZY_API_KEY": "YOUR_KEY_HERE"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
*(Requires the package to be [published on npm](https://www.npmjs.com/package/lemonsqueezy-mcp-server). For local development, use the path-based config below.)*
|
|
67
|
+
|
|
68
|
+
**For VS Code (local path):**
|
|
69
|
+
1. Open VS Code Settings
|
|
70
|
+
2. Go to Extensions → MCP
|
|
71
|
+
3. Add a new MCP server with:
|
|
72
|
+
* **Command:** `node`
|
|
73
|
+
* **Args:** `["/absolute/path/to/lemonsqueezy-mcp-server/dist/index.js"]`
|
|
74
|
+
* **Env:** `{"LEMONSQUEEZY_API_KEY": "your_api_key_here"}`
|
|
75
|
+
|
|
76
|
+
**For Claude Desktop (local path):**
|
|
77
|
+
1. Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (Mac) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows)
|
|
78
|
+
2. Add the same configuration as above (command `node`, args with full path to `dist/index.js`)
|
|
79
|
+
3. Restart Claude Desktop
|
|
80
|
+
|
|
81
|
+
**For Other MCP Clients:**
|
|
82
|
+
Refer to your client's documentation for adding MCP servers. The server runs via `node /path/to/dist/index.js` with the `LEMONSQUEEZY_API_KEY` environment variable set.
|
|
83
|
+
|
|
84
|
+
After configuring, restart your AI editor and try asking: *"Show me my last 5 orders."*
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 🚀 Medium User Level: Basic Usage & Configuration
|
|
89
|
+
|
|
90
|
+
**Who is this for?** You are comfortable with config files, environment variables, and want to customize how the server works.
|
|
91
|
+
|
|
92
|
+
### Philosophy: "Sensible Defaults"
|
|
93
|
+
This server is designed to work out of the box with just **one** required setting: your `LEMONSQUEEZY_API_KEY`. Everything else is optional and has pre-configured defaults that work for 90% of users.
|
|
94
|
+
|
|
95
|
+
### Configuration Options
|
|
96
|
+
You can configure the server using Environment Variables in your MCP settings or a `.env` file.
|
|
97
|
+
|
|
98
|
+
| Variable | Description | Default |
|
|
99
|
+
|----------|-------------|---------|
|
|
100
|
+
| `LEMONSQUEEZY_API_KEY` | **Required.** Your live API key. | - |
|
|
101
|
+
| `LEMONSQUEEZY_TEST_API_KEY` | Optional. Use for testing without affecting real data. | - |
|
|
102
|
+
| `ENABLE_RESOURCES` | Set to `true` to let the AI see "active context" like failed payments automatically. | `false` |
|
|
103
|
+
| `POLL_FAILED_PAYMENTS` | Set to `true` to check for failed payments every few minutes. | `false` |
|
|
104
|
+
|
|
105
|
+
### Common Tasks
|
|
106
|
+
|
|
107
|
+
**1. Using Test Mode**
|
|
108
|
+
If you want to develop without touching real money, generate a "Test API Key" in Lemon Squeezy and use `LEMONSQUEEZY_TEST_API_KEY`. The server will automatically prioritize the live key if both are present, so remove the live key to force test mode.
|
|
109
|
+
|
|
110
|
+
**2. Enabling Salesforce Integration (Bonus)**
|
|
111
|
+
Want to sync customers to your CRM?
|
|
112
|
+
Add these variables:
|
|
113
|
+
- `SALESFORCE_USERNAME`
|
|
114
|
+
- `SALESFORCE_PASSWORD`
|
|
115
|
+
- `SALESFORCE_TOKEN` (Security Token)
|
|
116
|
+
|
|
117
|
+
The tools for Salesforce (like `sync_customer_to_crm`) will automatically appear in your AI's toolkit.
|
|
118
|
+
|
|
119
|
+
### Troubleshooting
|
|
120
|
+
* **"Command not found":** Ensure you ran `npm run build` after installing.
|
|
121
|
+
* **"Authentication Error":** Double-check your API key. Did you copy an extra space?
|
|
122
|
+
* **Logs:** The server outputs logs to the "MCP Log" window in your editor. Check there for specific error messages.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 🛠️ Advanced User Level: Technical Documentation
|
|
127
|
+
|
|
128
|
+
**Who is this for?** Developers, Architects, and DevOps engineers looking for deep technical details, architecture diagrams, security compliance, and deployment strategies.
|
|
129
|
+
|
|
130
|
+
**Containers:** This repo has both a **Containerfile** and a **Dockerfile** with the same build. The Dockerfile exists so registries (e.g. Smithery) and CI that look for the filename `Dockerfile` can discover and build the image. You can build with Podman or Docker; see **[CONTAINERS.md](./CONTAINERS.md)** for why both exist and how to build.
|
|
131
|
+
|
|
132
|
+
For a comprehensive breakdown of the system architecture, code modules, security protocols, and enterprise deployment guides, please refer to the:
|
|
133
|
+
|
|
134
|
+
👉 **[Technical Solution Design Document (TSD)](./TECHNICAL_SOLUTION_DESIGN.md)**
|
|
135
|
+
|
|
136
|
+
The TSD covers:
|
|
137
|
+
* **System Architecture & Diagrams**
|
|
138
|
+
* **Module Interflows & Data Paths**
|
|
139
|
+
* **Security & Compliance (AWS Secrets Manager, etc.)**
|
|
140
|
+
* **Deployment (Docker/OCI Containers)**
|
|
141
|
+
* **Risk Mitigation Strategies**
|
package/SETUP.md
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# Quick Setup Checklist
|
|
2
|
+
|
|
3
|
+
Follow these steps to get your Lemon Squeezy MCP Server running:
|
|
4
|
+
|
|
5
|
+
## ✅ Pre-Flight Checklist
|
|
6
|
+
|
|
7
|
+
- [ ] Node.js 18+ installed (`node --version`)
|
|
8
|
+
- [ ] Lemon Squeezy account created
|
|
9
|
+
- [ ] API key obtained from Lemon Squeezy dashboard
|
|
10
|
+
|
|
11
|
+
## 📦 Installation Steps
|
|
12
|
+
|
|
13
|
+
1. **Install dependencies:**
|
|
14
|
+
```bash
|
|
15
|
+
npm install
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
2. **Build the project:**
|
|
19
|
+
```bash
|
|
20
|
+
npm run build
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
3. **Verify build succeeded:**
|
|
24
|
+
```bash
|
|
25
|
+
ls dist/index.js
|
|
26
|
+
```
|
|
27
|
+
(Should show the file exists)
|
|
28
|
+
|
|
29
|
+
## 🔑 Configuration Steps
|
|
30
|
+
|
|
31
|
+
1. **Get your API key:**
|
|
32
|
+
- Go to https://app.lemonsqueezy.com/settings/api
|
|
33
|
+
- Create a new API key (start with Test key)
|
|
34
|
+
- Copy it
|
|
35
|
+
|
|
36
|
+
2. **Configure your AI client:**
|
|
37
|
+
- **VS Code:** Settings → Extensions → MCP
|
|
38
|
+
- **Claude Desktop:** Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (Mac) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows)
|
|
39
|
+
- **Other MCP clients:** Refer to your client's documentation for MCP server configuration
|
|
40
|
+
|
|
41
|
+
3. **Add this configuration:**
|
|
42
|
+
|
|
43
|
+
**Option A — One-copy-paste (npx, after npm publish):**
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"mcpServers": {
|
|
47
|
+
"lemonsqueezy": {
|
|
48
|
+
"command": "npx",
|
|
49
|
+
"args": ["-y", "lemonsqueezy-mcp-server"],
|
|
50
|
+
"env": {
|
|
51
|
+
"LEMONSQUEEZY_API_KEY": "paste_your_key_here"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Option B — Local path (development):**
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"mcpServers": {
|
|
62
|
+
"lemonsqueezy": {
|
|
63
|
+
"command": "node",
|
|
64
|
+
"args": ["/FULL/PATH/TO/THIS/PROJECT/dist/index.js"],
|
|
65
|
+
"env": {
|
|
66
|
+
"LEMONSQUEEZY_TEST_API_KEY": "paste_your_key_here"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
4. **Important:**
|
|
74
|
+
- Replace `/FULL/PATH/TO/THIS/PROJECT` with your actual path
|
|
75
|
+
- Use absolute path (full path from root), not relative
|
|
76
|
+
- Save the file
|
|
77
|
+
- Restart your AI client completely
|
|
78
|
+
|
|
79
|
+
## 🧪 Testing
|
|
80
|
+
|
|
81
|
+
After restarting, ask your AI:
|
|
82
|
+
|
|
83
|
+
> "What was the last successful payment from Lemon Squeezy?"
|
|
84
|
+
|
|
85
|
+
If it works, you're done! 🎉
|
|
86
|
+
|
|
87
|
+
## 🆘 Common Issues
|
|
88
|
+
|
|
89
|
+
**"Tools not showing up"**
|
|
90
|
+
- Did you save the config file?
|
|
91
|
+
- Did you restart your AI client?
|
|
92
|
+
- Check the path is absolute and correct
|
|
93
|
+
|
|
94
|
+
**"Server not found"**
|
|
95
|
+
- Run `npm run build` again
|
|
96
|
+
- Verify `dist/index.js` exists
|
|
97
|
+
- Check the path in your config
|
|
98
|
+
|
|
99
|
+
**"API errors"**
|
|
100
|
+
- Verify your API key is correct
|
|
101
|
+
- Make sure you copied the full key
|
|
102
|
+
- Check key hasn't expired in Lemon Squeezy dashboard
|
|
103
|
+
|
|
104
|
+
## 📍 Finding Your Path
|
|
105
|
+
|
|
106
|
+
**Mac/Linux:**
|
|
107
|
+
```bash
|
|
108
|
+
pwd
|
|
109
|
+
# Copy the output and use it in your config
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Windows:**
|
|
113
|
+
```cmd
|
|
114
|
+
cd
|
|
115
|
+
# Copy the output and use it in your config (use forward slashes or double backslashes)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## 🎯 Next Steps
|
|
119
|
+
|
|
120
|
+
Once it's working:
|
|
121
|
+
- Try different queries (see README examples)
|
|
122
|
+
- Switch to production API key when ready
|
|
123
|
+
- Explore all 45+ available tools
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 🔐 Adding Salesforce Integration with AWS Secrets Manager (Optional)
|
|
128
|
+
|
|
129
|
+
If you want to add Salesforce CRM integration later using AWS Secrets Manager:
|
|
130
|
+
|
|
131
|
+
### Step 1: Create Secret in AWS Secrets Manager
|
|
132
|
+
|
|
133
|
+
1. Go to [AWS Secrets Manager Console](https://console.aws.amazon.com/secretsmanager/)
|
|
134
|
+
2. Click "Store a new secret"
|
|
135
|
+
3. Choose "Other type of secret"
|
|
136
|
+
4. Select "Plaintext" or "JSON"
|
|
137
|
+
5. **For JSON format**, enter:
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"username": "your_salesforce_username@example.com",
|
|
141
|
+
"password": "your_salesforce_password",
|
|
142
|
+
"securityToken": "your_security_token"
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
6. **For plain text**, enter:
|
|
146
|
+
```
|
|
147
|
+
username=your_salesforce_username@example.com
|
|
148
|
+
password=your_salesforce_password
|
|
149
|
+
securityToken=your_security_token
|
|
150
|
+
```
|
|
151
|
+
7. Name your secret (e.g., `your-project/salesforce-credentials` or `prod/salesforce-auth`)
|
|
152
|
+
8. Note your AWS region (e.g., `us-west-2`, `us-east-1`)
|
|
153
|
+
|
|
154
|
+
### Step 2: Update Your MCP Configuration
|
|
155
|
+
|
|
156
|
+
Add these environment variables to your MCP config file (location depends on your AI client):
|
|
157
|
+
|
|
158
|
+
```json
|
|
159
|
+
{
|
|
160
|
+
"mcpServers": {
|
|
161
|
+
"lemonsqueezy": {
|
|
162
|
+
"command": "node",
|
|
163
|
+
"args": ["/absolute/path/to/TypeScript-MCP-Server/dist/index.js"],
|
|
164
|
+
"env": {
|
|
165
|
+
"LEMONSQUEEZY_TEST_API_KEY": "your_test_api_key_here",
|
|
166
|
+
"AWS_SALESFORCE_SECRET_NAME": "your-project/salesforce-credentials",
|
|
167
|
+
"AWS_REGION": "us-west-2"
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Do NOT include:**
|
|
175
|
+
- ❌ `AWS_ACCESS_KEY_ID`
|
|
176
|
+
- ❌ `AWS_SECRET_ACCESS_KEY`
|
|
177
|
+
|
|
178
|
+
**Important:**
|
|
179
|
+
- Replace `your-project/salesforce-credentials` with **your own secret name** from AWS Secrets Manager
|
|
180
|
+
- Replace `us-east-1` with **your AWS region** where the secret is stored
|
|
181
|
+
- Use your own naming convention (e.g., `your-project/salesforce-credentials`, `prod/salesforce-auth`)
|
|
182
|
+
|
|
183
|
+
### Step 3: Configure AWS Credentials (IMPORTANT - Security Best Practice)
|
|
184
|
+
|
|
185
|
+
**DO NOT store AWS credentials directly in mcp.json.** Instead, use AWS CLI to configure credentials securely.
|
|
186
|
+
|
|
187
|
+
**Recommended Setup (AWS CLI Method):**
|
|
188
|
+
|
|
189
|
+
1. **Install AWS CLI** (if not already installed):
|
|
190
|
+
```bash
|
|
191
|
+
brew install awscli # macOS
|
|
192
|
+
# or download from https://aws.amazon.com/cli/
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
2. **Configure AWS credentials:**
|
|
196
|
+
```bash
|
|
197
|
+
aws configure
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Enter when prompted:
|
|
201
|
+
- **AWS Access Key ID:** `AKIA...` (from AWS IAM Console)
|
|
202
|
+
- **AWS Secret Access Key:** `...` (from AWS IAM Console)
|
|
203
|
+
- **Default region:** `us-west-2` (or your region)
|
|
204
|
+
- **Output format:** `json` (or press Enter)
|
|
205
|
+
|
|
206
|
+
3. **Validation:**
|
|
207
|
+
|
|
208
|
+
Test AWS credentials are working:
|
|
209
|
+
```bash
|
|
210
|
+
aws secretsmanager get-secret-value --secret-id your-project/salesforce-credentials --region us-west-2
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
If successful, your MCP server will automatically use these credentials.
|
|
214
|
+
|
|
215
|
+
**Why this is better:**
|
|
216
|
+
- ✅ More secure (credentials not in plain text config files)
|
|
217
|
+
- ✅ AWS best practice
|
|
218
|
+
- ✅ Credentials stored in `~/.aws/credentials` (encrypted by OS)
|
|
219
|
+
- ✅ Works across all AWS tools automatically
|
|
220
|
+
- ✅ Easier credential rotation
|
|
221
|
+
|
|
222
|
+
**Note:** The server uses AWS SDK's default credential chain, which will automatically use credentials from `~/.aws/credentials` configured via `aws configure`.
|
|
223
|
+
|
|
224
|
+
### Step 4: Set IAM Permissions
|
|
225
|
+
|
|
226
|
+
Ensure your AWS credentials have permission to read the secret:
|
|
227
|
+
|
|
228
|
+
```json
|
|
229
|
+
{
|
|
230
|
+
"Effect": "Allow",
|
|
231
|
+
"Action": ["secretsmanager:GetSecretValue"],
|
|
232
|
+
"Resource": "arn:aws:secretsmanager:us-east-1:account:secret:your-project/salesforce-credentials-*"
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Replace `us-east-1` with your region, `account` with your AWS account ID, and `your-project/salesforce-credentials` with your secret name.
|
|
237
|
+
|
|
238
|
+
### Step 5: Restart Your AI Client
|
|
239
|
+
|
|
240
|
+
Save the MCP config file and restart your AI client completely.
|
|
241
|
+
|
|
242
|
+
**That's it!** The server will automatically fetch credentials from AWS Secrets Manager when you use Salesforce tools.
|
|
243
|
+
|
|
244
|
+
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface Config {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
enableResources: boolean;
|
|
4
|
+
awsRegion: string;
|
|
5
|
+
awsSalesforceSecretName?: string;
|
|
6
|
+
awsFirebaseSecretName?: string;
|
|
7
|
+
salesforceUsername?: string;
|
|
8
|
+
salesforcePassword?: string;
|
|
9
|
+
salesforceToken?: string;
|
|
10
|
+
salesforceClientId?: string;
|
|
11
|
+
salesforcePrivateKey?: string;
|
|
12
|
+
salesforceLoginUrl?: string;
|
|
13
|
+
firebaseServiceAccountKey?: string;
|
|
14
|
+
firebaseProjectId?: string;
|
|
15
|
+
lemonSqueezyStoreId?: string;
|
|
16
|
+
pollFailedPayments: boolean;
|
|
17
|
+
pollIntervalMinutes: number;
|
|
18
|
+
webhookLogPath?: string;
|
|
19
|
+
webhookPort: number;
|
|
20
|
+
webhookSecret?: string;
|
|
21
|
+
enableNgrok: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare const config: Config;
|
|
24
|
+
export declare function resetConfig(): void;
|
|
25
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;CACtB;AAkED,eAAO,MAAM,MAAM,EAAE,MAKjB,CAAC;AAGL,wBAAgB,WAAW,IAAI,IAAI,CAGlC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as dotenv from "dotenv";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
import { lemonSqueezySetup } from "@lemonsqueezy/lemonsqueezy.js";
|
|
5
|
+
import { logger } from "./utils/logger.js";
|
|
6
|
+
// Load .env relative to script location
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
const rootDir = path.resolve(__dirname, "..");
|
|
10
|
+
dotenv.config({ path: path.join(rootDir, ".env") });
|
|
11
|
+
// Validate and initialize Lemon Squeezy SDK
|
|
12
|
+
// Priority: LEMONSQUEEZY_API_KEY (production) > LEMONSQUEEZY_TEST_API_KEY (test)
|
|
13
|
+
function getApiKey() {
|
|
14
|
+
const apiKey = process.env.LEMONSQUEEZY_API_KEY ||
|
|
15
|
+
process.env.LEMON_SQUEEZY_API_KEY ||
|
|
16
|
+
process.env.LEMONSQUEEZY_TEST_API_KEY ||
|
|
17
|
+
process.env.LEMON_SQUEEZY_TEST_API_KEY;
|
|
18
|
+
if (!apiKey) {
|
|
19
|
+
const error = new Error("LEMONSQUEEZY_API_KEY or LEMONSQUEEZY_TEST_API_KEY must be set");
|
|
20
|
+
logger.fatal({
|
|
21
|
+
cwd: process.cwd(),
|
|
22
|
+
envPath: path.join(rootDir, ".env"),
|
|
23
|
+
envKeys: Object.keys(process.env).filter(k => k.includes("LEMONSQUEEZY"))
|
|
24
|
+
}, "API Key missing");
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
return apiKey;
|
|
28
|
+
}
|
|
29
|
+
function initializeLemonSqueezy(apiKey) {
|
|
30
|
+
lemonSqueezySetup({
|
|
31
|
+
apiKey: apiKey,
|
|
32
|
+
onError: (error) => logger.error({ error }, "Lemon Squeezy Error"),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
// Lazy initialization - only initialize SDK when config is accessed
|
|
36
|
+
let configInstance = null;
|
|
37
|
+
let sdkInitialized = false;
|
|
38
|
+
function createConfig() {
|
|
39
|
+
const apiKey = getApiKey();
|
|
40
|
+
// Initialize SDK only once
|
|
41
|
+
if (!sdkInitialized) {
|
|
42
|
+
initializeLemonSqueezy(apiKey);
|
|
43
|
+
sdkInitialized = true;
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
apiKey,
|
|
47
|
+
enableResources: process.env.ENABLE_RESOURCES === "true",
|
|
48
|
+
awsRegion: process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION || "us-east-1",
|
|
49
|
+
awsSalesforceSecretName: process.env.AWS_SALESFORCE_SECRET_NAME,
|
|
50
|
+
awsFirebaseSecretName: process.env.AWS_FIREBASE_SECRET_NAME,
|
|
51
|
+
salesforceUsername: process.env.SALESFORCE_USERNAME,
|
|
52
|
+
salesforcePassword: process.env.SALESFORCE_PASSWORD,
|
|
53
|
+
salesforceToken: process.env.SALESFORCE_TOKEN,
|
|
54
|
+
salesforceClientId: process.env.SALESFORCE_CLIENT_ID,
|
|
55
|
+
salesforcePrivateKey: process.env.SALESFORCE_PRIVATE_KEY,
|
|
56
|
+
salesforceLoginUrl: process.env.SALESFORCE_LOGIN_URL,
|
|
57
|
+
firebaseServiceAccountKey: process.env.FIREBASE_SERVICE_ACCOUNT_KEY,
|
|
58
|
+
firebaseProjectId: process.env.FIREBASE_PROJECT_ID,
|
|
59
|
+
lemonSqueezyStoreId: process.env.LEMON_SQUEEZY_STORE_ID,
|
|
60
|
+
pollFailedPayments: process.env.POLL_FAILED_PAYMENTS === "true",
|
|
61
|
+
pollIntervalMinutes: parseInt(process.env.POLL_INTERVAL_MINUTES || "5", 10),
|
|
62
|
+
webhookLogPath: process.env.WEBHOOK_LOG_PATH,
|
|
63
|
+
webhookPort: parseInt(process.env.WEBHOOK_PORT || "3000", 10),
|
|
64
|
+
webhookSecret: process.env.LEMONSQUEEZY_WEBHOOK_SECRET,
|
|
65
|
+
enableNgrok: process.env.ENABLE_NGROK === "true",
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
// Export config getter - throws error if API key is missing
|
|
69
|
+
export const config = (() => {
|
|
70
|
+
if (!configInstance) {
|
|
71
|
+
configInstance = createConfig();
|
|
72
|
+
}
|
|
73
|
+
return configInstance;
|
|
74
|
+
})();
|
|
75
|
+
// Export function for testing that allows overriding
|
|
76
|
+
export function resetConfig() {
|
|
77
|
+
configInstance = null;
|
|
78
|
+
sdkInitialized = false;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../src/config.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from "vitest";
|
|
2
|
+
import { resetConfig } from "./config.js";
|
|
3
|
+
describe("Config", () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
// Reset config state before each test
|
|
6
|
+
resetConfig();
|
|
7
|
+
// Clear environment variables
|
|
8
|
+
delete process.env.LEMONSQUEEZY_API_KEY;
|
|
9
|
+
delete process.env.LEMONSQUEEZY_TEST_API_KEY;
|
|
10
|
+
});
|
|
11
|
+
it("should throw error when API key is missing", () => {
|
|
12
|
+
expect(() => {
|
|
13
|
+
// Access config to trigger initialization
|
|
14
|
+
const { config } = require("./config.js");
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
16
|
+
config.apiKey;
|
|
17
|
+
}).toThrow("LEMONSQUEEZY_API_KEY or LEMONSQUEEZY_TEST_API_KEY must be set");
|
|
18
|
+
});
|
|
19
|
+
it("should use test API key when provided", () => {
|
|
20
|
+
process.env.LEMONSQUEEZY_TEST_API_KEY = "test_key_123";
|
|
21
|
+
const { config } = require("./config.js");
|
|
22
|
+
expect(config.apiKey).toBe("test_key_123");
|
|
23
|
+
});
|
|
24
|
+
it("should prefer production API key over test key", () => {
|
|
25
|
+
process.env.LEMONSQUEEZY_API_KEY = "prod_key_123";
|
|
26
|
+
process.env.LEMONSQUEEZY_TEST_API_KEY = "test_key_123";
|
|
27
|
+
const { config } = require("./config.js");
|
|
28
|
+
expect(config.apiKey).toBe("prod_key_123");
|
|
29
|
+
});
|
|
30
|
+
it("should parse webhook port from environment", () => {
|
|
31
|
+
process.env.LEMONSQUEEZY_TEST_API_KEY = "test_key";
|
|
32
|
+
process.env.WEBHOOK_PORT = "8080";
|
|
33
|
+
const { config } = require("./config.js");
|
|
34
|
+
expect(config.webhookPort).toBe(8080);
|
|
35
|
+
});
|
|
36
|
+
it("should default webhook port to 3000", () => {
|
|
37
|
+
process.env.LEMONSQUEEZY_TEST_API_KEY = "test_key";
|
|
38
|
+
delete process.env.WEBHOOK_PORT;
|
|
39
|
+
const { config } = require("./config.js");
|
|
40
|
+
expect(config.webhookPort).toBe(3000);
|
|
41
|
+
});
|
|
42
|
+
it("should parse poll interval minutes", () => {
|
|
43
|
+
process.env.LEMONSQUEEZY_TEST_API_KEY = "test_key";
|
|
44
|
+
process.env.POLL_INTERVAL_MINUTES = "10";
|
|
45
|
+
const { config } = require("./config.js");
|
|
46
|
+
expect(config.pollIntervalMinutes).toBe(10);
|
|
47
|
+
});
|
|
48
|
+
it("should default poll interval to 5 minutes", () => {
|
|
49
|
+
process.env.LEMONSQUEEZY_TEST_API_KEY = "test_key";
|
|
50
|
+
delete process.env.POLL_INTERVAL_MINUTES;
|
|
51
|
+
const { config } = require("./config.js");
|
|
52
|
+
expect(config.pollIntervalMinutes).toBe(5);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.test.js","sourceRoot":"","sources":["../src/config.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAM,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;IACtB,UAAU,CAAC,GAAG,EAAE;QACd,sCAAsC;QACtC,WAAW,EAAE,CAAC;QACd,8BAA8B;QAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;QACxC,OAAO,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,GAAG,EAAE;YACV,0CAA0C;YAC1C,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;YAC1C,oEAAoE;YACpE,MAAM,CAAC,MAAM,CAAC;QAChB,CAAC,CAAC,CAAC,OAAO,CAAC,+DAA+D,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,OAAO,CAAC,GAAG,CAAC,yBAAyB,GAAG,cAAc,CAAC;QACvD,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,cAAc,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,yBAAyB,GAAG,cAAc,CAAC;QACvD,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,OAAO,CAAC,GAAG,CAAC,yBAAyB,GAAG,UAAU,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,YAAY,GAAG,MAAM,CAAC;QAClC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,OAAO,CAAC,GAAG,CAAC,yBAAyB,GAAG,UAAU,CAAC;QACnD,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QAChC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,OAAO,CAAC,GAAG,CAAC,yBAAyB,GAAG,UAAU,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,qBAAqB,GAAG,IAAI,CAAC;QACzC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,OAAO,CAAC,GAAG,CAAC,yBAAyB,GAAG,UAAU,CAAC;QACnD,OAAO,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;QACzC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|