@neobiotechlabs/neobiotech-dev-agent 0.1.7

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.
Files changed (155) hide show
  1. package/.claude-plugin/marketplace.json +22 -0
  2. package/.claude-plugin/plugin.json +58 -0
  3. package/.mcp.json +14 -0
  4. package/README.md +442 -0
  5. package/dist/__tests__/adf.test.d.ts +1 -0
  6. package/dist/__tests__/adf.test.js +68 -0
  7. package/dist/__tests__/adf.test.js.map +1 -0
  8. package/dist/__tests__/annex-ii-template.test.d.ts +1 -0
  9. package/dist/__tests__/annex-ii-template.test.js +39 -0
  10. package/dist/__tests__/annex-ii-template.test.js.map +1 -0
  11. package/dist/__tests__/doc-render.test.d.ts +1 -0
  12. package/dist/__tests__/doc-render.test.js +93 -0
  13. package/dist/__tests__/doc-render.test.js.map +1 -0
  14. package/dist/__tests__/help.test.d.ts +1 -0
  15. package/dist/__tests__/help.test.js +31 -0
  16. package/dist/__tests__/help.test.js.map +1 -0
  17. package/dist/__tests__/jira-fields.test.d.ts +1 -0
  18. package/dist/__tests__/jira-fields.test.js +81 -0
  19. package/dist/__tests__/jira-fields.test.js.map +1 -0
  20. package/dist/__tests__/plugin-manifest.test.d.ts +1 -0
  21. package/dist/__tests__/plugin-manifest.test.js +91 -0
  22. package/dist/__tests__/plugin-manifest.test.js.map +1 -0
  23. package/dist/__tests__/setup.test.d.ts +1 -0
  24. package/dist/__tests__/setup.test.js +7 -0
  25. package/dist/__tests__/setup.test.js.map +1 -0
  26. package/dist/__tests__/sync-version.test.d.ts +1 -0
  27. package/dist/__tests__/sync-version.test.js +37 -0
  28. package/dist/__tests__/sync-version.test.js.map +1 -0
  29. package/dist/clients/risk-client.d.ts +17 -0
  30. package/dist/clients/risk-client.js +54 -0
  31. package/dist/clients/risk-client.js.map +1 -0
  32. package/dist/clients/xray-client.d.ts +34 -0
  33. package/dist/clients/xray-client.js +127 -0
  34. package/dist/clients/xray-client.js.map +1 -0
  35. package/dist/config/project-config.d.ts +14 -0
  36. package/dist/config/project-config.js +45 -0
  37. package/dist/config/project-config.js.map +1 -0
  38. package/dist/confluence-client.d.ts +16 -0
  39. package/dist/confluence-client.js +97 -0
  40. package/dist/confluence-client.js.map +1 -0
  41. package/dist/index.d.ts +2 -0
  42. package/dist/index.js +60 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/jira-client.d.ts +35 -0
  45. package/dist/jira-client.js +119 -0
  46. package/dist/jira-client.js.map +1 -0
  47. package/dist/tools/annex-ii-template.d.ts +30 -0
  48. package/dist/tools/annex-ii-template.js +129 -0
  49. package/dist/tools/annex-ii-template.js.map +1 -0
  50. package/dist/tools/confluence.d.ts +2 -0
  51. package/dist/tools/confluence.js +54 -0
  52. package/dist/tools/confluence.js.map +1 -0
  53. package/dist/tools/cvss.d.ts +2 -0
  54. package/dist/tools/cvss.js +59 -0
  55. package/dist/tools/cvss.js.map +1 -0
  56. package/dist/tools/doc-render.d.ts +2 -0
  57. package/dist/tools/doc-render.js +96 -0
  58. package/dist/tools/doc-render.js.map +1 -0
  59. package/dist/tools/doc-validation.d.ts +2 -0
  60. package/dist/tools/doc-validation.js +221 -0
  61. package/dist/tools/doc-validation.js.map +1 -0
  62. package/dist/tools/help-data.d.ts +7 -0
  63. package/dist/tools/help-data.js +144 -0
  64. package/dist/tools/help-data.js.map +1 -0
  65. package/dist/tools/help.d.ts +2 -0
  66. package/dist/tools/help.js +39 -0
  67. package/dist/tools/help.js.map +1 -0
  68. package/dist/tools/iec.d.ts +2 -0
  69. package/dist/tools/iec.js +203 -0
  70. package/dist/tools/iec.js.map +1 -0
  71. package/dist/tools/init.d.ts +2 -0
  72. package/dist/tools/init.js +38 -0
  73. package/dist/tools/init.js.map +1 -0
  74. package/dist/tools/jira-crud.d.ts +2 -0
  75. package/dist/tools/jira-crud.js +142 -0
  76. package/dist/tools/jira-crud.js.map +1 -0
  77. package/dist/tools/risk.d.ts +2 -0
  78. package/dist/tools/risk.js +172 -0
  79. package/dist/tools/risk.js.map +1 -0
  80. package/dist/tools/traceability.d.ts +2 -0
  81. package/dist/tools/traceability.js +85 -0
  82. package/dist/tools/traceability.js.map +1 -0
  83. package/dist/tools/types.d.ts +13 -0
  84. package/dist/tools/types.js +2 -0
  85. package/dist/tools/types.js.map +1 -0
  86. package/dist/tools/usability.d.ts +2 -0
  87. package/dist/tools/usability.js +149 -0
  88. package/dist/tools/usability.js.map +1 -0
  89. package/dist/tools/xray.d.ts +2 -0
  90. package/dist/tools/xray.js +35 -0
  91. package/dist/tools/xray.js.map +1 -0
  92. package/dist/utils/adf.d.ts +27 -0
  93. package/dist/utils/adf.js +104 -0
  94. package/dist/utils/adf.js.map +1 -0
  95. package/dist/utils/cvss.d.ts +15 -0
  96. package/dist/utils/cvss.js +86 -0
  97. package/dist/utils/cvss.js.map +1 -0
  98. package/dist/utils/doc-render.d.ts +28 -0
  99. package/dist/utils/doc-render.js +50 -0
  100. package/dist/utils/doc-render.js.map +1 -0
  101. package/dist/utils/jira-fields.d.ts +38 -0
  102. package/dist/utils/jira-fields.js +53 -0
  103. package/dist/utils/jira-fields.js.map +1 -0
  104. package/dist/utils/sync-version.d.ts +2 -0
  105. package/dist/utils/sync-version.js +20 -0
  106. package/dist/utils/sync-version.js.map +1 -0
  107. package/package.json +49 -0
  108. package/skills/doc-render/SKILL.md +79 -0
  109. package/vendor/dev-docs-templates/templates/dev_docs/plan_template.md +104 -0
  110. package/vendor/dev-docs-templates/templates/dev_docs/prd_template.md +110 -0
  111. package/vendor/dev-docs-templates/templates/dev_docs/spec_template.md +81 -0
  112. package/vendor/dev-docs-templates/templates/dev_docs/tasks_template.md +122 -0
  113. package/vendor/dev-docs-templates/templates/mdr_docs/CA/checklist-clinical-evaluation.md +81 -0
  114. package/vendor/dev-docs-templates/templates/mdr_docs/CA/checklist-gspr-mdr.md +403 -0
  115. package/vendor/dev-docs-templates/templates/mdr_docs/CA/clinical-evaluation-report.md +492 -0
  116. package/vendor/dev-docs-templates/templates/mdr_docs/CA/instructions-for-use.md +132 -0
  117. package/vendor/dev-docs-templates/templates/mdr_docs/CA/literature-evaluation-table.md +15 -0
  118. package/vendor/dev-docs-templates/templates/mdr_docs/CA/mdr-declaration-of-conformity.md +75 -0
  119. package/vendor/dev-docs-templates/templates/mdr_docs/CA/post-market-clinical-follow-up-plan.md +162 -0
  120. package/vendor/dev-docs-templates/templates/mdr_docs/CA/post-market-surveillance-plan.md +175 -0
  121. package/vendor/dev-docs-templates/templates/mdr_docs/CA/risk-management-cybersecurity-checklist.md +67 -0
  122. package/vendor/dev-docs-templates/templates/mdr_docs/CA/risk-management-report.md +111 -0
  123. package/vendor/dev-docs-templates/templates/mdr_docs/CA/usability-evaluation-report.md +70 -0
  124. package/vendor/dev-docs-templates/templates/mdr_docs/EA/clinical-evaluation-plan.md +154 -0
  125. package/vendor/dev-docs-templates/templates/mdr_docs/EA/list-of-hazard-related-use-scenarios.md +34 -0
  126. package/vendor/dev-docs-templates/templates/mdr_docs/EA/risk-table-fmea.md +155 -0
  127. package/vendor/dev-docs-templates/templates/mdr_docs/EA/software-architecture-description.md +307 -0
  128. package/vendor/dev-docs-templates/templates/mdr_docs/EA/software-requirements-list.md +156 -0
  129. package/vendor/dev-docs-templates/templates/mdr_docs/EA/soup-list.md +82 -0
  130. package/vendor/dev-docs-templates/templates/mdr_docs/EA/usability-evaluation-plan.md +103 -0
  131. package/vendor/dev-docs-templates/templates/mdr_docs/ER/global/bug-fixes-documentation-list.md +35 -0
  132. package/vendor/dev-docs-templates/templates/mdr_docs/ER/global/change-evaluation-list.md +100 -0
  133. package/vendor/dev-docs-templates/templates/mdr_docs/ER/global/list-of-known-anomalies.md +29 -0
  134. package/vendor/dev-docs-templates/templates/mdr_docs/ER/sprint/algorithm-validation-report.md +170 -0
  135. package/vendor/dev-docs-templates/templates/mdr_docs/ER/sprint/checklist-software-release.md +52 -0
  136. package/vendor/dev-docs-templates/templates/mdr_docs/ER/sprint/checklist-software-requirements-review.md +50 -0
  137. package/vendor/dev-docs-templates/templates/mdr_docs/ER/sprint/software-architecture-checklist.md +41 -0
  138. package/vendor/dev-docs-templates/templates/mdr_docs/ER/sprint/software-detailed-design.md +321 -0
  139. package/vendor/dev-docs-templates/templates/mdr_docs/ER/sprint/software-system-test-plan.md +155 -0
  140. package/vendor/dev-docs-templates/templates/mdr_docs/ER/sprint/usability-evaluation-protocol.md +63 -0
  141. package/vendor/dev-docs-templates/templates/mdr_docs/PA/intended-use.md +116 -0
  142. package/vendor/dev-docs-templates/templates/mdr_docs/PA/mdr-classification-document.md +114 -0
  143. package/vendor/dev-docs-templates/templates/mdr_docs/PA/risk-management-plan.md +198 -0
  144. package/vendor/dev-docs-templates/templates/mdr_docs/PA/software-development-maintenance-plan.md +225 -0
  145. package/vendor/dev-docs-templates/templates/mdr_docs/PA/system-requirements-spec.md +182 -0
  146. package/vendor/dev-docs-templates/templates/mdr_docs/global/information_security/information-security-controls.md +966 -0
  147. package/vendor/dev-docs-templates/templates/mdr_docs/global/information_security/information-security-policy-and-scope.md +99 -0
  148. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/quality-manual-policy-objectives.md +187 -0
  149. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/sop-capa.md +112 -0
  150. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/sop-change-management.md +128 -0
  151. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/sop-clinical-evaluation.md +102 -0
  152. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/sop-feedback-management.md +140 -0
  153. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/sop-integrated-software-development.md +361 -0
  154. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/sop-post-market-surveillance.md +159 -0
  155. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/sop-software-problem-resolution.md +99 -0
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "neobiotech",
3
+ "owner": {
4
+ "name": "NeoBiotech"
5
+ },
6
+ "plugins": [
7
+ {
8
+ "name": "neobiotech-dev-agent",
9
+ "source": {
10
+ "source": "npm",
11
+ "package": "@neobiotechlabs/neobiotech-dev-agent",
12
+ "registry": "https://registry.npmjs.org",
13
+ "version": "0.1.7"
14
+ },
15
+ "description": "의료기기 SW 규제 개발 자동화 (Jira·Confluence·Risk·CVSS·Xray·IEC 62304/62366·MDR·문서 렌더)",
16
+ "category": "medical-device",
17
+ "skills": [
18
+ "./skills/doc-render"
19
+ ]
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "neobiotech-dev-agent",
3
+ "version": "0.1.7",
4
+ "displayName": "NeoBiotech Dev Agent (MedDev)",
5
+ "description": "의료기기 SW 규제 개발 자동화 — Jira·Confluence·Risk·CVSS·Xray·IEC 62304/62366·MDR·문서 렌더",
6
+ "author": {
7
+ "name": "NeoBiotech"
8
+ },
9
+ "homepage": "https://github.com/NeobiotechLabs/jira-mcp-server",
10
+ "keywords": [
11
+ "medical-device",
12
+ "iec-62304",
13
+ "mdr",
14
+ "jira",
15
+ "confluence"
16
+ ],
17
+ "userConfig": {
18
+ "JIRA_URL": {
19
+ "type": "string",
20
+ "title": "Jira URL",
21
+ "description": "Jira 인스턴스 URL (https 권장 — http에선 node-fetch 리다이렉트가 POST를 GET으로 변환해 생성/수정이 실패함)",
22
+ "required": true
23
+ },
24
+ "JIRA_EMAIL": {
25
+ "type": "string",
26
+ "title": "Jira 이메일",
27
+ "description": "Jira 계정 이메일",
28
+ "required": true
29
+ },
30
+ "JIRA_API_TOKEN": {
31
+ "type": "string",
32
+ "title": "Jira API 토큰",
33
+ "description": "Jira API 토큰 (https://id.atlassian.com/manage-profile/security/api-tokens)",
34
+ "sensitive": true,
35
+ "required": true
36
+ },
37
+ "XRAY_CLIENT_ID": {
38
+ "type": "string",
39
+ "title": "Xray Client ID",
40
+ "description": "Xray Cloud client ID (선택)",
41
+ "required": false
42
+ },
43
+ "XRAY_CLIENT_SECRET": {
44
+ "type": "string",
45
+ "title": "Xray Client Secret",
46
+ "description": "Xray Cloud client secret (선택)",
47
+ "sensitive": true,
48
+ "required": false
49
+ },
50
+ "RISK_PLUGIN_AUTH_TOKEN": {
51
+ "type": "string",
52
+ "title": "Risk Plugin Auth Token",
53
+ "description": "Risk Management Plugin 인증 토큰 (선택)",
54
+ "sensitive": true,
55
+ "required": false
56
+ }
57
+ }
58
+ }
package/.mcp.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "neobiotech-dev-agent": {
3
+ "command": "node",
4
+ "args": ["${CLAUDE_PLUGIN_ROOT}/dist/index.js"],
5
+ "env": {
6
+ "JIRA_URL": "${user_config.JIRA_URL}",
7
+ "JIRA_EMAIL": "${user_config.JIRA_EMAIL}",
8
+ "JIRA_API_TOKEN": "${user_config.JIRA_API_TOKEN}",
9
+ "XRAY_CLIENT_ID": "${user_config.XRAY_CLIENT_ID}",
10
+ "XRAY_CLIENT_SECRET": "${user_config.XRAY_CLIENT_SECRET}",
11
+ "RISK_PLUGIN_AUTH_TOKEN": "${user_config.RISK_PLUGIN_AUTH_TOKEN}"
12
+ }
13
+ }
14
+ }
package/README.md ADDED
@@ -0,0 +1,442 @@
1
+ # @neobiotechlabs/neobiotech-dev-agent
2
+
3
+ IEC 62304 의료기기 소프트웨어 개발을 위한 Jira MCP Server. Claude Code에서 Jira, Confluence, Risk Management, CVSS, Xray, 추적성 관리를 직접 사용할 수 있습니다.
4
+
5
+ ## 사전 설정
6
+
7
+ 공개 npm 패키지(npmjs.org)로 게시되어 별도 registry 인증 없이 아래 설치 명령으로 바로 사용할 수 있습니다.
8
+
9
+ ## 설치
10
+
11
+ ```bash
12
+ # 글로벌 설치 (추천)
13
+ npm install -g @neobiotechlabs/neobiotech-dev-agent
14
+
15
+ # 또는 매번 최신 버전 실행 (설치 불필요)
16
+ npx -y @neobiotechlabs/neobiotech-dev-agent
17
+ ```
18
+
19
+ 업데이트:
20
+ ```bash
21
+ npm update -g @neobiotechlabs/neobiotech-dev-agent
22
+ ```
23
+
24
+ 베타 테스트:
25
+ ```bash
26
+ npm install -g @neobiotechlabs/neobiotech-dev-agent@beta
27
+ ```
28
+
29
+ ## 로컬 빌드 (개발/브랜치 테스트용)
30
+
31
+ 소스 코드를 직접 빌드하여 사용할 수도 있습니다:
32
+
33
+ ```bash
34
+ # submodule 포함 clone 권장 (doc_render 툴이 vendor/dev-docs-templates/ 사용)
35
+ git clone --recurse-submodules https://github.com/NeobiotechLabs/jira-mcp-server.git
36
+ cd jira-mcp-server
37
+ npm install
38
+ npm run build
39
+ ```
40
+
41
+ 이미 clone한 경우 submodule을 별도로 초기화:
42
+
43
+ ```bash
44
+ git submodule update --init --recursive
45
+ ```
46
+
47
+ ## Claude Code 설정
48
+
49
+ ### 방법 1: `claude mcp add` 명령어
50
+
51
+ **npm 패키지 설치 시:**
52
+
53
+ ```bash
54
+ claude mcp add jira \
55
+ -e JIRA_URL=https://your-domain.atlassian.net \
56
+ -e JIRA_EMAIL=your-email@example.com \
57
+ -e JIRA_API_TOKEN=your-api-token \
58
+ -- npx -y @neobiotechlabs/neobiotech-dev-agent
59
+ ```
60
+
61
+ **로컬 빌드 시:**
62
+
63
+ ```bash
64
+ claude mcp add jira \
65
+ -e JIRA_URL=https://your-domain.atlassian.net \
66
+ -e JIRA_EMAIL=your-email@example.com \
67
+ -e JIRA_API_TOKEN=your-api-token \
68
+ -- node /절대경로/jira-mcp-server/dist/index.js
69
+ ```
70
+
71
+ 선택 환경 변수도 함께 추가할 수 있습니다:
72
+
73
+ ```bash
74
+ -e XRAY_CLIENT_ID=... \
75
+ -e XRAY_CLIENT_SECRET=... \
76
+ -e RISK_PLUGIN_AUTH_TOKEN=... \
77
+ -- npx -y @neobiotechlabs/neobiotech-dev-agent
78
+ ```
79
+
80
+ **주의:** `-e` 옵션은 `--` 앞에 와야 합니다.
81
+
82
+ ### 방법 2: `~/.claude/settings.json` 직접 편집
83
+
84
+ **패키지 설치 시:**
85
+
86
+ ```json
87
+ {
88
+ "mcpServers": {
89
+ "jira": {
90
+ "command": "npx",
91
+ "args": ["-y", "@neobiotechlabs/neobiotech-dev-agent"],
92
+ "env": {
93
+ "JIRA_URL": "https://your-domain.atlassian.net",
94
+ "JIRA_EMAIL": "your-email@example.com",
95
+ "JIRA_API_TOKEN": "your-api-token",
96
+ "XRAY_CLIENT_ID": "",
97
+ "XRAY_CLIENT_SECRET": "",
98
+ "RISK_PLUGIN_AUTH_TOKEN": ""
99
+ }
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ **로컬 빌드 시:**
106
+
107
+ ```json
108
+ {
109
+ "mcpServers": {
110
+ "jira": {
111
+ "command": "node",
112
+ "args": ["/절대경로/jira-mcp-server/dist/index.js"],
113
+ "env": {
114
+ "JIRA_URL": "https://your-domain.atlassian.net",
115
+ "JIRA_EMAIL": "your-email@example.com",
116
+ "JIRA_API_TOKEN": "your-api-token"
117
+ }
118
+ }
119
+ }
120
+ }
121
+ ```
122
+
123
+ ### 방법 3: 프로젝트 `.mcp.json` 사용
124
+
125
+ 각 프로젝트 루트에 `.mcp.json`과 `.env` 파일을 만들면, 프로젝트별로 설정을 관리할 수 있습니다.
126
+
127
+ **`.mcp.json`** (git에 커밋):
128
+
129
+ ```json
130
+ {
131
+ "mcpServers": {
132
+ "jira": {
133
+ "command": "npx",
134
+ "args": ["-y", "@neobiotechlabs/neobiotech-dev-agent"],
135
+ "env": {
136
+ "JIRA_URL": "${JIRA_URL}",
137
+ "JIRA_EMAIL": "${JIRA_EMAIL}",
138
+ "JIRA_API_TOKEN": "${JIRA_API_TOKEN}"
139
+ }
140
+ }
141
+ }
142
+ }
143
+ ```
144
+
145
+ **`.env`** (개인 설정, git에 커밋하지 않음):
146
+
147
+ ```
148
+ JIRA_URL=https://your-domain.atlassian.net
149
+ JIRA_EMAIL=your-email@example.com
150
+ JIRA_API_TOKEN=your-api-token
151
+ ```
152
+
153
+ ## 환경 변수
154
+
155
+ | 변수 | 필수 | 설명 |
156
+ |------|------|------|
157
+ | `JIRA_URL` | O | Jira 인스턴스 URL (**https 권장** — http에선 node-fetch 리다이렉트가 POST를 GET으로 변환해 생성/수정이 실패함) |
158
+ | `JIRA_EMAIL` | O | Jira 계정 이메일 |
159
+ | `JIRA_API_TOKEN` | O | Jira API 토큰 ([발급](https://id.atlassian.com/manage-profile/security/api-tokens)) |
160
+ | `XRAY_CLIENT_ID` | X | Xray Cloud client ID |
161
+ | `XRAY_CLIENT_SECRET` | X | Xray Cloud client secret |
162
+ | `RISK_PLUGIN_AUTH_TOKEN` | X | Risk Management Plugin 인증 토큰 |
163
+ | `PROJECT_CONFIG_PATH` | X | (사용하지 않음) |
164
+
165
+ ## 릴리즈 절차
166
+
167
+ ### 정식 릴리즈
168
+
169
+ ```bash
170
+ # 1. main 브랜치에서
171
+ npm version patch # 0.1.0 → 0.1.1 (또는 minor, major)
172
+ git push --follow-tags
173
+ # → GitHub Actions가 자동으로 npm(npmjs.org)에 latest로 publish
174
+ ```
175
+
176
+ ### 베타 릴리즈
177
+
178
+ ```bash
179
+ # 1. main 브랜치에서 베타 버전 생성
180
+ npm version prerelease --preid=beta
181
+ # → 0.1.0 → 0.1.1-beta.0
182
+
183
+ git push --follow-tags
184
+ # → GitHub Actions가 자동으로 npm(npmjs.org)에 beta로 publish
185
+
186
+ # 2. 테스터가 설치
187
+ npm install -g @neobiotechlabs/neobiotech-dev-agent@beta
188
+
189
+ # 3. 테스트 완료 후 정식 릴리즈
190
+ npm version patch # 0.1.1-beta.0 → 0.1.1
191
+ git push --follow-tags
192
+ # → latest로 publish, beta 사용자는 npm update로 자동 업그레이드
193
+ ```
194
+
195
+ ### 태그별 dist-tag 매핑
196
+
197
+ | git 태그 | npm dist-tag | 설치 명령어 |
198
+ |----------|-------------|-------------|
199
+ | `v0.1.1-beta.0` | `beta` | `npm i -g @neobiotechlabs/neobiotech-dev-agent@beta` |
200
+ | `v0.1.1` | `latest` | `npm i -g @neobiotechlabs/neobiotech-dev-agent` |
201
+
202
+ ## 툴 목록 (48개)
203
+
204
+ ### Jira 기본 CRUD (12)
205
+
206
+ | 툴 | 설명 |
207
+ |-----|------|
208
+ | `jira_get_issue` | 이슈 조회 (필드 선택, linked issues 포함) |
209
+ | `jira_search` | JQL로 이슈 검색 |
210
+ | `jira_create_issue` | 이슈 생성 (custom fields 지원, rich_text customfield ADF 자동 변환) |
211
+ | `jira_update_issue` | 이슈 필드 업데이트 (description + rich_text customfield ADF 자동 변환) |
212
+ | `jira_add_comment` | 코멘트 추가 |
213
+ | `jira_create_link` | 이슈 간 링크 생성 (Blocks, Implements, Relates, Mitigates, Risk Source 등) |
214
+ | `jira_get_links` | 이슈 링크 조회 |
215
+ | `jira_delete_link` | 이슈 링크 삭제 |
216
+ | `jira_get_transitions` | 상태 전이 목록 조회 |
217
+ | `jira_transition` | 이슈 상태 변경 |
218
+ | `jira_delete_issue` | 이슈 삭제 |
219
+ | `jira_get_issue_type_schema` | 이슈 타입의 필드 스키마 동적 조회 |
220
+
221
+ ### Confluence (7)
222
+
223
+ | 툴 | 설명 |
224
+ |-----|------|
225
+ | `confluence_get_page` | 페이지 조회 |
226
+ | `confluence_search` | CQL로 페이지 검색 |
227
+ | `confluence_create_page` | 페이지 생성 |
228
+ | `confluence_update_page` | 페이지 업데이트 |
229
+ | `confluence_delete_page` | 페이지 삭제 |
230
+ | `confluence_get_spaces` | 스페이스 목록 |
231
+ | `confluence_get_page_children` | 하위 페이지 조회 |
232
+
233
+ ### Risk Management (5)
234
+
235
+ Risk Management Plugin과 연동하여 Hazard 티켓의 Risk 값을 관리합니다.
236
+
237
+ | 툴 | 설명 |
238
+ |-----|------|
239
+ | `risk_get_config` | 프로젝트 Risk Management 설정 조회 |
240
+ | `risk_activate_panel` | Risk Management Plugin 패널 활성화 |
241
+ | `risk_set_values` | Risk 값(severity, p1, p2) 설정 |
242
+ | `risk_create_hazards` | **(High-level)** Hazard 일괄 생성 + Risk 패널 + Risk 값 + Risk Source 링크 |
243
+ | `risk_create_mitigation` | **(High-level)** 완화 Requirement 생성 + Mitigates 링크 + Hazard P2 업데이트 |
244
+
245
+ ### CVSS / Vulnerability (3)
246
+
247
+ CVSS v4.0 기반 보안 취약점 평가.
248
+
249
+ | 툴 | 설명 |
250
+ |-----|------|
251
+ | `cvss_calculate` | CVSS v4.0 metrics → 점수/심각도 계산 |
252
+ | `cvss_set_vector` | Vulnerability 티켓에 CVSS Vector + Score 설정 |
253
+ | `cvss_get_vector` | Vulnerability 티켓의 CVSS Vector + Score 조회 |
254
+
255
+ ### Xray (4)
256
+
257
+ Xray Cloud API + GraphQL로 테스트 관리.
258
+
259
+ | 툴 | 설명 |
260
+ |-----|------|
261
+ | `xray_get_test_keys` | Test Execution의 Test 키 목록 조회 |
262
+ | `xray_export_cucumber` | Cucumber feature 파일 export |
263
+ | `xray_import_results` | 테스트 실행 결과 import |
264
+ | `xray_create_test` | Xray에 테스트 케이스 생성 |
265
+
266
+ ### Traceability (3)
267
+
268
+ IEC 62304 추적성 관리.
269
+
270
+ | 툴 | 설명 |
271
+ |-----|------|
272
+ | `traceability_check` | 티켓의 추적성 상태 확인 (모든 링크 표시) |
273
+ | `traceability_find_missing` | Gate 내 누락된 링크 찾기 |
274
+ | `traceability_fix` | 누락된 링크 일괄 생성 |
275
+
276
+ ### IEC 62304 워크플로우 (4)
277
+
278
+ | 툴 | 설명 |
279
+ |-----|------|
280
+ | `sds_create_task` | Task 생성 + SDS/DD 링크 연결 |
281
+ | `doc_update_description` | 티켓 description을 문서 내용으로 업데이트 |
282
+
283
+ ( `risk_create_hazards`, `risk_create_mitigation`은 위 Risk Management에 포함)
284
+
285
+ ### HELP (1)
286
+
287
+ | 툴 | 설명 |
288
+ |-----|------|
289
+ | `help` | 전체 툴 카탈로그, 워크플로우 가이드, 툴 상세 정보 |
290
+
291
+ ### 사용성 공학 - IEC 62366-1 (4)
292
+
293
+ | 툴 | 설명 |
294
+ |-----|------|
295
+ | `usability_create_use_spec` | Use Specification 정의 (사용자 프로파일, 사용 환경, 의도된 사용) |
296
+ | `usability_create_scenarios` | 사용 시나리오 일괄 생성 (Normal Use / Abnormal Use) |
297
+ | `usability_link_to_hazard` | 사용 시나리오 → Hazard Risk Source 연결 |
298
+ | `usability_create_validation` | 사용성 검증 결과 기록 (방법, 결과, 증빙) |
299
+
300
+ ### 기술 문서 검증 - MDR Annex II (3)
301
+
302
+ | 툴 | 설명 |
303
+ |-----|------|
304
+ | `doc_create_from_template` | MDR Annex II 구조로 누락 문서 자동 생성 |
305
+ | `doc_check_completeness` | 필수 문서 누락/미승인 항목 검사 (✅⚠️❌) |
306
+ | `doc_generate_evidence` | NB 심사용 증거 패키지 (추적성/리스크/V&V 매트릭스) |
307
+
308
+ ### 개발 문서 렌더 (1)
309
+
310
+ | 툴 | 설명 |
311
+ |-----|------|
312
+ | `doc_render` | dev_docs(PRD/Spec/Plan/Tasks)·mdr_docs(intended-use) 템플릿 모드 기반(freeform) 결정적 렌더 — 메타만 치환, 자유 텍스트/AI 지침은 consumer가 채움 |
313
+
314
+ ### 초기 설정 (1)
315
+
316
+ | 툴 | 설명 |
317
+ |-----|------|
318
+ | `jira_init_project` | 프로젝트 폴더에 Jira 프로젝트 키 초기 설정 |
319
+
320
+ ## doc_render 작성 skill (consumer 워크플로우)
321
+
322
+ 이 서버는 `.claude/skills/doc-render/` 절차 가이드를 함께 제공한다. consumer(Claude Code)가 doc_render 출력으로 MDR/dev 문서를 자동 작성해 자기 repo `docs/`에 저장하고 Jira 티켓 description에 미러한다.
323
+
324
+ ### 설치 (수동 copy)
325
+
326
+ 이 repo의 `.claude/skills/doc-render/` 를 consumer 프로젝트의 `.claude/skills/doc-render/` 로 복사:
327
+
328
+ ```bash
329
+ cp -R <이-repo>/.claude/skills/doc-render <consumer-repo>/.claude/skills/
330
+ ```
331
+
332
+ ### 사용
333
+
334
+ consumer Claude Code 세션에서:
335
+
336
+ > "DYN-8 intended use 문서 작성"
337
+
338
+ skill이 doc_render 호출 → 자동 초안 → 리뷰 게이트 → `docs/mdr/PA/intended-use-DYN-8.md` 저장 → DYN-8 description 미러까지 수행한다. 자세한 절차·저장 경로·frontmatter 스키마는 [`skills/doc-render/SKILL.md`](skills/doc-render/SKILL.md) 와 [설계 문서](docs/superpowers/specs/2026-07-03-doc-render-skill-design.md) 참조.
339
+
340
+ > 이 서버는 **npm-as-plugin**으로 배포됩니다 — `/plugin install neobiotech-dev-agent@neobiotech` 한 번으로 MCP 서버 자동 등록 + doc-render skill 자동 배포 + userConfig(키체인) 인증이 처리됩니다. 설치 절차는 [docs/developer-guide.md §3 / §10](docs/developer-guide.md) 참조.
341
+
342
+ ## 프로젝트 초기 설정
343
+
344
+ 각 프로젝트 폴더에서 최초 1회 실행:
345
+
346
+ ```
347
+ jira_init_project(project_key: "SCW")
348
+ ```
349
+
350
+ → `CLAUDE.md`에 프로젝트 키가 자동 추가되어, 이후 Claude가 모든 툴에서 해당 키를 자동으로 사용합니다.
351
+
352
+ 사용 예시:
353
+
354
+ ```
355
+ # Claude Code 안에서
356
+ jira 프로젝트 초기 설정해줘. 프로젝트 키는 SCW야
357
+ ```
358
+
359
+ 또는 여러 프로젝트를 진행할 경우, 각 프로젝트 폴더에서 별도로 초기 설정:
360
+
361
+ ```
362
+ # A 프로젝트 폴더
363
+ jira_init_project(project_key: "SCW")
364
+
365
+ # B 프로젝트 폴더
366
+ jira_init_project(project_key: "NEO")
367
+ ```
368
+
369
+ ## 사용 예시
370
+
371
+ ```
372
+ PLAYG-1234 이슈 내용 알려줘
373
+ ```
374
+ → `jira_get_issue`
375
+
376
+ ```
377
+ Hazard 티켓 2개 만들어줘. [HAZ-1] 영상 렌더링 오류, [HAZ-2] 측정 오차
378
+ ```
379
+ → `risk_create_hazards` (생성 + Risk 패널 + Risk 값 + 링크 한 번에)
380
+
381
+ ```
382
+ 이 Vulnerability의 CVSS 점수 계산해줘. AV:N, AC:L, PR:N, VC:H
383
+ ```
384
+ → `cvss_calculate` + `cvss_set_vector`
385
+
386
+ ```
387
+ PLAYG-2550의 추적성 확인해줘
388
+ ```
389
+ → `traceability_check`
390
+
391
+ ```
392
+ Use Specification 만들어줘. 수술실 의사, 수술실 환경, 수술 네비게이션 목적
393
+ ```
394
+ → `usability_create_use_spec` + `usability_create_scenarios`
395
+
396
+ ```
397
+ MDR Annex II 기술 문서 완전성 검사해줘
398
+ ```
399
+ → `doc_check_completeness`
400
+
401
+ ```
402
+ 사용 가능한 툴 목록 보여줘
403
+ ```
404
+ → `help`
405
+
406
+ ## 추적성 관계 맵
407
+
408
+ ```
409
+ PA Gate
410
+ ├── [Intended Use] Document ── Blocks ──→ Gate
411
+ │ └── Intended Use ── Relates ──→ IU Document
412
+ ├── [System Requirement Spec] ── Blocks ──→ Gate
413
+ │ └── System Requirement ── Relates ──→ SyRS Document
414
+ ├── [Classification] Document ── Blocks ──→ Gate
415
+ │ └── Classification ── Relates ──→ Classification Document
416
+ ├── [SW Development Plan] ── Blocks ──→ Gate
417
+ ├── [Risk Management Plan] ── Blocks ──→ Gate
418
+ ├── [Security Maintenance Plan] ── Blocks ──→ Gate
419
+ ├── [Configuration Management Plan] ── Blocks ──→ Gate
420
+ └── [Use Specification] ── Blocks ──→ Gate ← IEC 62366-1
421
+ └── Use Scenario ── Relates ──→ Use Spec
422
+ └── Abnormal Use Scenario ── Risk Source ──→ Hazard
423
+
424
+ EA Gate
425
+ ├── [Risk Management Report] ── Blocks ──→ Gate
426
+ │ └── Hazard ── Risk Source ──→ IU/SyRS / Use Scenario
427
+ │ └── Hazard ── Relates ──→ RMR Document
428
+ ├── [SW Requirements Spec] ── Blocks ──→ Gate
429
+ │ └── Requirement ── Mitigates ──→ Hazard
430
+ │ └── Requirement ── Implements ──→ System Requirement
431
+ ├── [SW Architecture Document] ── Blocks ──→ Gate
432
+ │ └── Architecture ── Implements ──→ Requirement
433
+ └── [SW Detailed Design Document] ── Blocks ──→ Gate
434
+ └── Detailed Design ── Implements ──→ Requirement
435
+ └── Detailed Design ── Implements ──→ Architecture
436
+ └── Task ── Implements ──→ Detailed Design
437
+ └── 선행 Task ── Blocks ──→ 후행 Task
438
+ ```
439
+
440
+ ## 라이선스
441
+
442
+ MIT
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,68 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { adfToMarkdown, textToAdf } from '../utils/adf.js';
3
+ const p = (text) => ({ type: 'paragraph', content: [{ type: 'text', text }] });
4
+ const doc = (...content) => ({ type: 'doc', version: 1, content });
5
+ describe('adfToMarkdown', () => {
6
+ it('빈/undefined/비객체 → 빈 문자열', () => {
7
+ expect(adfToMarkdown(undefined)).toBe('');
8
+ expect(adfToMarkdown(null)).toBe('');
9
+ expect(adfToMarkdown({})).toBe('');
10
+ expect(adfToMarkdown('plain string')).toBe('');
11
+ });
12
+ it('단일 paragraph → text', () => {
13
+ expect(adfToMarkdown(doc(p('hello')))).toBe('hello');
14
+ });
15
+ it('여러 paragraph → 빈 줄로 구분', () => {
16
+ expect(adfToMarkdown(doc(p('a'), p('b')))).toBe('a\n\nb');
17
+ });
18
+ it('빈 content paragraph는 무시', () => {
19
+ expect(adfToMarkdown(doc({ type: 'paragraph', content: [] }))).toBe('');
20
+ expect(adfToMarkdown(doc(p('a'), { type: 'paragraph', content: [] }, p('b')))).toBe('a\n\nb');
21
+ });
22
+ it('heading → # level', () => {
23
+ const h2 = { type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: 'Title' }] };
24
+ expect(adfToMarkdown(doc(h2))).toBe('## Title');
25
+ });
26
+ it('bulletList → - items (줄바꿈)', () => {
27
+ const list = {
28
+ type: 'bulletList',
29
+ content: [
30
+ { type: 'listItem', content: [p('one')] },
31
+ { type: 'listItem', content: [p('two')] },
32
+ ],
33
+ };
34
+ expect(adfToMarkdown(doc(list))).toBe('- one\n- two');
35
+ });
36
+ it('orderedList → 1. items', () => {
37
+ const list = { type: 'orderedList', content: [{ type: 'listItem', content: [p('a')] }] };
38
+ expect(adfToMarkdown(doc(list))).toBe('1. a');
39
+ });
40
+ it('text marks: strong/em/code/strike', () => {
41
+ const strong = { type: 'text', text: 'b', marks: [{ type: 'strong' }] };
42
+ const em = { type: 'text', text: 'i', marks: [{ type: 'em' }] };
43
+ const code = { type: 'text', text: 'c', marks: [{ type: 'code' }] };
44
+ expect(adfToMarkdown(doc({ type: 'paragraph', content: [strong] }))).toBe('**b**');
45
+ expect(adfToMarkdown(doc({ type: 'paragraph', content: [em] }))).toBe('*i*');
46
+ expect(adfToMarkdown(doc({ type: 'paragraph', content: [code] }))).toBe('`c`');
47
+ });
48
+ it('hardBreak → 줄바꿈', () => {
49
+ const para = {
50
+ type: 'paragraph',
51
+ content: [{ type: 'text', text: 'a' }, { type: 'hardBreak' }, { type: 'text', text: 'b' }],
52
+ };
53
+ expect(adfToMarkdown(doc(para))).toBe('a\nb');
54
+ });
55
+ it('codeBlock → 펜스', () => {
56
+ const cb = { type: 'codeBlock', content: [{ type: 'text', text: 'const x = 1;' }] };
57
+ expect(adfToMarkdown(doc(cb))).toBe('```\nconst x = 1;\n```');
58
+ });
59
+ it('혼합: paragraph + heading + list', () => {
60
+ const result = adfToMarkdown(doc(p('intro'), { type: 'heading', attrs: { level: 3 }, content: [{ type: 'text', text: 'Sub' }] }, { type: 'bulletList', content: [{ type: 'listItem', content: [p('item')] }] }));
61
+ expect(result).toBe('intro\n\n### Sub\n\n- item');
62
+ });
63
+ it('textToAdf와 왕복 (단일 줄)', () => {
64
+ // textToAdf로 만든 ADF를 다시 markdown으로 (구조 보존)
65
+ expect(adfToMarkdown(textToAdf('한 줄'))).toBe('한 줄');
66
+ });
67
+ });
68
+ //# sourceMappingURL=adf.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adf.test.js","sourceRoot":"","sources":["../../src/__tests__/adf.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,39 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { ANNEX_II_TEMPLATE, matchSection, checkCompleteness } from '../tools/annex-ii-template.js';
3
+ describe('annex-ii-template', () => {
4
+ it('has 9 sections covering all Annex II requirements', () => {
5
+ expect(ANNEX_II_TEMPLATE.sections).toHaveLength(9);
6
+ });
7
+ it('all required sections have match keywords', () => {
8
+ const required = ANNEX_II_TEMPLATE.sections.filter(s => s.required);
9
+ for (const section of required) {
10
+ expect(section.matchKeywords.length).toBeGreaterThan(0);
11
+ }
12
+ });
13
+ it('matchSection finds correct section by summary', () => {
14
+ const risk = matchSection('[Risk Management Report]');
15
+ expect(risk?.id).toBe('risk-management');
16
+ const iu = matchSection('[Intended Use] Document');
17
+ expect(iu?.id).toBe('device-description');
18
+ const arch = matchSection('[SW Architecture Document]');
19
+ expect(arch?.id).toBe('design-manufacturing');
20
+ });
21
+ it('checkCompleteness reports missing required sections', () => {
22
+ const result = checkCompleteness(ANNEX_II_TEMPLATE.sections, []);
23
+ const missing = result.filter(r => r.status === 'missing');
24
+ expect(missing.length).toBeGreaterThan(0);
25
+ });
26
+ it('checkCompleteness reports found when ticket exists', () => {
27
+ const result = checkCompleteness(ANNEX_II_TEMPLATE.sections, [{ key: 'TEST-1', summary: 'PMS 시판후 감시 계획', status: 'Done', issuetype: 'Document' }]);
28
+ const pms = result.find(r => r.section.id === 'pms');
29
+ expect(pms?.status).toBe('found');
30
+ expect(pms?.tickets).toHaveLength(1);
31
+ });
32
+ it('checkCompleteness reports incomplete when approval required but not approved', () => {
33
+ const result = checkCompleteness(ANNEX_II_TEMPLATE.sections, [{ key: 'TEST-1', summary: '[3. 설계 및 제조 정보]', status: 'In Progress', issuetype: 'Document' }]);
34
+ const design = result.find(r => r.section.id === 'design-manufacturing');
35
+ expect(design?.status).toBe('incomplete');
36
+ expect(design?.issues.length).toBeGreaterThan(0);
37
+ });
38
+ });
39
+ //# sourceMappingURL=annex-ii-template.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annex-ii-template.test.js","sourceRoot":"","sources":["../../src/__tests__/annex-ii-template.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};