tdecollab 0.1.0 → 0.1.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 +117 -39
- package/dist/{chunk-7JOEVDKT.js → chunk-3TQ2OSYU.js} +12 -11
- package/dist/chunk-3TQ2OSYU.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{server-PHNRVUXJ.js → server-H24WSQEE.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-7JOEVDKT.js.map +0 -1
- /package/dist/{server-PHNRVUXJ.js.map → server-H24WSQEE.js.map} +0 -0
package/README.md
CHANGED
|
@@ -17,103 +17,181 @@ tdecollab은 TDE 포털에서 제공하는 협업 도구들을 하나의 CLI와
|
|
|
17
17
|
## 요구사항
|
|
18
18
|
|
|
19
19
|
- Node.js 20 이상
|
|
20
|
-
- pnpm
|
|
21
20
|
|
|
22
21
|
## 설치
|
|
23
22
|
|
|
23
|
+
### npm에서 설치 (권장)
|
|
24
|
+
|
|
24
25
|
```bash
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
```
|
|
26
|
+
# 전역 설치
|
|
27
|
+
npm install -g tdecollab
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
# 또는 npx로 즉시 실행 (설치 불필요)
|
|
30
|
+
npx -y tdecollab --help
|
|
31
|
+
```
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
### 소스에서 빌드 (개발자용)
|
|
32
34
|
|
|
33
35
|
```bash
|
|
34
|
-
|
|
36
|
+
git clone <repository-url>
|
|
37
|
+
cd tdecollab
|
|
38
|
+
pnpm install
|
|
39
|
+
pnpm build
|
|
35
40
|
```
|
|
36
41
|
|
|
42
|
+
## 설정
|
|
43
|
+
|
|
37
44
|
### 환경변수
|
|
38
45
|
|
|
46
|
+
tdecollab은 다음 환경변수를 통해 각 서비스에 접속합니다:
|
|
47
|
+
|
|
39
48
|
```env
|
|
40
|
-
# Confluence
|
|
41
|
-
CONFLUENCE_BASE_URL=https://confluence.
|
|
42
|
-
|
|
49
|
+
# Confluence (현재 지원)
|
|
50
|
+
CONFLUENCE_BASE_URL=https://confluence.example.com
|
|
51
|
+
CONFLUENCE_USERNAME=your-username # Basic Auth 사용 시 (선택)
|
|
43
52
|
CONFLUENCE_API_TOKEN=your-api-token
|
|
44
53
|
|
|
45
|
-
# JIRA
|
|
46
|
-
JIRA_BASE_URL=https://jira.
|
|
47
|
-
|
|
54
|
+
# JIRA (개발 예정)
|
|
55
|
+
JIRA_BASE_URL=https://jira.example.com
|
|
56
|
+
JIRA_USERNAME=your-username
|
|
48
57
|
JIRA_API_TOKEN=your-api-token
|
|
49
58
|
|
|
50
|
-
# GitLab
|
|
51
|
-
GITLAB_BASE_URL=https://gitlab.
|
|
59
|
+
# GitLab (개발 예정)
|
|
60
|
+
GITLAB_BASE_URL=https://gitlab.example.com
|
|
52
61
|
GITLAB_PRIVATE_TOKEN=your-private-token
|
|
53
62
|
```
|
|
54
63
|
|
|
64
|
+
### 설정 방법
|
|
65
|
+
|
|
66
|
+
**방법 1: .env 파일 사용 (로컬 개발)**
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# 프로젝트 루트에 .env 파일 생성
|
|
70
|
+
echo "CONFLUENCE_BASE_URL=https://confluence.example.com" > .env
|
|
71
|
+
echo "CONFLUENCE_API_TOKEN=your-token" >> .env
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**방법 2: 환경변수 직접 설정**
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
export CONFLUENCE_BASE_URL=https://confluence.example.com
|
|
78
|
+
export CONFLUENCE_API_TOKEN=your-token
|
|
79
|
+
tdecollab confluence space list
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**방법 3: MCP 서버 설정에 포함 (Claude Desktop)**
|
|
83
|
+
|
|
84
|
+
Claude Desktop 설정 파일의 `env` 섹션에 환경변수를 추가합니다 (아래 MCP 서버 섹션 참조).
|
|
85
|
+
|
|
55
86
|
## 사용법
|
|
56
87
|
|
|
57
|
-
### CLI
|
|
88
|
+
### CLI 명령어
|
|
89
|
+
|
|
90
|
+
#### Confluence (현재 지원)
|
|
58
91
|
|
|
59
92
|
```bash
|
|
60
|
-
#
|
|
93
|
+
# 스페이스 목록 조회
|
|
94
|
+
tdecollab confluence space list
|
|
95
|
+
|
|
96
|
+
# 페이지 조회
|
|
61
97
|
tdecollab confluence page get <pageId>
|
|
62
|
-
tdecollab confluence page get <pageId> --raw
|
|
63
|
-
tdecollab confluence page
|
|
98
|
+
tdecollab confluence page get <pageId> --raw # Storage Format 출력
|
|
99
|
+
tdecollab confluence page get <pageId> --quiet # 메타데이터 생략
|
|
100
|
+
tdecollab confluence page get <pageId> --raw --quiet > page.html
|
|
101
|
+
|
|
102
|
+
# 페이지 생성
|
|
64
103
|
tdecollab confluence page create --space <key> --title <title> --content "Markdown 내용"
|
|
65
|
-
tdecollab confluence
|
|
104
|
+
tdecollab confluence page create --space <key> --title <title> --file <path>
|
|
66
105
|
|
|
67
|
-
#
|
|
106
|
+
# 페이지 검색 (CQL)
|
|
107
|
+
tdecollab confluence search "title ~ 'guide'"
|
|
108
|
+
tdecollab confluence search "space = MYSPACE AND type = page"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### JIRA (개발 예정)
|
|
112
|
+
|
|
113
|
+
```bash
|
|
68
114
|
tdecollab jira issue get <issueKey>
|
|
69
115
|
tdecollab jira search <jql>
|
|
70
|
-
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### GitLab (개발 예정)
|
|
71
119
|
|
|
72
|
-
|
|
73
|
-
tdecollab gitlab mr list <projectId>
|
|
74
|
-
tdecollab gitlab pipeline get <projectId> <pipelineId>
|
|
120
|
+
```bash
|
|
121
|
+
tdecollab gitlab mr list <projectId>
|
|
75
122
|
```
|
|
76
123
|
|
|
77
|
-
### MCP 서버
|
|
124
|
+
### MCP 서버 (Claude Desktop 연동)
|
|
125
|
+
|
|
126
|
+
Claude Desktop에서 Confluence 도구를 사용할 수 있습니다.
|
|
78
127
|
|
|
79
|
-
|
|
128
|
+
#### 설정 파일 위치
|
|
80
129
|
|
|
81
|
-
|
|
130
|
+
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
131
|
+
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
132
|
+
|
|
133
|
+
#### npx 사용 (권장)
|
|
134
|
+
|
|
135
|
+
별도 설치 없이 최신 버전을 자동으로 실행합니다:
|
|
82
136
|
|
|
83
137
|
```json
|
|
84
138
|
{
|
|
85
139
|
"mcpServers": {
|
|
86
|
-
"tdecollab
|
|
87
|
-
"command": "
|
|
88
|
-
"args": ["
|
|
140
|
+
"tdecollab": {
|
|
141
|
+
"command": "npx",
|
|
142
|
+
"args": ["-y", "tdecollab", "mcp"],
|
|
89
143
|
"env": {
|
|
90
|
-
"CONFLUENCE_BASE_URL": "
|
|
91
|
-
"
|
|
144
|
+
"CONFLUENCE_BASE_URL": "https://confluence.example.com",
|
|
145
|
+
"CONFLUENCE_USERNAME": "your-username",
|
|
146
|
+
"CONFLUENCE_API_TOKEN": "your-api-token"
|
|
92
147
|
}
|
|
93
148
|
}
|
|
94
149
|
}
|
|
95
150
|
}
|
|
96
151
|
```
|
|
97
152
|
|
|
98
|
-
|
|
153
|
+
#### 전역 설치 사용
|
|
99
154
|
|
|
100
|
-
|
|
155
|
+
```bash
|
|
156
|
+
npm install -g tdecollab
|
|
157
|
+
```
|
|
101
158
|
|
|
102
159
|
```json
|
|
103
160
|
{
|
|
104
161
|
"mcpServers": {
|
|
105
162
|
"tdecollab": {
|
|
106
|
-
"command": "
|
|
107
|
-
"args": ["
|
|
163
|
+
"command": "tdecollab",
|
|
164
|
+
"args": ["mcp"],
|
|
108
165
|
"env": {
|
|
109
|
-
"CONFLUENCE_BASE_URL": "
|
|
110
|
-
"
|
|
166
|
+
"CONFLUENCE_BASE_URL": "https://confluence.example.com",
|
|
167
|
+
"CONFLUENCE_USERNAME": "your-username",
|
|
168
|
+
"CONFLUENCE_API_TOKEN": "your-api-token"
|
|
111
169
|
}
|
|
112
170
|
}
|
|
113
171
|
}
|
|
114
172
|
}
|
|
115
173
|
```
|
|
116
174
|
|
|
175
|
+
#### 로컬 개발 버전 사용
|
|
176
|
+
|
|
177
|
+
```json
|
|
178
|
+
{
|
|
179
|
+
"mcpServers": {
|
|
180
|
+
"tdecollab-dev": {
|
|
181
|
+
"command": "node",
|
|
182
|
+
"args": ["/absolute/path/to/tdecollab/dist/index.js"],
|
|
183
|
+
"env": {
|
|
184
|
+
"CONFLUENCE_BASE_URL": "https://confluence.example.com",
|
|
185
|
+
"CONFLUENCE_USERNAME": "your-username",
|
|
186
|
+
"CONFLUENCE_API_TOKEN": "your-api-token"
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
설정 후 Claude Desktop을 재시작하면 Confluence 도구를 사용할 수 있습니다.
|
|
194
|
+
|
|
117
195
|
## 개발
|
|
118
196
|
|
|
119
197
|
```bash
|
|
@@ -49,7 +49,7 @@ function registerConfluenceTools(server) {
|
|
|
49
49
|
const storageToMd = new StorageToMarkdownConverter();
|
|
50
50
|
server.tool(
|
|
51
51
|
"confluence_get_page",
|
|
52
|
-
"Confluence \uD398\uC774\uC9C0 \uC0C1\uC138 \uC870\uD68C
|
|
52
|
+
"TDE Confluence \uD398\uC774\uC9C0 \uC0C1\uC138 \uC870\uD68C. \uD398\uC774\uC9C0 \uB0B4\uC6A9\uC744 Markdown\uC73C\uB85C \uBCC0\uD658\uD558\uC5EC \uBC18\uD658\uD569\uB2C8\uB2E4.",
|
|
53
53
|
{
|
|
54
54
|
pageId: z.string().describe("\uD398\uC774\uC9C0 ID")
|
|
55
55
|
},
|
|
@@ -73,7 +73,7 @@ ${md}`
|
|
|
73
73
|
);
|
|
74
74
|
server.tool(
|
|
75
75
|
"confluence_create_page",
|
|
76
|
-
"Confluence \uD398\uC774\uC9C0 \uC0DD\uC131",
|
|
76
|
+
"TDE Confluence\uC5D0 \uC0C8 \uD398\uC774\uC9C0\uB97C \uC0DD\uC131\uD569\uB2C8\uB2E4. Markdown \uD615\uC2DD\uC758 \uB0B4\uC6A9\uC744 Confluence Storage Format\uC73C\uB85C \uC790\uB3D9 \uBCC0\uD658\uD569\uB2C8\uB2E4.",
|
|
77
77
|
{
|
|
78
78
|
spaceKey: z.string().describe("\uC2A4\uD398\uC774\uC2A4 \uD0A4"),
|
|
79
79
|
title: z.string().describe("\uD398\uC774\uC9C0 \uC81C\uBAA9"),
|
|
@@ -103,7 +103,7 @@ URL: ${page._links?.base}${page._links?.webui}`
|
|
|
103
103
|
);
|
|
104
104
|
server.tool(
|
|
105
105
|
"confluence_update_page",
|
|
106
|
-
"Confluence \uD398\uC774\uC9C0 \uC218\uC815",
|
|
106
|
+
"TDE Confluence \uD398\uC774\uC9C0\uB97C \uC218\uC815\uD569\uB2C8\uB2E4. Markdown \uD615\uC2DD\uC758 \uB0B4\uC6A9\uC73C\uB85C \uC5C5\uB370\uC774\uD2B8\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
107
107
|
{
|
|
108
108
|
pageId: z.string().describe("\uD398\uC774\uC9C0 ID"),
|
|
109
109
|
title: z.string().describe("\uD398\uC774\uC9C0 \uC81C\uBAA9"),
|
|
@@ -130,7 +130,7 @@ URL: ${page._links?.base}${page._links?.webui}`
|
|
|
130
130
|
);
|
|
131
131
|
server.tool(
|
|
132
132
|
"confluence_search_pages",
|
|
133
|
-
"Confluence \uD398\uC774\uC9C0 \uAC80\uC0C9 (
|
|
133
|
+
"TDE Confluence\uC5D0\uC11C \uD398\uC774\uC9C0\uB97C \uAC80\uC0C9\uD569\uB2C8\uB2E4. CQL(Confluence Query Language)\uC744 \uC0AC\uC6A9\uD558\uC5EC \uACE0\uAE09 \uAC80\uC0C9\uC774 \uAC00\uB2A5\uD569\uB2C8\uB2E4.",
|
|
134
134
|
{
|
|
135
135
|
cql: z.string().describe('Confluence Query Language (\uC608: title ~ "guide")'),
|
|
136
136
|
limit: z.number().default(10).describe("\uACB0\uACFC \uAC1C\uC218 \uC81C\uD55C")
|
|
@@ -151,7 +151,7 @@ ${summary}`
|
|
|
151
151
|
);
|
|
152
152
|
server.tool(
|
|
153
153
|
"confluence_get_spaces",
|
|
154
|
-
"Confluence \uC2A4\uD398\uC774\uC2A4 \uBAA9\uB85D \uC870\uD68C",
|
|
154
|
+
"TDE Confluence\uC758 \uC2A4\uD398\uC774\uC2A4 \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4.",
|
|
155
155
|
{
|
|
156
156
|
limit: z.number().default(20).describe("\uACB0\uACFC \uAC1C\uC218 \uC81C\uD55C")
|
|
157
157
|
},
|
|
@@ -166,7 +166,7 @@ ${summary}` }]
|
|
|
166
166
|
);
|
|
167
167
|
server.tool(
|
|
168
168
|
"confluence_delete_page",
|
|
169
|
-
"Confluence \uD398\uC774\uC9C0 \uC0AD\uC81C",
|
|
169
|
+
"TDE Confluence \uD398\uC774\uC9C0\uB97C \uC0AD\uC81C\uD569\uB2C8\uB2E4.",
|
|
170
170
|
{
|
|
171
171
|
pageId: z.string().describe("\uD398\uC774\uC9C0 ID")
|
|
172
172
|
},
|
|
@@ -184,7 +184,7 @@ ${summary}` }]
|
|
|
184
184
|
);
|
|
185
185
|
server.tool(
|
|
186
186
|
"confluence_get_page_tree",
|
|
187
|
-
"Confluence \uD398\uC774\uC9C0 \
|
|
187
|
+
"TDE Confluence \uD398\uC774\uC9C0\uC758 \uD558\uC704 \uD398\uC774\uC9C0(\uC790\uC2DD \uD398\uC774\uC9C0) \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4.",
|
|
188
188
|
{
|
|
189
189
|
pageId: z.string().describe("\uD398\uC774\uC9C0 ID"),
|
|
190
190
|
limit: z.number().default(20).describe("\uACB0\uACFC \uAC1C\uC218 \uC81C\uD55C")
|
|
@@ -205,7 +205,7 @@ ${summary}`
|
|
|
205
205
|
);
|
|
206
206
|
server.tool(
|
|
207
207
|
"confluence_manage_labels",
|
|
208
|
-
"Confluence \uB77C\uBCA8 \uAD00\uB9AC",
|
|
208
|
+
"TDE Confluence \uD398\uC774\uC9C0\uC758 \uB77C\uBCA8\uC744 \uAD00\uB9AC\uD569\uB2C8\uB2E4. \uB77C\uBCA8 \uC870\uD68C, \uCD94\uAC00, \uC0AD\uC81C \uAE30\uB2A5\uC744 \uC81C\uACF5\uD569\uB2C8\uB2E4.",
|
|
209
209
|
{
|
|
210
210
|
pageId: z.string().describe("\uD398\uC774\uC9C0 ID"),
|
|
211
211
|
action: z.enum(["list", "add", "remove"]).describe("\uC791\uC5C5 \uC720\uD615"),
|
|
@@ -241,7 +241,7 @@ ${summary}`
|
|
|
241
241
|
);
|
|
242
242
|
server.tool(
|
|
243
243
|
"confluence_convert_content",
|
|
244
|
-
"Confluence \uCEE8\uD150\uCE20 \uD3EC\uB9F7 \uBCC0\uD658
|
|
244
|
+
"TDE Confluence \uCEE8\uD150\uCE20 \uD3EC\uB9F7\uC744 \uBCC0\uD658\uD569\uB2C8\uB2E4. Markdown\uACFC Confluence Storage Format \uAC04 \uC591\uBC29\uD5A5 \uBCC0\uD658\uC744 \uC9C0\uC6D0\uD569\uB2C8\uB2E4.",
|
|
245
245
|
{
|
|
246
246
|
content: z.string().describe("\uBCC0\uD658\uD560 \uCEE8\uD150\uCE20"),
|
|
247
247
|
format: z.enum(["storage_to_markdown", "markdown_to_storage"]).describe("\uBCC0\uD658 \uBC29\uD5A5")
|
|
@@ -268,7 +268,8 @@ async function runServer() {
|
|
|
268
268
|
try {
|
|
269
269
|
const server = new McpServer({
|
|
270
270
|
name: "TDE Collab",
|
|
271
|
-
version: "1.0.0"
|
|
271
|
+
version: "1.0.0",
|
|
272
|
+
description: "TDE \uD3EC\uD138(Confluence, JIRA, GitLab) \uD1B5\uD569 \uB3C4\uAD6C. TDE Confluence \uD398\uC774\uC9C0 \uAD00\uB9AC, \uAC80\uC0C9, \uD3B8\uC9D1 \uAE30\uB2A5\uC744 \uC81C\uACF5\uD569\uB2C8\uB2E4."
|
|
272
273
|
});
|
|
273
274
|
registerConfluenceTools(server);
|
|
274
275
|
const transport = new StdioServerTransport();
|
|
@@ -283,4 +284,4 @@ async function runServer() {
|
|
|
283
284
|
export {
|
|
284
285
|
runServer
|
|
285
286
|
};
|
|
286
|
-
//# sourceMappingURL=chunk-
|
|
287
|
+
//# sourceMappingURL=chunk-3TQ2OSYU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp/server.ts","../src/confluence/tools/index.ts","../src/confluence/api/label.ts"],"sourcesContent":["\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { registerConfluenceTools } from '../confluence/tools/index.js';\nimport { logger } from '../common/logger.js';\n\nexport async function runServer() {\n try {\n const server = new McpServer({\n name: 'TDE Collab',\n version: '1.0.0',\n description: 'TDE 포털(Confluence, JIRA, GitLab) 통합 도구. TDE Confluence 페이지 관리, 검색, 편집 기능을 제공합니다.',\n });\n\n // Confluence 도구 등록\n registerConfluenceTools(server);\n\n // Stdio 전송 계층 연결\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n logger.info('TDE Collab MCP Server running on stdio');\n } catch (error) {\n logger.error(`Fatal error in MCP Server: ${error}`);\n process.exit(1);\n }\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { ConfluenceContentApi } from '../api/content.js';\nimport { ConfluenceSpaceApi } from '../api/space.js';\nimport { ConfluenceSearchApi } from '../api/search.js';\nimport { ConfluenceLabelApi } from '../api/label.js';\nimport { createConfluenceClient } from '../api/client.js';\nimport { MarkdownToStorageConverter } from '../converters/md-to-storage.js';\nimport { StorageToMarkdownConverter } from '../converters/storage-to-md.js';\nimport { loadConfluenceConfig } from '../../common/config.js';\nimport { logger } from '../../common/logger.js';\n\nexport function registerConfluenceTools(server: McpServer) {\n try {\n const config = loadConfluenceConfig();\n const client = createConfluenceClient(config);\n\n const contentApi = new ConfluenceContentApi(client);\n const spaceApi = new ConfluenceSpaceApi(client);\n const searchApi = new ConfluenceSearchApi(client);\n const labelApi = new ConfluenceLabelApi(client);\n\n const mdToStorage = new MarkdownToStorageConverter();\n const storageToMd = new StorageToMarkdownConverter();\n\n // Tools\n\n server.tool(\n 'confluence_get_page',\n 'TDE Confluence 페이지 상세 조회. 페이지 내용을 Markdown으로 변환하여 반환합니다.',\n {\n pageId: z.string().describe('페이지 ID'),\n },\n async ({ pageId }) => {\n const page = await contentApi.getPage(pageId);\n const md = page.body?.storage?.value ? storageToMd.convert(page.body.storage.value) : '';\n\n return {\n content: [\n {\n type: 'text',\n text: `Title: ${page.title}\\nID: ${page.id}\\nSpace: ${page.space?.name} (${page.space?.key})\\nURL: ${page._links?.base}${page._links?.webui}\\n\\n${md}`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_create_page',\n 'TDE Confluence에 새 페이지를 생성합니다. Markdown 형식의 내용을 Confluence Storage Format으로 자동 변환합니다.',\n {\n spaceKey: z.string().describe('스페이스 키'),\n title: z.string().describe('페이지 제목'),\n content: z.string().describe('페이지 내용 (Markdown)'),\n parentId: z.string().optional().describe('부모 페이지 ID'),\n labels: z.array(z.string()).optional().describe('라벨 목록'),\n },\n async ({ spaceKey, title, content, parentId, labels }) => {\n const storageBody = mdToStorage.convert(content);\n const page = await contentApi.createPage({\n spaceKey,\n title,\n body: storageBody,\n parentId,\n labels\n });\n\n return {\n content: [\n {\n type: 'text',\n text: `페이지 생성 성공: ${page.title} (ID: ${page.id})\\nURL: ${page._links?.base}${page._links?.webui}`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_update_page',\n 'TDE Confluence 페이지를 수정합니다. Markdown 형식의 내용으로 업데이트할 수 있습니다.',\n {\n pageId: z.string().describe('페이지 ID'),\n title: z.string().describe('페이지 제목'),\n content: z.string().describe('페이지 내용 (Markdown)'),\n version: z.number().describe('현재 페이지 버전 (충돌 방지용)'),\n },\n async ({ pageId, title, content, version }) => {\n const storageBody = mdToStorage.convert(content);\n const page = await contentApi.updatePage({\n id: pageId,\n title,\n body: storageBody,\n version\n });\n\n return {\n content: [\n {\n type: 'text',\n text: `페이지 수정 성공: ${page.title} (Version: ${page.version?.number})`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_search_pages',\n 'TDE Confluence에서 페이지를 검색합니다. CQL(Confluence Query Language)을 사용하여 고급 검색이 가능합니다.',\n {\n cql: z.string().describe('Confluence Query Language (예: title ~ \"guide\")'),\n limit: z.number().default(10).describe('결과 개수 제한'),\n },\n async ({ cql, limit }) => {\n const result = await searchApi.searchByCql(cql, 0, limit);\n const summary = result.results.map(p => `- [${p.id}] ${p.title} (Space: ${p.space?.key})`).join('\\n');\n\n return {\n content: [\n {\n type: 'text',\n text: `검색 결과 (${result.size}/${result.totalSize}):\\n${summary}`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_get_spaces',\n 'TDE Confluence의 스페이스 목록을 조회합니다.',\n {\n limit: z.number().default(20).describe('결과 개수 제한')\n },\n async ({ limit }) => {\n const spaces = await spaceApi.getSpaces('global', 0, limit);\n const summary = spaces.map(s => `- [${s.key}] ${s.name}`).join('\\n');\n return {\n content: [{ type: 'text', text: `스페이스 목록:\\n${summary}` }]\n };\n }\n );\n\n server.tool(\n 'confluence_delete_page',\n 'TDE Confluence 페이지를 삭제합니다.',\n {\n pageId: z.string().describe('페이지 ID'),\n },\n async ({ pageId }) => {\n await contentApi.deletePage(pageId);\n return {\n content: [\n {\n type: 'text',\n text: `페이지 삭제 성공 (ID: ${pageId})`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_get_page_tree',\n 'TDE Confluence 페이지의 하위 페이지(자식 페이지) 목록을 조회합니다.',\n {\n pageId: z.string().describe('페이지 ID'),\n limit: z.number().default(20).describe('결과 개수 제한'),\n },\n async ({ pageId, limit }) => {\n const children = await contentApi.getChildPages(pageId, 0, limit);\n const summary = children.map(p => `- [${p.id}] ${p.title}`).join('\\n');\n return {\n content: [\n {\n type: 'text',\n text: `자식 페이지 목록 (${children.length}):\\n${summary}`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_manage_labels',\n 'TDE Confluence 페이지의 라벨을 관리합니다. 라벨 조회, 추가, 삭제 기능을 제공합니다.',\n {\n pageId: z.string().describe('페이지 ID'),\n action: z.enum(['list', 'add', 'remove']).describe('작업 유형'),\n labels: z.array(z.string()).optional().describe('추가할 라벨 목록 (add 작업 시 필수)'),\n label: z.string().optional().describe('삭제할 라벨 (remove 작업 시 필수)'),\n },\n async ({ pageId, action, labels, label }) => {\n if (action === 'list') {\n const result = await labelApi.getLabels(pageId);\n const summary = result.map(l => l.name).join(', ');\n return {\n content: [{ type: 'text', text: `라벨 목록: ${summary}` }],\n };\n } else if (action === 'add') {\n if (!labels || labels.length === 0) {\n throw new Error('라벨 목록을 입력해주세요.');\n }\n await labelApi.addLabels(pageId, labels);\n return {\n content: [{ type: 'text', text: `라벨 추가 성공: ${labels.join(', ')}` }],\n };\n } else if (action === 'remove') {\n if (!label) {\n throw new Error('삭제할 라벨을 입력해주세요.');\n }\n await labelApi.removeLabel(pageId, label);\n return {\n content: [{ type: 'text', text: `라벨 삭제 성공: ${label}` }],\n };\n }\n return { content: [] };\n }\n );\n\n server.tool(\n 'confluence_convert_content',\n 'TDE Confluence 컨텐츠 포맷을 변환합니다. Markdown과 Confluence Storage Format 간 양방향 변환을 지원합니다.',\n {\n content: z.string().describe('변환할 컨텐츠'),\n format: z.enum(['storage_to_markdown', 'markdown_to_storage']).describe('변환 방향'),\n },\n async ({ content, format }) => {\n let result = '';\n if (format === 'storage_to_markdown') {\n result = storageToMd.convert(content);\n } else {\n result = mdToStorage.convert(content);\n }\n return {\n content: [{ type: 'text', text: result }],\n };\n }\n );\n\n } catch (error) {\n logger.warn(`Confluence 설정 로드 실패 또는 도구 등록 중 오류 발생: ${(error as Error).message}`);\n // Do not throw, just skip registration if config is missing (optional module pattern)\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { ConfluenceLabel } from '../types.js';\n\nexport class ConfluenceLabelApi {\n constructor(private client: AxiosInstance) { }\n\n async getLabels(pageId: string): Promise<ConfluenceLabel[]> {\n const response = await this.client.get(`/rest/api/content/${pageId}/label`);\n return response.data.results;\n }\n\n async addLabels(pageId: string, labels: string[]): Promise<void> {\n const data = labels.map(name => ({ prefix: 'global', name }));\n await this.client.post(`/rest/api/content/${pageId}/label`, data);\n }\n\n async removeLabel(pageId: string, labelName: string): Promise<void> {\n // Label deletion usually requires query param for name\n // /rest/api/content/{id}/label?name={name}\n await this.client.delete(`/rest/api/content/${pageId}/label`, {\n params: { name: labelName }\n });\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -138,7 +138,7 @@ var program = new Command();
|
|
|
138
138
|
program.name("tdecollab").description("TDE Collaboration CLI").version("0.1.0");
|
|
139
139
|
registerConfluenceCommands(program);
|
|
140
140
|
program.command("mcp").description("Run MCP Server").action(async () => {
|
|
141
|
-
const { runServer } = await import("./server-
|
|
141
|
+
const { runServer } = await import("./server-H24WSQEE.js");
|
|
142
142
|
await runServer();
|
|
143
143
|
});
|
|
144
144
|
program.parse(process.argv);
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/server.ts","../src/confluence/tools/index.ts","../src/confluence/api/label.ts"],"sourcesContent":["\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { registerConfluenceTools } from '../confluence/tools/index.js';\nimport { logger } from '../common/logger.js';\n\nexport async function runServer() {\n try {\n const server = new McpServer({\n name: 'TDE Collab',\n version: '1.0.0',\n });\n\n // Confluence 도구 등록\n registerConfluenceTools(server);\n\n // Stdio 전송 계층 연결\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n logger.info('TDE Collab MCP Server running on stdio');\n } catch (error) {\n logger.error(`Fatal error in MCP Server: ${error}`);\n process.exit(1);\n }\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { ConfluenceContentApi } from '../api/content.js';\nimport { ConfluenceSpaceApi } from '../api/space.js';\nimport { ConfluenceSearchApi } from '../api/search.js';\nimport { ConfluenceLabelApi } from '../api/label.js';\nimport { createConfluenceClient } from '../api/client.js';\nimport { MarkdownToStorageConverter } from '../converters/md-to-storage.js';\nimport { StorageToMarkdownConverter } from '../converters/storage-to-md.js';\nimport { loadConfluenceConfig } from '../../common/config.js';\nimport { logger } from '../../common/logger.js';\n\nexport function registerConfluenceTools(server: McpServer) {\n try {\n const config = loadConfluenceConfig();\n const client = createConfluenceClient(config);\n\n const contentApi = new ConfluenceContentApi(client);\n const spaceApi = new ConfluenceSpaceApi(client);\n const searchApi = new ConfluenceSearchApi(client);\n const labelApi = new ConfluenceLabelApi(client);\n\n const mdToStorage = new MarkdownToStorageConverter();\n const storageToMd = new StorageToMarkdownConverter();\n\n // Tools\n\n server.tool(\n 'confluence_get_page',\n 'Confluence 페이지 상세 조회 (Markdown 변환 포함)',\n {\n pageId: z.string().describe('페이지 ID'),\n },\n async ({ pageId }) => {\n const page = await contentApi.getPage(pageId);\n const md = page.body?.storage?.value ? storageToMd.convert(page.body.storage.value) : '';\n\n return {\n content: [\n {\n type: 'text',\n text: `Title: ${page.title}\\nID: ${page.id}\\nSpace: ${page.space?.name} (${page.space?.key})\\nURL: ${page._links?.base}${page._links?.webui}\\n\\n${md}`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_create_page',\n 'Confluence 페이지 생성',\n {\n spaceKey: z.string().describe('스페이스 키'),\n title: z.string().describe('페이지 제목'),\n content: z.string().describe('페이지 내용 (Markdown)'),\n parentId: z.string().optional().describe('부모 페이지 ID'),\n labels: z.array(z.string()).optional().describe('라벨 목록'),\n },\n async ({ spaceKey, title, content, parentId, labels }) => {\n const storageBody = mdToStorage.convert(content);\n const page = await contentApi.createPage({\n spaceKey,\n title,\n body: storageBody,\n parentId,\n labels\n });\n\n return {\n content: [\n {\n type: 'text',\n text: `페이지 생성 성공: ${page.title} (ID: ${page.id})\\nURL: ${page._links?.base}${page._links?.webui}`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_update_page',\n 'Confluence 페이지 수정',\n {\n pageId: z.string().describe('페이지 ID'),\n title: z.string().describe('페이지 제목'),\n content: z.string().describe('페이지 내용 (Markdown)'),\n version: z.number().describe('현재 페이지 버전 (충돌 방지용)'),\n },\n async ({ pageId, title, content, version }) => {\n const storageBody = mdToStorage.convert(content);\n const page = await contentApi.updatePage({\n id: pageId,\n title,\n body: storageBody,\n version\n });\n\n return {\n content: [\n {\n type: 'text',\n text: `페이지 수정 성공: ${page.title} (Version: ${page.version?.number})`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_search_pages',\n 'Confluence 페이지 검색 (CQL)',\n {\n cql: z.string().describe('Confluence Query Language (예: title ~ \"guide\")'),\n limit: z.number().default(10).describe('결과 개수 제한'),\n },\n async ({ cql, limit }) => {\n const result = await searchApi.searchByCql(cql, 0, limit);\n const summary = result.results.map(p => `- [${p.id}] ${p.title} (Space: ${p.space?.key})`).join('\\n');\n\n return {\n content: [\n {\n type: 'text',\n text: `검색 결과 (${result.size}/${result.totalSize}):\\n${summary}`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_get_spaces',\n 'Confluence 스페이스 목록 조회',\n {\n limit: z.number().default(20).describe('결과 개수 제한')\n },\n async ({ limit }) => {\n const spaces = await spaceApi.getSpaces('global', 0, limit);\n const summary = spaces.map(s => `- [${s.key}] ${s.name}`).join('\\n');\n return {\n content: [{ type: 'text', text: `스페이스 목록:\\n${summary}` }]\n };\n }\n );\n\n server.tool(\n 'confluence_delete_page',\n 'Confluence 페이지 삭제',\n {\n pageId: z.string().describe('페이지 ID'),\n },\n async ({ pageId }) => {\n await contentApi.deletePage(pageId);\n return {\n content: [\n {\n type: 'text',\n text: `페이지 삭제 성공 (ID: ${pageId})`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_get_page_tree',\n 'Confluence 페이지 트리 (자식 페이지) 조회',\n {\n pageId: z.string().describe('페이지 ID'),\n limit: z.number().default(20).describe('결과 개수 제한'),\n },\n async ({ pageId, limit }) => {\n const children = await contentApi.getChildPages(pageId, 0, limit);\n const summary = children.map(p => `- [${p.id}] ${p.title}`).join('\\n');\n return {\n content: [\n {\n type: 'text',\n text: `자식 페이지 목록 (${children.length}):\\n${summary}`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_manage_labels',\n 'Confluence 라벨 관리',\n {\n pageId: z.string().describe('페이지 ID'),\n action: z.enum(['list', 'add', 'remove']).describe('작업 유형'),\n labels: z.array(z.string()).optional().describe('추가할 라벨 목록 (add 작업 시 필수)'),\n label: z.string().optional().describe('삭제할 라벨 (remove 작업 시 필수)'),\n },\n async ({ pageId, action, labels, label }) => {\n if (action === 'list') {\n const result = await labelApi.getLabels(pageId);\n const summary = result.map(l => l.name).join(', ');\n return {\n content: [{ type: 'text', text: `라벨 목록: ${summary}` }],\n };\n } else if (action === 'add') {\n if (!labels || labels.length === 0) {\n throw new Error('라벨 목록을 입력해주세요.');\n }\n await labelApi.addLabels(pageId, labels);\n return {\n content: [{ type: 'text', text: `라벨 추가 성공: ${labels.join(', ')}` }],\n };\n } else if (action === 'remove') {\n if (!label) {\n throw new Error('삭제할 라벨을 입력해주세요.');\n }\n await labelApi.removeLabel(pageId, label);\n return {\n content: [{ type: 'text', text: `라벨 삭제 성공: ${label}` }],\n };\n }\n return { content: [] };\n }\n );\n\n server.tool(\n 'confluence_convert_content',\n 'Confluence 컨텐츠 포맷 변환 (Markdown ↔ Storage)',\n {\n content: z.string().describe('변환할 컨텐츠'),\n format: z.enum(['storage_to_markdown', 'markdown_to_storage']).describe('변환 방향'),\n },\n async ({ content, format }) => {\n let result = '';\n if (format === 'storage_to_markdown') {\n result = storageToMd.convert(content);\n } else {\n result = mdToStorage.convert(content);\n }\n return {\n content: [{ type: 'text', text: result }],\n };\n }\n );\n\n } catch (error) {\n logger.warn(`Confluence 설정 로드 실패 또는 도구 등록 중 오류 발생: ${(error as Error).message}`);\n // Do not throw, just skip registration if config is missing (optional module pattern)\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { ConfluenceLabel } from '../types.js';\n\nexport class ConfluenceLabelApi {\n constructor(private client: AxiosInstance) { }\n\n async getLabels(pageId: string): Promise<ConfluenceLabel[]> {\n const response = await this.client.get(`/rest/api/content/${pageId}/label`);\n return response.data.results;\n }\n\n async addLabels(pageId: string, labels: string[]): Promise<void> {\n const data = labels.map(name => ({ prefix: 'global', name }));\n await this.client.post(`/rest/api/content/${pageId}/label`, data);\n }\n\n async removeLabel(pageId: string, labelName: string): Promise<void> {\n // Label deletion usually requires query param for name\n // /rest/api/content/{id}/label?name={name}\n await this.client.delete(`/rest/api/content/${pageId}/label`, {\n params: { name: labelName }\n });\n }\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|