mcp-http-webhook 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/.eslintrc.json +16 -0
- package/.prettierrc.json +8 -0
- package/ARCHITECTURE.md +269 -0
- package/CONTRIBUTING.md +136 -0
- package/GETTING_STARTED.md +310 -0
- package/IMPLEMENTATION.md +294 -0
- package/LICENSE +21 -0
- package/MIGRATION_TO_SDK.md +263 -0
- package/README.md +496 -0
- package/SDK_INTEGRATION_COMPLETE.md +300 -0
- package/STANDARD_SUBSCRIPTIONS.md +268 -0
- package/STANDARD_SUBSCRIPTIONS_COMPLETE.md +309 -0
- package/SUMMARY.md +272 -0
- package/Spec.md +2778 -0
- package/dist/errors/index.d.ts +52 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +81 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol/ProtocolHandler.d.ts +37 -0
- package/dist/protocol/ProtocolHandler.d.ts.map +1 -0
- package/dist/protocol/ProtocolHandler.js +172 -0
- package/dist/protocol/ProtocolHandler.js.map +1 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +502 -0
- package/dist/server.js.map +1 -0
- package/dist/stores/InMemoryStore.d.ts +27 -0
- package/dist/stores/InMemoryStore.d.ts.map +1 -0
- package/dist/stores/InMemoryStore.js +73 -0
- package/dist/stores/InMemoryStore.js.map +1 -0
- package/dist/stores/RedisStore.d.ts +18 -0
- package/dist/stores/RedisStore.d.ts.map +1 -0
- package/dist/stores/RedisStore.js +45 -0
- package/dist/stores/RedisStore.js.map +1 -0
- package/dist/stores/index.d.ts +3 -0
- package/dist/stores/index.d.ts.map +1 -0
- package/dist/stores/index.js +9 -0
- package/dist/stores/index.js.map +1 -0
- package/dist/subscriptions/SubscriptionManager.d.ts +49 -0
- package/dist/subscriptions/SubscriptionManager.d.ts.map +1 -0
- package/dist/subscriptions/SubscriptionManager.js +181 -0
- package/dist/subscriptions/SubscriptionManager.js.map +1 -0
- package/dist/types/index.d.ts +271 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +16 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.d.ts +51 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +154 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/webhooks/WebhookManager.d.ts +27 -0
- package/dist/webhooks/WebhookManager.d.ts.map +1 -0
- package/dist/webhooks/WebhookManager.js +174 -0
- package/dist/webhooks/WebhookManager.js.map +1 -0
- package/examples/GITHUB_LIVE_EXAMPLE.md +308 -0
- package/examples/GITHUB_LIVE_SETUP.md +253 -0
- package/examples/QUICKSTART.md +130 -0
- package/examples/basic-setup.ts +142 -0
- package/examples/github-server-live.ts +690 -0
- package/examples/github-server.ts +223 -0
- package/examples/google-drive-server-live.ts +773 -0
- package/examples/start-github-live.sh +53 -0
- package/jest.config.js +20 -0
- package/package.json +58 -0
- package/src/errors/index.ts +81 -0
- package/src/index.ts +19 -0
- package/src/server.ts +595 -0
- package/src/stores/InMemoryStore.ts +87 -0
- package/src/stores/RedisStore.ts +51 -0
- package/src/stores/index.ts +2 -0
- package/src/subscriptions/SubscriptionManager.ts +240 -0
- package/src/types/index.ts +341 -0
- package/src/utils/index.ts +156 -0
- package/src/webhooks/WebhookManager.ts +230 -0
- package/test-sdk-integration.sh +157 -0
- package/tsconfig.json +21 -0
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"parser": "@typescript-eslint/parser",
|
|
3
|
+
"extends": [
|
|
4
|
+
"eslint:recommended",
|
|
5
|
+
"plugin:@typescript-eslint/recommended"
|
|
6
|
+
],
|
|
7
|
+
"parserOptions": {
|
|
8
|
+
"ecmaVersion": 2020,
|
|
9
|
+
"sourceType": "module"
|
|
10
|
+
},
|
|
11
|
+
"rules": {
|
|
12
|
+
"@typescript-eslint/explicit-function-return-type": "off",
|
|
13
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
14
|
+
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }]
|
|
15
|
+
}
|
|
16
|
+
}
|
package/.prettierrc.json
ADDED
package/ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# MCP HTTP Webhook Architecture
|
|
2
|
+
|
|
3
|
+
## System Architecture
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
7
|
+
│ MCP Client │
|
|
8
|
+
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
9
|
+
│ │ - Calls tools via HTTP POST │ │
|
|
10
|
+
│ │ - Reads resources via HTTP POST │ │
|
|
11
|
+
│ │ - Subscribes with callback URL │ │
|
|
12
|
+
│ │ - Receives notifications via webhook │ │
|
|
13
|
+
│ └──────────────────────────────────────────────────────────┘ │
|
|
14
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
15
|
+
│ ▲
|
|
16
|
+
│ HTTP POST /mcp/tools/call │
|
|
17
|
+
│ HTTP POST /mcp/resources/read │
|
|
18
|
+
│ HTTP POST /mcp/resources/subscribe │
|
|
19
|
+
│ │ HTTP POST
|
|
20
|
+
▼ │ (notification)
|
|
21
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
22
|
+
│ MCP HTTP Webhook Server │
|
|
23
|
+
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
24
|
+
│ │ Express Application │ │
|
|
25
|
+
│ │ ┌────────────┐ ┌─────────────┐ ┌──────────────────┐ │ │
|
|
26
|
+
│ │ │ Protocol │ │ Subscription│ │ Webhook │ │ │
|
|
27
|
+
│ │ │ Handler │ │ Manager │ │ Manager │ │ │
|
|
28
|
+
│ │ └────────────┘ └─────────────┘ └──────────────────┘ │ │
|
|
29
|
+
│ └──────────────────────────────────────────────────────────┘ │
|
|
30
|
+
│ │ │
|
|
31
|
+
│ ▼ │
|
|
32
|
+
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
33
|
+
│ │ Key-Value Store Interface │ │
|
|
34
|
+
│ │ (Redis / DynamoDB / PostgreSQL) │ │
|
|
35
|
+
│ │ - Subscription data │ │
|
|
36
|
+
│ │ - User indexes │ │
|
|
37
|
+
│ │ - Metadata │ │
|
|
38
|
+
│ └──────────────────────────────────────────────────────────┘ │
|
|
39
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
40
|
+
│ ▲
|
|
41
|
+
│ Register webhook │
|
|
42
|
+
│ (onSubscribe) │ HTTP POST
|
|
43
|
+
│ │ (third-party event)
|
|
44
|
+
▼ │
|
|
45
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
46
|
+
│ Third-Party Services │
|
|
47
|
+
│ ┌────────────┐ ┌──────────┐ ┌──────┐ ┌──────────────┐ │
|
|
48
|
+
│ │ GitHub │ │ Slack │ │ Drive│ │ PostgreSQL │ │
|
|
49
|
+
│ │ Webhooks │ │ Events │ │ Push │ │ NOTIFY │ │
|
|
50
|
+
│ └────────────┘ └──────────┘ └──────┘ └──────────────┘ │
|
|
51
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Subscription Flow
|
|
55
|
+
|
|
56
|
+
### 1. Subscribe Request
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
Client MCP Server Third-Party
|
|
60
|
+
│ │ │
|
|
61
|
+
│ POST /resources/subscribe │ │
|
|
62
|
+
│ { │ │
|
|
63
|
+
│ uri: "...", │ │
|
|
64
|
+
│ callbackUrl: "..." │ │
|
|
65
|
+
│ } │ │
|
|
66
|
+
│──────────────────────────>│ │
|
|
67
|
+
│ │ │
|
|
68
|
+
│ │ Generate subscriptionId │
|
|
69
|
+
│ │ Create webhook URL │
|
|
70
|
+
│ │ │
|
|
71
|
+
│ │ Register webhook │
|
|
72
|
+
│ │─────────────────────────>│
|
|
73
|
+
│ │ │
|
|
74
|
+
│ │ Store in KV store │
|
|
75
|
+
│ │ │
|
|
76
|
+
│ Response: │ │
|
|
77
|
+
│ { subscriptionId: "..." } │ │
|
|
78
|
+
│<──────────────────────────│ │
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 2. Webhook Notification Flow
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
Third-Party MCP Server Client
|
|
85
|
+
│ │ │
|
|
86
|
+
│ POST /webhooks/incoming/ │ │
|
|
87
|
+
│ {subscriptionId} │ │
|
|
88
|
+
│──────────────────────────>│ │
|
|
89
|
+
│ │ │
|
|
90
|
+
│ │ Load subscription │
|
|
91
|
+
│ │ from KV store │
|
|
92
|
+
│ │ │
|
|
93
|
+
│ │ Process webhook │
|
|
94
|
+
│ │ (onWebhook handler) │
|
|
95
|
+
│ │ │
|
|
96
|
+
│ 200 OK │ │
|
|
97
|
+
│<──────────────────────────│ │
|
|
98
|
+
│ │ │
|
|
99
|
+
│ │ POST to callbackUrl │
|
|
100
|
+
│ │ { │
|
|
101
|
+
│ │ subscriptionId, │
|
|
102
|
+
│ │ resourceUri, │
|
|
103
|
+
│ │ changeType, │
|
|
104
|
+
│ │ data │
|
|
105
|
+
│ │ } │
|
|
106
|
+
│ │─────────────────────────>│
|
|
107
|
+
│ │ │
|
|
108
|
+
│ │ 200 OK │
|
|
109
|
+
│ │<─────────────────────────│
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Component Interaction
|
|
113
|
+
|
|
114
|
+
### Protocol Handler
|
|
115
|
+
- Handles MCP protocol messages
|
|
116
|
+
- Validates input using JSON Schema
|
|
117
|
+
- Executes tool handlers
|
|
118
|
+
- Reads resources
|
|
119
|
+
- Returns formatted responses
|
|
120
|
+
|
|
121
|
+
### Subscription Manager
|
|
122
|
+
- Creates and deletes subscriptions
|
|
123
|
+
- Manages subscription lifecycle
|
|
124
|
+
- Stores data in KV store
|
|
125
|
+
- Maintains user indexes
|
|
126
|
+
- Verifies ownership
|
|
127
|
+
|
|
128
|
+
### Webhook Manager
|
|
129
|
+
- Processes incoming webhooks
|
|
130
|
+
- Verifies signatures
|
|
131
|
+
- Calls client callbacks
|
|
132
|
+
- Implements retry logic
|
|
133
|
+
- Handles timeouts
|
|
134
|
+
|
|
135
|
+
### Key-Value Store
|
|
136
|
+
- Stores subscription data
|
|
137
|
+
- Maintains indexes
|
|
138
|
+
- Supports TTL
|
|
139
|
+
- Provides scan functionality
|
|
140
|
+
- Enables horizontal scaling
|
|
141
|
+
|
|
142
|
+
## Data Flow
|
|
143
|
+
|
|
144
|
+
### Tool Call
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
1. Client sends HTTP POST to /mcp/tools/call
|
|
148
|
+
2. Server authenticates request
|
|
149
|
+
3. ProtocolHandler validates input against JSON Schema
|
|
150
|
+
4. Tool handler executes
|
|
151
|
+
5. Response returned to client
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Resource Read
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
1. Client sends HTTP POST to /mcp/resources/read
|
|
158
|
+
2. Server authenticates request
|
|
159
|
+
3. ProtocolHandler finds resource by URI
|
|
160
|
+
4. Resource read handler executes
|
|
161
|
+
5. Contents returned to client
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Subscription Creation
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
1. Client sends HTTP POST to /mcp/resources/subscribe
|
|
168
|
+
2. Server authenticates request
|
|
169
|
+
3. SubscriptionManager generates ID and webhook URL
|
|
170
|
+
4. Resource onSubscribe handler called
|
|
171
|
+
5. Handler registers with third-party service
|
|
172
|
+
6. Subscription stored in KV store
|
|
173
|
+
7. Subscription ID returned to client
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Notification Delivery
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
1. Third-party sends webhook to /webhooks/incoming/{id}
|
|
180
|
+
2. Server loads subscription from KV store
|
|
181
|
+
3. Resource onWebhook handler processes payload
|
|
182
|
+
4. WebhookManager signs and sends to client callback
|
|
183
|
+
5. Retry on failure with exponential backoff
|
|
184
|
+
6. Dead letter queue if all retries fail
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Scaling Strategy
|
|
188
|
+
|
|
189
|
+
### Horizontal Scaling
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
┌─────────────┐
|
|
193
|
+
│Load Balancer│
|
|
194
|
+
└──────┬──────┘
|
|
195
|
+
│
|
|
196
|
+
├──────────┬──────────┬──────────┐
|
|
197
|
+
│ │ │ │
|
|
198
|
+
▼ ▼ ▼ ▼
|
|
199
|
+
┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐
|
|
200
|
+
│MCP 1│ │MCP 2│ │MCP 3│ │MCP N│
|
|
201
|
+
└──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘
|
|
202
|
+
│ │ │ │
|
|
203
|
+
└──────────┴──────────┴──────────┘
|
|
204
|
+
│
|
|
205
|
+
▼
|
|
206
|
+
┌──────────┐
|
|
207
|
+
│ Redis │
|
|
208
|
+
│ Cluster │
|
|
209
|
+
└──────────┘
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Benefits:
|
|
213
|
+
- No session affinity required
|
|
214
|
+
- Simple round-robin load balancing
|
|
215
|
+
- Shared state in Redis
|
|
216
|
+
- Independent instance scaling
|
|
217
|
+
- Zero-downtime deployments
|
|
218
|
+
|
|
219
|
+
## Security Layers
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
┌─────────────────────────────────────┐
|
|
223
|
+
│ HTTPS/TLS (Required) │
|
|
224
|
+
└─────────────────────────────────────┘
|
|
225
|
+
┌─────────────────────────────────────┐
|
|
226
|
+
│ Authentication Middleware │
|
|
227
|
+
│ (JWT, API Key, OAuth2) │
|
|
228
|
+
└─────────────────────────────────────┘
|
|
229
|
+
┌─────────────────────────────────────┐
|
|
230
|
+
│ Webhook Signature Verification │
|
|
231
|
+
│ (HMAC SHA-256, Timing-Safe) │
|
|
232
|
+
└─────────────────────────────────────┘
|
|
233
|
+
┌─────────────────────────────────────┐
|
|
234
|
+
│ Input Validation │
|
|
235
|
+
│ (JSON Schema, AJV) │
|
|
236
|
+
└─────────────────────────────────────┘
|
|
237
|
+
┌─────────────────────────────────────┐
|
|
238
|
+
│ Rate Limiting │
|
|
239
|
+
│ (Optional Middleware) │
|
|
240
|
+
└─────────────────────────────────────┘
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Performance Optimizations
|
|
244
|
+
|
|
245
|
+
1. **Connection Pooling**
|
|
246
|
+
- HTTP keep-alive
|
|
247
|
+
- Redis connection pool
|
|
248
|
+
- Database connection pool
|
|
249
|
+
|
|
250
|
+
2. **Caching**
|
|
251
|
+
- Resource read results
|
|
252
|
+
- Tool metadata
|
|
253
|
+
- Configuration data
|
|
254
|
+
|
|
255
|
+
3. **Async Processing**
|
|
256
|
+
- Non-blocking I/O
|
|
257
|
+
- Promise-based handlers
|
|
258
|
+
- Background webhook delivery
|
|
259
|
+
|
|
260
|
+
4. **Retry Strategy**
|
|
261
|
+
- Exponential backoff
|
|
262
|
+
- Circuit breaker pattern
|
|
263
|
+
- Dead letter queue
|
|
264
|
+
|
|
265
|
+
5. **Monitoring**
|
|
266
|
+
- Prometheus metrics
|
|
267
|
+
- Structured logging
|
|
268
|
+
- Health check endpoints
|
|
269
|
+
- Distributed tracing
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Contributing to MCP HTTP Webhook
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing! This document provides guidelines and instructions for contributing.
|
|
4
|
+
|
|
5
|
+
## Development Setup
|
|
6
|
+
|
|
7
|
+
1. **Fork and Clone**
|
|
8
|
+
```bash
|
|
9
|
+
git clone https://github.com/your-username/mcp-http-webhook.git
|
|
10
|
+
cd mcp-http-webhook
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. **Install Dependencies**
|
|
14
|
+
```bash
|
|
15
|
+
npm install
|
|
16
|
+
# or
|
|
17
|
+
pnpm install
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
3. **Build**
|
|
21
|
+
```bash
|
|
22
|
+
npm run build
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
4. **Run Tests**
|
|
26
|
+
```bash
|
|
27
|
+
npm test
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Code Style
|
|
31
|
+
|
|
32
|
+
We use ESLint and Prettier for code formatting:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Lint code
|
|
36
|
+
npm run lint
|
|
37
|
+
|
|
38
|
+
# Format code
|
|
39
|
+
npm run format
|
|
40
|
+
|
|
41
|
+
# Type check
|
|
42
|
+
npm run type-check
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### TypeScript Guidelines
|
|
46
|
+
|
|
47
|
+
- Use explicit types for public APIs
|
|
48
|
+
- Prefer `const` over `let`
|
|
49
|
+
- Use async/await over promises
|
|
50
|
+
- Document public APIs with JSDoc comments
|
|
51
|
+
|
|
52
|
+
Example:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
/**
|
|
56
|
+
* Creates a new MCP server instance
|
|
57
|
+
* @param config - Server configuration
|
|
58
|
+
* @returns Configured MCP server
|
|
59
|
+
*/
|
|
60
|
+
export function createMCPServer(config: MCPServerConfig): MCPServer {
|
|
61
|
+
// ...
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Testing
|
|
66
|
+
|
|
67
|
+
- Write tests for all new features
|
|
68
|
+
- Maintain >80% code coverage
|
|
69
|
+
- Use descriptive test names
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
describe('SubscriptionManager', () => {
|
|
73
|
+
it('should create a new subscription', async () => {
|
|
74
|
+
// Test implementation
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Commit Messages
|
|
80
|
+
|
|
81
|
+
We follow [Conventional Commits](https://www.conventionalcommits.org/):
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
feat: add webhook retry backoff configuration
|
|
85
|
+
fix: resolve subscription cleanup race condition
|
|
86
|
+
docs: update subscription flow diagram
|
|
87
|
+
test: add tests for webhook signature verification
|
|
88
|
+
chore: update dependencies
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Pull Request Process
|
|
92
|
+
|
|
93
|
+
1. **Create a Branch**
|
|
94
|
+
```bash
|
|
95
|
+
git checkout -b feature/my-new-feature
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
2. **Make Changes**
|
|
99
|
+
- Write code following style guidelines
|
|
100
|
+
- Add/update tests
|
|
101
|
+
- Update documentation
|
|
102
|
+
|
|
103
|
+
3. **Run Quality Checks**
|
|
104
|
+
```bash
|
|
105
|
+
npm run lint
|
|
106
|
+
npm run format
|
|
107
|
+
npm test
|
|
108
|
+
npm run type-check
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
4. **Commit Changes**
|
|
112
|
+
```bash
|
|
113
|
+
git commit -m "feat: add my new feature"
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
5. **Push to Fork**
|
|
117
|
+
```bash
|
|
118
|
+
git push origin feature/my-new-feature
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
6. **Create Pull Request**
|
|
122
|
+
- Provide clear description of changes
|
|
123
|
+
- Link related issues
|
|
124
|
+
- Include screenshots/examples if applicable
|
|
125
|
+
|
|
126
|
+
## Code of Conduct
|
|
127
|
+
|
|
128
|
+
This project follows the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).
|
|
129
|
+
|
|
130
|
+
## Questions?
|
|
131
|
+
|
|
132
|
+
Feel free to open an issue or ask in our [Discord community](https://discord.gg/mcp-webhook).
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
By contributing, you agree that your contributions will be licensed under the MIT License.
|