@koseha/api-mcp 0.0.0 → 0.0.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/dist/index.js +18 -21
- package/dist/resources/greeting.resource.js +9 -0
- package/dist/resources/index.js +7 -0
- package/dist/server.js +10 -0
- package/dist/swagger/swaggerLoader.js +21 -0
- package/dist/tools/add.tool.js +10 -0
- package/dist/tools/getApiList.tool.js +16 -0
- package/dist/tools/index.js +9 -0
- package/openapi.json +63 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,23 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* MCP 서버 엔트리포인트
|
|
3
|
+
*/
|
|
2
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import { createServer } from "./server.js";
|
|
6
|
+
import { registerTools } from "./tools/index.js";
|
|
7
|
+
import { registerResources } from "./resources/index.js";
|
|
8
|
+
async function main() {
|
|
9
|
+
const server = createServer();
|
|
10
|
+
registerTools(server);
|
|
11
|
+
registerResources(server);
|
|
12
|
+
const transport = new StdioServerTransport();
|
|
13
|
+
await server.connect(transport);
|
|
14
|
+
// 👇 이 줄이 핵심
|
|
15
|
+
process.stdin.resume();
|
|
16
|
+
}
|
|
17
|
+
main().catch((err) => {
|
|
18
|
+
process.stderr.write(err.stack + "\n");
|
|
19
|
+
process.exit(1);
|
|
7
20
|
});
|
|
8
|
-
server.registerTool("add", {
|
|
9
|
-
title: "Addition Tool",
|
|
10
|
-
description: "Add two numbers",
|
|
11
|
-
inputSchema: { a: z.number(), b: z.number() },
|
|
12
|
-
}, async ({ a, b }) => ({
|
|
13
|
-
content: [{ type: "text", text: String(a + b) }],
|
|
14
|
-
}));
|
|
15
|
-
server.registerResource("greeting", new ResourceTemplate("greeting://{name}", { list: undefined }), {
|
|
16
|
-
title: "Greeting Resource",
|
|
17
|
-
description: "Dynamic greeting generator",
|
|
18
|
-
}, async (uri, { name }) => ({
|
|
19
|
-
contents: [{ uri: uri.href, text: `Hello, ${name}!` }],
|
|
20
|
-
}));
|
|
21
|
-
const transport = new StdioServerTransport();
|
|
22
|
-
await server.connect(transport);
|
|
23
|
-
console.log("MCP server is running via stdio.");
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
export function registerGreetingResource(server) {
|
|
3
|
+
server.registerResource("greeting", new ResourceTemplate("greeting://{name}", { list: undefined }), {
|
|
4
|
+
title: "Greeting Resource",
|
|
5
|
+
description: "Dynamic greeting generator",
|
|
6
|
+
}, async (uri, { name }) => ({
|
|
7
|
+
contents: [{ uri: uri.href, text: `Hello, ${name}!` }],
|
|
8
|
+
}));
|
|
9
|
+
}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* openapi.json 파일 읽기 + TTL 캐시
|
|
3
|
+
*/
|
|
4
|
+
import { readFile } from "fs/promises";
|
|
5
|
+
import { join, dirname } from "path";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
let cache = null;
|
|
10
|
+
let cachedAt = 0;
|
|
11
|
+
const TTL = 5 * 60 * 1000;
|
|
12
|
+
export async function loadSwagger() {
|
|
13
|
+
if (cache && Date.now() - cachedAt < TTL) {
|
|
14
|
+
return cache;
|
|
15
|
+
}
|
|
16
|
+
const openapiPath = join(__dirname, "../../openapi.json");
|
|
17
|
+
const fileContent = await readFile(openapiPath, "utf-8");
|
|
18
|
+
cache = JSON.parse(fileContent);
|
|
19
|
+
cachedAt = Date.now();
|
|
20
|
+
return cache;
|
|
21
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerAddTool(server) {
|
|
3
|
+
server.registerTool("add", {
|
|
4
|
+
title: "Addition Tool",
|
|
5
|
+
description: "Add two numbers",
|
|
6
|
+
inputSchema: { a: z.number(), b: z.number() },
|
|
7
|
+
}, async ({ a, b }) => ({
|
|
8
|
+
content: [{ type: "text", text: String(a + b) }],
|
|
9
|
+
}));
|
|
10
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: API 목록 조회
|
|
3
|
+
*/
|
|
4
|
+
import { loadSwagger } from "../swagger/swaggerLoader.js";
|
|
5
|
+
export function registerGetApiList(server) {
|
|
6
|
+
server.registerTool("getApiList", {
|
|
7
|
+
title: "API 목록 조회",
|
|
8
|
+
description: "API 목록을 조회합니다.",
|
|
9
|
+
}, async () => {
|
|
10
|
+
const swagger = await loadSwagger();
|
|
11
|
+
// paths → list 가공
|
|
12
|
+
return {
|
|
13
|
+
content: [{ type: "text", text: JSON.stringify(swagger.paths) }],
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
}
|
package/openapi.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"openapi": "3.0.3",
|
|
3
|
+
"info": {
|
|
4
|
+
"title": "Swagger Petstore - OpenAPI 3.0",
|
|
5
|
+
"version": "1.0.11"
|
|
6
|
+
},
|
|
7
|
+
"servers": [
|
|
8
|
+
{
|
|
9
|
+
"url": "https://petstore3.swagger.io/api/v3"
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"tags": [
|
|
13
|
+
{
|
|
14
|
+
"name": "pet",
|
|
15
|
+
"description": "당신의 애완동물에 대한 모든 것"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"paths": {
|
|
19
|
+
"/pet/{petId}/uploadImage": {
|
|
20
|
+
"post": {
|
|
21
|
+
"tags": ["pet"],
|
|
22
|
+
"summary": "이미지를 업로드합니다.",
|
|
23
|
+
"operationId": "uploadFile",
|
|
24
|
+
"parameters": [
|
|
25
|
+
{
|
|
26
|
+
"name": "petId",
|
|
27
|
+
"in": "path",
|
|
28
|
+
"description": "업데이트할 애완동물 ID",
|
|
29
|
+
"required": true,
|
|
30
|
+
"schema": {
|
|
31
|
+
"type": "integer",
|
|
32
|
+
"format": "int64"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "additionalMetadata",
|
|
37
|
+
"in": "query",
|
|
38
|
+
"description": "추가 메타데이터",
|
|
39
|
+
"required": false,
|
|
40
|
+
"schema": {
|
|
41
|
+
"type": "string"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"requestBody": {
|
|
46
|
+
"content": {
|
|
47
|
+
"application/octet-stream": {
|
|
48
|
+
"schema": {
|
|
49
|
+
"type": "string",
|
|
50
|
+
"format": "binary"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"responses": {
|
|
56
|
+
"200": {
|
|
57
|
+
"description": "성공적인 작업"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|