@auto-docs-test-code/test-code-mcp 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.
Files changed (3) hide show
  1. package/README.md +78 -0
  2. package/index.mjs +267 -0
  3. package/package.json +28 -0
package/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # @auto-docs/test-code-mcp
2
+
3
+ Auto Docs 백엔드의 `POST /api/ai/api-tests/generate`를 MCP tool로 노출하는 패키지입니다.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @auto-docs/test-code-mcp
9
+ # or
10
+ yarn add @auto-docs/test-code-mcp
11
+ ```
12
+
13
+ 개발 중 로컬 테스트:
14
+
15
+ ```bash
16
+ npm install ./tools/auto-docs-test-code-mcp
17
+ # or
18
+ yarn add file:./tools/auto-docs-test-code-mcp
19
+ ```
20
+
21
+ ## Environment
22
+
23
+ ```bash
24
+ export AUTO_DOCS_API_BASE_URL=http://localhost:8080/api
25
+ export AUTO_DOCS_ACCESS_TOKEN=<your-jwt>
26
+ ```
27
+
28
+ ## MCP Server command
29
+
30
+ ```bash
31
+ auto-docs-test-code-mcp
32
+ ```
33
+
34
+ ## Tool
35
+
36
+ ### `generate_api_tests_and_qa`
37
+
38
+ 입력 파라미터:
39
+ - `projectId` (required, number)
40
+ - `request` (required, string)
41
+ - `baseUrl` (optional)
42
+ - `token` (optional)
43
+ - `apiSpec` (optional)
44
+ - `implementationContext` (optional)
45
+ - `framework` (optional)
46
+ - `targetFilePathHint` (optional)
47
+ - `maxQaItems` (optional)
48
+ - `createQaTickets` (optional, default: `false`)
49
+ - `qaLabels` (optional, string[])
50
+ - `assignees` (optional, string[])
51
+
52
+ 반환:
53
+ - Auto Docs API `data` payload(JSON text)
54
+
55
+ ## Example MCP config
56
+
57
+ ```json
58
+ {
59
+ "mcpServers": {
60
+ "auto-docs-test-code": {
61
+ "command": "auto-docs-test-code-mcp",
62
+ "env": {
63
+ "AUTO_DOCS_API_BASE_URL": "http://localhost:8080/api",
64
+ "AUTO_DOCS_ACCESS_TOKEN": "<JWT>"
65
+ }
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ ## Publish
72
+
73
+ 패키지 퍼블리시는 이 디렉터리에서 실행:
74
+
75
+ ```bash
76
+ cd tools/auto-docs-test-code-mcp
77
+ npm publish --access public
78
+ ```
package/index.mjs ADDED
@@ -0,0 +1,267 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
4
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
5
+ import {
6
+ CallToolRequestSchema,
7
+ ListToolsRequestSchema,
8
+ McpError,
9
+ ErrorCode,
10
+ } from '@modelcontextprotocol/sdk/types.js';
11
+
12
+ const TOOL_NAME = 'generate_api_tests_and_qa';
13
+ const DEFAULT_BASE_URL = 'http://localhost:8080/api';
14
+
15
+ function normalizeBaseUrl(raw) {
16
+ const value = `${raw || DEFAULT_BASE_URL}`.trim();
17
+ if (!value) {
18
+ return DEFAULT_BASE_URL;
19
+ }
20
+ return value.replace(/\/+$/, '');
21
+ }
22
+
23
+ function assertString(value, name, required = false) {
24
+ if (value === undefined || value === null) {
25
+ if (required) {
26
+ throw new McpError(ErrorCode.InvalidParams, `${name} is required.`);
27
+ }
28
+ return undefined;
29
+ }
30
+
31
+ if (typeof value !== 'string') {
32
+ throw new McpError(ErrorCode.InvalidParams, `${name} must be a string.`);
33
+ }
34
+
35
+ const normalized = value.trim();
36
+ if (!normalized && required) {
37
+ throw new McpError(ErrorCode.InvalidParams, `${name} cannot be empty.`);
38
+ }
39
+
40
+ return normalized || undefined;
41
+ }
42
+
43
+ function assertNumber(value, name, required = false) {
44
+ if (value === undefined || value === null) {
45
+ if (required) {
46
+ throw new McpError(ErrorCode.InvalidParams, `${name} is required.`);
47
+ }
48
+ return undefined;
49
+ }
50
+
51
+ const parsed = Number(value);
52
+ if (!Number.isFinite(parsed)) {
53
+ throw new McpError(ErrorCode.InvalidParams, `${name} must be a number.`);
54
+ }
55
+
56
+ return parsed;
57
+ }
58
+
59
+ function assertBoolean(value, name, defaultValue) {
60
+ if (value === undefined || value === null) {
61
+ return defaultValue;
62
+ }
63
+
64
+ if (typeof value !== 'boolean') {
65
+ throw new McpError(ErrorCode.InvalidParams, `${name} must be a boolean.`);
66
+ }
67
+
68
+ return value;
69
+ }
70
+
71
+ function assertStringArray(value, name) {
72
+ if (value === undefined || value === null) {
73
+ return undefined;
74
+ }
75
+
76
+ if (!Array.isArray(value) || value.some((item) => typeof item !== 'string')) {
77
+ throw new McpError(
78
+ ErrorCode.InvalidParams,
79
+ `${name} must be an array of strings.`,
80
+ );
81
+ }
82
+
83
+ return value.map((item) => item.trim()).filter(Boolean);
84
+ }
85
+
86
+ async function callGenerateApiTests(payload) {
87
+ const baseUrl = normalizeBaseUrl(payload.baseUrl || process.env.AUTO_DOCS_API_BASE_URL);
88
+ const token = assertString(
89
+ payload.token || process.env.AUTO_DOCS_ACCESS_TOKEN,
90
+ 'token',
91
+ true,
92
+ );
93
+
94
+ const response = await fetch(`${baseUrl}/ai/api-tests/generate`, {
95
+ method: 'POST',
96
+ headers: {
97
+ 'Content-Type': 'application/json',
98
+ Authorization: `Bearer ${token}`,
99
+ },
100
+ body: JSON.stringify({
101
+ projectId: payload.projectId,
102
+ request: payload.request,
103
+ apiSpec: payload.apiSpec,
104
+ implementationContext: payload.implementationContext,
105
+ framework: payload.framework,
106
+ targetFilePathHint: payload.targetFilePathHint,
107
+ maxQaItems: payload.maxQaItems,
108
+ createQaTickets: payload.createQaTickets,
109
+ qaLabels: payload.qaLabels,
110
+ assignees: payload.assignees,
111
+ }),
112
+ });
113
+
114
+ const json = await response.json().catch(() => null);
115
+
116
+ if (!response.ok) {
117
+ const reason =
118
+ json?.message ||
119
+ json?.error?.message ||
120
+ `Request failed with status ${response.status}`;
121
+
122
+ throw new McpError(ErrorCode.InternalError, `Auto Docs API error: ${reason}`);
123
+ }
124
+
125
+ return json;
126
+ }
127
+
128
+ function createServer() {
129
+ const server = new Server(
130
+ {
131
+ name: '@auto-docs/test-code-mcp',
132
+ version: '0.1.0',
133
+ },
134
+ {
135
+ capabilities: {
136
+ tools: {},
137
+ },
138
+ },
139
+ );
140
+
141
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
142
+ tools: [
143
+ {
144
+ name: TOOL_NAME,
145
+ description:
146
+ 'Generate API test draft and optional QA tickets via Auto Docs backend.',
147
+ inputSchema: {
148
+ type: 'object',
149
+ additionalProperties: false,
150
+ properties: {
151
+ baseUrl: {
152
+ type: 'string',
153
+ description:
154
+ 'Auto Docs API base URL. Default: AUTO_DOCS_API_BASE_URL or http://localhost:8080/api',
155
+ },
156
+ token: {
157
+ type: 'string',
158
+ description:
159
+ 'Access token. Default: AUTO_DOCS_ACCESS_TOKEN environment variable.',
160
+ },
161
+ projectId: {
162
+ type: 'number',
163
+ description: 'Project ID',
164
+ },
165
+ request: {
166
+ type: 'string',
167
+ description: 'Natural-language request for API test generation',
168
+ },
169
+ apiSpec: {
170
+ type: 'string',
171
+ description: 'API specification summary',
172
+ },
173
+ implementationContext: {
174
+ type: 'string',
175
+ description: 'Implementation context summary',
176
+ },
177
+ framework: {
178
+ type: 'string',
179
+ description: 'Testing framework hint (e.g., jest + supertest)',
180
+ },
181
+ targetFilePathHint: {
182
+ type: 'string',
183
+ description: 'Target test file path hint',
184
+ },
185
+ maxQaItems: {
186
+ type: 'number',
187
+ description: 'Maximum number of QA tickets to generate',
188
+ },
189
+ createQaTickets: {
190
+ type: 'boolean',
191
+ description: 'Whether to create QA tickets in backend (default: false)',
192
+ },
193
+ qaLabels: {
194
+ type: 'array',
195
+ items: { type: 'string' },
196
+ description: 'Labels for generated QA tickets',
197
+ },
198
+ assignees: {
199
+ type: 'array',
200
+ items: { type: 'string' },
201
+ description: 'Assignees for generated QA tickets',
202
+ },
203
+ },
204
+ required: ['projectId', 'request'],
205
+ },
206
+ },
207
+ ],
208
+ }));
209
+
210
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
211
+ const { name, arguments: args = {} } = request.params;
212
+
213
+ if (name !== TOOL_NAME) {
214
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
215
+ }
216
+
217
+ const projectId = assertNumber(args.projectId, 'projectId', true);
218
+ if (!Number.isInteger(projectId) || projectId <= 0) {
219
+ throw new McpError(
220
+ ErrorCode.InvalidParams,
221
+ 'projectId must be a positive integer.',
222
+ );
223
+ }
224
+
225
+ const payload = {
226
+ baseUrl: assertString(args.baseUrl, 'baseUrl'),
227
+ token: assertString(args.token, 'token'),
228
+ projectId,
229
+ request: assertString(args.request, 'request', true),
230
+ apiSpec: assertString(args.apiSpec, 'apiSpec'),
231
+ implementationContext: assertString(
232
+ args.implementationContext,
233
+ 'implementationContext',
234
+ ),
235
+ framework: assertString(args.framework, 'framework'),
236
+ targetFilePathHint: assertString(args.targetFilePathHint, 'targetFilePathHint'),
237
+ maxQaItems: assertNumber(args.maxQaItems, 'maxQaItems'),
238
+ createQaTickets: assertBoolean(args.createQaTickets, 'createQaTickets', false),
239
+ qaLabels: assertStringArray(args.qaLabels, 'qaLabels'),
240
+ assignees: assertStringArray(args.assignees, 'assignees'),
241
+ };
242
+
243
+ const result = await callGenerateApiTests(payload);
244
+
245
+ return {
246
+ content: [
247
+ {
248
+ type: 'text',
249
+ text: JSON.stringify(result?.data ?? result, null, 2),
250
+ },
251
+ ],
252
+ };
253
+ });
254
+
255
+ return server;
256
+ }
257
+
258
+ async function main() {
259
+ const server = createServer();
260
+ const transport = new StdioServerTransport();
261
+ await server.connect(transport);
262
+ }
263
+
264
+ main().catch((error) => {
265
+ console.error('[auto-docs-test-code-mcp] fatal error:', error);
266
+ process.exit(1);
267
+ });
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@auto-docs-test-code/test-code-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for Auto Docs AI API test generation",
5
+ "type": "module",
6
+ "main": "index.mjs",
7
+ "bin": {
8
+ "auto-docs-test-code-mcp": "index.mjs"
9
+ },
10
+ "files": [
11
+ "index.mjs",
12
+ "README.md"
13
+ ],
14
+ "keywords": [
15
+ "mcp",
16
+ "model-context-protocol",
17
+ "auto-docs",
18
+ "api-test",
19
+ "qa"
20
+ ],
21
+ "license": "MIT",
22
+ "engines": {
23
+ "node": ">=18"
24
+ },
25
+ "dependencies": {
26
+ "@modelcontextprotocol/sdk": "^1.18.1"
27
+ }
28
+ }