@roottale/cms-mcp 0.34.1 → 0.35.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/CHANGELOG.md +15 -0
- package/dist/index.js +1 -1
- package/docs/api-reference.md +19 -0
- package/docs/custom-redirects.md +83 -0
- package/examples/nextjs/middleware.ts +23 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @roottale/cms-mcp
|
|
2
2
|
|
|
3
|
+
## 0.35.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- cfddfc7: 커스텀 리다이렉트 (WP RankMath Redirections 패리티) — 운영자가 어드민 "설정 >
|
|
8
|
+
주소 이동"에서 글이 아닌 임의 경로 이동 규칙(`/old-event → /promo`, 301/302)을
|
|
9
|
+
정의하고, 사이트 미들웨어가 적용한다.
|
|
10
|
+
- `@roottale/cms-client`: `fetchRedirects()` 추가 — `GET /v1/cms/public/redirects`
|
|
11
|
+
의 활성 규칙 목록을 가져온다(404 → 빈 배열 fail-soft).
|
|
12
|
+
- `@roottale/cms-renderer-next`: `createRedirectMiddleware()` 추가(+ 순수 함수
|
|
13
|
+
`matchRedirect`/`normalizeRedirectPath`), `/routes` 서브패스로 노출. 규칙을
|
|
14
|
+
TTL 캐시하고 API 실패 시 트래픽을 막지 않는다.
|
|
15
|
+
- `@roottale/cms-mcp`: `custom-redirects.md` 연동 가이드 + api-reference 의
|
|
16
|
+
`/redirects` 항목 + nextjs `middleware.ts` 예시.
|
|
17
|
+
|
|
3
18
|
## 0.34.1
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -279,7 +279,7 @@ function registerTools(server2) {
|
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
// src/server.ts
|
|
282
|
-
var VERSION = true ? "0.
|
|
282
|
+
var VERSION = true ? "0.35.0" : "dev";
|
|
283
283
|
var SERVER_INSTRUCTIONS = `
|
|
284
284
|
roottale-cms-mcp\uB294 RootTale CMS\uB97C \uC678\uBD80 \uC0AC\uC774\uD2B8(\uC8FC\uB85C Next.js)\uC5D0 \uC5F0\uB3D9\uD558\uAE30 \uC704\uD55C
|
|
285
285
|
\uD1B5\uD569 \uBB38\uC11C\xB7\uC608\uC2DC \uCF54\uB4DC\xB7\uACF5\uAC1C API \uC870\uD68C tool\uC744 \uC81C\uACF5\uD569\uB2C8\uB2E4.
|
package/docs/api-reference.md
CHANGED
|
@@ -83,6 +83,25 @@ JS/TS 는 `@roottale/cms-client/server` 의 `searchPosts({ apiKey, query })` 를
|
|
|
83
83
|
위치 핸들(`primary`, `footer` 등)로 메뉴 1개. 없으면 `404` — 사이트는 자체
|
|
84
84
|
fallback 네비를 렌더하세요 (`menus.md` 참고).
|
|
85
85
|
|
|
86
|
+
## GET /v1/cms/public/redirects
|
|
87
|
+
|
|
88
|
+
어드민 "설정 > 주소 이동"에서 정의한 **활성** 커스텀 리다이렉트 규칙 전체.
|
|
89
|
+
사이트 미들웨어가 요청 경로를 매칭해 301/302 처리합니다. 비활성 규칙과 운영자
|
|
90
|
+
메모는 응답에 포함되지 않습니다. 라우트 미배포(구 서버)는 `404` — 빈 목록으로
|
|
91
|
+
처리하세요. 연동은 `custom-redirects.md` 참고.
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
{ "tenant_id": "…", "site_id": "…",
|
|
95
|
+
"items": [ { "id": "…", "from_path": "/old-event",
|
|
96
|
+
"to_target": "/promo", "status_code": 301 } ] }
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
| 필드 | 설명 |
|
|
100
|
+
|---|---|
|
|
101
|
+
| `from_path` | 출발 경로 — 정규화된 사이트 내부 절대 경로(앞 슬래시, 쿼리 제외). |
|
|
102
|
+
| `to_target` | 도착지 — 내부 경로(`/promo`) 또는 절대 URL(`https://…`). |
|
|
103
|
+
| `status_code` | `301`(영구) 또는 `302`(임시). |
|
|
104
|
+
|
|
86
105
|
## GET /v1/cms/public/theme
|
|
87
106
|
|
|
88
107
|
어드민에서 설정한 디자인 토큰. 설정된 그룹만 포함됩니다.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 주소 이동 (커스텀 리다이렉트) 연동
|
|
3
|
+
description: 어드민 "설정 > 주소 이동"에서 정의한 임의 경로 리다이렉트를 사이트 미들웨어로 적용
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 주소 이동 (커스텀 리다이렉트) 연동
|
|
7
|
+
|
|
8
|
+
어드민(mysite.roottale.com)의 **설정 > 주소 이동**에서 운영자가 정의한 임의
|
|
9
|
+
경로 이동 규칙(`/old-event → /promo`)을 사이트 미들웨어로 적용합니다. 코드
|
|
10
|
+
수정 없이 고객이 직접 규칙을 추가·수정·삭제할 수 있습니다.
|
|
11
|
+
|
|
12
|
+
두 종류의 주소 이동이 있습니다.
|
|
13
|
+
|
|
14
|
+
- **글 주소 변경 자동 301** — 블로그 글의 슬러그를 바꾸면 자동으로 옛 주소가
|
|
15
|
+
새 주소로 이어집니다. 글 라우트에서 처리되며 별도 설정이 필요 없습니다
|
|
16
|
+
(`blog.md` 의 `postRedirectPath` 참고).
|
|
17
|
+
- **커스텀 리다이렉트(이 문서)** — 글이 아닌 임의 경로를 옮깁니다. 라우팅
|
|
18
|
+
*이전* 단계인 **미들웨어**에서만 가로챌 수 있어, 아래 설정이 필요합니다.
|
|
19
|
+
|
|
20
|
+
규칙은 `GET /v1/cms/public/redirects` 로 내려오며 **활성** 규칙만 포함됩니다
|
|
21
|
+
(`api-reference.md`). 출발 경로는 정규화된 사이트 내부 절대 경로, 도착지는
|
|
22
|
+
내부 경로 또는 절대 URL, 상태는 `301`(영구) 또는 `302`(임시)입니다.
|
|
23
|
+
|
|
24
|
+
## 미들웨어 설정
|
|
25
|
+
|
|
26
|
+
`@roottale/cms-renderer-next` 의 `createRedirectMiddleware` 를 프로젝트 루트
|
|
27
|
+
`middleware.ts` 에 마운트합니다. 규칙을 자동 캐시(기본 60초)하며, API 실패 시
|
|
28
|
+
트래픽을 막지 않고 통과시킵니다(fail-soft).
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
// middleware.ts
|
|
32
|
+
import { NextResponse } from "next/server";
|
|
33
|
+
import { createRedirectMiddleware } from "@roottale/cms-renderer-next/routes";
|
|
34
|
+
|
|
35
|
+
const redirects = createRedirectMiddleware({
|
|
36
|
+
apiKey: process.env.ROOTTALE_API_KEY!,
|
|
37
|
+
// apiBase, siteId, cacheTtlMs 는 선택.
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export async function middleware(req: Request) {
|
|
41
|
+
return (await redirects(req)) ?? NextResponse.next();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Next 내부·API·알려진 정적 자산만 제외합니다. 점 포함 경로를 전부 막으면
|
|
45
|
+
// `/old.html`·`/foo.php` 같은 레거시 마이그레이션 리다이렉트가 동작하지
|
|
46
|
+
// 않으므로, 자산 확장자만 명시적으로 제외합니다.
|
|
47
|
+
export const config = {
|
|
48
|
+
matcher: [
|
|
49
|
+
"/((?!_next/|api/|.*\\.(?:ico|png|jpg|jpeg|gif|svg|webp|css|js|txt|xml|json|woff2?|map)$).*)",
|
|
50
|
+
],
|
|
51
|
+
};
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- `ROOTTALE_API_KEY` 는 블로그 조회와 **같은** 키입니다. 서버 전용 — 절대
|
|
55
|
+
브라우저에 노출하지 마세요.
|
|
56
|
+
- 매칭은 **정확 경로 일치**입니다(와일드카드 없음). 출발 경로의 앞/뒤 슬래시와
|
|
57
|
+
한글 percent-encoding 차이는 자동 정규화해 비교합니다.
|
|
58
|
+
- 도착지가 내부 경로면 요청 origin 기준 절대 URL 로 변환해 리다이렉트합니다.
|
|
59
|
+
- 매칭이 없으면 `null` 을 반환하므로 `NextResponse.next()` 로 통과시키세요.
|
|
60
|
+
|
|
61
|
+
## 캐시와 즉시성
|
|
62
|
+
|
|
63
|
+
규칙은 미들웨어가 TTL(기본 60초) 동안 캐시합니다. 운영자가 규칙을 바꾸면
|
|
64
|
+
최대 TTL 만큼 뒤 반영됩니다. 더 빠른 반영이 필요하면 `cacheTtlMs` 를 줄이세요
|
|
65
|
+
(요청당 API 호출이 늘어납니다).
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
const redirects = createRedirectMiddleware({
|
|
69
|
+
apiKey: process.env.ROOTTALE_API_KEY!,
|
|
70
|
+
cacheTtlMs: 10_000, // 10초
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## 직접 호출 (미들웨어 없이)
|
|
75
|
+
|
|
76
|
+
규칙 목록만 필요하면 `fetchRedirects` 로 직접 가져올 수 있습니다.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { fetchRedirects } from "@roottale/cms-client/server";
|
|
80
|
+
|
|
81
|
+
const rules = await fetchRedirects({ apiKey: process.env.ROOTTALE_API_KEY! });
|
|
82
|
+
// [{ id, fromPath, toTarget, statusCode }]
|
|
83
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// middleware.ts — 커스텀 리다이렉트(어드민 "설정 > 주소 이동") 적용.
|
|
2
|
+
//
|
|
3
|
+
// 글 슬러그 변경 자동 301 은 글 라우트에서 처리되지만(blog 예시 참고), 글이
|
|
4
|
+
// 아닌 임의 경로(`/old-event → /promo`)는 라우팅 이전 단계인 미들웨어에서만
|
|
5
|
+
// 가로챌 수 있다. 규칙은 자동 캐시되고, API 실패 시 트래픽을 막지 않는다.
|
|
6
|
+
import { NextResponse } from "next/server";
|
|
7
|
+
import { createRedirectMiddleware } from "@roottale/cms-renderer-next/routes";
|
|
8
|
+
|
|
9
|
+
const redirects = createRedirectMiddleware({
|
|
10
|
+
apiKey: process.env.ROOTTALE_API_KEY!,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export async function middleware(req: Request) {
|
|
14
|
+
return (await redirects(req)) ?? NextResponse.next();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Next 내부·API·알려진 정적 자산만 제외. 점 포함 경로를 전부 막으면
|
|
18
|
+
// `/old.html`·`/foo.php` 같은 레거시 마이그레이션 리다이렉트가 동작하지 않는다.
|
|
19
|
+
export const config = {
|
|
20
|
+
matcher: [
|
|
21
|
+
"/((?!_next/|api/|.*\\.(?:ico|png|jpg|jpeg|gif|svg|webp|css|js|txt|xml|json|woff2?|map)$).*)",
|
|
22
|
+
],
|
|
23
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@roottale/cms-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "RootTale CMS integration MCP server — bundled integration docs, Next.js example code, and public API lookup tools. Run with: npx @roottale/cms-mcp",
|
|
6
6
|
"bin": {
|