skedyul 1.4.11 → 1.5.2
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/README.md +157 -240
- package/dist/cli/index.js +324 -255
- package/dist/config/index.d.ts +0 -1
- package/dist/config/loader.js +208 -0
- package/dist/config/loader.mjs +184 -0
- package/dist/config/transpileConfigMetadata.d.ts +1 -0
- package/dist/esm/index.mjs +37 -141
- package/dist/index.d.ts +1 -1
- package/dist/index.js +37 -138
- package/package.json +9 -2
package/README.md
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
# skedyul
|
|
2
2
|
|
|
3
|
-
The official Node.js SDK for building Skedyul integration apps.
|
|
3
|
+
The official Node.js SDK for building [Skedyul](https://skedyul.com) integration apps. Publish tools, webhooks, CRM models, agents, skills, and workflows — then run them on serverless (Lambda) or dedicated (Docker/ECS) compute.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Package:** `skedyul` · **Version:** 1.4.x · **Node:** 22+
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## What you can build
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
| Capability | Description |
|
|
10
|
+
|------------|-------------|
|
|
11
|
+
| **MCP tools** | Functions AI agents invoke via the Model Context Protocol |
|
|
12
|
+
| **Webhooks** | HTTP handlers for SMS, email, OAuth callbacks, and third-party events |
|
|
13
|
+
| **Lifecycle hooks** | Install, provision, uninstall, and OAuth flows |
|
|
14
|
+
| **CRM models** | App-owned (internal) and user-mapped (shared) data models |
|
|
15
|
+
| **Agents (v3)** | Skills-based autonomous agents deployed per workplace |
|
|
16
|
+
| **Skills & workflows** | YAML-defined capabilities and event-driven automation |
|
|
17
|
+
| **Core API client** | Typed client for workplaces, channels, instances, files, cron, AI, calls, and more |
|
|
18
|
+
| **CLI** | Local dev server, tunneling, deploy, CRM schema sync, agent testing |
|
|
17
19
|
|
|
18
20
|
## Installation
|
|
19
21
|
|
|
@@ -23,19 +25,24 @@ npm install skedyul
|
|
|
23
25
|
pnpm add skedyul
|
|
24
26
|
```
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
The CLI is included:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
skedyul --help
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick start
|
|
27
35
|
|
|
28
|
-
### 1. Create
|
|
36
|
+
### 1. Create `skedyul.config.ts`
|
|
29
37
|
|
|
30
38
|
```ts
|
|
31
|
-
// skedyul.config.ts
|
|
32
39
|
import { defineConfig } from 'skedyul'
|
|
33
40
|
import pkg from './package.json'
|
|
34
41
|
|
|
35
42
|
export default defineConfig({
|
|
36
43
|
name: 'My Integration',
|
|
37
44
|
version: pkg.version,
|
|
38
|
-
description: '
|
|
45
|
+
description: 'What this app does',
|
|
39
46
|
computeLayer: 'serverless',
|
|
40
47
|
|
|
41
48
|
tools: import('./src/registries'),
|
|
@@ -44,67 +51,31 @@ export default defineConfig({
|
|
|
44
51
|
})
|
|
45
52
|
```
|
|
46
53
|
|
|
47
|
-
### 2.
|
|
54
|
+
### 2. Aggregate provision config
|
|
48
55
|
|
|
49
56
|
```ts
|
|
50
57
|
// provision.ts
|
|
51
58
|
import type { ProvisionConfig } from 'skedyul'
|
|
52
|
-
|
|
53
59
|
import env from './env'
|
|
54
60
|
import { models, relationships } from './crm'
|
|
55
61
|
import * as channels from './channels'
|
|
56
62
|
import * as pages from './pages'
|
|
57
63
|
import navigation from './pages/navigation'
|
|
58
64
|
|
|
59
|
-
|
|
65
|
+
export default {
|
|
60
66
|
env,
|
|
61
67
|
navigation,
|
|
62
68
|
models: Object.values(models),
|
|
63
69
|
channels: Object.values(channels),
|
|
64
70
|
pages: Object.values(pages),
|
|
65
71
|
relationships,
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export default config
|
|
72
|
+
} satisfies ProvisionConfig
|
|
69
73
|
```
|
|
70
74
|
|
|
71
|
-
### 3. Define a
|
|
75
|
+
### 3. Define a tool
|
|
72
76
|
|
|
73
77
|
```ts
|
|
74
|
-
|
|
75
|
-
import { defineModel } from 'skedyul'
|
|
76
|
-
|
|
77
|
-
export default defineModel({
|
|
78
|
-
handle: 'contact',
|
|
79
|
-
label: 'Contact',
|
|
80
|
-
labelPlural: 'Contacts',
|
|
81
|
-
scope: 'shared',
|
|
82
|
-
|
|
83
|
-
fields: [
|
|
84
|
-
{
|
|
85
|
-
handle: 'name',
|
|
86
|
-
label: 'Name',
|
|
87
|
-
type: 'string',
|
|
88
|
-
required: true,
|
|
89
|
-
owner: 'workplace',
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
handle: 'email',
|
|
93
|
-
label: 'Email',
|
|
94
|
-
type: 'string',
|
|
95
|
-
required: false,
|
|
96
|
-
owner: 'workplace',
|
|
97
|
-
},
|
|
98
|
-
],
|
|
99
|
-
})
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### 4. Define a tool
|
|
103
|
-
|
|
104
|
-
```ts
|
|
105
|
-
// src/tools/hello.ts
|
|
106
|
-
import { z } from 'skedyul'
|
|
107
|
-
import type { ToolHandler, ToolDefinition } from 'skedyul'
|
|
78
|
+
import { z, type ToolHandler, type ToolDefinition } from 'skedyul'
|
|
108
79
|
|
|
109
80
|
const inputSchema = z.object({
|
|
110
81
|
name: z.string().optional(),
|
|
@@ -113,13 +84,11 @@ const inputSchema = z.object({
|
|
|
113
84
|
type Input = z.infer<typeof inputSchema>
|
|
114
85
|
type Output = { message: string }
|
|
115
86
|
|
|
116
|
-
const handler: ToolHandler<Input, Output> = async (input
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
}
|
|
87
|
+
const handler: ToolHandler<Input, Output> = async (input) => ({
|
|
88
|
+
output: { message: `Hello, ${input.name ?? 'world'}!` },
|
|
89
|
+
billing: { credits: 1 },
|
|
90
|
+
meta: { success: true, message: 'Greeting sent', toolName: 'hello' },
|
|
91
|
+
})
|
|
123
92
|
|
|
124
93
|
export const helloTool: ToolDefinition<Input, Output> = {
|
|
125
94
|
name: 'hello',
|
|
@@ -129,228 +98,176 @@ export const helloTool: ToolDefinition<Input, Output> = {
|
|
|
129
98
|
}
|
|
130
99
|
```
|
|
131
100
|
|
|
132
|
-
###
|
|
133
|
-
|
|
134
|
-
```ts
|
|
135
|
-
// src/server.ts
|
|
136
|
-
import { server } from 'skedyul'
|
|
137
|
-
import { toolRegistry } from './tools/registry'
|
|
138
|
-
|
|
139
|
-
const mcpServer = server.create(
|
|
140
|
-
{
|
|
141
|
-
computeLayer: 'dedicated',
|
|
142
|
-
metadata: { name: 'my-integration', version: '1.0.0' },
|
|
143
|
-
},
|
|
144
|
-
toolRegistry,
|
|
145
|
-
)
|
|
101
|
+
### 4. Build and run locally
|
|
146
102
|
|
|
147
|
-
|
|
103
|
+
```bash
|
|
104
|
+
skedyul auth login
|
|
105
|
+
skedyul dev link --workplace my-clinic
|
|
106
|
+
skedyul build
|
|
107
|
+
skedyul dev serve --workplace my-clinic
|
|
148
108
|
```
|
|
149
109
|
|
|
150
|
-
|
|
110
|
+
See [Local development](./docs/cli.md#local-development) for the full workflow.
|
|
151
111
|
|
|
152
|
-
|
|
153
|
-
|-------|-------------|
|
|
154
|
-
| [Authentication](./docs/authentication.md) | Token types, scopes, and configuration |
|
|
155
|
-
| [Tools](./docs/tools.md) | Building MCP tools with handlers and schemas |
|
|
156
|
-
| [Webhooks](./docs/webhooks.md) | Receiving external events and callbacks |
|
|
157
|
-
| [Lifecycle Hooks](./docs/lifecycle-hooks.md) | Install, provision, and uninstall handlers |
|
|
158
|
-
| [Core API](./docs/core-api.md) | Client for Skedyul platform resources |
|
|
159
|
-
| [Configuration](./docs/configuration.md) | skedyul.config.ts reference |
|
|
160
|
-
| [Errors](./docs/errors.md) | Error types and handling patterns |
|
|
112
|
+
## Package exports
|
|
161
113
|
|
|
162
|
-
|
|
114
|
+
| Import path | Use case |
|
|
115
|
+
|-------------|----------|
|
|
116
|
+
| `skedyul` | Main SDK — config, tools, webhooks, Core API, schemas |
|
|
117
|
+
| `skedyul/serverless` | AWS Lambda handler entry |
|
|
118
|
+
| `skedyul/dedicated` | Long-running HTTP server entry |
|
|
119
|
+
| `skedyul/schemas/agent-schema-v3` | Agent YAML v3 types and validation |
|
|
120
|
+
| `skedyul/schemas/agent-schema` | Legacy multi-stage agent schema |
|
|
121
|
+
| `skedyul/skills/types` | Skill YAML types |
|
|
122
|
+
| `skedyul/scheduling` | Workflow-safe time windows and wait calculations |
|
|
123
|
+
| `skedyul/cli/utils/auth` | CLI auth helpers (for monorepo tooling) |
|
|
163
124
|
|
|
164
|
-
|
|
125
|
+
## Server modes
|
|
165
126
|
|
|
166
|
-
|
|
167
|
-
my-app/
|
|
168
|
-
├── skedyul.config.ts # App metadata + imports
|
|
169
|
-
├── provision.ts # Aggregates all modular configs
|
|
170
|
-
├── env.ts # Environment variables
|
|
171
|
-
├── crm/
|
|
172
|
-
│ ├── index.ts # Re-exports models + relationships
|
|
173
|
-
│ ├── relationships.ts # Model relationships
|
|
174
|
-
│ └── models/
|
|
175
|
-
│ ├── index.ts
|
|
176
|
-
│ └── contact.ts
|
|
177
|
-
├── channels/
|
|
178
|
-
│ ├── index.ts
|
|
179
|
-
│ └── phone.ts
|
|
180
|
-
├── pages/
|
|
181
|
-
│ ├── index.ts
|
|
182
|
-
│ ├── navigation.ts # Root navigation
|
|
183
|
-
│ └── settings/
|
|
184
|
-
│ └── page.ts
|
|
185
|
-
└── src/
|
|
186
|
-
└── registries.ts # Tools and webhooks
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
## Server Modes
|
|
190
|
-
|
|
191
|
-
### Dedicated (Docker/ECS)
|
|
192
|
-
|
|
193
|
-
Long-running HTTP server with request counting and graceful shutdown:
|
|
127
|
+
### Serverless (Lambda)
|
|
194
128
|
|
|
195
129
|
```ts
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
computeLayer: 'dedicated',
|
|
199
|
-
metadata: { name: 'my-app', version: '1.0.0' },
|
|
200
|
-
defaultPort: 3000,
|
|
201
|
-
maxRequests: 1000,
|
|
202
|
-
ttlExtendSeconds: 3600,
|
|
203
|
-
},
|
|
204
|
-
toolRegistry,
|
|
205
|
-
webhookRegistry,
|
|
206
|
-
)
|
|
130
|
+
import { server } from 'skedyul'
|
|
131
|
+
import config from './skedyul.config'
|
|
207
132
|
|
|
208
|
-
|
|
209
|
-
|
|
133
|
+
const mcpServer = server.create({
|
|
134
|
+
...config,
|
|
135
|
+
computeLayer: 'serverless',
|
|
136
|
+
tools: toolRegistry,
|
|
137
|
+
webhooks: webhookRegistry,
|
|
138
|
+
})
|
|
210
139
|
|
|
211
|
-
|
|
140
|
+
export const handler = mcpServer.handler
|
|
141
|
+
```
|
|
212
142
|
|
|
213
|
-
|
|
143
|
+
Or use the dedicated subpath export:
|
|
214
144
|
|
|
215
145
|
```ts
|
|
216
|
-
|
|
217
|
-
{
|
|
218
|
-
computeLayer: 'serverless',
|
|
219
|
-
metadata: { name: 'my-app', version: '1.0.0' },
|
|
220
|
-
cors: { allowOrigin: '*' },
|
|
221
|
-
},
|
|
222
|
-
toolRegistry,
|
|
223
|
-
webhookRegistry,
|
|
224
|
-
)
|
|
225
|
-
|
|
226
|
-
export const handler = mcpServer.handler
|
|
146
|
+
import { handler } from 'skedyul/serverless'
|
|
227
147
|
```
|
|
228
148
|
|
|
229
|
-
|
|
149
|
+
### Dedicated (Docker / ECS)
|
|
230
150
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
| `/uninstall` | POST | Uninstall handler |
|
|
240
|
-
| `/oauth_callback` | POST | OAuth callback handler |
|
|
241
|
-
|
|
242
|
-
---
|
|
151
|
+
```ts
|
|
152
|
+
const mcpServer = server.create({
|
|
153
|
+
...config,
|
|
154
|
+
computeLayer: 'dedicated',
|
|
155
|
+
defaultPort: 3000,
|
|
156
|
+
tools: toolRegistry,
|
|
157
|
+
webhooks: webhookRegistry,
|
|
158
|
+
})
|
|
243
159
|
|
|
244
|
-
|
|
160
|
+
await mcpServer.listen()
|
|
161
|
+
```
|
|
245
162
|
|
|
246
|
-
|
|
163
|
+
See [Server runtime](./docs/server.md) for endpoints, hooks, and compute-layer differences.
|
|
247
164
|
|
|
248
|
-
##
|
|
165
|
+
## Documentation
|
|
249
166
|
|
|
250
|
-
|
|
251
|
-
# 1. Authenticate with Skedyul
|
|
252
|
-
skedyul auth login
|
|
167
|
+
Full documentation lives in [`docs/`](./docs/README.md).
|
|
253
168
|
|
|
254
|
-
|
|
255
|
-
cd integrations/my-app
|
|
169
|
+
### Getting started
|
|
256
170
|
|
|
257
|
-
|
|
258
|
-
|
|
171
|
+
| Guide | Description |
|
|
172
|
+
|-------|-------------|
|
|
173
|
+
| [Configuration](./docs/configuration.md) | `skedyul.config.ts` reference — models, channels, pages, env, queues |
|
|
174
|
+
| [Tools](./docs/tools.md) | Building MCP tools with Zod schemas and handlers |
|
|
175
|
+
| [Webhooks](./docs/webhooks.md) | Receiving external events and lifecycle hooks on channels |
|
|
176
|
+
| [Lifecycle hooks](./docs/lifecycle-hooks.md) | Install, provision, uninstall, OAuth |
|
|
177
|
+
| [Authentication](./docs/authentication.md) | Token types, scopes, and SDK configuration |
|
|
178
|
+
| [Core API](./docs/core-api.md) | Platform resource client reference |
|
|
179
|
+
| [Errors](./docs/errors.md) | Install and runtime error types |
|
|
259
180
|
|
|
260
|
-
|
|
261
|
-
skedyul dev serve --workplace my-clinic
|
|
262
|
-
```
|
|
181
|
+
### Platform features
|
|
263
182
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
-
|
|
268
|
-
-
|
|
183
|
+
| Guide | Description |
|
|
184
|
+
|-------|-------------|
|
|
185
|
+
| [Agents, skills & workflows](./docs/agents.md) | Agent YAML v3, skills, workflow YAML, compiler, context |
|
|
186
|
+
| [CRM schema](./docs/crm-schema.md) | Workplace-level schema migrations (`defineSchema`) |
|
|
187
|
+
| [Rate-limit queues](./docs/rate-limit-queues.md) | `queuedFetch` for external API throttling |
|
|
188
|
+
| [Server runtime](./docs/server.md) | HTTP endpoints, dedicated vs serverless, MCP protocol |
|
|
189
|
+
| [CLI reference](./docs/cli.md) | All `skedyul` commands and flags |
|
|
269
190
|
|
|
270
|
-
##
|
|
191
|
+
## Project structure
|
|
271
192
|
|
|
272
|
-
|
|
193
|
+
Recommended layout for a modular integration app:
|
|
273
194
|
|
|
274
|
-
```bash
|
|
275
|
-
skedyul auth login # Log in via browser OAuth
|
|
276
|
-
skedyul auth status # Check authentication status
|
|
277
|
-
skedyul auth logout # Log out
|
|
278
195
|
```
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
196
|
+
my-app/
|
|
197
|
+
├── skedyul.config.ts # App metadata, registries, build, queues
|
|
198
|
+
├── provision.ts # Aggregates version-level config
|
|
199
|
+
├── install.ts # Optional per-installation config (shared models)
|
|
200
|
+
├── env.ts # Environment variable definitions
|
|
201
|
+
├── crm/
|
|
202
|
+
│ ├── index.ts
|
|
203
|
+
│ ├── relationships.ts
|
|
204
|
+
│ └── models/
|
|
205
|
+
├── channels/
|
|
206
|
+
├── pages/
|
|
207
|
+
├── agents/ # Agent YAML v3 files (deployed via CLI)
|
|
208
|
+
├── skills/ # Skill YAML files
|
|
209
|
+
├── workflows/ # Workflow YAML v2 files
|
|
210
|
+
└── src/
|
|
211
|
+
├── registries.ts # Tool and webhook registries
|
|
212
|
+
└── server.ts # Optional custom server entry
|
|
286
213
|
```
|
|
287
214
|
|
|
288
|
-
|
|
289
|
-
|-----|-------------|---------|
|
|
290
|
-
| `defaultServer` | Skedyul server URL | `https://admin.skedyul.it` |
|
|
291
|
-
| `ngrokAuthtoken` | Your ngrok authtoken | - |
|
|
292
|
-
|
|
293
|
-
### Development
|
|
215
|
+
## CLI overview
|
|
294
216
|
|
|
295
217
|
```bash
|
|
296
|
-
|
|
297
|
-
skedyul
|
|
298
|
-
skedyul
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
skedyul dev
|
|
302
|
-
skedyul dev
|
|
218
|
+
# Authentication
|
|
219
|
+
skedyul auth login
|
|
220
|
+
skedyul auth use <profile>
|
|
221
|
+
|
|
222
|
+
# Local development (linked mode)
|
|
223
|
+
skedyul dev link --workplace <subdomain>
|
|
224
|
+
skedyul dev install --workplace <subdomain>
|
|
225
|
+
skedyul build
|
|
226
|
+
skedyul dev serve --workplace <subdomain>
|
|
227
|
+
|
|
228
|
+
# Deploy
|
|
229
|
+
skedyul dev diff --workplace <subdomain>
|
|
230
|
+
skedyul dev deploy --workplace <subdomain>
|
|
231
|
+
|
|
232
|
+
# Agents, skills, workflows
|
|
233
|
+
skedyul agents deploy --file ./agents/booking.yaml --workplace <subdomain>
|
|
234
|
+
skedyul skills deploy --file ./skills/scheduling.yaml --workplace <subdomain>
|
|
235
|
+
skedyul workflows deploy --file ./workflows/reminder.yaml --workplace <subdomain>
|
|
236
|
+
|
|
237
|
+
# Testing
|
|
238
|
+
skedyul chat --agent booking --workplace <subdomain>
|
|
239
|
+
skedyul dev invoke my_tool --workplace <subdomain>
|
|
303
240
|
```
|
|
304
241
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
| Flag | Description |
|
|
308
|
-
|------|-------------|
|
|
309
|
-
| `--workplace, -w` | Workplace subdomain (enables sidecar mode) |
|
|
310
|
-
| `--port, -p` | Port to listen on (default: 60000) |
|
|
311
|
-
| `--registry, -r` | Path to registry file |
|
|
312
|
-
| `--no-tunnel` | Don't start ngrok tunnel |
|
|
313
|
-
| `--tunnel-url` | Use existing tunnel URL |
|
|
314
|
-
| `--env, -e` | Set environment variable |
|
|
315
|
-
| `--env-file` | Load env vars from file |
|
|
242
|
+
See [CLI reference](./docs/cli.md) for every command, flag, and config file path.
|
|
316
243
|
|
|
317
|
-
## Configuration
|
|
244
|
+
## Configuration files
|
|
318
245
|
|
|
319
246
|
| File | Purpose |
|
|
320
247
|
|------|---------|
|
|
321
|
-
| `~/.skedyul/
|
|
322
|
-
| `~/.skedyul/config.json` | Global
|
|
323
|
-
| `.skedyul.local.json` |
|
|
324
|
-
| `.skedyul/links
|
|
325
|
-
| `.skedyul/env
|
|
326
|
-
|
|
327
|
-
## Ngrok Setup
|
|
328
|
-
|
|
329
|
-
1. Get a free authtoken at [ngrok.com](https://dashboard.ngrok.com/get-started/your-authtoken)
|
|
330
|
-
2. Set it: `skedyul config set ngrokAuthtoken <your-token>`
|
|
248
|
+
| `~/.skedyul/profiles.json` | Auth profiles (multi-server support) |
|
|
249
|
+
| `~/.skedyul/config.json` | Global CLI config (`defaultServer`, `ngrokAuthtoken`) |
|
|
250
|
+
| `.skedyul.local.json` | Project-level server URL override |
|
|
251
|
+
| `.skedyul/links/<workplace>.json` | Per-workplace link config |
|
|
252
|
+
| `.skedyul/env/<workplace>.env` | Per-workplace environment variables |
|
|
331
253
|
|
|
332
|
-
##
|
|
333
|
-
|
|
334
|
-
| Issue | Solution |
|
|
335
|
-
|-------|----------|
|
|
336
|
-
| "Not linked to {workplace}" | Run `skedyul dev link --workplace {workplace}` |
|
|
337
|
-
| "Authentication required" | Run `skedyul auth login` |
|
|
338
|
-
| Port already in use | Use `--port 8080` or let CLI auto-increment |
|
|
339
|
-
| ngrok auth failed | Run `skedyul config set ngrokAuthtoken <token>` |
|
|
340
|
-
|
|
341
|
-
---
|
|
342
|
-
|
|
343
|
-
## Development
|
|
254
|
+
## Development (this package)
|
|
344
255
|
|
|
345
256
|
```bash
|
|
346
|
-
|
|
347
|
-
|
|
257
|
+
pnpm install
|
|
258
|
+
pnpm build # Compile TypeScript + bundle with tsup
|
|
259
|
+
pnpm test # Node test runner
|
|
348
260
|
```
|
|
349
261
|
|
|
350
262
|
## Contributing
|
|
351
263
|
|
|
352
|
-
1.
|
|
353
|
-
2. Keep MCP transports lean
|
|
354
|
-
3. Add unit tests under `tests/`
|
|
264
|
+
1. Use strict TypeScript — no `any`
|
|
265
|
+
2. Keep MCP transports lean; shared logic belongs in `src/server/route-handlers`
|
|
266
|
+
3. Add unit tests under `tests/` for new behavior
|
|
267
|
+
4. Update docs in `docs/` when adding public APIs or CLI commands
|
|
355
268
|
|
|
356
269
|
Open a PR with a clear summary for review.
|
|
270
|
+
|
|
271
|
+
## License
|
|
272
|
+
|
|
273
|
+
MIT
|