@koseha/api-mcp 0.0.7 → 0.0.8
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 +144 -125
- package/dist/swagger/swaggerLoader.js +21 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,194 +1,176 @@
|
|
|
1
1
|
# API MCP 서버
|
|
2
2
|
|
|
3
|
-
Model Context Protocol (MCP) 서버입니다.
|
|
3
|
+
Swagger/OpenAPI 스펙 기반의 Model Context Protocol (MCP) 서버입니다. OpenAPI 문서를 통해 API 목록과 상세 정보를 조회할 수 있는 도구를 제공합니다.
|
|
4
4
|
|
|
5
5
|
## 기능
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- **리소스 (Resources)**: `greeting://{name}` - 동적 인사말 생성 리소스
|
|
7
|
+
### 도구 (Tools)
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
- **`getApiList`** - API 목록 조회
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
- OpenAPI 스펙에서 모든 API 엔드포인트 목록을 조회합니다.
|
|
12
|
+
- 반환 형식: 각 경로별 HTTP 메서드와 `tags`, `operationId`, `summary` 정보
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
- **`getApiDetail`** - API 상세 조회
|
|
15
|
+
- 특정 API의 상세 정보를 조회합니다.
|
|
16
|
+
- 파라미터: `requestUrl` (string), `httpMethod` (get|post|put|delete|patch)
|
|
17
|
+
- 반환 형식: `parameters`, `requestBody`, `responses` 정보
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
npm run build
|
|
18
|
-
```
|
|
19
|
+
### 리소스 (Resources)
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
npm publish
|
|
24
|
-
```
|
|
21
|
+
- **`greeting://{name}`** - 동적 인사말 생성 리소스
|
|
25
22
|
|
|
26
|
-
|
|
23
|
+
## 설치
|
|
27
24
|
|
|
28
|
-
|
|
25
|
+
### NPM 패키지로 설치
|
|
29
26
|
|
|
30
27
|
```bash
|
|
31
|
-
|
|
32
|
-
npm install api-mcp
|
|
28
|
+
npm install @koseha/api-mcp
|
|
33
29
|
```
|
|
34
30
|
|
|
35
|
-
|
|
31
|
+
또는
|
|
36
32
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
```javascript
|
|
40
|
-
import { spawn } from 'child_process';
|
|
41
|
-
import { join } from 'path';
|
|
42
|
-
|
|
43
|
-
const mcpServer = spawn('npx', ['api-mcp'], {
|
|
44
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
45
|
-
});
|
|
33
|
+
```bash
|
|
34
|
+
npm install @koseha/api-mcp@latest
|
|
46
35
|
```
|
|
47
36
|
|
|
48
|
-
|
|
37
|
+
## 사용 방법
|
|
49
38
|
|
|
50
|
-
|
|
39
|
+
### 방법 1: Cursor IDE 에서 사용
|
|
51
40
|
|
|
52
|
-
|
|
41
|
+
Cursor 설정 파일에 추가:
|
|
53
42
|
|
|
54
|
-
```bash
|
|
55
|
-
npm link
|
|
56
43
|
```
|
|
44
|
+
{
|
|
45
|
+
"mcpServers": {
|
|
46
|
+
"api-mcp": {
|
|
47
|
+
"command": "node",
|
|
48
|
+
"args": ["./node_modules/@koseha/api-mcp/dist/index.js"]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
57
52
|
|
|
58
|
-
#### 2단계: 다른 프로젝트에서 링크
|
|
59
|
-
|
|
60
|
-
다른 프로젝트에서:
|
|
61
|
-
|
|
62
|
-
```bash
|
|
63
|
-
cd ../다른-프로젝트
|
|
64
|
-
npm link api-mcp
|
|
65
53
|
```
|
|
66
54
|
|
|
67
|
-
|
|
55
|
+
### 방법 2: Claude Desktop에서 사용
|
|
68
56
|
|
|
69
|
-
|
|
57
|
+
Claude Desktop 설정 파일에 추가:
|
|
70
58
|
|
|
71
|
-
|
|
59
|
+
**macOS:**
|
|
72
60
|
|
|
73
|
-
```json
|
|
74
|
-
{
|
|
75
|
-
"dependencies": {
|
|
76
|
-
"api-mcp": "file:../api-mcp"
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
61
|
```
|
|
80
|
-
|
|
81
|
-
그런 다음:
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
npm install
|
|
62
|
+
~/Library/Application Support/Claude/claude_desktop_config.json
|
|
85
63
|
```
|
|
86
64
|
|
|
87
|
-
|
|
65
|
+
**Windows:**
|
|
88
66
|
|
|
89
|
-
|
|
67
|
+
```
|
|
68
|
+
%APPDATA%\Claude\claude_desktop_config.json
|
|
69
|
+
```
|
|
90
70
|
|
|
91
|
-
|
|
92
|
-
`%APPDATA%\Claude\claude_desktop_config.json` (Windows) 파일에 추가:
|
|
71
|
+
설정 예시:
|
|
93
72
|
|
|
94
73
|
```json
|
|
95
74
|
{
|
|
96
75
|
"mcpServers": {
|
|
97
76
|
"api-mcp": {
|
|
98
|
-
"command": "
|
|
99
|
-
"args": ["
|
|
77
|
+
"command": "npx",
|
|
78
|
+
"args": ["-y", "@koseha/api-mcp"]
|
|
100
79
|
}
|
|
101
80
|
}
|
|
102
81
|
}
|
|
103
82
|
```
|
|
104
83
|
|
|
105
|
-
또는
|
|
84
|
+
또는 로컬 경로 사용:
|
|
106
85
|
|
|
107
86
|
```json
|
|
108
87
|
{
|
|
109
88
|
"mcpServers": {
|
|
110
89
|
"api-mcp": {
|
|
111
|
-
"command": "
|
|
112
|
-
"args": ["
|
|
90
|
+
"command": "node",
|
|
91
|
+
"args": ["/path/to/api-mcp/dist/index.js"]
|
|
113
92
|
}
|
|
114
93
|
}
|
|
115
94
|
}
|
|
116
95
|
```
|
|
117
96
|
|
|
118
|
-
### 방법
|
|
119
|
-
|
|
120
|
-
다른 Node.js 프로젝트에서:
|
|
97
|
+
### 방법 3: Node.js 프로젝트에서 직접 사용
|
|
121
98
|
|
|
122
99
|
```javascript
|
|
123
|
-
|
|
124
|
-
import { spawn } from 'child_process';
|
|
125
|
-
import { fileURLToPath } from 'url';
|
|
126
|
-
import { dirname, join } from 'path';
|
|
127
|
-
|
|
128
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
129
|
-
const __dirname = dirname(__filename);
|
|
130
|
-
|
|
131
|
-
// MCP 서버 경로 (상대 또는 절대 경로)
|
|
132
|
-
const serverPath = join(__dirname, '../api-mcp/dist/index.js');
|
|
100
|
+
import { spawn } from "child_process";
|
|
133
101
|
|
|
134
|
-
const mcpServer = spawn(
|
|
135
|
-
stdio: [
|
|
102
|
+
const mcpServer = spawn("npx", ["-y", "@koseha/api-mcp"], {
|
|
103
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
136
104
|
});
|
|
137
105
|
|
|
138
106
|
// JSON-RPC 요청 보내기
|
|
139
107
|
function sendRequest(method, params) {
|
|
140
108
|
const request = {
|
|
141
|
-
jsonrpc:
|
|
109
|
+
jsonrpc: "2.0",
|
|
142
110
|
id: Date.now(),
|
|
143
111
|
method,
|
|
144
|
-
params: params || {}
|
|
112
|
+
params: params || {},
|
|
145
113
|
};
|
|
146
|
-
mcpServer.stdin?.write(JSON.stringify(request) +
|
|
114
|
+
mcpServer.stdin?.write(JSON.stringify(request) + "\n");
|
|
147
115
|
}
|
|
148
116
|
|
|
149
|
-
//
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const lines = buffer.split('\n');
|
|
154
|
-
buffer = lines.pop() || '';
|
|
155
|
-
|
|
156
|
-
for (const line of lines) {
|
|
157
|
-
if (line.trim()) {
|
|
158
|
-
try {
|
|
159
|
-
const response = JSON.parse(line);
|
|
160
|
-
console.log('응답:', response);
|
|
161
|
-
} catch (e) {
|
|
162
|
-
// 파싱 오류 무시
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
117
|
+
// API 목록 조회
|
|
118
|
+
sendRequest("tools/call", {
|
|
119
|
+
name: "getApiList",
|
|
120
|
+
arguments: {},
|
|
166
121
|
});
|
|
167
122
|
|
|
168
|
-
//
|
|
169
|
-
sendRequest(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
123
|
+
// API 상세 조회
|
|
124
|
+
sendRequest("tools/call", {
|
|
125
|
+
name: "getApiDetail",
|
|
126
|
+
arguments: {
|
|
127
|
+
requestUrl: "/pet/{petId}/uploadImage",
|
|
128
|
+
httpMethod: "post",
|
|
174
129
|
},
|
|
175
|
-
clientInfo: {
|
|
176
|
-
name: 'my-client',
|
|
177
|
-
version: '1.0.0'
|
|
178
|
-
}
|
|
179
130
|
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 방법 4: 로컬 개발 중 사용
|
|
134
|
+
|
|
135
|
+
#### npm link 사용
|
|
136
|
+
|
|
137
|
+
현재 프로젝트에서:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
npm link
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
다른 프로젝트에서:
|
|
180
144
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
145
|
+
```bash
|
|
146
|
+
npm link @koseha/api-mcp
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### 상대 경로 사용
|
|
150
|
+
|
|
151
|
+
다른 프로젝트의 `package.json`에 추가:
|
|
152
|
+
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"dependencies": {
|
|
156
|
+
"@koseha/api-mcp": "file:../api-mcp"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
188
159
|
```
|
|
189
160
|
|
|
190
161
|
## 개발
|
|
191
162
|
|
|
163
|
+
### 사전 요구사항
|
|
164
|
+
|
|
165
|
+
- Node.js 18 이상
|
|
166
|
+
- npm 또는 yarn
|
|
167
|
+
|
|
168
|
+
### 설치
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
npm install
|
|
172
|
+
```
|
|
173
|
+
|
|
192
174
|
### 빌드
|
|
193
175
|
|
|
194
176
|
```bash
|
|
@@ -201,10 +183,10 @@ npm run build
|
|
|
201
183
|
npm start
|
|
202
184
|
```
|
|
203
185
|
|
|
204
|
-
|
|
186
|
+
또는 개발 모드:
|
|
205
187
|
|
|
206
188
|
```bash
|
|
207
|
-
|
|
189
|
+
npm run dev
|
|
208
190
|
```
|
|
209
191
|
|
|
210
192
|
## 프로젝트 구조
|
|
@@ -212,24 +194,61 @@ node test-client.js
|
|
|
212
194
|
```
|
|
213
195
|
api-mcp/
|
|
214
196
|
├── src/
|
|
215
|
-
│ ├── index.ts
|
|
216
|
-
│
|
|
217
|
-
│
|
|
218
|
-
├──
|
|
219
|
-
│
|
|
197
|
+
│ ├── index.ts # MCP 서버 엔트리포인트
|
|
198
|
+
│ ├── server.ts # 서버 생성 로직
|
|
199
|
+
│ ├── tools/ # 도구 모듈
|
|
200
|
+
│ │ ├── index.ts
|
|
201
|
+
│ │ ├── getApiList.tool.ts # API 목록 조회 도구
|
|
202
|
+
│ │ └── getApiDetail.tool.ts # API 상세 조회 도구
|
|
203
|
+
│ ├── resources/ # 리소스 모듈
|
|
204
|
+
│ │ ├── index.ts
|
|
205
|
+
│ │ └── greeting.resource.ts
|
|
206
|
+
│ └── swagger/ # Swagger 로더
|
|
207
|
+
│ └── swaggerLoader.ts
|
|
208
|
+
├── dist/ # 빌드된 파일
|
|
209
|
+
├── openapi.json # OpenAPI 스펙 파일
|
|
220
210
|
├── package.json
|
|
211
|
+
├── tsconfig.json
|
|
221
212
|
└── README.md
|
|
222
213
|
```
|
|
223
214
|
|
|
215
|
+
## OpenAPI 스펙 파일
|
|
216
|
+
|
|
217
|
+
프로젝트 루트의 `openapi.json` 파일을 수정하여 사용할 API 스펙을 설정할 수 있습니다. 기본적으로 5분간 캐시되며, 파일 변경 시 자동으로 다시 로드됩니다.
|
|
218
|
+
|
|
224
219
|
## 의존성
|
|
225
220
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
-
|
|
221
|
+
### 프로덕션 의존성
|
|
222
|
+
|
|
223
|
+
- `@modelcontextprotocol/sdk`: MCP SDK (^1.25.1)
|
|
224
|
+
- `zod`: 스키마 검증 (^4.2.1)
|
|
225
|
+
|
|
226
|
+
### 개발 의존성
|
|
227
|
+
|
|
228
|
+
- `typescript`: 타입스크립트 컴파일러 (^5.9.3)
|
|
229
|
+
- `@types/node`: Node.js 타입 정의 (^25.0.3)
|
|
230
|
+
- `ts-node`: TypeScript 실행 도구 (^10.9.2)
|
|
231
|
+
|
|
232
|
+
## 버전
|
|
233
|
+
|
|
234
|
+
현재 버전: **0.0.7**
|
|
235
|
+
|
|
236
|
+
## History
|
|
237
|
+
|
|
238
|
+
| 버전 | 날짜 | 변경사항 |
|
|
239
|
+
| ----- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
240
|
+
| 0.0.7 | KST 2025.12.31 | - tool 요청 시 openapi.json 문서의 특정 부분만 추출하여 사용하도록 변경 <br/> >> 전체 openapi.json 문서 내용이 사용되지 않도록 함. token 절약 |
|
|
241
|
+
|
|
242
|
+
## 라이선스
|
|
243
|
+
|
|
244
|
+
ISC
|
|
229
245
|
|
|
230
246
|
## 참고 자료
|
|
231
247
|
|
|
232
248
|
- [MCP 공식 문서](https://modelcontextprotocol.io)
|
|
233
249
|
- [MCP SDK GitHub](https://github.com/modelcontextprotocol/typescript-sdk)
|
|
250
|
+
- [OpenAPI 스펙](https://swagger.io/specification/)
|
|
234
251
|
|
|
252
|
+
## 기여
|
|
235
253
|
|
|
254
|
+
이슈나 풀 리퀘스트는 [GitHub 저장소](https://github.com/koseha/api-mcp)에서 환영합니다.
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* openapi.json
|
|
2
|
+
* openapi.json HTTP 요청으로 읽기 + TTL 캐시
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
import { join, dirname } from "path";
|
|
6
|
-
import { fileURLToPath } from "url";
|
|
7
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
-
const __dirname = dirname(__filename);
|
|
4
|
+
const DEFAULT_OPENAPI_URL = "https://petstore3.swagger.io/api/v3/openapi.json";
|
|
9
5
|
let cache = null;
|
|
10
6
|
let cachedAt = 0;
|
|
11
7
|
const TTL = 5 * 60 * 1000; // 5분
|
|
@@ -13,9 +9,23 @@ export async function loadSwagger() {
|
|
|
13
9
|
if (cache && Date.now() - cachedAt < TTL) {
|
|
14
10
|
return cache;
|
|
15
11
|
}
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
const openapiUrl = process.env.OPENAPI_URL ||
|
|
13
|
+
process.env.OPENAPI_JSON_URL ||
|
|
14
|
+
DEFAULT_OPENAPI_URL;
|
|
15
|
+
try {
|
|
16
|
+
const response = await fetch(openapiUrl);
|
|
17
|
+
if (!response.ok) {
|
|
18
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText} - ${openapiUrl}`);
|
|
19
|
+
}
|
|
20
|
+
const fileContent = await response.text();
|
|
21
|
+
cache = JSON.parse(fileContent);
|
|
22
|
+
cachedAt = Date.now();
|
|
23
|
+
return cache;
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (error instanceof Error) {
|
|
27
|
+
throw new Error(`OpenAPI 문서를 불러오는 중 오류 발생: ${error.message}`);
|
|
28
|
+
}
|
|
29
|
+
throw error;
|
|
30
|
+
}
|
|
21
31
|
}
|