cc-jandi 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 kwag93
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,658 @@
1
+ # cc-jandi
2
+
3
+ [![npm version](https://badge.fury.io/js/cc-jandi.svg)](https://badge.fury.io/js/cc-jandi)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ 잔디(Jandi) 웹훅을 위한 **MCP 서버 & Claude Code 플러그인**입니다.
7
+ Claude Desktop, Cursor, VS Code 등 MCP 클라이언트에서 **"잔디에 메시지 보내줘"** 한마디면 동작하고, Claude Code 플러그인으로 설치하면 `/cc-jandi:notify`, `/cc-jandi:alert` 같은 Skills과 Agents까지 사용할 수 있습니다.
8
+
9
+ ## 지원하는 웹훅 타입
10
+
11
+ | 타입 | 방향 | 용도 |
12
+ |------|------|------|
13
+ | **Incoming Webhook** | 서버 → 잔디 채널 | 채널에 메시지 보내기 |
14
+ | **Team Incoming Webhook** | 서버 → 특정 사용자 | 이메일로 지정한 사람에게 개인 메시지 보내기 |
15
+ | **Outgoing Webhook** | 잔디 → 외부 서버 | 잔디에서 키워드 입력 시 외부 서버 호출 |
16
+ | **Team Outgoing Webhook** | 잔디 → 외부 서버 | 위와 동일, 작성자 상세 정보(이메일, 전화번호) 포함 |
17
+
18
+ > Outgoing / Team Outgoing Webhook 도구는 핸들러 서버 개발을 돕는 헬퍼입니다. 실제 메시지 수신은 별도 서버가 필요합니다.
19
+
20
+ ---
21
+
22
+ ## 빠른 시작
23
+
24
+ ### 1단계: 잔디에서 웹훅 토큰 발급
25
+
26
+ 1. 잔디 앱에서 메시지를 보낼 토픽으로 이동
27
+ 2. 토픽 상단의 **플러그 아이콘** 클릭 → **인커밍 웹훅** 선택
28
+ 3. 웹훅 이름 입력 후 **커넥트 추가**
29
+ 4. 생성된 URL에서 토큰 부분 복사
30
+
31
+ ```
32
+ https://wh.jandi.com/connect-api/webhook/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
33
+ └──────── 이 부분이 토큰 ────────┘
34
+ ```
35
+
36
+ ### 2단계: MCP 클라이언트에 등록
37
+
38
+ **Claude Desktop** — `claude_desktop_config.json` 파일을 열어 아래 내용을 추가합니다.
39
+
40
+ macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
41
+ Windows: `%APPDATA%\Claude\claude_desktop_config.json`
42
+
43
+ ```json
44
+ {
45
+ "mcpServers": {
46
+ "cc-jandi": {
47
+ "command": "npx",
48
+ "args": ["cc-jandi"],
49
+ "env": {
50
+ "JANDI_TOKEN": "발급받은_토큰"
51
+ }
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ ### Claude Code 플러그인으로 설치
58
+
59
+ ```bash
60
+ /plugin install cc-jandi
61
+ ```
62
+
63
+ ### 3단계: 사용
64
+
65
+ Claude Desktop을 재시작하고 대화창에 입력하세요.
66
+
67
+ ```
68
+ 잔디에 "배포 완료!" 메시지 보내줘
69
+ ```
70
+
71
+ 별도 설치 과정 없이 `npx`가 알아서 처리합니다.
72
+
73
+ ---
74
+
75
+ ## Skills
76
+
77
+ Claude Code 플러그인에서 사용할 수 있는 슬래시 커맨드입니다.
78
+
79
+ | 커맨드 | 설명 |
80
+ |--------|------|
81
+ | `/cc-jandi:notify` | 빠른 채널 알림 |
82
+ | `/cc-jandi:alert` | 심각도별 알림 (info/success/warning/error) |
83
+ | `/cc-jandi:deploy-notify` | 배포 결과 알림 (git 정보 자동 포함) |
84
+ | `/cc-jandi:daily-report` | 일일 작업 리포트 |
85
+
86
+ ---
87
+
88
+ ## Agents
89
+
90
+ Claude Code 플러그인에서 사용할 수 있는 에이전트입니다.
91
+
92
+ | 에이전트 | 설명 |
93
+ |----------|------|
94
+ | `notification-composer` | 리치 메시지 작성 도우미 |
95
+ | `webhook-debugger` | 웹훅 연결 진단 |
96
+
97
+ ---
98
+
99
+ ## 사용 예시
100
+
101
+ | 하고 싶은 것 | 이렇게 말하면 됩니다 |
102
+ |-------------|---------------------|
103
+ | 기본 메시지 | "잔디에 빌드 완료 메시지 보내줘" |
104
+ | 색상 + 상세정보 | "잔디에 빨간색으로 서버 경고 보내줘. 제목은 CPU, 설명은 80% 초과" |
105
+ | 특정 채널 | "dev 채널 잔디에 테스트 결과 보내줘" (토큰 별칭 사용) |
106
+ | 개인 메시지 | "hong@company.com 에게 잔디 메시지 보내줘" (팀 웹훅 사용) |
107
+ | 토큰 확인 | "잔디 토큰 유효한지 확인해줘" |
108
+ | 스크립트 생성 | "Python으로 잔디 메시지 보내는 스크립트 만들어줘" |
109
+ | 핸들러 생성 | "Express로 잔디 아웃고잉 웹훅 핸들러 만들어줘" |
110
+
111
+ ---
112
+
113
+ ## 도구 목록
114
+
115
+ ### 채널 메시지 (Incoming Webhook)
116
+
117
+ | 도구명 | 설명 |
118
+ |--------|------|
119
+ | `send_message` | 채널에 텍스트 메시지 전송 |
120
+ | `send_rich_message` | 색상, 제목, 설명, 이미지가 포함된 리치 메시지 전송 |
121
+ | `validate_token` | 웹훅 토큰이 유효한지 확인 |
122
+ | `test_webhook` | 웹훅 연결 상태 종합 테스트 |
123
+
124
+ ### 개인 메시지 (Team Incoming Webhook)
125
+
126
+ | 도구명 | 설명 |
127
+ |--------|------|
128
+ | `send_team_message` | 이메일로 지정한 사용자에게 메시지 전송 (최대 100명) |
129
+ | `send_team_rich_message` | 특정 사용자에게 리치 메시지 전송 |
130
+ | `validate_team_token` | 팀 웹훅 토큰 유효성 확인 |
131
+
132
+ ### 아웃고잉 웹훅 개발 헬퍼 (Outgoing / Team Outgoing Webhook)
133
+
134
+ | 도구명 | 설명 |
135
+ |--------|------|
136
+ | `simulate_outgoing_payload` | 테스트용 페이로드 JSON 생성 (`outgoing` / `team-outgoing` 선택) |
137
+ | `generate_outgoing_handler` | 핸들러 서버 코드 생성 (Express, FastAPI, Flask) |
138
+ | `validate_outgoing_response` | 응답 포맷이 잔디 규격에 맞는지 검증 |
139
+
140
+ ### 공통
141
+
142
+ | 도구명 | 설명 |
143
+ |--------|------|
144
+ | `generate_webhook_script` | Python / Node.js / curl / bash 스크립트 생성 (incoming, team-incoming) |
145
+
146
+ ---
147
+
148
+ ## 토큰 설정
149
+
150
+ ### 기본 — 토큰 1개
151
+
152
+ ```json
153
+ {
154
+ "mcpServers": {
155
+ "cc-jandi": {
156
+ "command": "npx",
157
+ "args": ["cc-jandi"],
158
+ "env": {
159
+ "JANDI_TOKEN": "your_token"
160
+ }
161
+ }
162
+ }
163
+ }
164
+ ```
165
+
166
+ ### 채널별 토큰 여러 개
167
+
168
+ 별칭(alias)을 붙여서 여러 채널에 보낼 수 있습니다.
169
+ `JANDI_TOKEN_별칭` 형식으로 추가하면 도구에서 `tokenAlias`로 선택합니다.
170
+
171
+ ```json
172
+ {
173
+ "mcpServers": {
174
+ "cc-jandi": {
175
+ "command": "npx",
176
+ "args": ["cc-jandi"],
177
+ "env": {
178
+ "JANDI_TOKEN": "기본_토큰",
179
+ "JANDI_TOKEN_DEV": "개발채널_토큰",
180
+ "JANDI_TOKEN_DEPLOY": "배포채널_토큰"
181
+ }
182
+ }
183
+ }
184
+ }
185
+ ```
186
+
187
+ ### 팀 웹훅 — 개인 메시지
188
+
189
+ 팀 웹훅은 `TEAM_ID`와 `TEAM_TOKEN`이 한 쌍입니다. 별칭이 같아야 매칭됩니다.
190
+
191
+ ```json
192
+ {
193
+ "env": {
194
+ "JANDI_TEAM_ID_SALES": "팀_ID",
195
+ "JANDI_TEAM_TOKEN_SALES": "팀_토큰"
196
+ }
197
+ }
198
+ ```
199
+
200
+ ### 아웃고잉 웹훅 검증 토큰
201
+
202
+ ```json
203
+ {
204
+ "env": {
205
+ "JANDI_OUTGOING_TOKEN_DEPLOY": "검증_토큰"
206
+ }
207
+ }
208
+ ```
209
+
210
+ <details>
211
+ <summary>전체 환경 변수 목록</summary>
212
+
213
+ | 환경 변수 | 용도 | 비고 |
214
+ |-----------|------|------|
215
+ | `JANDI_TOKEN` | 기본 Incoming 웹훅 토큰 | Incoming 사용 시 필수 |
216
+ | `JANDI_TOKEN_{별칭}` | 채널별 Incoming 토큰 | 선택 |
217
+ | `JANDI_URL_{별칭}` | 채널별 커스텀 URL | 선택, 기본: `wh.jandi.com` |
218
+ | `JANDI_TEAM_ID_{별칭}` | Team Incoming 팀 ID | 반드시 TOKEN과 쌍으로 |
219
+ | `JANDI_TEAM_TOKEN_{별칭}` | Team Incoming 토큰 | 반드시 ID와 쌍으로 |
220
+ | `JANDI_TEAM_URL_{별칭}` | Team Incoming 커스텀 URL | 선택 |
221
+ | `JANDI_OUTGOING_TOKEN_{별칭}` | Outgoing 검증 토큰 | 핸들러 개발 시 사용 |
222
+
223
+ 별칭은 대소문자 구분 없음 (내부적으로 대문자 변환). 예: `JANDI_TOKEN_dev` = `JANDI_TOKEN_DEV`
224
+
225
+ </details>
226
+
227
+ ---
228
+
229
+ ## 다른 MCP 클라이언트에서 사용
230
+
231
+ <details>
232
+ <summary>Claude Code (CLI)</summary>
233
+
234
+ 프로젝트 루트에 `.mcp.json` 파일을 만듭니다.
235
+
236
+ ```json
237
+ {
238
+ "mcpServers": {
239
+ "cc-jandi": {
240
+ "command": "npx",
241
+ "args": ["cc-jandi"],
242
+ "env": {
243
+ "JANDI_TOKEN": "your_token"
244
+ }
245
+ }
246
+ }
247
+ }
248
+ ```
249
+
250
+ 또는 CLI로 추가:
251
+
252
+ ```bash
253
+ claude mcp add cc-jandi -- npx cc-jandi
254
+ ```
255
+
256
+ </details>
257
+
258
+ <details>
259
+ <summary>Cursor</summary>
260
+
261
+ 프로젝트 루트에 `.cursor/mcp.json` 파일을 만듭니다.
262
+
263
+ ```json
264
+ {
265
+ "mcpServers": {
266
+ "cc-jandi": {
267
+ "command": "npx",
268
+ "args": ["cc-jandi"],
269
+ "env": {
270
+ "JANDI_TOKEN": "your_token"
271
+ }
272
+ }
273
+ }
274
+ }
275
+ ```
276
+
277
+ </details>
278
+
279
+ <details>
280
+ <summary>VS Code (Copilot)</summary>
281
+
282
+ 프로젝트 루트에 `.vscode/mcp.json` 파일을 만듭니다.
283
+
284
+ ```json
285
+ {
286
+ "servers": {
287
+ "cc-jandi": {
288
+ "command": "npx",
289
+ "args": ["cc-jandi"],
290
+ "env": {
291
+ "JANDI_TOKEN": "your_token"
292
+ }
293
+ }
294
+ }
295
+ }
296
+ ```
297
+
298
+ </details>
299
+
300
+ ---
301
+
302
+ ## CLI 사용법
303
+
304
+ `npx`로 직접 실행하거나, AI 에이전트가 자동으로 호출할 수 있습니다.
305
+
306
+ ```bash
307
+ # 환경 변수와 함께 실행
308
+ JANDI_TOKEN=your_token npx cc-jandi
309
+
310
+ # 또는 .env 파일 사용
311
+ echo "JANDI_TOKEN=your_token" > .env
312
+ npx cc-jandi
313
+ ```
314
+
315
+ **AI 에이전트 연동** — MCP 클라이언트가 stdio로 통신합니다:
316
+
317
+ ```bash
318
+ # Claude Code에서 MCP 서버로 등록
319
+ claude mcp add cc-jandi -- npx cc-jandi
320
+
321
+ # 환경 변수 포함 등록
322
+ claude mcp add cc-jandi -e JANDI_TOKEN=your_token -- npx cc-jandi
323
+ ```
324
+
325
+ **Claude Code 플러그인으로 설치** (Skills/Agents 포함):
326
+
327
+ ```bash
328
+ # 마켓플레이스에서 설치
329
+ /plugin install cc-jandi
330
+
331
+ # 로컬 개발 시
332
+ claude --plugin-dir /path/to/cc-jandi
333
+ ```
334
+
335
+ ---
336
+
337
+ ## 응답 형식
338
+
339
+ 모든 도구는 `ToolResult` 형태로 응답합니다:
340
+
341
+ ```json
342
+ {
343
+ "success": true,
344
+ "data": {
345
+ "message": "Message sent successfully to Jandi",
346
+ "tokenUsed": "default"
347
+ }
348
+ }
349
+ ```
350
+
351
+ 실패 시:
352
+
353
+ ```json
354
+ {
355
+ "success": false,
356
+ "error": "Invalid webhook token format or inactive/deleted webhook",
357
+ "errorCode": 40000
358
+ }
359
+ ```
360
+
361
+ ---
362
+
363
+ ## 제한사항
364
+
365
+ | 항목 | 제한 |
366
+ |------|------|
367
+ | 메시지 길이 | 최대 5,000자 |
368
+ | 요청 크기 | 최대 256KB |
369
+ | 분당 요청 | 60회 |
370
+ | 10분당 요청 | 500회 |
371
+ | 팀 웹훅 수신자 | 최대 100명 |
372
+
373
+ 속도 제한(42900 에러)에 걸리면 서버가 자동으로 지수 백오프 재시도(최대 3회)를 수행합니다.
374
+
375
+ ---
376
+
377
+ ## 로컬 개발
378
+
379
+ ```bash
380
+ git clone https://github.com/kwag93/cc-jandi.git
381
+ cd cc-jandi
382
+ npm install
383
+ cp .env.example .env # 토큰 입력
384
+ npm run build
385
+ ```
386
+
387
+ 개발 중 Claude Desktop에서 테스트하려면:
388
+
389
+ ```json
390
+ {
391
+ "mcpServers": {
392
+ "cc-jandi": {
393
+ "command": "node",
394
+ "args": ["/절대/경로/cc-jandi/dist/index.js"]
395
+ }
396
+ }
397
+ }
398
+ ```
399
+
400
+ | 명령어 | 설명 |
401
+ |--------|------|
402
+ | `npm run build` | TypeScript 컴파일 + mcp-build 패키징 |
403
+ | `npm run watch` | 파일 변경 시 자동 컴파일 |
404
+ | `npm run start` | 서버 직접 실행 |
405
+
406
+ ---
407
+
408
+ <details>
409
+ <summary><strong>에이전트용: 자동 설정 및 개발 가이드</strong></summary>
410
+
411
+ > 이 섹션은 AI 에이전트가 이 프로젝트를 자동으로 설정하고 도구를 호출할 수 있도록 작성되었습니다.
412
+
413
+ ### MCP 서버 자동 설정
414
+
415
+ **필수 조건**: Node.js >= 18.19.0, npx 사용 가능
416
+
417
+ **설치 없이 실행** (npx):
418
+ ```bash
419
+ npx cc-jandi
420
+ ```
421
+
422
+ **환경 변수 설정 후 실행**:
423
+ ```bash
424
+ JANDI_TOKEN=your_32char_hex_token npx cc-jandi
425
+ ```
426
+
427
+ 서버는 stdio 전송을 사용합니다. MCP 클라이언트가 프로세스를 직접 실행하고 stdin/stdout으로 통신합니다.
428
+
429
+ ### 도구 입력 스키마
430
+
431
+ 각 도구의 정확한 파라미터 명세입니다. `?`는 선택 파라미터입니다.
432
+
433
+ #### `send_message`
434
+ ```
435
+ message: string — 메시지 내용
436
+ token?: string — 직접 토큰 (32자 hex)
437
+ tokenAlias?: string — 환경 변수 별칭 (예: "dev", "prod")
438
+ ```
439
+ 토큰 해석 순서: `token` → `tokenAlias` → `JANDI_TOKEN` (기본값)
440
+
441
+ #### `send_rich_message`
442
+ ```
443
+ message: string — 메시지 본문
444
+ color?: string — 색상 hex (예: "#FF0000")
445
+ connectInfo?: array — [{title?, description?, imageUrl?}]
446
+ token?: string
447
+ tokenAlias?: string
448
+ ```
449
+
450
+ #### `validate_token`
451
+ ```
452
+ token?: string
453
+ tokenAlias?: string
454
+ ```
455
+
456
+ #### `test_webhook`
457
+ ```
458
+ token?: string
459
+ tokenAlias?: string
460
+ ```
461
+
462
+ #### `send_team_message`
463
+ ```
464
+ email: string — 수신자 이메일 (쉼표 구분, 최대 100명)
465
+ message: string — 메시지 내용
466
+ teamId?: string — 팀 ID (tokenAlias 미사용 시 필수)
467
+ token?: string — 팀 토큰 (tokenAlias 미사용 시 필수)
468
+ tokenAlias?: string — 팀 토큰 별칭 (예: "sales")
469
+ ```
470
+ 팀 토큰 해석: `teamId`+`token` → `tokenAlias`로 `JANDI_TEAM_ID_{alias}` + `JANDI_TEAM_TOKEN_{alias}` 조회
471
+
472
+ #### `send_team_rich_message`
473
+ ```
474
+ email: string
475
+ message: string
476
+ color?: string
477
+ connectInfo?: array — [{title?, description?, imageUrl?}]
478
+ teamId?: string
479
+ token?: string
480
+ tokenAlias?: string
481
+ ```
482
+
483
+ #### `validate_team_token`
484
+ ```
485
+ teamId?: string
486
+ token?: string
487
+ tokenAlias?: string
488
+ ```
489
+
490
+ #### `simulate_outgoing_payload`
491
+ ```
492
+ text: string — 트리거 메시지
493
+ webhookType?: "outgoing"|"team-outgoing" — 기본: "outgoing"
494
+ keyword?: string — 트리거 키워드 (기본: "test")
495
+ teamName?: string
496
+ roomName?: string
497
+ writerName?: string
498
+ writerEmail?: string
499
+ ```
500
+
501
+ #### `generate_outgoing_handler`
502
+ ```
503
+ framework: "express"|"fastapi"|"flask" — 서버 프레임워크
504
+ verificationToken?: string — 요청 검증 토큰
505
+ handlerLogic?: string — 커스텀 로직 설명
506
+ ```
507
+
508
+ #### `validate_outgoing_response`
509
+ ```
510
+ body: string — 응답 body (필수, 최대 5000자)
511
+ connectColor?: string — hex 색상
512
+ connectInfo?: array — [{title?, description?, imageUrl?}]
513
+ ```
514
+
515
+ #### `generate_webhook_script`
516
+ ```
517
+ language: "python"|"nodejs"|"curl"|"bash" — 언어
518
+ token: string — 웹훅 토큰 (필수)
519
+ message: string — 메시지 내용
520
+ webhookType?: "incoming"|"team-incoming" — 기본: "incoming"
521
+ color?: string
522
+ title?: string
523
+ description?: string
524
+ imageUrl?: string
525
+ teamId?: string — team-incoming 시 필수
526
+ email?: string — team-incoming 시 필수
527
+ ```
528
+
529
+ ### 기술 스택
530
+
531
+ - **런타임**: Node.js >= 18.19.0
532
+ - **언어**: TypeScript (ES modules, `.js` 확장자 import 필수)
533
+ - **프레임워크**: [mcp-framework](https://github.com/QuantGeekDev/mcp-framework) — `src/tools/` 하위를 재귀 탐색하여 도구 자동 등록
534
+ - **HTTP**: axios
535
+ - **환경변수**: dotenv
536
+
537
+ ### 디렉토리 구조
538
+
539
+ ```
540
+ src/
541
+ ├── index.ts # 진입점 (ConfigService 초기화 → MCPServer 시작)
542
+ ├── types/
543
+ │ ├── common.ts # JandiConnectInfo, JandiColors, BaseWebhookConfig, etc.
544
+ │ ├── incoming.ts # IncomingWebhookConfig, IncomingMessage
545
+ │ ├── team-incoming.ts # TeamIncomingWebhookConfig, TeamIncomingMessage
546
+ │ ├── outgoing.ts # OutgoingWebhookPayload, TeamOutgoingWebhookPayload
547
+ │ └── index.ts # 모든 타입 re-export
548
+ ├── services/
549
+ │ ├── base/BaseWebhookService.ts # 추상 베이스 (HTTP, 검증, 에러 핸들링)
550
+ │ ├── IncomingWebhookService.ts # POST wh.jandi.com/connect-api/webhook/{token}
551
+ │ ├── TeamIncomingWebhookService.ts # POST wh.jandi.com/connect-api/team-webhook/{teamId}/{token}
552
+ │ ├── configService.ts # 환경 변수 → 토큰 Map 관리
553
+ │ └── index.ts
554
+ ├── utils/
555
+ │ ├── resolveToken.ts # Incoming 토큰 해석 (token → alias → default)
556
+ │ ├── resolveTeamToken.ts # Team 토큰 해석 (teamId+token → alias)
557
+ │ ├── validateColor.ts # Hex 색상 검증 (#RRGGBB)
558
+ │ └── index.ts
559
+ └── tools/
560
+ ├── incoming/ # 4개: send_message, send_rich_message, validate_token, test_webhook
561
+ ├── team-incoming/ # 3개: send_team_message, send_team_rich_message, validate_team_token
562
+ ├── outgoing/ # 3개: simulate_outgoing_payload, generate_outgoing_handler, validate_outgoing_response
563
+ └── GenerateWebhookScriptTool.ts # 1개: generate_webhook_script
564
+ ```
565
+
566
+ ### 도구 추가 방법
567
+
568
+ `src/tools/` 하위에 파일을 만들면 자동 등록됩니다.
569
+
570
+ ```typescript
571
+ import { MCPTool } from "mcp-framework";
572
+ import { z } from "zod";
573
+ import { IncomingWebhookService } from "../../services/IncomingWebhookService.js";
574
+ import { resolveIncomingToken } from "../../utils/resolveToken.js";
575
+ import type { ToolResult } from "../../types/common.js";
576
+
577
+ interface MyToolInput {
578
+ message: string;
579
+ tokenAlias?: string;
580
+ }
581
+
582
+ class MyTool extends MCPTool<MyToolInput> {
583
+ name = "my_tool";
584
+ description = "도구 설명";
585
+
586
+ schema = {
587
+ message: { type: z.string(), description: "메시지 내용" },
588
+ tokenAlias: { type: z.string().optional(), description: "토큰 별칭" },
589
+ };
590
+
591
+ async execute(input: MyToolInput): Promise<ToolResult> {
592
+ const resolved = resolveIncomingToken(input);
593
+ if (!resolved.success) return { success: false, error: resolved.error };
594
+
595
+ const message = IncomingWebhookService.createBasicMessage(input.message);
596
+ const result = await IncomingWebhookService.sendMessage(resolved.config, message);
597
+
598
+ if (result.success) {
599
+ return { success: true, data: { message: "완료", tokenUsed: resolved.config.alias || 'direct' } };
600
+ }
601
+ return { success: false, error: result.error };
602
+ }
603
+ }
604
+
605
+ export default MyTool;
606
+ ```
607
+
608
+ **규칙:**
609
+ - `MCPTool<T>` 상속 + `default export` 필수
610
+ - import 경로에 `.js` 확장자 필수 (ES modules)
611
+ - Incoming 도구: `resolveIncomingToken()` 사용
612
+ - Team 도구: `resolveTeamToken()` 사용
613
+ - Outgoing 도구: 토큰 해석 불필요 (개발 헬퍼)
614
+
615
+ ### 잔디 API 포맷
616
+
617
+ **요청** (Incoming / Team Incoming):
618
+ ```json
619
+ {
620
+ "body": "메시지 본문",
621
+ "connectColor": "#FAC11B",
622
+ "connectInfo": [{"title": "제목", "description": "설명", "imageUrl": "URL"}]
623
+ }
624
+ ```
625
+ Team Incoming은 `"to": "user@example.com"` 필드 추가.
626
+
627
+ **필수 HTTP 헤더**:
628
+ ```
629
+ Accept: application/vnd.tosslab.jandi-v2+json
630
+ Content-Type: application/json
631
+ ```
632
+
633
+ **에러 코드**: `40000` = 토큰 무효/비활성, `42900` = 속도 제한 초과
634
+
635
+ ### 빌드
636
+
637
+ `npm run build` = `tsc` → `mcp-build`. 결과물: `dist/index.js` (진입점)
638
+
639
+ </details>
640
+
641
+ ---
642
+
643
+ ## 문의 및 지원
644
+
645
+ - [GitHub Issues](https://github.com/kwag93/cc-jandi/issues) — 버그 리포트 및 기능 요청
646
+ - [잔디 커넥트 문서](https://support.jandi.com/ko/categories/%EC%BB%A4%EB%84%A5%ED%8A%B8-fdf97953) — 잔디 웹훅 설정 가이드
647
+
648
+ ## 기여하기
649
+
650
+ 1. Fork
651
+ 2. 브랜치 생성 (`git checkout -b feature/my-feature`)
652
+ 3. 커밋 (`git commit -m 'feat: 기능 설명'`)
653
+ 4. Push (`git push origin feature/my-feature`)
654
+ 5. Pull Request 생성
655
+
656
+ ## 라이선스
657
+
658
+ MIT — [LICENSE](LICENSE) 파일 참조
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { MCPServer } from "mcp-framework";
3
+ import { ConfigService } from "./services/configService.js";
4
+ // Initialize configuration service
5
+ ConfigService.initialize();
6
+ const server = new MCPServer();
7
+ server.start();