@bimatrix-aud-platform/aud_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 ADDED
@@ -0,0 +1,128 @@
1
+ # @bimatrix-aud-platform/mcp-mtsd-validator
2
+
3
+ MTSD (i-AUD 화면 UI 정의 JSON) 문서를 검증하기 위한 MCP(Model Context Protocol) Server입니다.
4
+
5
+ Claude AI가 MTSD 문서를 생성할 때 실시간으로 스키마 검증을 수행하여 정확한 문서를 만들 수 있도록 도와줍니다.
6
+
7
+ ## 설치 및 등록
8
+
9
+ ### 방법 1: npx로 바로 사용 (권장)
10
+
11
+ 별도 설치 없이 MCP 설정에 다음을 추가합니다.
12
+
13
+ **Claude Code 프로젝트 설정** (`.mcp.json`):
14
+
15
+ ```json
16
+ {
17
+ "mcpServers": {
18
+ "mtsd-validator": {
19
+ "command": "npx",
20
+ "args": ["-y", "@bimatrix-aud-platform/mcp-mtsd-validator"]
21
+ }
22
+ }
23
+ }
24
+ ```
25
+
26
+ **Claude Desktop 전역 설정** (`%APPDATA%\Claude\claude_desktop_config.json`):
27
+
28
+ ```json
29
+ {
30
+ "mcpServers": {
31
+ "mtsd-validator": {
32
+ "command": "npx",
33
+ "args": ["-y", "@bimatrix-aud-platform/mcp-mtsd-validator"]
34
+ }
35
+ }
36
+ }
37
+ ```
38
+
39
+ ### 방법 2: 글로벌 설치 후 사용
40
+
41
+ ```bash
42
+ npm install -g @bimatrix-aud-platform/mcp-mtsd-validator
43
+ ```
44
+
45
+ MCP 설정:
46
+
47
+ ```json
48
+ {
49
+ "mcpServers": {
50
+ "mtsd-validator": {
51
+ "command": "mcp-mtsd-validator"
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ ### 방법 3: 로컬 설치
58
+
59
+ ```bash
60
+ npm install @bimatrix-aud-platform/mcp-mtsd-validator
61
+ ```
62
+
63
+ MCP 설정:
64
+
65
+ ```json
66
+ {
67
+ "mcpServers": {
68
+ "mtsd-validator": {
69
+ "command": "node",
70
+ "args": ["node_modules/@bimatrix-aud-platform/mcp-mtsd-validator/dist/index.js"]
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ ## 제공 도구
77
+
78
+ ### validate_mtsd
79
+ 전체 MTSD 문서를 검증합니다.
80
+
81
+ ```
82
+ 입력: { document: <JSON 문자열 또는 객체> }
83
+ 출력: { valid: boolean, errors?: [...] }
84
+ ```
85
+
86
+ ### validate_part
87
+ 특정 부분만 검증합니다 (점진적 생성 시 유용).
88
+
89
+ ```
90
+ 입력: { partName: "Form", data: <JSON> }
91
+ 출력: { valid: boolean, errors?: [...] }
92
+
93
+ partName 예시:
94
+ - ReportInfo, DataSource, Form, Element
95
+ - LabelElement, ButtonElement, DataGridElement
96
+ - Variable, Module, ExecutionPlan
97
+ ```
98
+
99
+ ### get_schema_info
100
+ 특정 타입의 스키마 정보를 조회합니다.
101
+
102
+ ```
103
+ 입력: { typeName: "Form" }
104
+ 출력: { required: [...], optional: [...], properties: {...} }
105
+ ```
106
+
107
+ ### get_element_types
108
+ 사용 가능한 Element 타입 목록을 반환합니다.
109
+
110
+ ### get_root_structure
111
+ MTSD 문서의 최상위 구조를 반환합니다.
112
+
113
+ ## 사용 예시
114
+
115
+ Claude에게 MTSD 문서 생성을 요청할 때:
116
+
117
+ 1. `get_root_structure`로 전체 구조 파악
118
+ 2. `get_schema_info`로 각 섹션의 필수/선택 속성 확인
119
+ 3. 부분별로 생성 후 `validate_part`로 즉시 검증
120
+ 4. 전체 완성 후 `validate_mtsd`로 최종 검증
121
+
122
+ ## 요구사항
123
+
124
+ - Node.js >= 18.0.0
125
+
126
+ ## 라이선스
127
+
128
+ MIT
@@ -0,0 +1,19 @@
1
+ export interface DataSourceInput {
2
+ name: string;
3
+ connection: string;
4
+ sql?: string;
5
+ params?: string[];
6
+ columns?: Array<{
7
+ name: string;
8
+ type?: string;
9
+ }>;
10
+ dsType?: number;
11
+ useMeta?: boolean;
12
+ useCache?: boolean;
13
+ encrypted?: boolean;
14
+ [key: string]: any;
15
+ }
16
+ export declare function generateDataSource(input: DataSourceInput): {
17
+ dataSource: Record<string, any>;
18
+ warnings: string[];
19
+ };
@@ -0,0 +1,72 @@
1
+ import { generateId } from "../utils/uuid.js";
2
+ const PROCESSED_KEYS = new Set([
3
+ "name",
4
+ "connection",
5
+ "sql",
6
+ "params",
7
+ "columns",
8
+ "dsType",
9
+ "useMeta",
10
+ "useCache",
11
+ "encrypted",
12
+ ]);
13
+ /**
14
+ * SQL 텍스트에서 파라미터 이름 자동 추출
15
+ * 패턴: @:PARAM, :PARAM, %:PARAM
16
+ */
17
+ function extractParamsFromSQL(sql) {
18
+ const paramSet = new Set();
19
+ const regex = /[@%]?:([A-Za-z_][A-Za-z0-9_]*)/g;
20
+ let match;
21
+ while ((match = regex.exec(sql)) !== null) {
22
+ paramSet.add(match[1]);
23
+ }
24
+ return Array.from(paramSet);
25
+ }
26
+ export function generateDataSource(input) {
27
+ const warnings = [];
28
+ const id = generateId("DS");
29
+ // 파라미터 추출
30
+ let paramNames = [];
31
+ if (input.params && input.params.length > 0) {
32
+ paramNames = input.params;
33
+ }
34
+ else if (input.sql) {
35
+ paramNames = extractParamsFromSQL(input.sql);
36
+ if (paramNames.length > 0) {
37
+ warnings.push(`SQL에서 ${paramNames.length}개의 파라미터를 자동 추출했습니다: ${paramNames.join(", ")}`);
38
+ }
39
+ }
40
+ // Params 배열 (스키마: Name, Value 필수)
41
+ const params = paramNames.map((name) => ({
42
+ Name: name.startsWith(":") ? name : `:${name}`,
43
+ Value: "",
44
+ }));
45
+ // Columns 배열 (스키마: Name, Type 필수)
46
+ const columns = (input.columns || []).map((col) => ({
47
+ Name: col.name,
48
+ Type: col.type || "string",
49
+ }));
50
+ const dataSource = {
51
+ Id: id,
52
+ Name: input.name,
53
+ UseMeta: input.useMeta, //? "True" : "False",
54
+ UseCache: input.useCache, // ? "True" : "False",
55
+ ConnectionCode: input.connection,
56
+ Encrypted: input.encrypted, //? "True" : "False",
57
+ DSType: input.dsType ?? 0,
58
+ SQL: input.sql || "",
59
+ Params: params,
60
+ Columns: columns,
61
+ };
62
+ // 나머지 pass-through
63
+ for (const [key, value] of Object.entries(input)) {
64
+ if (!PROCESSED_KEYS.has(key)) {
65
+ const schemaKey = key.charAt(0).toUpperCase() + key.slice(1);
66
+ if (!(schemaKey in dataSource)) {
67
+ dataSource[schemaKey] = value;
68
+ }
69
+ }
70
+ }
71
+ return { dataSource, warnings };
72
+ }
@@ -0,0 +1,163 @@
1
+ export declare function defaultColor(): {
2
+ R: number;
3
+ G: number;
4
+ B: number;
5
+ A: number;
6
+ };
7
+ export declare function defaultBackground(): {};
8
+ export declare function defaultBorder(): {
9
+ CornerRadius: string;
10
+ LineType: "none";
11
+ Thickness: string;
12
+ };
13
+ export declare function defaultFont(): {
14
+ Color: {
15
+ R: number;
16
+ G: number;
17
+ B: number;
18
+ A: number;
19
+ };
20
+ Size: number;
21
+ Family: string;
22
+ Bold: boolean;
23
+ Italic: boolean;
24
+ UnderLine: boolean;
25
+ HorizontalAlignment: "left";
26
+ VerticalAlignment: "middle";
27
+ };
28
+ export declare function defaultDocking(): {
29
+ Left: boolean;
30
+ Right: boolean;
31
+ Top: boolean;
32
+ Bottom: boolean;
33
+ Margin: string;
34
+ HoldSize: boolean;
35
+ MinWidth: number;
36
+ MinHeight: number;
37
+ };
38
+ export declare function defaultPosition(): {
39
+ Left: number;
40
+ Top: number;
41
+ Width: number;
42
+ Height: number;
43
+ ZIndex: number;
44
+ TabIndex: number;
45
+ Docking: {
46
+ Left: boolean;
47
+ Right: boolean;
48
+ Top: boolean;
49
+ Bottom: boolean;
50
+ Margin: string;
51
+ HoldSize: boolean;
52
+ MinWidth: number;
53
+ MinHeight: number;
54
+ };
55
+ };
56
+ export declare function defaultStyle(): {
57
+ Type: number;
58
+ BoxStyle: string;
59
+ Background: {};
60
+ Border: {
61
+ CornerRadius: string;
62
+ LineType: "none";
63
+ Thickness: string;
64
+ };
65
+ };
66
+ export declare function defaultValidator(): {
67
+ ValidateType: number;
68
+ UseGuideMessage: boolean;
69
+ GuideLanguageCode: string;
70
+ UseErrorMessage: boolean;
71
+ ErrorLanguageCode: string;
72
+ };
73
+ export declare function labelDefaults(): {
74
+ LanguageCode: string;
75
+ Text: string;
76
+ Cursor: string;
77
+ Formula: string;
78
+ UseTextOverflow: boolean;
79
+ UseAutoLineBreak: boolean;
80
+ LineSpacing: number;
81
+ HasLineSpacing: boolean;
82
+ MxBinding: string;
83
+ MxBindingUseStyle: boolean;
84
+ };
85
+ export declare function buttonDefaults(): {
86
+ LanguageCode: string;
87
+ Value: string;
88
+ Cursor: string;
89
+ HasNewRadius: boolean;
90
+ };
91
+ export declare function dataGridDefaults(): {
92
+ CellMargin: string;
93
+ Columns: any[];
94
+ UsePPTExport: boolean;
95
+ };
96
+ export declare function groupDefaults(): {
97
+ ChildElements: any[];
98
+ };
99
+ export declare function checkBoxDefaults(): {
100
+ LanguageCode: string;
101
+ Text: string;
102
+ TextPosition: string;
103
+ GroupName: string;
104
+ CheckedValue: string;
105
+ UnCheckedValue: string;
106
+ Checked: boolean;
107
+ ViewType: number;
108
+ };
109
+ export declare function comboBoxDefaults(): {
110
+ DataSource: string;
111
+ Value: string;
112
+ Text: string;
113
+ InitType: number;
114
+ RefreshType: number;
115
+ IsReadOnly: boolean;
116
+ SortType: number;
117
+ AutoRefresh: boolean;
118
+ AfterRefresh: string;
119
+ UseAllItems: boolean;
120
+ UseAllItemsText: string;
121
+ DisplayType: number;
122
+ DataSourceInfo: {
123
+ LabelField: string;
124
+ ValueField: string;
125
+ };
126
+ InitValue: string;
127
+ };
128
+ export declare function textBoxDefaults(): Record<string, any>;
129
+ export declare function numberBoxDefaults(): {
130
+ Format: string;
131
+ Formula: string;
132
+ Value: number;
133
+ Text: string;
134
+ IsReadOnly: boolean;
135
+ Maximum: number;
136
+ Minimum: number;
137
+ MxBinding: string;
138
+ MxBindingUseStyle: boolean;
139
+ };
140
+ export declare function imageDefaults(): {
141
+ Cursor: string;
142
+ Image: {
143
+ FolderCode: string;
144
+ SaveName: string;
145
+ };
146
+ };
147
+ export declare function richTextBoxDefaults(): {
148
+ Formula: string;
149
+ IsReadOnly: boolean;
150
+ MaxLength: number;
151
+ LineSpacing: number;
152
+ HasLineSpacing: boolean;
153
+ MxBinding: string;
154
+ MxBindingUseStyle: boolean;
155
+ Value: string;
156
+ Text: string;
157
+ };
158
+ export declare function userComponentDefaults(): {
159
+ DoRefresh: boolean;
160
+ DoExport: boolean;
161
+ ReportInfo: {};
162
+ };
163
+ export declare const ELEMENT_DEFAULTS_MAP: Record<string, () => Record<string, any>>;
@@ -0,0 +1,187 @@
1
+ // ---- Base structural defaults ----
2
+ export function defaultColor() {
3
+ return { R: 0, G: 0, B: 0, A: 255 };
4
+ }
5
+ export function defaultBackground() {
6
+ return {};
7
+ }
8
+ export function defaultBorder() {
9
+ return {
10
+ CornerRadius: "0,0,0,0",
11
+ LineType: "none",
12
+ Thickness: "0,0,0,0",
13
+ };
14
+ }
15
+ export function defaultFont() {
16
+ return {
17
+ Color: { R: 0, G: 0, B: 0, A: 255 },
18
+ Size: 12,
19
+ Family: "Malgun Gothic",
20
+ Bold: false,
21
+ Italic: false,
22
+ UnderLine: false,
23
+ HorizontalAlignment: "left",
24
+ VerticalAlignment: "middle",
25
+ };
26
+ }
27
+ export function defaultDocking() {
28
+ return {
29
+ Left: false,
30
+ Right: false,
31
+ Top: false,
32
+ Bottom: false,
33
+ Margin: "0,0,0,0",
34
+ HoldSize: false,
35
+ MinWidth: 0,
36
+ MinHeight: 0,
37
+ };
38
+ }
39
+ export function defaultPosition() {
40
+ return {
41
+ Left: 0,
42
+ Top: 0,
43
+ Width: 100,
44
+ Height: 30,
45
+ ZIndex: 1,
46
+ TabIndex: 0,
47
+ Docking: defaultDocking(),
48
+ };
49
+ }
50
+ export function defaultStyle() {
51
+ return {
52
+ Type: 0,
53
+ BoxStyle: "",
54
+ Background: defaultBackground(),
55
+ Border: defaultBorder(),
56
+ };
57
+ }
58
+ export function defaultValidator() {
59
+ return {
60
+ ValidateType: 0,
61
+ UseGuideMessage: false,
62
+ GuideLanguageCode: "",
63
+ UseErrorMessage: false,
64
+ ErrorLanguageCode: "",
65
+ };
66
+ }
67
+ // ---- Element 타입별 기본값 ----
68
+ export function labelDefaults() {
69
+ return {
70
+ LanguageCode: "",
71
+ Text: "",
72
+ Cursor: "default",
73
+ Formula: "",
74
+ UseTextOverflow: false,
75
+ UseAutoLineBreak: false,
76
+ LineSpacing: 0,
77
+ HasLineSpacing: false,
78
+ MxBinding: "",
79
+ MxBindingUseStyle: false,
80
+ };
81
+ }
82
+ export function buttonDefaults() {
83
+ return {
84
+ LanguageCode: "",
85
+ Value: "",
86
+ Cursor: "pointer",
87
+ HasNewRadius: false,
88
+ };
89
+ }
90
+ export function dataGridDefaults() {
91
+ return {
92
+ CellMargin: "2",
93
+ Columns: [],
94
+ UsePPTExport: false,
95
+ };
96
+ }
97
+ export function groupDefaults() {
98
+ return {
99
+ ChildElements: [],
100
+ };
101
+ }
102
+ export function checkBoxDefaults() {
103
+ return {
104
+ LanguageCode: "",
105
+ Text: "",
106
+ TextPosition: "right",
107
+ GroupName: "",
108
+ CheckedValue: "Y",
109
+ UnCheckedValue: "N",
110
+ Checked: false,
111
+ ViewType: 0,
112
+ };
113
+ }
114
+ export function comboBoxDefaults() {
115
+ return {
116
+ DataSource: "",
117
+ Value: "",
118
+ Text: "",
119
+ InitType: 0,
120
+ RefreshType: 0,
121
+ IsReadOnly: false,
122
+ SortType: 0,
123
+ AutoRefresh: false,
124
+ AfterRefresh: "",
125
+ UseAllItems: false,
126
+ UseAllItemsText: "",
127
+ DisplayType: 0,
128
+ DataSourceInfo: { LabelField: "", ValueField: "" },
129
+ InitValue: "",
130
+ };
131
+ }
132
+ export function textBoxDefaults() {
133
+ return {};
134
+ }
135
+ export function numberBoxDefaults() {
136
+ return {
137
+ Format: "#,##0",
138
+ Formula: "",
139
+ Value: 0,
140
+ Text: "",
141
+ IsReadOnly: false,
142
+ Maximum: 999999999,
143
+ Minimum: -999999999,
144
+ MxBinding: "",
145
+ MxBindingUseStyle: false,
146
+ };
147
+ }
148
+ export function imageDefaults() {
149
+ return {
150
+ Cursor: "default",
151
+ Image: { FolderCode: "", SaveName: "" },
152
+ };
153
+ }
154
+ export function richTextBoxDefaults() {
155
+ return {
156
+ Formula: "",
157
+ IsReadOnly: false,
158
+ MaxLength: 0,
159
+ LineSpacing: 0,
160
+ HasLineSpacing: false,
161
+ MxBinding: "",
162
+ MxBindingUseStyle: false,
163
+ Value: "",
164
+ Text: "",
165
+ };
166
+ }
167
+ export function userComponentDefaults() {
168
+ return {
169
+ DoRefresh: false,
170
+ DoExport: false,
171
+ ReportInfo: {},
172
+ };
173
+ }
174
+ // Type → defaults 팩토리 매핑
175
+ export const ELEMENT_DEFAULTS_MAP = {
176
+ Label: labelDefaults,
177
+ Button: buttonDefaults,
178
+ DataGrid: dataGridDefaults,
179
+ Group: groupDefaults,
180
+ CheckBox: checkBoxDefaults,
181
+ ComboBox: comboBoxDefaults,
182
+ TextBox: textBoxDefaults,
183
+ NumberBox: numberBoxDefaults,
184
+ Image: imageDefaults,
185
+ RichTextBox: richTextBoxDefaults,
186
+ UserComponent: userComponentDefaults,
187
+ };
@@ -0,0 +1,31 @@
1
+ export interface ElementInput {
2
+ type: string;
3
+ id?: string;
4
+ name?: string;
5
+ text?: string;
6
+ position?: {
7
+ left?: number;
8
+ top?: number;
9
+ width?: number;
10
+ height?: number;
11
+ };
12
+ docking?: string;
13
+ font?: {
14
+ size?: number;
15
+ bold?: boolean;
16
+ italic?: boolean;
17
+ color?: string;
18
+ family?: string;
19
+ align?: string;
20
+ valign?: string;
21
+ };
22
+ background?: string;
23
+ border?: string;
24
+ color?: string;
25
+ visible?: boolean;
26
+ [key: string]: any;
27
+ }
28
+ export declare function generateElement(input: ElementInput): {
29
+ element: Record<string, any>;
30
+ warnings: string[];
31
+ };