fmea-api-mcp-server 1.0.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/README.md +87 -0
- package/dist/index.js +191 -0
- package/endpoints/v1/authentication.json +171 -0
- package/endpoints/v1/block-diagrams.json +214 -0
- package/endpoints/v1/divisions.json +118 -0
- package/endpoints/v1/failure-modes.json +301 -0
- package/endpoints/v1/files.json +33 -0
- package/endpoints/v1/fta.json +149 -0
- package/endpoints/v1/knowledge-base.json +359 -0
- package/endpoints/v1/projects.json +342 -0
- package/endpoints/v1/synonyms.json +230 -0
- package/endpoints/v1/terms.json +190 -0
- package/endpoints/v1/users.json +214 -0
- package/endpoints/v1/worksheets.json +61 -0
- package/endpoints/v2/api-keys.json +426 -0
- package/endpoints/v2/block-diagrams.json +371 -0
- package/endpoints/v2/divisions.json +34 -0
- package/endpoints/v2/documents.json +266 -0
- package/endpoints/v2/failure-modes.json +93 -0
- package/endpoints/v2/files.json +41 -0
- package/endpoints/v2/fourm.json +204 -0
- package/endpoints/v2/projects.json +271 -0
- package/endpoints/v2/system.json +61 -0
- package/endpoints/v2/templates.json +137 -0
- package/endpoints/v2/users.json +61 -0
- package/endpoints/v2/worksheets.json +530 -0
- package/package.json +25 -0
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# API Docs MCP Server
|
|
2
|
+
|
|
3
|
+
This project is a Model Context Protocol (MCP) server that provides API specifications from the `endpoints` directory to AI assistants (Claude, Zed, etc.).
|
|
4
|
+
|
|
5
|
+
## Installation & Execution (NPM)
|
|
6
|
+
|
|
7
|
+
This project runs in a Node.js environment.
|
|
8
|
+
|
|
9
|
+
1. **Install Dependencies**
|
|
10
|
+
```bash
|
|
11
|
+
cd mcp-server
|
|
12
|
+
npm install
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
2. **Build**
|
|
16
|
+
```bash
|
|
17
|
+
npm run build
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
3. **Run**
|
|
21
|
+
```bash
|
|
22
|
+
npm start
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Publishing
|
|
26
|
+
|
|
27
|
+
To publish the package to NPM, use the following command:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
cd mcp-server
|
|
31
|
+
npm publish --access public
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
After publishing, you can run it from anywhere using `npx`:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx -y fmea-api-mcp-server
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Client Configuration (Load Configuration)
|
|
41
|
+
|
|
42
|
+
To use this server with clients like Claude Desktop or Zed, add the following to your configuration file.
|
|
43
|
+
|
|
44
|
+
### Local Execution (Source-based)
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"mcpServers": {
|
|
49
|
+
"api-docs": {
|
|
50
|
+
"command": "node",
|
|
51
|
+
"args": [
|
|
52
|
+
"/absolute/path/to/fmea-api-mcp/mcp-server/dist/index.js"
|
|
53
|
+
],
|
|
54
|
+
"env": {
|
|
55
|
+
"ENDPOINTS_DIR": "/absolute/path/to/fmea-api-mcp/endpoints"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### NPX Execution (Published Package-based)
|
|
63
|
+
|
|
64
|
+
When the package is published to NPM:
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"mcpServers": {
|
|
69
|
+
"api-docs": {
|
|
70
|
+
"command": "npx",
|
|
71
|
+
"args": [
|
|
72
|
+
"-y",
|
|
73
|
+
"fmea-api-mcp-server"
|
|
74
|
+
],
|
|
75
|
+
"env": {
|
|
76
|
+
"ENDPOINTS_DIR": "/absolute/path/to/fmea-api-mcp/endpoints"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
- `ENDPOINTS_DIR`: The absolute path to the directory containing API specification files. The default is `../endpoints` (relative path from mcp-server), but it's recommended to set this explicitly when using npx.
|
|
84
|
+
|
|
85
|
+
## Features
|
|
86
|
+
- **Resources**: Can read JSON files in the `endpoints` folder.
|
|
87
|
+
- **Tools**: Use the `search_apis` tool to search APIs by keyword.
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { CallToolRequestSchema, ErrorCode, ListResourcesRequestSchema, ListToolsRequestSchema, McpError, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import * as fs from "fs/promises";
|
|
6
|
+
import * as fsSync from "fs";
|
|
7
|
+
import * as path from "path";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
// Directory where endpoint definitions are stored.
|
|
12
|
+
// Priority:
|
|
13
|
+
// 1. Environment variable ENDPOINTS_DIR
|
|
14
|
+
// 2. Packaged: dist/../endpoints (relative to bundled index.js)
|
|
15
|
+
// 3. Local Dev: dist/../../endpoints (relative to mcp-server/src)
|
|
16
|
+
const PACKAGED_ENDPOINTS_DIR = path.resolve(__dirname, "../endpoints");
|
|
17
|
+
const LOCAL_ENDPOINTS_DIR = path.resolve(__dirname, "../../endpoints");
|
|
18
|
+
const ENDPOINTS_DIR = process.env.ENDPOINTS_DIR ||
|
|
19
|
+
(fsSync.existsSync(PACKAGED_ENDPOINTS_DIR) ? PACKAGED_ENDPOINTS_DIR : LOCAL_ENDPOINTS_DIR);
|
|
20
|
+
class ApiDocsServer {
|
|
21
|
+
server;
|
|
22
|
+
constructor() {
|
|
23
|
+
this.server = new Server({
|
|
24
|
+
name: "api-docs-mcp",
|
|
25
|
+
version: "1.0.0",
|
|
26
|
+
}, {
|
|
27
|
+
capabilities: {
|
|
28
|
+
resources: {},
|
|
29
|
+
tools: {},
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
this.setupResourceHandlers();
|
|
33
|
+
this.setupToolHandlers();
|
|
34
|
+
// Error handling
|
|
35
|
+
this.server.onerror = (error) => console.error("[MCP Error]", error);
|
|
36
|
+
process.on("SIGINT", async () => {
|
|
37
|
+
await this.server.close();
|
|
38
|
+
process.exit(0);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
async setupResourceHandlers() {
|
|
42
|
+
// List available resources (files in endpoints directory)
|
|
43
|
+
this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
44
|
+
try {
|
|
45
|
+
const files = await this.getAllFiles(ENDPOINTS_DIR);
|
|
46
|
+
const resources = files.map((filePath) => {
|
|
47
|
+
const relativePath = path.relative(ENDPOINTS_DIR, filePath);
|
|
48
|
+
// URI scheme: endpoints://v1/system.json
|
|
49
|
+
const uri = `endpoints://${relativePath}`;
|
|
50
|
+
return {
|
|
51
|
+
uri,
|
|
52
|
+
name: relativePath,
|
|
53
|
+
mimeType: "application/json",
|
|
54
|
+
description: `API Documentation for ${relativePath}`
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
return {
|
|
58
|
+
resources,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
console.error("Error listing resources:", error);
|
|
63
|
+
return { resources: [] };
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
// Read specific resource
|
|
67
|
+
this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
68
|
+
const uri = request.params.uri;
|
|
69
|
+
if (!uri.startsWith("endpoints://")) {
|
|
70
|
+
throw new McpError(ErrorCode.InvalidRequest, "Unknown URI scheme");
|
|
71
|
+
}
|
|
72
|
+
const relativePath = uri.replace("endpoints://", "");
|
|
73
|
+
const finalPath = path.join(ENDPOINTS_DIR, relativePath);
|
|
74
|
+
// Security check: prevent directory traversal
|
|
75
|
+
if (!finalPath.startsWith(ENDPOINTS_DIR)) {
|
|
76
|
+
throw new McpError(ErrorCode.InvalidRequest, "Access denied");
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const content = await fs.readFile(finalPath, "utf-8");
|
|
80
|
+
return {
|
|
81
|
+
contents: [
|
|
82
|
+
{
|
|
83
|
+
uri,
|
|
84
|
+
mimeType: "application/json",
|
|
85
|
+
text: content,
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
throw new McpError(ErrorCode.InvalidRequest, `File not found: ${relativePath}`);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
async setupToolHandlers() {
|
|
96
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
97
|
+
return {
|
|
98
|
+
tools: [
|
|
99
|
+
{
|
|
100
|
+
name: "search_apis",
|
|
101
|
+
description: "Search for API endpoints by keyword across all documentation files",
|
|
102
|
+
inputSchema: {
|
|
103
|
+
type: "object",
|
|
104
|
+
properties: {
|
|
105
|
+
query: {
|
|
106
|
+
type: "string",
|
|
107
|
+
description: "Search query (e.g. 'user login', 'POST /api/v1')",
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
required: ["query"],
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
117
|
+
if (request.params.name === "search_apis") {
|
|
118
|
+
const query = String(request.params.arguments?.query).toLowerCase();
|
|
119
|
+
const results = await this.searchInFiles(query);
|
|
120
|
+
return {
|
|
121
|
+
content: [
|
|
122
|
+
{
|
|
123
|
+
type: "text",
|
|
124
|
+
text: JSON.stringify(results, null, 2),
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
throw new McpError(ErrorCode.MethodNotFound, "Tool not found");
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
// Recursive file listing helper
|
|
133
|
+
async getAllFiles(dir) {
|
|
134
|
+
let results = [];
|
|
135
|
+
try {
|
|
136
|
+
const list = await fs.readdir(dir);
|
|
137
|
+
for (const file of list) {
|
|
138
|
+
const filePath = path.join(dir, file);
|
|
139
|
+
const stat = await fs.stat(filePath);
|
|
140
|
+
if (stat && stat.isDirectory()) {
|
|
141
|
+
results = results.concat(await this.getAllFiles(filePath));
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
if (file.endsWith(".json")) {
|
|
145
|
+
results.push(filePath);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
// Directory might not exist or be empty
|
|
152
|
+
console.error(`Warning: Could not read directory ${dir}`);
|
|
153
|
+
}
|
|
154
|
+
return results;
|
|
155
|
+
}
|
|
156
|
+
// Simple search helper
|
|
157
|
+
async searchInFiles(query) {
|
|
158
|
+
const files = await this.getAllFiles(ENDPOINTS_DIR);
|
|
159
|
+
const matches = [];
|
|
160
|
+
for (const filePath of files) {
|
|
161
|
+
try {
|
|
162
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
163
|
+
const json = JSON.parse(content);
|
|
164
|
+
const fileName = path.relative(ENDPOINTS_DIR, filePath);
|
|
165
|
+
// Assuming structure has "endpoints" array
|
|
166
|
+
if (json.endpoints && Array.isArray(json.endpoints)) {
|
|
167
|
+
for (const endpoint of json.endpoints) {
|
|
168
|
+
const str = JSON.stringify(endpoint).toLowerCase();
|
|
169
|
+
if (str.includes(query)) {
|
|
170
|
+
matches.push({
|
|
171
|
+
source: fileName,
|
|
172
|
+
...endpoint
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch (e) {
|
|
179
|
+
// Ignore parse errors
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return matches;
|
|
183
|
+
}
|
|
184
|
+
async run() {
|
|
185
|
+
const transport = new StdioServerTransport();
|
|
186
|
+
await this.server.connect(transport);
|
|
187
|
+
console.error("MCP Server running on stdio");
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
const server = new ApiDocsServer();
|
|
191
|
+
server.run().catch(console.error);
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
{
|
|
2
|
+
"category": "Authentication",
|
|
3
|
+
"version": "v1",
|
|
4
|
+
"description": "인증/인가 관련 API",
|
|
5
|
+
"endpoints": [
|
|
6
|
+
{
|
|
7
|
+
"path": "/api/v1/auth/login",
|
|
8
|
+
"method": "POST",
|
|
9
|
+
"operationId": "login",
|
|
10
|
+
"summary": "User login",
|
|
11
|
+
"description": "Authenticate user with credentials",
|
|
12
|
+
"tags": [],
|
|
13
|
+
"parameters": [],
|
|
14
|
+
"requestBody": {
|
|
15
|
+
"content": {
|
|
16
|
+
"*/*": {
|
|
17
|
+
"schema": {
|
|
18
|
+
"$ref": "#/components/schemas/CredentialsDTO"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"responses": {
|
|
24
|
+
"default": {
|
|
25
|
+
"description": "default response",
|
|
26
|
+
"content": {
|
|
27
|
+
"*/*": {}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"path": "/api/v1/auth/logout",
|
|
34
|
+
"method": "POST",
|
|
35
|
+
"operationId": "logout",
|
|
36
|
+
"summary": "User logout",
|
|
37
|
+
"description": "Logout user with refresh token",
|
|
38
|
+
"tags": [],
|
|
39
|
+
"parameters": [],
|
|
40
|
+
"requestBody": {
|
|
41
|
+
"content": {
|
|
42
|
+
"application/json": {
|
|
43
|
+
"schema": {
|
|
44
|
+
"$ref": "#/components/schemas/TokenDTO"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"responses": {
|
|
50
|
+
"default": {
|
|
51
|
+
"description": "default response",
|
|
52
|
+
"content": {
|
|
53
|
+
"*/*": {}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"path": "/api/v1/auth/refresh",
|
|
60
|
+
"method": "POST",
|
|
61
|
+
"operationId": "refresh",
|
|
62
|
+
"summary": "Refresh access token",
|
|
63
|
+
"description": "Refresh authentication token using refresh token",
|
|
64
|
+
"tags": [],
|
|
65
|
+
"parameters": [],
|
|
66
|
+
"requestBody": {
|
|
67
|
+
"content": {
|
|
68
|
+
"*/*": {
|
|
69
|
+
"schema": {
|
|
70
|
+
"$ref": "#/components/schemas/TokenDTO"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"responses": {
|
|
76
|
+
"default": {
|
|
77
|
+
"description": "default response",
|
|
78
|
+
"content": {
|
|
79
|
+
"*/*": {}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"path": "/api/v1/auth/change-password",
|
|
86
|
+
"method": "POST",
|
|
87
|
+
"operationId": "changePassword",
|
|
88
|
+
"summary": "Change password",
|
|
89
|
+
"description": "Change user password",
|
|
90
|
+
"tags": [],
|
|
91
|
+
"parameters": [],
|
|
92
|
+
"requestBody": {
|
|
93
|
+
"content": {
|
|
94
|
+
"*/*": {
|
|
95
|
+
"schema": {
|
|
96
|
+
"$ref": "#/components/schemas/PasswordChangeDTO"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"responses": {
|
|
102
|
+
"default": {
|
|
103
|
+
"description": "default response",
|
|
104
|
+
"content": {
|
|
105
|
+
"*/*": {}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"path": "/api/v1/auth/password-reset-request",
|
|
112
|
+
"method": "POST",
|
|
113
|
+
"operationId": "passwordResetRequest",
|
|
114
|
+
"summary": "Password reset request",
|
|
115
|
+
"description": "Request password reset",
|
|
116
|
+
"tags": [],
|
|
117
|
+
"parameters": [],
|
|
118
|
+
"requestBody": {
|
|
119
|
+
"content": {
|
|
120
|
+
"*/*": {
|
|
121
|
+
"schema": {
|
|
122
|
+
"$ref": "#/components/schemas/PasswordResetDTO"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"responses": {
|
|
128
|
+
"default": {
|
|
129
|
+
"description": "default response",
|
|
130
|
+
"content": {
|
|
131
|
+
"*/*": {}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"path": "/api/v1/oauth/callback/{service}",
|
|
138
|
+
"method": "GET",
|
|
139
|
+
"operationId": "callback",
|
|
140
|
+
"summary": "OAuth callback",
|
|
141
|
+
"description": "OAuth authentication callback endpoint",
|
|
142
|
+
"tags": [],
|
|
143
|
+
"parameters": [
|
|
144
|
+
{
|
|
145
|
+
"name": "service",
|
|
146
|
+
"in": "path",
|
|
147
|
+
"required": true,
|
|
148
|
+
"schema": {
|
|
149
|
+
"type": "string"
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"name": "code",
|
|
154
|
+
"in": "query",
|
|
155
|
+
"schema": {
|
|
156
|
+
"type": "string"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
],
|
|
160
|
+
"requestBody": null,
|
|
161
|
+
"responses": {
|
|
162
|
+
"default": {
|
|
163
|
+
"description": "default response",
|
|
164
|
+
"content": {
|
|
165
|
+
"*/*": {}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
{
|
|
2
|
+
"category": "Block Diagrams",
|
|
3
|
+
"version": "v1",
|
|
4
|
+
"description": "블록 다이어그램 관련 API",
|
|
5
|
+
"endpoints": [
|
|
6
|
+
{
|
|
7
|
+
"path": "/api/v1/projects/{projectId}/blockdiagrams",
|
|
8
|
+
"method": "GET",
|
|
9
|
+
"operationId": "list",
|
|
10
|
+
"summary": "List block diagrams",
|
|
11
|
+
"description": "Get all block diagrams for a project",
|
|
12
|
+
"tags": [],
|
|
13
|
+
"parameters": [
|
|
14
|
+
{
|
|
15
|
+
"name": "projectId",
|
|
16
|
+
"in": "path",
|
|
17
|
+
"required": true,
|
|
18
|
+
"schema": {
|
|
19
|
+
"type": "string"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"requestBody": null,
|
|
24
|
+
"responses": {
|
|
25
|
+
"default": {
|
|
26
|
+
"description": "default response",
|
|
27
|
+
"content": {
|
|
28
|
+
"application/json": {}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"path": "/api/v1/projects/{projectId}/blockdiagrams/search",
|
|
35
|
+
"method": "GET",
|
|
36
|
+
"operationId": "search",
|
|
37
|
+
"summary": "Search block diagrams",
|
|
38
|
+
"description": "Search block diagrams by model, item, division, or block title",
|
|
39
|
+
"tags": [],
|
|
40
|
+
"parameters": [
|
|
41
|
+
{
|
|
42
|
+
"name": "projectId",
|
|
43
|
+
"in": "path",
|
|
44
|
+
"required": true,
|
|
45
|
+
"schema": {
|
|
46
|
+
"type": "string"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"name": "model",
|
|
51
|
+
"in": "query",
|
|
52
|
+
"schema": {
|
|
53
|
+
"type": "string"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"name": "item",
|
|
58
|
+
"in": "query",
|
|
59
|
+
"schema": {
|
|
60
|
+
"type": "string"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "divisionId",
|
|
65
|
+
"in": "query",
|
|
66
|
+
"schema": {
|
|
67
|
+
"type": "integer",
|
|
68
|
+
"format": "int32"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "blockTitle",
|
|
73
|
+
"in": "query",
|
|
74
|
+
"schema": {
|
|
75
|
+
"type": "string"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
],
|
|
79
|
+
"requestBody": null,
|
|
80
|
+
"responses": {
|
|
81
|
+
"default": {
|
|
82
|
+
"description": "default response",
|
|
83
|
+
"content": {
|
|
84
|
+
"application/json": {}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"path": "/api/v1/projects/{projectId}/blockdiagrams/{blockId}/nodes",
|
|
91
|
+
"method": "GET",
|
|
92
|
+
"operationId": "findNodesByIds",
|
|
93
|
+
"summary": "Find nodes by IDs",
|
|
94
|
+
"description": "Get nodes for a specific block diagram",
|
|
95
|
+
"tags": [],
|
|
96
|
+
"parameters": [
|
|
97
|
+
{
|
|
98
|
+
"name": "projectId",
|
|
99
|
+
"in": "path",
|
|
100
|
+
"required": true,
|
|
101
|
+
"schema": {
|
|
102
|
+
"type": "string"
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"name": "blockId",
|
|
107
|
+
"in": "path",
|
|
108
|
+
"required": true,
|
|
109
|
+
"schema": {
|
|
110
|
+
"type": "string"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
"requestBody": null,
|
|
115
|
+
"responses": {
|
|
116
|
+
"default": {
|
|
117
|
+
"description": "default response",
|
|
118
|
+
"content": {
|
|
119
|
+
"application/json": {}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"path": "/api/v1/projects/{projectId}/blockdiagrams/{blockId}/nodes",
|
|
126
|
+
"method": "POST",
|
|
127
|
+
"operationId": "saveNodes",
|
|
128
|
+
"summary": "Save nodes",
|
|
129
|
+
"description": "Save nodes for a block diagram",
|
|
130
|
+
"tags": [],
|
|
131
|
+
"parameters": [
|
|
132
|
+
{
|
|
133
|
+
"name": "projectId",
|
|
134
|
+
"in": "path",
|
|
135
|
+
"required": true,
|
|
136
|
+
"schema": {
|
|
137
|
+
"type": "string"
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"name": "blockId",
|
|
142
|
+
"in": "path",
|
|
143
|
+
"required": true,
|
|
144
|
+
"schema": {
|
|
145
|
+
"type": "string"
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
],
|
|
149
|
+
"requestBody": {
|
|
150
|
+
"content": {
|
|
151
|
+
"application/json": {
|
|
152
|
+
"schema": {
|
|
153
|
+
"$ref": "#/components/schemas/BlockNodeSaveDTO"
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"responses": {
|
|
159
|
+
"default": {
|
|
160
|
+
"description": "default response",
|
|
161
|
+
"content": {
|
|
162
|
+
"application/json": {}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"path": "/api/v1/projects/{projectId}/blockdiagrams/{blockId}/nodes/batch",
|
|
169
|
+
"method": "POST",
|
|
170
|
+
"operationId": "batchNodes",
|
|
171
|
+
"summary": "Batch create nodes",
|
|
172
|
+
"description": "Create multiple nodes in a batch operation",
|
|
173
|
+
"tags": [],
|
|
174
|
+
"parameters": [
|
|
175
|
+
{
|
|
176
|
+
"name": "projectId",
|
|
177
|
+
"in": "path",
|
|
178
|
+
"required": true,
|
|
179
|
+
"schema": {
|
|
180
|
+
"type": "string"
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"name": "blockId",
|
|
185
|
+
"in": "path",
|
|
186
|
+
"required": true,
|
|
187
|
+
"schema": {
|
|
188
|
+
"type": "string"
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
],
|
|
192
|
+
"requestBody": {
|
|
193
|
+
"content": {
|
|
194
|
+
"application/json": {
|
|
195
|
+
"schema": {
|
|
196
|
+
"type": "array",
|
|
197
|
+
"items": {
|
|
198
|
+
"$ref": "#/components/schemas/BlockNodeBatchDTO"
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
"responses": {
|
|
205
|
+
"default": {
|
|
206
|
+
"description": "default response",
|
|
207
|
+
"content": {
|
|
208
|
+
"application/json": {}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
]
|
|
214
|
+
}
|