@sgrsoft/page24-mcp-server 0.1.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.
@@ -0,0 +1,13 @@
1
+ export interface ApiResponse<T = any> {
2
+ code: number;
3
+ message: string | null;
4
+ result: T;
5
+ }
6
+ export declare class Page24ApiClient {
7
+ private client;
8
+ private siteId;
9
+ constructor(apiUrl: string, apiKey: string, siteId: string);
10
+ get<T = any>(path: string, params?: Record<string, any>): Promise<ApiResponse<T>>;
11
+ post<T = any>(path: string, data?: Record<string, any>): Promise<ApiResponse<T>>;
12
+ getSiteId(): string;
13
+ }
@@ -0,0 +1,32 @@
1
+ import axios from "axios";
2
+ export class Page24ApiClient {
3
+ client;
4
+ siteId;
5
+ constructor(apiUrl, apiKey, siteId) {
6
+ this.siteId = siteId;
7
+ this.client = axios.create({
8
+ baseURL: apiUrl,
9
+ headers: {
10
+ "x-p24-api-key": apiKey,
11
+ "Content-Type": "application/json",
12
+ },
13
+ timeout: 30000,
14
+ });
15
+ }
16
+ async get(path, params = {}) {
17
+ const res = await this.client.get(path, {
18
+ params: { siteId: this.siteId, ...params },
19
+ });
20
+ return res.data;
21
+ }
22
+ async post(path, data = {}) {
23
+ const res = await this.client.post(path, {
24
+ siteId: this.siteId,
25
+ ...data,
26
+ });
27
+ return res.data;
28
+ }
29
+ getSiteId() {
30
+ return this.siteId;
31
+ }
32
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { createServer } from "./server.js";
4
+ const server = createServer();
5
+ const transport = new StdioServerTransport();
6
+ await server.connect(transport);
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function createServer(): McpServer;
package/dist/server.js ADDED
@@ -0,0 +1,27 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { Page24ApiClient } from "./api-client.js";
3
+ import { registerPostTools } from "./tools/posts.js";
4
+ import { registerMenuTools } from "./tools/menus.js";
5
+ import { registerSiteTools } from "./tools/site.js";
6
+ import { registerMemberTools } from "./tools/members.js";
7
+ import { registerFormTools } from "./tools/forms.js";
8
+ export function createServer() {
9
+ const apiUrl = process.env.PAGE24_API_URL;
10
+ const apiKey = process.env.PAGE24_API_KEY;
11
+ const siteId = process.env.PAGE24_SITE_ID;
12
+ if (!apiUrl || !apiKey || !siteId) {
13
+ console.error("환경변수가 설정되지 않았습니다: PAGE24_API_URL, PAGE24_API_KEY, PAGE24_SITE_ID");
14
+ process.exit(1);
15
+ }
16
+ const api = new Page24ApiClient(apiUrl, apiKey, siteId);
17
+ const server = new McpServer({
18
+ name: "page24",
19
+ version: "0.1.0",
20
+ });
21
+ registerMenuTools(server, api);
22
+ registerPostTools(server, api);
23
+ registerSiteTools(server, api);
24
+ registerMemberTools(server, api);
25
+ registerFormTools(server, api);
26
+ return server;
27
+ }
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { Page24ApiClient } from "../api-client.js";
3
+ export declare function registerFormTools(server: McpServer, api: Page24ApiClient): void;
@@ -0,0 +1,14 @@
1
+ import { z } from "zod";
2
+ export function registerFormTools(server, api) {
3
+ server.tool("list_form_submissions", "폼(문의/신청) 응답 목록을 조회합니다.", {
4
+ mcode: z.string().describe("폼이 속한 메뉴 코드"),
5
+ pageNo: z.number().optional().default(1).describe("페이지 번호"),
6
+ limit: z.number().optional().default(20).describe("페이지당 개수"),
7
+ }, async ({ mcode, pageNo, limit }) => {
8
+ const res = await api.get("/form/list", { mcode, pageNo, limit });
9
+ if (res.code !== 200) {
10
+ return { content: [{ type: "text", text: `오류: ${res.message}` }] };
11
+ }
12
+ return { content: [{ type: "text", text: JSON.stringify(res.result, null, 2) }] };
13
+ });
14
+ }
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { Page24ApiClient } from "../api-client.js";
3
+ export declare function registerMemberTools(server: McpServer, api: Page24ApiClient): void;
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+ export function registerMemberTools(server, api) {
3
+ server.tool("list_members", "사이트 회원 목록을 조회합니다.", {
4
+ pageNo: z.number().optional().default(1).describe("페이지 번호"),
5
+ limit: z.number().optional().default(20).describe("페이지당 개수"),
6
+ keyword: z.string().optional().describe("검색어 (닉네임, 아이디)"),
7
+ }, async ({ pageNo, limit, keyword }) => {
8
+ const res = await api.get("/member/memberManageList", {
9
+ pageNo,
10
+ limit,
11
+ keyword: keyword || "",
12
+ });
13
+ if (res.code !== 200) {
14
+ return { content: [{ type: "text", text: `오류: ${res.message}` }] };
15
+ }
16
+ return { content: [{ type: "text", text: JSON.stringify(res.result, null, 2) }] };
17
+ });
18
+ }
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { Page24ApiClient } from "../api-client.js";
3
+ export declare function registerMenuTools(server: McpServer, api: Page24ApiClient): void;
@@ -0,0 +1,19 @@
1
+ export function registerMenuTools(server, api) {
2
+ server.tool("list_menus", "사이트의 메뉴(페이지) 목록을 조회합니다. 각 메뉴의 mcode를 확인할 수 있습니다.", {}, async () => {
3
+ const res = await api.get("/menu/listAll");
4
+ if (res.code !== 200) {
5
+ return { content: [{ type: "text", text: `오류: ${res.message}` }] };
6
+ }
7
+ const menus = res.result;
8
+ const summary = Array.isArray(menus)
9
+ ? menus.map((m) => ({
10
+ mcode: m.mcode,
11
+ title: m.title,
12
+ type: m.type,
13
+ state: m.state,
14
+ scode: m.scode,
15
+ }))
16
+ : menus;
17
+ return { content: [{ type: "text", text: JSON.stringify(summary, null, 2) }] };
18
+ });
19
+ }
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { Page24ApiClient } from "../api-client.js";
3
+ export declare function registerPostTools(server: McpServer, api: Page24ApiClient): void;
@@ -0,0 +1,72 @@
1
+ import { z } from "zod";
2
+ export function registerPostTools(server, api) {
3
+ server.tool("list_posts", "게시글 목록을 조회합니다. mcode(메뉴코드)가 필요합니다. list_menus로 먼저 메뉴 목록을 확인하세요.", {
4
+ mcode: z.string().describe("메뉴 코드 (list_menus로 확인)"),
5
+ pageNo: z.number().optional().default(1).describe("페이지 번호"),
6
+ limit: z.number().optional().default(10).describe("페이지당 개수"),
7
+ keyword: z.string().optional().describe("검색어"),
8
+ }, async ({ mcode, pageNo, limit, keyword }) => {
9
+ const res = await api.get("/board/List", {
10
+ mcode,
11
+ pageNo,
12
+ limit,
13
+ keyword: keyword || "",
14
+ });
15
+ if (res.code !== 200) {
16
+ return { content: [{ type: "text", text: `오류: ${res.message}` }] };
17
+ }
18
+ return { content: [{ type: "text", text: JSON.stringify(res.result, null, 2) }] };
19
+ });
20
+ server.tool("get_post", "게시글 상세 내용을 조회합니다.", {
21
+ mcode: z.string().describe("메뉴 코드"),
22
+ board_id: z.number().describe("게시글 번호"),
23
+ }, async ({ mcode, board_id }) => {
24
+ const res = await api.get("/board/read", { mcode, board_id });
25
+ if (res.code !== 200) {
26
+ return { content: [{ type: "text", text: `오류: ${res.message}` }] };
27
+ }
28
+ return { content: [{ type: "text", text: JSON.stringify(res.result, null, 2) }] };
29
+ });
30
+ server.tool("create_post", "새 게시글을 작성합니다. (readwrite 권한 필요)", {
31
+ mcode: z.string().describe("메뉴 코드"),
32
+ title: z.string().describe("게시글 제목"),
33
+ content: z.string().describe("게시글 내용 (HTML)"),
34
+ category: z.string().optional().describe("카테고리"),
35
+ }, async ({ mcode, title, content, category }) => {
36
+ const data = { mcode, title, content };
37
+ if (category)
38
+ data.category = category;
39
+ const res = await api.post("/board/write", data);
40
+ if (res.code !== 200) {
41
+ return { content: [{ type: "text", text: `오류: ${res.message}` }] };
42
+ }
43
+ return { content: [{ type: "text", text: `게시글 작성 완료: ${JSON.stringify(res.result)}` }] };
44
+ });
45
+ server.tool("update_post", "기존 게시글을 수정합니다. (readwrite 권한 필요)", {
46
+ mcode: z.string().describe("메뉴 코드"),
47
+ board_id: z.number().describe("게시글 번호"),
48
+ title: z.string().optional().describe("수정할 제목"),
49
+ content: z.string().optional().describe("수정할 내용 (HTML)"),
50
+ }, async ({ mcode, board_id, title, content }) => {
51
+ const data = { mcode, board_id };
52
+ if (title)
53
+ data.title = title;
54
+ if (content)
55
+ data.content = content;
56
+ const res = await api.post("/board/update", data);
57
+ if (res.code !== 200) {
58
+ return { content: [{ type: "text", text: `오류: ${res.message}` }] };
59
+ }
60
+ return { content: [{ type: "text", text: `게시글 수정 완료: ${JSON.stringify(res.result)}` }] };
61
+ });
62
+ server.tool("delete_post", "게시글을 삭제합니다. (readwrite 권한 필요)", {
63
+ mcode: z.string().describe("메뉴 코드"),
64
+ board_id: z.number().describe("게시글 번호"),
65
+ }, async ({ mcode, board_id }) => {
66
+ const res = await api.post("/board/delete", { mcode, board_id });
67
+ if (res.code !== 200) {
68
+ return { content: [{ type: "text", text: `오류: ${res.message}` }] };
69
+ }
70
+ return { content: [{ type: "text", text: `게시글 삭제 완료` }] };
71
+ });
72
+ }
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { Page24ApiClient } from "../api-client.js";
3
+ export declare function registerSiteTools(server: McpServer, api: Page24ApiClient): void;
@@ -0,0 +1,11 @@
1
+ export function registerSiteTools(server, api) {
2
+ server.tool("get_site_config", "사이트 설정 정보를 조회합니다.", {}, async () => {
3
+ const res = await api.get("/siteConfig/info", {
4
+ hostid: api.getSiteId(),
5
+ });
6
+ if (res.code !== 200) {
7
+ return { content: [{ type: "text", text: `오류: ${res.message}` }] };
8
+ }
9
+ return { content: [{ type: "text", text: JSON.stringify(res.result, null, 2) }] };
10
+ });
11
+ }
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@sgrsoft/page24-mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for page24 CMS",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "page24-mcp": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsx src/index.ts",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "dependencies": {
16
+ "@modelcontextprotocol/sdk": "^1.12.1",
17
+ "axios": "^1.7.9",
18
+ "zod": "^3.24.0"
19
+ },
20
+ "devDependencies": {
21
+ "typescript": "^5.7.0",
22
+ "tsx": "^4.19.0",
23
+ "@types/node": "^22.0.0"
24
+ },
25
+ "files": ["dist"],
26
+ "license": "MIT"
27
+ }