easyread-mcp 0.1.0 → 0.1.1
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 +53 -13
- package/dist/schema-dialect.js +41 -0
- package/dist/schema-dialect.js.map +1 -0
- package/dist/server.js +5 -1
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,31 +1,61 @@
|
|
|
1
1
|
# EASYREAD — 쉬운 정보(Easy-Read) MCP 서버
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/easyread-mcp)
|
|
4
|
+
[](https://github.com/SWJoong/EASYREAD/actions/workflows/ci.yml)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](#설치하기)
|
|
7
|
+
|
|
8
|
+
발달장애인·저문해력 사용자를 위해 복잡한 한국어 텍스트를 **쉬운 정보(Easy-Read)** 로 바꾸는 일을 돕는 MCP(Model Context Protocol) 서버입니다.
|
|
4
9
|
|
|
5
10
|
- 서버는 **지침·사전·검증 도구**를 제공하고, 실제 문장 변환은 클라이언트 LLM(Claude 등)이 수행합니다.
|
|
6
|
-
-
|
|
11
|
+
- 모든 검증은 **오프라인·결정적**으로 동작하며, 입력을 저장하거나 기록하지 않습니다.
|
|
12
|
+
- 기술 스택: TypeScript + `@modelcontextprotocol/sdk` (Node.js 22 LTS+), 런타임 의존성 2개.
|
|
13
|
+
|
|
14
|
+
> ⚠️ **이 도구의 결과는 감수를 거치지 않은 초안입니다.** 도구는 감수를 대신하지 않습니다.
|
|
15
|
+
> 최종본은 반드시 **발달장애인 당사자의 확인·감수**를 거쳐 정합니다.
|
|
7
16
|
|
|
8
17
|
## 설치하기
|
|
9
18
|
|
|
10
|
-
Node.js 22 이상이 필요합니다. 인터넷은
|
|
19
|
+
Node.js 22 이상이 필요합니다. 인터넷은 **설치할 때만** 필요하고, 검사할 때는 필요 없습니다.
|
|
20
|
+
|
|
21
|
+
**Claude Code** — 터미널에 한 줄:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
claude mcp add easyread -- npx -y easyread-mcp
|
|
25
|
+
```
|
|
11
26
|
|
|
12
|
-
|
|
13
|
-
- **Claude Code**: [docs/install/claude-code.md](docs/install/claude-code.md) — `claude mcp add easyread -- npx -y easyread-mcp` 한 줄.
|
|
27
|
+
**Claude Desktop** — 설정 파일에 아래 블록을 넣고 앱을 다시 시작합니다:
|
|
14
28
|
|
|
15
29
|
```json
|
|
16
30
|
{ "mcpServers": { "easyread": { "command": "npx", "args": ["-y", "easyread-mcp"] } } }
|
|
17
31
|
```
|
|
18
32
|
|
|
19
|
-
|
|
33
|
+
자세한 순서: [Claude Desktop 설치](docs/install/claude-desktop.md) · [Claude Code 설치](docs/install/claude-code.md)
|
|
34
|
+
|
|
35
|
+
**처음이라면 → [처음 사용해보기(따라하기)](docs/install/first-use.md)** — 예시 문장으로 한 번 연습해 봅니다.
|
|
36
|
+
|
|
37
|
+
## 써보기
|
|
38
|
+
|
|
39
|
+
1. 어려운 글을 한 토막 준비합니다.
|
|
40
|
+
2. `simplify-text` 프롬프트로 **쉬운 정보 초안**을 만듭니다.
|
|
41
|
+
3. `validate_easy_read`로 초안을 **원문과 함께** 검사합니다 — 규칙 위반과 함께, 날짜·금액·기관명이 바뀌지 않았는지(정확성 ACC)를 확인합니다.
|
|
42
|
+
4. `error`가 없어질 때까지 고치고, 마지막에 **당사자 감수**를 받습니다.
|
|
20
43
|
|
|
21
|
-
|
|
44
|
+
## 제공 기능
|
|
45
|
+
|
|
46
|
+
- **도구 4종**: `validate_easy_read`(규칙 검증·원문 대조), `analyze_readability`(가독성 지표), `lookup_easy_word`(쉬운 낱말 찾기), `get_guidelines`(작성 지침).
|
|
22
47
|
- **프롬프트 2종**: `simplify-text`(쉬운 정보로 바꾸기), `easy-read-review`(초안 검토).
|
|
23
|
-
-
|
|
24
|
-
- **검증 규칙 25
|
|
48
|
+
- **리소스 4종**: `easyread://guidelines` · `.../checklist` · `easyread://dictionary` · `easyread://resources`.
|
|
49
|
+
- **검증 규칙 25종**: 문장(SEN)·어휘(VOC)·숫자(NUM)·구성(STR)·표기(TYP)·정확성(ACC).
|
|
50
|
+
- **번들 데이터**: 쉬운 낱말 사전과 Easy-Read 근거·표준·사례 카탈로그 66건(각 항목에 출처·라이선스 분류 보존).
|
|
51
|
+
|
|
52
|
+
## 보안·프라이버시
|
|
25
53
|
|
|
26
|
-
|
|
54
|
+
오프라인 동작(네트워크 미호출), 입력 무저장·무로깅, 입력 크기 상한. 자세한 내용은 [SECURITY.md](SECURITY.md)를 참고하세요. 버전별 변경 내역은 [CHANGELOG.md](CHANGELOG.md)에 있습니다.
|
|
27
55
|
|
|
28
|
-
|
|
56
|
+
## 개발·기여
|
|
57
|
+
|
|
58
|
+
구현 계획은 [docs/plan/](docs/plan/) 아래 파트별로 정리되어 있습니다.
|
|
29
59
|
|
|
30
60
|
| 문서 | 담당 역할 |
|
|
31
61
|
|---|---|
|
|
@@ -36,6 +66,16 @@ Node.js 22 이상이 필요합니다. 인터넷은 설치할 때만 필요하고
|
|
|
36
66
|
| [04-qa-plan.md](docs/plan/04-qa-plan.md) | QA — 테스트 전략 |
|
|
37
67
|
| [05-release-plan.md](docs/plan/05-release-plan.md) | DevOps — 배포/릴리스 |
|
|
38
68
|
|
|
39
|
-
|
|
69
|
+
`.claude/skills/` 아래 역할별 스킬(`/pm`·`/pl`·`/backend`·`/qa`·`/devops`)로 각 파트 계획을 작성·갱신할 수 있고, `easyread-domain` 스킬이 쉬운 정보 작성 도메인 지식을 제공합니다.
|
|
70
|
+
|
|
71
|
+
빌드·테스트:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npm ci && npm run build && npm test
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
버그·오탐/미탐 신고는 [이슈 템플릿](.github/ISSUE_TEMPLATE)으로 받습니다.
|
|
78
|
+
|
|
79
|
+
## 라이선스
|
|
40
80
|
|
|
41
|
-
|
|
81
|
+
[MIT](LICENSE). 번들 데이터의 출처·이용조건 고지는 LICENSE의 데이터 고지(NFR-04)와 `assets/resources.json`의 `license` 필드를 참고하세요.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 도구 스키마의 JSON Schema 방언을 최신 MCP 클라이언트와 호환되게 맞춘다.
|
|
3
|
+
*
|
|
4
|
+
* 배경: `@modelcontextprotocol/sdk` 1.30.0의 `McpServer`는 zod 스키마를 JSON Schema로
|
|
5
|
+
* 변환할 때 방언 target을 지정하지 않아 `zod-to-json-schema` 기본값인 **draft-07**로
|
|
6
|
+
* `$schema`를 방출한다(server/mcp.js의 tools/list 핸들러). 최신 MCP 클라이언트는 JSON
|
|
7
|
+
* Schema **2020-12**만 검증하므로, draft-07을 선언한 도구 outputSchema를 거부한다
|
|
8
|
+
* ("unsupported dialect ($schema: http://json-schema.org/draft-07/schema#)").
|
|
9
|
+
*
|
|
10
|
+
* 도구 스키마 본문은 두 방언에서 동일한 키워드(type·properties·required·enum·min/max
|
|
11
|
+
* 등)만 쓰므로, tools/list 응답에서 최상위 `$schema` 선언만 제거하면 클라이언트가 기본
|
|
12
|
+
* 방언(2020-12)으로 해석해 통과한다. SDK가 변환 target을 지정하는 공개 API를 노출하지
|
|
13
|
+
* 않으므로, 응답을 후처리하는 이 방식이 가장 작은 수정이다.
|
|
14
|
+
*
|
|
15
|
+
* 반드시 도구 등록 **전**에 호출한다. SDK가 tools/list 핸들러를 설치하는 순간을 가로채
|
|
16
|
+
* 응답을 감싸야 하기 때문이다.
|
|
17
|
+
*/
|
|
18
|
+
export function normalizeToolSchemaDialect(server) {
|
|
19
|
+
const low = server.server;
|
|
20
|
+
const originalSetRequestHandler = low.setRequestHandler.bind(low);
|
|
21
|
+
low.setRequestHandler = (schema, handler) => {
|
|
22
|
+
originalSetRequestHandler(schema, async (...args) => {
|
|
23
|
+
const result = await handler(...args);
|
|
24
|
+
const tools = result?.tools;
|
|
25
|
+
if (Array.isArray(tools)) {
|
|
26
|
+
for (const tool of tools) {
|
|
27
|
+
stripDollarSchema(tool.inputSchema);
|
|
28
|
+
stripDollarSchema(tool.outputSchema);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** JSON Schema 객체의 최상위 `$schema` 방언 선언을 제거한다(있을 때만). */
|
|
36
|
+
function stripDollarSchema(schema) {
|
|
37
|
+
if (typeof schema === "object" && schema !== null && "$schema" in schema) {
|
|
38
|
+
delete schema.$schema;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=schema-dialect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-dialect.js","sourceRoot":"","sources":["../src/schema-dialect.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,0BAA0B,CAAC,MAAiB;IAK1D,MAAM,GAAG,GAAG,MAAM,CAAC,MAAmC,CAAC;IACvD,MAAM,yBAAyB,GAAG,GAAG,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClE,GAAG,CAAC,iBAAiB,GAAG,CAAC,MAAe,EAAE,OAAuB,EAAQ,EAAE;QACzE,yBAAyB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAe,EAAoB,EAAE;YAC/E,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;YACtC,MAAM,KAAK,GAAI,MAAmD,EAAE,KAAK,CAAC;YAC1E,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,iBAAiB,CAAE,IAAkC,CAAC,WAAW,CAAC,CAAC;oBACnE,iBAAiB,CAAE,IAAmC,CAAC,YAAY,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,wDAAwD;AACxD,SAAS,iBAAiB,CAAC,MAAe;IACxC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;QACzE,OAAQ,MAAkC,CAAC,OAAO,CAAC;IACrD,CAAC;AACH,CAAC"}
|
package/dist/server.js
CHANGED
|
@@ -7,11 +7,15 @@ import { registerAnalyzeTool } from "./tools/analyze.js";
|
|
|
7
7
|
import { registerGuidelinesTool } from "./tools/guidelines.js";
|
|
8
8
|
import { registerLookupTool } from "./tools/lookup.js";
|
|
9
9
|
import { registerValidateTool } from "./tools/validate.js";
|
|
10
|
+
import { normalizeToolSchemaDialect } from "./schema-dialect.js";
|
|
10
11
|
/**
|
|
11
12
|
* EASYREAD MCP 서버를 조립한다. 도구·프롬프트·리소스 등록만 담당하고 로직은 갖지 않는다(03 §1).
|
|
12
13
|
*/
|
|
13
14
|
export function createServer(dictionary, catalog) {
|
|
14
|
-
const server = new McpServer({ name: "easyread", version: "0.1.
|
|
15
|
+
const server = new McpServer({ name: "easyread", version: "0.1.1" });
|
|
16
|
+
// SDK가 도구 스키마를 draft-07로 방출 → 최신 클라이언트(2020-12) 호환되게 정규화.
|
|
17
|
+
// 반드시 도구 등록 전에 호출한다(tools/list 핸들러 설치 시점을 가로채기 위함).
|
|
18
|
+
normalizeToolSchemaDialect(server);
|
|
15
19
|
registerValidateTool(server, dictionary);
|
|
16
20
|
registerAnalyzeTool(server, dictionary);
|
|
17
21
|
registerLookupTool(server, dictionary);
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEnF,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|