@yinuo-ngm/mcp-server 0.1.2 → 0.1.4
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 +191 -208
- package/lib/audit/audit-event.d.ts +14 -0
- package/lib/audit/audit-event.js +2 -0
- package/lib/audit/audit-log.service.d.ts +7 -0
- package/lib/audit/audit-log.service.js +187 -0
- package/lib/audit/redact.d.ts +3 -0
- package/lib/audit/redact.js +28 -0
- package/lib/catalog/capabilities/blocked-local-actions.d.ts +1 -0
- package/lib/catalog/capabilities/blocked-local-actions.js +18 -0
- package/lib/catalog/capabilities/frontend-standard.d.ts +2 -0
- package/lib/catalog/capabilities/frontend-standard.js +36 -0
- package/lib/catalog/capabilities/hub-v2.d.ts +2 -0
- package/lib/catalog/capabilities/hub-v2.js +34 -0
- package/lib/catalog/capabilities/nginx.d.ts +2 -0
- package/lib/catalog/capabilities/nginx.js +23 -0
- package/lib/catalog/capabilities/project.d.ts +2 -0
- package/lib/catalog/capabilities/project.js +23 -0
- package/lib/catalog/capabilities/router.d.ts +2 -0
- package/lib/catalog/capabilities/router.js +11 -0
- package/lib/catalog/capabilities/runtime.d.ts +2 -0
- package/lib/catalog/capabilities/runtime.js +17 -0
- package/lib/catalog/capabilities/workspace.d.ts +2 -0
- package/lib/catalog/capabilities/workspace.js +23 -0
- package/lib/catalog/helpers.d.ts +3 -0
- package/lib/catalog/helpers.js +42 -0
- package/lib/catalog/index.d.ts +4 -0
- package/lib/catalog/index.js +23 -0
- package/lib/catalog/tools/frontend-standard.d.ts +2 -0
- package/lib/catalog/tools/frontend-standard.js +166 -0
- package/lib/catalog/tools/hub-v2-api.d.ts +2 -0
- package/lib/catalog/tools/hub-v2-api.js +124 -0
- package/lib/catalog/tools/hub-v2-docs.d.ts +2 -0
- package/lib/catalog/tools/hub-v2-docs.js +40 -0
- package/lib/catalog/tools/nginx.d.ts +2 -0
- package/lib/catalog/tools/nginx.js +82 -0
- package/lib/catalog/tools/project.d.ts +2 -0
- package/lib/catalog/tools/project.js +124 -0
- package/lib/catalog/tools/router.d.ts +2 -0
- package/lib/catalog/tools/router.js +26 -0
- package/lib/catalog/tools/runtime.d.ts +2 -0
- package/lib/catalog/tools/runtime.js +40 -0
- package/lib/catalog/tools/workspace.d.ts +2 -0
- package/lib/catalog/tools/workspace.js +75 -0
- package/lib/catalog/types.d.ts +15 -0
- package/lib/catalog/types.js +2 -0
- package/lib/context/create-tool-context.js +11 -10
- package/lib/context/local-server-client.d.ts +2 -0
- package/lib/context/local-server-client.js +174 -0
- package/lib/context/tool-context.d.ts +36 -0
- package/lib/doctor.d.ts +8 -0
- package/lib/doctor.js +194 -0
- package/lib/errors/error-codes.d.ts +12 -0
- package/lib/errors/error-codes.js +14 -0
- package/lib/errors/mcp-tool-error.d.ts +8 -0
- package/lib/errors/mcp-tool-error.js +14 -0
- package/lib/filesystem/project-files.d.ts +18 -0
- package/lib/filesystem/project-files.js +112 -0
- package/lib/git/local-git-read-service.d.ts +2 -0
- package/lib/git/local-git-read-service.js +96 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +4 -0
- package/lib/policy/assert-tool-policy.js +10 -1
- package/lib/register-tools.js +67 -10
- package/lib/registry/tool-names.d.ts +95 -0
- package/lib/registry/tool-names.js +97 -0
- package/lib/services/path-guard.service.d.ts +4 -0
- package/lib/services/path-guard.service.js +75 -0
- package/lib/services/permission.service.d.ts +5 -0
- package/lib/services/permission.service.js +38 -0
- package/lib/services/project-resolver.service.d.ts +32 -0
- package/lib/services/project-resolver.service.js +95 -0
- package/lib/standard/frontend-standard.default.d.ts +2 -0
- package/lib/standard/frontend-standard.default.js +51 -0
- package/lib/standard/frontend-standard.schema.d.ts +196 -0
- package/lib/standard/frontend-standard.schema.js +61 -0
- package/lib/standard/frontend-standard.service.d.ts +79 -0
- package/lib/standard/frontend-standard.service.js +115 -0
- package/lib/standard/project-scan.d.ts +9 -0
- package/lib/standard/project-scan.js +91 -0
- package/lib/standard/validators/angular-structure.validator.d.ts +4 -0
- package/lib/standard/validators/angular-structure.validator.js +75 -0
- package/lib/standard/validators/component.validator.d.ts +4 -0
- package/lib/standard/validators/component.validator.js +94 -0
- package/lib/standard/validators/git.validator.d.ts +8 -0
- package/lib/standard/validators/git.validator.js +32 -0
- package/lib/standard/validators/review.validator.d.ts +15 -0
- package/lib/standard/validators/review.validator.js +67 -0
- package/lib/standard/validators/test.validator.d.ts +19 -0
- package/lib/standard/validators/test.validator.js +89 -0
- package/lib/tool-catalog.d.ts +2 -0
- package/lib/tool-catalog.js +6 -0
- package/lib/tools/angular/angular-standard.tools.d.ts +2 -0
- package/lib/tools/angular/angular-standard.tools.js +53 -0
- package/lib/tools/angular/index.d.ts +1 -0
- package/lib/tools/angular/index.js +5 -0
- package/lib/tools/capability.tools.d.ts +2 -0
- package/lib/tools/capability.tools.js +205 -0
- package/lib/tools/controlled/index.d.ts +2 -0
- package/lib/tools/controlled/index.js +13 -0
- package/lib/tools/controlled/local-server.d.ts +6 -0
- package/lib/tools/controlled/local-server.js +17 -0
- package/lib/tools/controlled/operation-policy.d.ts +22 -0
- package/lib/tools/controlled/operation-policy.js +50 -0
- package/lib/tools/controlled/operation-result.d.ts +30 -0
- package/lib/tools/controlled/operation-result.js +33 -0
- package/lib/tools/controlled/schemas.d.ts +159 -0
- package/lib/tools/controlled/schemas.js +49 -0
- package/lib/tools/controlled.tools.d.ts +1 -0
- package/lib/tools/controlled.tools.js +5 -0
- package/lib/tools/file-write.tools.d.ts +2 -0
- package/lib/tools/file-write.tools.js +70 -0
- package/lib/tools/git.tools.js +109 -8
- package/lib/tools/hub-v2/client.d.ts +6 -1
- package/lib/tools/hub-v2/client.js +15 -0
- package/lib/tools/hub-v2/config/config-paths.d.ts +2 -0
- package/lib/tools/hub-v2/config/config-paths.js +17 -0
- package/lib/tools/hub-v2/config/env.d.ts +1 -0
- package/lib/tools/hub-v2/config/env.js +12 -0
- package/lib/tools/hub-v2/config/index.d.ts +8 -0
- package/lib/tools/hub-v2/config/index.js +18 -0
- package/lib/tools/hub-v2/config/jsonc.d.ts +5 -0
- package/lib/tools/hub-v2/config/jsonc.js +86 -0
- package/lib/tools/hub-v2/config/load-config.d.ts +18 -0
- package/lib/tools/hub-v2/config/load-config.js +93 -0
- package/lib/tools/hub-v2/config/project-selector.d.ts +5 -0
- package/lib/tools/hub-v2/config/project-selector.js +92 -0
- package/lib/tools/hub-v2/config/resolve-context.d.ts +13 -0
- package/lib/tools/hub-v2/config/resolve-context.js +33 -0
- package/lib/tools/hub-v2/docs.tools.js +138 -4
- package/lib/tools/hub-v2/index.js +2 -0
- package/lib/tools/hub-v2/issues-workflow.tools.d.ts +2 -0
- package/lib/tools/hub-v2/issues-workflow.tools.js +199 -0
- package/lib/tools/hub-v2/issues.tools.js +96 -6
- package/lib/tools/hub-v2/projects.tools.js +16 -3
- package/lib/tools/hub-v2/raw.d.ts +8 -0
- package/lib/tools/hub-v2/raw.js +33 -0
- package/lib/tools/hub-v2/rd.tools.js +167 -8
- package/lib/tools/hub-v2/schemas.d.ts +668 -71
- package/lib/tools/hub-v2/schemas.js +152 -1
- package/lib/tools/hub-v2/upload.tools.js +53 -5
- package/lib/tools/index.d.ts +1 -0
- package/lib/tools/index.js +22 -0
- package/lib/tools/log.tools.js +33 -6
- package/lib/tools/nginx/index.d.ts +1 -0
- package/lib/tools/nginx/index.js +5 -0
- package/lib/tools/nginx/nginx-control.tools.d.ts +2 -0
- package/lib/tools/nginx/nginx-control.tools.js +133 -0
- package/lib/tools/nginx/nginx-proxy.d.ts +24 -0
- package/lib/tools/nginx/nginx-proxy.js +154 -0
- package/lib/tools/nginx.tools.d.ts +2 -0
- package/lib/tools/nginx.tools.js +111 -0
- package/lib/tools/project/index.d.ts +2 -0
- package/lib/tools/project/index.js +7 -0
- package/lib/tools/project/launch-status.d.ts +10 -0
- package/lib/tools/project/launch-status.js +78 -0
- package/lib/tools/project/local-diagnostics.d.ts +19 -0
- package/lib/tools/project/local-diagnostics.js +97 -0
- package/lib/tools/project/observe-redaction.d.ts +3 -0
- package/lib/tools/project/observe-redaction.js +25 -0
- package/lib/tools/project/observe-runtime.d.ts +72 -0
- package/lib/tools/project/observe-runtime.js +147 -0
- package/lib/tools/project/project-control.tools.d.ts +2 -0
- package/lib/tools/project/project-control.tools.js +216 -0
- package/lib/tools/project/project-observe.tools.d.ts +2 -0
- package/lib/tools/project/project-observe.tools.js +191 -0
- package/lib/tools/project/runtime-config.d.ts +7 -0
- package/lib/tools/project/runtime-config.js +50 -0
- package/lib/tools/project-observe.tools.d.ts +1 -0
- package/lib/tools/project-observe.tools.js +5 -0
- package/lib/tools/project.tools.d.ts +8 -0
- package/lib/tools/project.tools.js +97 -6
- package/lib/tools/proxy.tools.js +4 -4
- package/lib/tools/review/index.d.ts +1 -0
- package/lib/tools/review/index.js +5 -0
- package/lib/tools/review/review.tools.d.ts +2 -0
- package/lib/tools/review/review.tools.js +152 -0
- package/lib/tools/runtime/index.d.ts +1 -0
- package/lib/tools/runtime/index.js +5 -0
- package/lib/tools/runtime/runtime-control.tools.d.ts +2 -0
- package/lib/tools/runtime/runtime-control.tools.js +89 -0
- package/lib/tools/runtime.tools.js +41 -4
- package/lib/tools/standard/index.d.ts +1 -0
- package/lib/tools/standard/index.js +5 -0
- package/lib/tools/standard/standard.tools.d.ts +2 -0
- package/lib/tools/standard/standard.tools.js +91 -0
- package/lib/tools/task.tools.js +44 -9
- package/lib/tools/test/index.d.ts +1 -0
- package/lib/tools/test/index.js +5 -0
- package/lib/tools/test/test-standard.tools.d.ts +2 -0
- package/lib/tools/test/test-standard.tools.js +51 -0
- package/lib/tools/tool-catalog.d.ts +2 -0
- package/lib/tools/tool-catalog.js +7 -0
- package/lib/tools/workflow/frontend-workflow.tools.d.ts +2 -0
- package/lib/tools/workflow/frontend-workflow.tools.js +364 -0
- package/lib/tools/workflow/index.d.ts +1 -0
- package/lib/tools/workflow/index.js +5 -0
- package/lib/tools/workspace-package.d.ts +22 -0
- package/lib/tools/workspace-package.js +130 -0
- package/lib/tools/workspace.tools.d.ts +7 -0
- package/lib/tools/workspace.tools.js +336 -0
- package/lib/utils/errors.js +6 -1
- package/lib/utils/result.d.ts +9 -0
- package/lib/utils/result.js +9 -0
- package/lib/workflow/frontend-task.schema.d.ts +83 -0
- package/lib/workflow/frontend-task.schema.js +25 -0
- package/lib/workflow/frontend-task.service.d.ts +57 -0
- package/lib/workflow/frontend-task.service.js +195 -0
- package/lib/workflow/workflow-status.d.ts +2 -0
- package/lib/workflow/workflow-status.js +14 -0
- package/lib/workflow/workflow-transition.d.ts +9 -0
- package/lib/workflow/workflow-transition.js +38 -0
- package/package.json +5 -3
- package/lib/tools/hub-v2/config.d.ts +0 -34
- package/lib/tools/hub-v2/config.js +0 -297
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.rdUpdateProgressSchema = exports.rdStageTaskCreateSchema = exports.rdStageTasksListSchema = exports.rdAdvanceStageSchema = exports.rdCreateSchema = exports.rdGetSchema = exports.rdListSchema = exports.markdownImageUploadSchema = exports.issueUpdateSchema = exports.issueCommentSchema = exports.issueCreateSchema = exports.issueGetSchema = exports.issuesListSchema = exports.docsGetBySlugSchema = exports.docsGetSchema = exports.docsListSchema = exports.pagingSchema = exports.projectSelectorSchema = void 0;
|
|
3
|
+
exports.rdUpdateSchema = exports.rdCloseSchema = exports.rdCompleteSchema = exports.rdBlockSchema = exports.rdSimpleWriteSchema = exports.rdUpdateProgressSchema = exports.rdStageTaskCreateSchema = exports.rdStageTasksListSchema = exports.rdAdvanceStageSchema = exports.rdCreateSchema = exports.rdUploadRawSchema = exports.rdReadDetailSchema = exports.rdGetSchema = exports.rdListSchema = exports.fileUploadSchema = exports.markdownImageUploadSchema = exports.issueUpdateSchema = exports.issueParticipantRemoveSchema = exports.issueBranchCompleteSchema = exports.issueBranchActionSchema = exports.issueBranchStartMineSchema = exports.issueBranchCreateSchema = exports.issueParticipantAddSchema = exports.issueCloseSchema = exports.issueReopenSchema = exports.issueResolveSchema = exports.issueSimpleWriteSchema = exports.issueAssignSchema = exports.issueCommentSchema = exports.issueCreateSchema = exports.issueUploadRawSchema = exports.issueAttachmentRawSchema = exports.issueReadDetailSchema = exports.issueGetSchema = exports.issuesListSchema = exports.docsPublishSchema = exports.docsUpdateSchema = exports.docsCreateSchema = exports.docsGetBySlugSchema = exports.docsGetSchema = exports.docsListSchema = exports.pagingSchema = exports.projectMembersListSchema = exports.projectSelectorSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
exports.projectSelectorSchema = zod_1.z.object({
|
|
6
6
|
project: zod_1.z.string().trim().min(1).optional(),
|
|
7
7
|
projectKey: zod_1.z.string().trim().min(1).optional(),
|
|
8
8
|
}).strict();
|
|
9
|
+
exports.projectMembersListSchema = exports.projectSelectorSchema;
|
|
9
10
|
exports.pagingSchema = zod_1.z.object({
|
|
10
11
|
page: zod_1.z.number().int().min(1).optional(),
|
|
11
12
|
pageSize: zod_1.z.number().int().min(1).max(200).optional(),
|
|
@@ -25,6 +26,39 @@ exports.docsGetBySlugSchema = exports.projectSelectorSchema.extend({
|
|
|
25
26
|
slug: zod_1.z.string().trim().min(1),
|
|
26
27
|
contentOnly: zod_1.z.boolean().optional(),
|
|
27
28
|
}).strict();
|
|
29
|
+
exports.docsCreateSchema = exports.projectSelectorSchema.extend({
|
|
30
|
+
title: zod_1.z.string().trim().min(1).max(120),
|
|
31
|
+
content: zod_1.z.string().min(1).optional(),
|
|
32
|
+
contentMd: zod_1.z.string().min(1).optional(),
|
|
33
|
+
slug: zod_1.z.string().trim().min(1).max(80).optional(),
|
|
34
|
+
category: zod_1.z.string().trim().max(80).optional(),
|
|
35
|
+
categoryId: zod_1.z.string().trim().max(80).optional(),
|
|
36
|
+
summary: zod_1.z.string().trim().max(500).optional(),
|
|
37
|
+
tags: zod_1.z.array(zod_1.z.string().trim().min(1).max(40)).max(20).optional(),
|
|
38
|
+
status: zod_1.z.enum(["draft"]).optional(),
|
|
39
|
+
source: zod_1.z.string().trim().max(40).optional(),
|
|
40
|
+
version: zod_1.z.string().trim().max(40).optional(),
|
|
41
|
+
confirm: zod_1.z.boolean().optional(),
|
|
42
|
+
}).strict();
|
|
43
|
+
exports.docsUpdateSchema = exports.projectSelectorSchema.extend({
|
|
44
|
+
docId: zod_1.z.string().trim().min(1),
|
|
45
|
+
title: zod_1.z.string().trim().min(1).max(120).optional(),
|
|
46
|
+
content: zod_1.z.string().min(1).optional(),
|
|
47
|
+
contentMd: zod_1.z.string().min(1).optional(),
|
|
48
|
+
slug: zod_1.z.string().trim().min(1).max(80).optional(),
|
|
49
|
+
category: zod_1.z.string().trim().max(80).optional(),
|
|
50
|
+
categoryId: zod_1.z.string().trim().max(80).optional(),
|
|
51
|
+
summary: zod_1.z.string().trim().max(500).nullable().optional(),
|
|
52
|
+
tags: zod_1.z.array(zod_1.z.string().trim().min(1).max(40)).max(20).optional(),
|
|
53
|
+
source: zod_1.z.string().trim().max(40).optional(),
|
|
54
|
+
version: zod_1.z.string().trim().max(40).nullable().optional(),
|
|
55
|
+
confirm: zod_1.z.boolean().optional(),
|
|
56
|
+
}).strict();
|
|
57
|
+
exports.docsPublishSchema = exports.projectSelectorSchema.extend({
|
|
58
|
+
docId: zod_1.z.string().trim().min(1),
|
|
59
|
+
source: zod_1.z.string().trim().max(40).optional(),
|
|
60
|
+
confirm: zod_1.z.boolean().optional(),
|
|
61
|
+
}).strict();
|
|
28
62
|
exports.issuesListSchema = exports.projectSelectorSchema.extend({
|
|
29
63
|
page: zod_1.z.number().int().min(1).optional(),
|
|
30
64
|
pageSize: zod_1.z.number().int().min(1).max(200).optional(),
|
|
@@ -38,6 +72,17 @@ exports.issuesListSchema = exports.projectSelectorSchema.extend({
|
|
|
38
72
|
exports.issueGetSchema = exports.projectSelectorSchema.extend({
|
|
39
73
|
issueId: zod_1.z.string().trim().min(1),
|
|
40
74
|
}).strict();
|
|
75
|
+
exports.issueReadDetailSchema = exports.issueGetSchema;
|
|
76
|
+
exports.issueAttachmentRawSchema = exports.projectSelectorSchema.extend({
|
|
77
|
+
issueId: zod_1.z.string().trim().min(1),
|
|
78
|
+
attachmentId: zod_1.z.string().trim().min(1),
|
|
79
|
+
maxBytes: zod_1.z.number().int().min(1).max(5 * 1024 * 1024).optional(),
|
|
80
|
+
}).strict();
|
|
81
|
+
exports.issueUploadRawSchema = exports.projectSelectorSchema.extend({
|
|
82
|
+
issueId: zod_1.z.string().trim().min(1),
|
|
83
|
+
uploadId: zod_1.z.string().trim().min(1),
|
|
84
|
+
maxBytes: zod_1.z.number().int().min(1).max(5 * 1024 * 1024).optional(),
|
|
85
|
+
}).strict();
|
|
41
86
|
const issueTypeSchema = zod_1.z.enum(["bug", "feature", "change", "improvement", "task", "test"]);
|
|
42
87
|
const issuePrioritySchema = zod_1.z.enum(["low", "medium", "high", "critical"]);
|
|
43
88
|
exports.issueCreateSchema = exports.projectSelectorSchema.extend({
|
|
@@ -59,6 +104,64 @@ exports.issueCommentSchema = exports.projectSelectorSchema.extend({
|
|
|
59
104
|
mentions: zod_1.z.array(zod_1.z.string().trim().min(1)).optional(),
|
|
60
105
|
confirm: zod_1.z.boolean().optional(),
|
|
61
106
|
}).strict();
|
|
107
|
+
exports.issueAssignSchema = exports.projectSelectorSchema.extend({
|
|
108
|
+
issueId: zod_1.z.string().trim().min(1),
|
|
109
|
+
assigneeId: zod_1.z.string().trim().min(1),
|
|
110
|
+
confirm: zod_1.z.boolean().optional(),
|
|
111
|
+
}).strict();
|
|
112
|
+
exports.issueSimpleWriteSchema = exports.projectSelectorSchema.extend({
|
|
113
|
+
issueId: zod_1.z.string().trim().min(1),
|
|
114
|
+
confirm: zod_1.z.boolean().optional(),
|
|
115
|
+
}).strict();
|
|
116
|
+
exports.issueResolveSchema = exports.projectSelectorSchema.extend({
|
|
117
|
+
issueId: zod_1.z.string().trim().min(1),
|
|
118
|
+
resolutionSummary: zod_1.z.string().optional(),
|
|
119
|
+
confirm: zod_1.z.boolean().optional(),
|
|
120
|
+
}).strict();
|
|
121
|
+
exports.issueReopenSchema = exports.projectSelectorSchema.extend({
|
|
122
|
+
issueId: zod_1.z.string().trim().min(1),
|
|
123
|
+
remark: zod_1.z.string().optional(),
|
|
124
|
+
confirm: zod_1.z.boolean().optional(),
|
|
125
|
+
}).strict();
|
|
126
|
+
exports.issueCloseSchema = exports.projectSelectorSchema.extend({
|
|
127
|
+
issueId: zod_1.z.string().trim().min(1),
|
|
128
|
+
reason: zod_1.z.string().trim().optional(),
|
|
129
|
+
remark: zod_1.z.string().optional(),
|
|
130
|
+
confirm: zod_1.z.boolean().optional(),
|
|
131
|
+
}).strict();
|
|
132
|
+
exports.issueParticipantAddSchema = exports.projectSelectorSchema.extend({
|
|
133
|
+
issueId: zod_1.z.string().trim().min(1),
|
|
134
|
+
userId: zod_1.z.string().trim().min(1),
|
|
135
|
+
taskTitle: zod_1.z.string().trim().max(80).optional(),
|
|
136
|
+
confirm: zod_1.z.boolean().optional(),
|
|
137
|
+
}).strict();
|
|
138
|
+
exports.issueBranchCreateSchema = exports.projectSelectorSchema.extend({
|
|
139
|
+
issueId: zod_1.z.string().trim().min(1),
|
|
140
|
+
ownerUserId: zod_1.z.string().trim().min(1),
|
|
141
|
+
title: zod_1.z.string().trim().min(1).max(80),
|
|
142
|
+
confirm: zod_1.z.boolean().optional(),
|
|
143
|
+
}).strict();
|
|
144
|
+
exports.issueBranchStartMineSchema = exports.projectSelectorSchema.extend({
|
|
145
|
+
issueId: zod_1.z.string().trim().min(1),
|
|
146
|
+
title: zod_1.z.string().trim().min(1).max(80),
|
|
147
|
+
confirm: zod_1.z.boolean().optional(),
|
|
148
|
+
}).strict();
|
|
149
|
+
exports.issueBranchActionSchema = exports.projectSelectorSchema.extend({
|
|
150
|
+
issueId: zod_1.z.string().trim().min(1),
|
|
151
|
+
branchId: zod_1.z.string().trim().min(1),
|
|
152
|
+
confirm: zod_1.z.boolean().optional(),
|
|
153
|
+
}).strict();
|
|
154
|
+
exports.issueBranchCompleteSchema = exports.projectSelectorSchema.extend({
|
|
155
|
+
issueId: zod_1.z.string().trim().min(1),
|
|
156
|
+
branchId: zod_1.z.string().trim().min(1),
|
|
157
|
+
summary: zod_1.z.string().trim().max(500).optional(),
|
|
158
|
+
confirm: zod_1.z.boolean().optional(),
|
|
159
|
+
}).strict();
|
|
160
|
+
exports.issueParticipantRemoveSchema = exports.projectSelectorSchema.extend({
|
|
161
|
+
issueId: zod_1.z.string().trim().min(1),
|
|
162
|
+
participantId: zod_1.z.string().trim().min(1),
|
|
163
|
+
confirm: zod_1.z.boolean().optional(),
|
|
164
|
+
}).strict();
|
|
62
165
|
exports.issueUpdateSchema = exports.projectSelectorSchema.extend({
|
|
63
166
|
issueId: zod_1.z.string().trim().min(1),
|
|
64
167
|
title: zod_1.z.string().trim().optional(),
|
|
@@ -79,6 +182,14 @@ exports.markdownImageUploadSchema = exports.projectSelectorSchema.extend({
|
|
|
79
182
|
alt: zod_1.z.string().trim().min(1).optional(),
|
|
80
183
|
confirm: zod_1.z.boolean().optional(),
|
|
81
184
|
}).strict();
|
|
185
|
+
exports.fileUploadSchema = exports.projectSelectorSchema.extend({
|
|
186
|
+
target: zod_1.z.enum(["issueAttachment", "taskSheetAttachment"]),
|
|
187
|
+
filePath: zod_1.z.string().trim().min(1).optional(),
|
|
188
|
+
contentBase64: zod_1.z.string().trim().min(1).optional(),
|
|
189
|
+
fileName: zod_1.z.string().trim().min(1).optional(),
|
|
190
|
+
mimeType: zod_1.z.string().trim().min(1).optional(),
|
|
191
|
+
confirm: zod_1.z.boolean().optional(),
|
|
192
|
+
}).strict();
|
|
82
193
|
exports.rdListSchema = exports.projectSelectorSchema.extend({
|
|
83
194
|
page: zod_1.z.number().int().min(1).optional(),
|
|
84
195
|
pageSize: zod_1.z.number().int().min(1).max(200).optional(),
|
|
@@ -92,6 +203,12 @@ exports.rdListSchema = exports.projectSelectorSchema.extend({
|
|
|
92
203
|
exports.rdGetSchema = exports.projectSelectorSchema.extend({
|
|
93
204
|
itemId: zod_1.z.string().trim().min(1),
|
|
94
205
|
}).strict();
|
|
206
|
+
exports.rdReadDetailSchema = exports.rdGetSchema;
|
|
207
|
+
exports.rdUploadRawSchema = exports.projectSelectorSchema.extend({
|
|
208
|
+
itemId: zod_1.z.string().trim().min(1),
|
|
209
|
+
uploadId: zod_1.z.string().trim().min(1),
|
|
210
|
+
maxBytes: zod_1.z.number().int().min(1).max(5 * 1024 * 1024).optional(),
|
|
211
|
+
}).strict();
|
|
95
212
|
const rdTypeSchema = zod_1.z.enum([
|
|
96
213
|
"feature_dev",
|
|
97
214
|
"tech_refactor",
|
|
@@ -165,3 +282,37 @@ exports.rdUpdateProgressSchema = exports.projectSelectorSchema.extend({
|
|
|
165
282
|
stageTaskId: zod_1.z.string().trim().min(1).optional(),
|
|
166
283
|
confirm: zod_1.z.boolean().optional(),
|
|
167
284
|
}).strict();
|
|
285
|
+
exports.rdSimpleWriteSchema = exports.projectSelectorSchema.extend({
|
|
286
|
+
itemId: zod_1.z.string().trim().min(1),
|
|
287
|
+
confirm: zod_1.z.boolean().optional(),
|
|
288
|
+
}).strict();
|
|
289
|
+
exports.rdBlockSchema = exports.projectSelectorSchema.extend({
|
|
290
|
+
itemId: zod_1.z.string().trim().min(1),
|
|
291
|
+
blockerReason: zod_1.z.string().optional(),
|
|
292
|
+
confirm: zod_1.z.boolean().optional(),
|
|
293
|
+
}).strict();
|
|
294
|
+
exports.rdCompleteSchema = exports.projectSelectorSchema.extend({
|
|
295
|
+
itemId: zod_1.z.string().trim().min(1),
|
|
296
|
+
reason: zod_1.z.string().trim().max(1000).optional(),
|
|
297
|
+
confirm: zod_1.z.boolean().optional(),
|
|
298
|
+
}).strict();
|
|
299
|
+
exports.rdCloseSchema = exports.projectSelectorSchema.extend({
|
|
300
|
+
itemId: zod_1.z.string().trim().min(1),
|
|
301
|
+
reason: zod_1.z.string().trim().optional(),
|
|
302
|
+
confirm: zod_1.z.boolean().optional(),
|
|
303
|
+
}).strict();
|
|
304
|
+
exports.rdUpdateSchema = exports.projectSelectorSchema.extend({
|
|
305
|
+
itemId: zod_1.z.string().trim().min(1),
|
|
306
|
+
version: zod_1.z.number().int().min(1),
|
|
307
|
+
title: zod_1.z.string().trim().optional(),
|
|
308
|
+
description: zod_1.z.string().nullable().optional(),
|
|
309
|
+
stageId: zod_1.z.string().trim().nullable().optional(),
|
|
310
|
+
type: rdTypeSchema.optional(),
|
|
311
|
+
priority: rdPrioritySchema.optional(),
|
|
312
|
+
memberIds: zod_1.z.array(zod_1.z.string().trim().min(1)).min(1).optional(),
|
|
313
|
+
verifierId: zod_1.z.string().trim().nullable().optional(),
|
|
314
|
+
planStartAt: zod_1.z.string().trim().nullable().optional(),
|
|
315
|
+
planEndAt: zod_1.z.string().trim().nullable().optional(),
|
|
316
|
+
stageDescription: zod_1.z.string().trim().max(4000).nullable().optional(),
|
|
317
|
+
confirm: zod_1.z.boolean().optional(),
|
|
318
|
+
}).strict();
|
|
@@ -7,7 +7,7 @@ exports.hubV2UploadTools = hubV2UploadTools;
|
|
|
7
7
|
const node_fs_1 = require("node:fs");
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const client_1 = require("./client");
|
|
10
|
-
const
|
|
10
|
+
const index_1 = require("./config/index");
|
|
11
11
|
const schemas_1 = require("./schemas");
|
|
12
12
|
const result_1 = require("../../utils/result");
|
|
13
13
|
function hubV2UploadTools() {
|
|
@@ -41,7 +41,7 @@ function hubV2UploadTools() {
|
|
|
41
41
|
},
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
|
-
const ctx = (0,
|
|
44
|
+
const ctx = (0, index_1.resolveHubV2Context)(args, "personal");
|
|
45
45
|
const client = new client_1.HubV2Client(ctx);
|
|
46
46
|
const file = resolveUploadFile(args);
|
|
47
47
|
const form = new FormData();
|
|
@@ -55,8 +55,57 @@ function hubV2UploadTools() {
|
|
|
55
55
|
return (0, result_1.ok)("hub_v2_upload_markdown_image", data);
|
|
56
56
|
},
|
|
57
57
|
},
|
|
58
|
+
{
|
|
59
|
+
name: "hub_v2_file_upload",
|
|
60
|
+
description: "Upload a local or base64 file with Personal Token and return a Hub V2 uploadId.",
|
|
61
|
+
riskLevel: "write",
|
|
62
|
+
inputSchema: schemas_1.fileUploadSchema,
|
|
63
|
+
allowPreviewWhenBlocked: true,
|
|
64
|
+
isConfirmed: (args) => args.confirm === true,
|
|
65
|
+
async handler(args) {
|
|
66
|
+
const uploadPath = "/uploads/file";
|
|
67
|
+
if (!args.confirm) {
|
|
68
|
+
return (0, result_1.ok)("hub_v2_file_upload", {
|
|
69
|
+
code: "PREVIEW",
|
|
70
|
+
message: "set confirm=true to upload this file",
|
|
71
|
+
data: {
|
|
72
|
+
method: "POST",
|
|
73
|
+
path: uploadPath,
|
|
74
|
+
requiredScope: fileUploadRequiredScope(args.target),
|
|
75
|
+
maxBytes: maxUploadBytes(),
|
|
76
|
+
input: {
|
|
77
|
+
target: args.target,
|
|
78
|
+
mode: args.filePath ? "filePath" : "contentBase64",
|
|
79
|
+
fileName: args.fileName,
|
|
80
|
+
mimeType: args.mimeType,
|
|
81
|
+
hasFilePath: Boolean(args.filePath),
|
|
82
|
+
hasContentBase64: Boolean(args.contentBase64),
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const ctx = (0, index_1.resolveHubV2Context)(args, "personal");
|
|
88
|
+
const client = new client_1.HubV2Client(ctx);
|
|
89
|
+
const file = resolveUploadFile(args);
|
|
90
|
+
const form = new FormData();
|
|
91
|
+
const bytes = new Uint8Array(file.content.byteLength);
|
|
92
|
+
bytes.set(file.content);
|
|
93
|
+
form.append("file", new Blob([bytes], { type: file.mimeType }), file.fileName);
|
|
94
|
+
form.append("target", args.target);
|
|
95
|
+
const data = await client.multipart("POST", client.personalUrl(uploadPath), form);
|
|
96
|
+
return (0, result_1.ok)("hub_v2_file_upload", data);
|
|
97
|
+
},
|
|
98
|
+
},
|
|
58
99
|
];
|
|
59
100
|
}
|
|
101
|
+
function fileUploadRequiredScope(target) {
|
|
102
|
+
switch (target) {
|
|
103
|
+
case "issueAttachment":
|
|
104
|
+
return "issue:update:write";
|
|
105
|
+
case "taskSheetAttachment":
|
|
106
|
+
return "rd:stage-task:write or rd:edit:write";
|
|
107
|
+
}
|
|
108
|
+
}
|
|
60
109
|
function resolveUploadFile(args) {
|
|
61
110
|
if (Boolean(args.filePath) === Boolean(args.contentBase64)) {
|
|
62
111
|
throw new Error("provide exactly one of filePath or contentBase64");
|
|
@@ -93,7 +142,7 @@ function maxUploadBytes() {
|
|
|
93
142
|
function assertUploadSize(fileSize) {
|
|
94
143
|
const maxBytes = maxUploadBytes();
|
|
95
144
|
if (fileSize > maxBytes) {
|
|
96
|
-
throw new Error(`upload
|
|
145
|
+
throw new Error(`upload file is too large: ${fileSize} bytes exceeds NGM_MCP_MAX_UPLOAD_BYTES=${maxBytes}`);
|
|
97
146
|
}
|
|
98
147
|
}
|
|
99
148
|
function decodeBase64Content(value) {
|
|
@@ -117,7 +166,6 @@ function decodeBase64Content(value) {
|
|
|
117
166
|
}
|
|
118
167
|
function assertAllowedFilePath(filePath) {
|
|
119
168
|
const roots = [
|
|
120
|
-
process.env.NGM_WORKSPACE_ROOT,
|
|
121
169
|
process.env.NGM_MCP_UPLOAD_ROOT,
|
|
122
170
|
process.cwd(),
|
|
123
171
|
]
|
|
@@ -126,7 +174,7 @@ function assertAllowedFilePath(filePath) {
|
|
|
126
174
|
.map((item) => node_path_1.default.resolve(item));
|
|
127
175
|
const allowed = roots.some((root) => filePath === root || filePath.startsWith(`${root}${node_path_1.default.sep}`));
|
|
128
176
|
if (!allowed) {
|
|
129
|
-
throw new Error("filePath must be under
|
|
177
|
+
throw new Error("filePath must be under NGM_MCP_UPLOAD_ROOT or the current working directory");
|
|
130
178
|
}
|
|
131
179
|
}
|
|
132
180
|
function inferMimeType(fileName) {
|
package/lib/tools/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export type McpToolDefinition<TSchema extends z.AnyZodObject = z.AnyZodObject> =
|
|
|
8
8
|
riskLevel: ToolRiskLevel;
|
|
9
9
|
inputSchema: TSchema;
|
|
10
10
|
allowPreviewWhenBlocked?: boolean;
|
|
11
|
+
deferPolicyToHandler?: boolean;
|
|
11
12
|
isConfirmed?: (args: z.infer<TSchema>) => boolean;
|
|
12
13
|
handler(args: z.infer<TSchema>, context: ToolContext): Promise<ToolResult> | ToolResult;
|
|
13
14
|
};
|
package/lib/tools/index.js
CHANGED
|
@@ -1,20 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.allTools = allTools;
|
|
4
|
+
const capability_tools_1 = require("./capability.tools");
|
|
5
|
+
const angular_1 = require("./angular");
|
|
6
|
+
const controlled_tools_1 = require("./controlled.tools");
|
|
7
|
+
const file_write_tools_1 = require("./file-write.tools");
|
|
4
8
|
const git_tools_1 = require("./git.tools");
|
|
5
9
|
const hub_v2_1 = require("./hub-v2");
|
|
6
10
|
const log_tools_1 = require("./log.tools");
|
|
11
|
+
const nginx_tools_1 = require("./nginx.tools");
|
|
12
|
+
const project_observe_tools_1 = require("./project-observe.tools");
|
|
7
13
|
const project_tools_1 = require("./project.tools");
|
|
8
14
|
const proxy_tools_1 = require("./proxy.tools");
|
|
9
15
|
const runtime_tools_1 = require("./runtime.tools");
|
|
16
|
+
const review_1 = require("./review");
|
|
17
|
+
const standard_1 = require("./standard");
|
|
10
18
|
const task_tools_1 = require("./task.tools");
|
|
19
|
+
const test_1 = require("./test");
|
|
20
|
+
const workspace_tools_1 = require("./workspace.tools");
|
|
21
|
+
const workflow_1 = require("./workflow");
|
|
11
22
|
function allTools() {
|
|
12
23
|
return [
|
|
24
|
+
...(0, capability_tools_1.capabilityTools)(),
|
|
25
|
+
...(0, workspace_tools_1.workspaceTools)(),
|
|
26
|
+
...(0, controlled_tools_1.controlledTools)(),
|
|
27
|
+
...(0, file_write_tools_1.fileWriteTools)(),
|
|
13
28
|
...(0, project_tools_1.projectTools)(),
|
|
29
|
+
...(0, project_observe_tools_1.projectObserveTools)(),
|
|
14
30
|
...(0, task_tools_1.taskTools)(),
|
|
15
31
|
...(0, log_tools_1.logTools)(),
|
|
16
32
|
...(0, git_tools_1.gitTools)(),
|
|
33
|
+
...(0, standard_1.standardTools)(),
|
|
34
|
+
...(0, test_1.testStandardTools)(),
|
|
35
|
+
...(0, angular_1.angularStandardTools)(),
|
|
36
|
+
...(0, review_1.reviewTools)(),
|
|
37
|
+
...(0, workflow_1.frontendWorkflowTools)(),
|
|
17
38
|
...(0, runtime_tools_1.runtimeTools)(),
|
|
39
|
+
...(0, nginx_tools_1.nginxTools)(),
|
|
18
40
|
...(0, proxy_tools_1.proxyTools)(),
|
|
19
41
|
...(0, hub_v2_1.hubV2Tools)(),
|
|
20
42
|
];
|
package/lib/tools/log.tools.js
CHANGED
|
@@ -23,22 +23,49 @@ function clampSearchLimit(value) {
|
|
|
23
23
|
function logTools() {
|
|
24
24
|
return [
|
|
25
25
|
{
|
|
26
|
-
name: "
|
|
26
|
+
name: "ngm_log_tail",
|
|
27
27
|
description: "Read recent task logs by runId or taskId.",
|
|
28
28
|
riskLevel: "read",
|
|
29
29
|
inputSchema: logTailSchema,
|
|
30
30
|
async handler(args, context) {
|
|
31
31
|
const tail = clampTail(args.tail);
|
|
32
32
|
let runId = args.runId;
|
|
33
|
+
const localServer = context.services.localServer;
|
|
34
|
+
const availability = localServer ? await localServer.availability() : { available: false, reason: "local server client is not configured" };
|
|
33
35
|
if (!runId && args.taskId) {
|
|
34
|
-
|
|
36
|
+
if (!availability.available || !localServer) {
|
|
37
|
+
return (0, result_1.ok)("ngm_log_tail", {
|
|
38
|
+
controlPlane: "unavailable",
|
|
39
|
+
localServer: availability,
|
|
40
|
+
status: "unavailable",
|
|
41
|
+
reason: "ng-manager local server is not running; start it with ngm server or ngm ui to read shared task logs",
|
|
42
|
+
taskId: args.taskId,
|
|
43
|
+
tail,
|
|
44
|
+
lines: [],
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const snapshot = await localServer.getTaskStatus(args.taskId);
|
|
35
48
|
runId = snapshot?.runId;
|
|
36
49
|
}
|
|
37
50
|
if (!runId) {
|
|
38
51
|
throw new Error("runId or taskId is required");
|
|
39
52
|
}
|
|
40
|
-
|
|
41
|
-
|
|
53
|
+
if (!availability.available || !localServer) {
|
|
54
|
+
return (0, result_1.ok)("ngm_log_tail", {
|
|
55
|
+
controlPlane: "unavailable",
|
|
56
|
+
localServer: availability,
|
|
57
|
+
status: "unavailable",
|
|
58
|
+
reason: "ng-manager local server is not running; start it with ngm server or ngm ui to read shared task logs",
|
|
59
|
+
runId,
|
|
60
|
+
tail,
|
|
61
|
+
lines: [],
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
const controlPlane = "local-server";
|
|
65
|
+
const lines = await localServer.getTaskLogTail(runId, tail);
|
|
66
|
+
return (0, result_1.ok)("ngm_log_tail", {
|
|
67
|
+
controlPlane,
|
|
68
|
+
localServer: availability,
|
|
42
69
|
runId,
|
|
43
70
|
tail,
|
|
44
71
|
lines,
|
|
@@ -46,7 +73,7 @@ function logTools() {
|
|
|
46
73
|
},
|
|
47
74
|
},
|
|
48
75
|
{
|
|
49
|
-
name: "
|
|
76
|
+
name: "ngm_log_search",
|
|
50
77
|
description: "Search recent ng-manager system logs by keyword.",
|
|
51
78
|
riskLevel: "read",
|
|
52
79
|
inputSchema: logSearchSchema,
|
|
@@ -64,7 +91,7 @@ function logTools() {
|
|
|
64
91
|
return text.includes(needle);
|
|
65
92
|
})
|
|
66
93
|
.slice(0, limit);
|
|
67
|
-
return (0, result_1.ok)("
|
|
94
|
+
return (0, result_1.ok)("ngm_log_search", {
|
|
68
95
|
query: args.query,
|
|
69
96
|
limit,
|
|
70
97
|
entries,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { nginxControlTools } from "./nginx-control.tools";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.nginxControlTools = void 0;
|
|
4
|
+
var nginx_control_tools_1 = require("./nginx-control.tools");
|
|
5
|
+
Object.defineProperty(exports, "nginxControlTools", { enumerable: true, get: function () { return nginx_control_tools_1.nginxControlTools; } });
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.nginxControlTools = nginxControlTools;
|
|
4
|
+
const operation_result_1 = require("../controlled/operation-result");
|
|
5
|
+
const schemas_1 = require("../controlled/schemas");
|
|
6
|
+
const nginx_proxy_1 = require("./nginx-proxy");
|
|
7
|
+
const result_1 = require("../../utils/result");
|
|
8
|
+
const operation_policy_1 = require("../controlled/operation-policy");
|
|
9
|
+
function reloadTool() {
|
|
10
|
+
return {
|
|
11
|
+
name: "ngm_nginx_reload",
|
|
12
|
+
description: "Skill ngm-nginx. Controlled execute tool for validating and reloading only the ng-manager managed local Nginx instance. Prefer this over direct nginx commands because it uses ng-manager's local service boundary and audit. Previews validation by default; real reload requires confirm=true and NGM_MCP_ALLOW_EXECUTE=true and is refused when validation fails.",
|
|
13
|
+
riskLevel: "execute",
|
|
14
|
+
allowPreviewWhenBlocked: true,
|
|
15
|
+
deferPolicyToHandler: true,
|
|
16
|
+
isConfirmed: operation_result_1.isConfirmed,
|
|
17
|
+
inputSchema: schemas_1.nginxReloadSchema,
|
|
18
|
+
async handler(args, context) {
|
|
19
|
+
const confirmed = (0, operation_result_1.isConfirmed)(args);
|
|
20
|
+
const nginx = context.services.core.nginx;
|
|
21
|
+
const instance = nginx.service.getInstance();
|
|
22
|
+
const status = await nginx.service.getStatus().catch((error) => ({
|
|
23
|
+
isRunning: false,
|
|
24
|
+
error: error instanceof Error ? error.message : String(error),
|
|
25
|
+
}));
|
|
26
|
+
const validation = await nginx.config.validateConfig();
|
|
27
|
+
const safetyMessage = "Validate and reload the ng-manager managed local Nginx instance.";
|
|
28
|
+
const preview = {
|
|
29
|
+
...(0, operation_result_1.controlledFields)("execute", confirmed, (0, operation_policy_1.requiredEnv)("execute")),
|
|
30
|
+
operation: (0, operation_result_1.operation)("preview", "service-control", "high", safetyMessage),
|
|
31
|
+
instance: instance ? { path: instance.path, configPath: instance.configPath } : null,
|
|
32
|
+
status,
|
|
33
|
+
validation,
|
|
34
|
+
};
|
|
35
|
+
if (!validation.valid) {
|
|
36
|
+
return (0, result_1.ok)("ngm_nginx_reload", { ...preview, operation: (0, operation_result_1.operation)("blocked", "service-control", "high", safetyMessage), reason: "Nginx config validation failed; reload refused." });
|
|
37
|
+
}
|
|
38
|
+
if (!confirmed)
|
|
39
|
+
return (0, result_1.ok)("ngm_nginx_reload", preview);
|
|
40
|
+
const policyBlock = (0, operation_policy_1.requireExecutePolicy)("service-control", "high", safetyMessage);
|
|
41
|
+
if (policyBlock)
|
|
42
|
+
return (0, result_1.ok)("ngm_nginx_reload", { ...(0, operation_result_1.controlledFields)("execute", true, (0, operation_policy_1.requiredEnv)("execute")), ...policyBlock });
|
|
43
|
+
return (0, result_1.ok)("ngm_nginx_reload", {
|
|
44
|
+
...preview,
|
|
45
|
+
...(0, operation_result_1.controlledFields)("execute", true, (0, operation_policy_1.requiredEnv)("execute")),
|
|
46
|
+
operation: (0, operation_result_1.operation)("executed", "service-control", "high", safetyMessage),
|
|
47
|
+
result: await nginx.service.reload(),
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function proxySaveTool() {
|
|
53
|
+
return {
|
|
54
|
+
name: "ngm_nginx_proxy_save",
|
|
55
|
+
description: "Skill ngm-nginx. Controlled write tool for creating or updating ng-manager managed Nginx proxy server blocks. Prefer this over editing Nginx files directly because it validates inputs, redacts sensitive fields, rolls back invalid saves, and audit logs confirmed writes. Previews by default; real write requires confirm=true and NGM_MCP_ALLOW_WRITE=true. It never writes arbitrary file paths and reloads only when reloadAfterSave=true plus execute policy is enabled.",
|
|
56
|
+
riskLevel: "write",
|
|
57
|
+
allowPreviewWhenBlocked: true,
|
|
58
|
+
deferPolicyToHandler: true,
|
|
59
|
+
isConfirmed: operation_result_1.isConfirmed,
|
|
60
|
+
inputSchema: schemas_1.nginxProxySaveSchema,
|
|
61
|
+
async handler(args, context) {
|
|
62
|
+
const confirmed = (0, operation_result_1.isConfirmed)(args);
|
|
63
|
+
const nginx = context.services.core.nginx;
|
|
64
|
+
const proxyArgs = args;
|
|
65
|
+
const existing = proxyArgs.serverId ? await nginx.server.getServer(proxyArgs.serverId) : null;
|
|
66
|
+
if (proxyArgs.serverId && !existing) {
|
|
67
|
+
return (0, result_1.ok)("ngm_nginx_proxy_save", (0, operation_result_1.blocked)("write", "high", "Save a managed Nginx proxy server block.", "serverId not found"));
|
|
68
|
+
}
|
|
69
|
+
let request;
|
|
70
|
+
try {
|
|
71
|
+
request = (0, nginx_proxy_1.normalizeProxyRequest)(proxyArgs, existing);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
return (0, result_1.ok)("ngm_nginx_proxy_save", (0, operation_result_1.blocked)("write", "high", "Save a managed Nginx proxy server block.", "invalid Nginx proxy input", {
|
|
75
|
+
error: error instanceof Error ? error.message : String(error),
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
const safetyMessage = `${proxyArgs.serverId ? "Update" : "Create"} ng-manager managed Nginx proxy server "${request.name}".`;
|
|
79
|
+
const mode = proxyArgs.serverId ? "update" : "create";
|
|
80
|
+
const preview = {
|
|
81
|
+
...(0, operation_result_1.controlledFields)("write", confirmed, (0, operation_policy_1.requiredEnv)("write")),
|
|
82
|
+
operation: (0, operation_result_1.operation)("preview", "write", "high", safetyMessage),
|
|
83
|
+
mode,
|
|
84
|
+
serverId: proxyArgs.serverId,
|
|
85
|
+
before: (0, nginx_proxy_1.sanitizeNginxServerForAgent)(existing),
|
|
86
|
+
afterRequest: (0, nginx_proxy_1.sanitizeNginxProxyRequestForAgent)(request),
|
|
87
|
+
reloadAfterSave: proxyArgs.reloadAfterSave === true,
|
|
88
|
+
reloadRequired: true,
|
|
89
|
+
};
|
|
90
|
+
if (!confirmed)
|
|
91
|
+
return (0, result_1.ok)("ngm_nginx_proxy_save", preview);
|
|
92
|
+
const policyBlock = (0, operation_policy_1.requireWritePolicy)("high", safetyMessage);
|
|
93
|
+
if (policyBlock)
|
|
94
|
+
return (0, result_1.ok)("ngm_nginx_proxy_save", { ...(0, operation_result_1.controlledFields)("write", true, (0, operation_policy_1.requiredEnv)("write")), ...policyBlock });
|
|
95
|
+
const saved = proxyArgs.serverId ? await nginx.server.updateServer(proxyArgs.serverId, request) : await nginx.server.createServer(request);
|
|
96
|
+
const validation = await nginx.config.validateConfig();
|
|
97
|
+
if (!validation.valid) {
|
|
98
|
+
const rollback = await (0, nginx_proxy_1.rollbackNginxProxySave)(context, mode, proxyArgs.serverId, saved, existing);
|
|
99
|
+
return (0, result_1.ok)("ngm_nginx_proxy_save", {
|
|
100
|
+
...preview,
|
|
101
|
+
...(0, operation_result_1.controlledFields)("write", true, (0, operation_policy_1.requiredEnv)("write")),
|
|
102
|
+
operation: (0, operation_result_1.operation)("failed", "write", "high", safetyMessage),
|
|
103
|
+
result: { status: "failed", reason: "Nginx config validation failed after save" },
|
|
104
|
+
server: (0, nginx_proxy_1.sanitizeNginxServerForAgent)(saved),
|
|
105
|
+
validation,
|
|
106
|
+
rollback,
|
|
107
|
+
reloadRequired: true,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const result = {
|
|
111
|
+
...preview,
|
|
112
|
+
...(0, operation_result_1.controlledFields)("write", true, (0, operation_policy_1.requiredEnv)("write")),
|
|
113
|
+
operation: (0, operation_result_1.operation)("executed", "write", "high", safetyMessage),
|
|
114
|
+
server: (0, nginx_proxy_1.sanitizeNginxServerForAgent)(saved),
|
|
115
|
+
validation,
|
|
116
|
+
reloadRequired: true,
|
|
117
|
+
};
|
|
118
|
+
if (proxyArgs.reloadAfterSave === true) {
|
|
119
|
+
const reloadBlock = (0, operation_policy_1.requireExecutePolicy)("service-control", "high", "Reload after saving a managed Nginx proxy server block.");
|
|
120
|
+
if (reloadBlock)
|
|
121
|
+
result.reload = { status: "blocked", action: "execute", confirmed: true, requires: (0, operation_policy_1.requiredEnv)("execute"), errorCode: reloadBlock.errorCode, reason: "reloadAfterSave requires NGM_MCP_ALLOW_EXECUTE=true" };
|
|
122
|
+
else {
|
|
123
|
+
result.reload = { status: "executed", result: await nginx.service.reload() };
|
|
124
|
+
result.reloadRequired = false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return (0, result_1.ok)("ngm_nginx_proxy_save", result);
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function nginxControlTools() {
|
|
132
|
+
return [reloadTool(), proxySaveTool()];
|
|
133
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ToolContext } from "../../context/tool-context";
|
|
2
|
+
import type { NginxProxySaveArgs } from "../controlled/schemas";
|
|
3
|
+
export type NginxProxyRequest = {
|
|
4
|
+
name: string;
|
|
5
|
+
listen: string[];
|
|
6
|
+
domains: string[];
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
protocol?: "http" | "https";
|
|
9
|
+
ssl?: boolean;
|
|
10
|
+
sslCert?: string;
|
|
11
|
+
sslKey?: string;
|
|
12
|
+
root?: string;
|
|
13
|
+
index?: string[];
|
|
14
|
+
extraConfig?: string;
|
|
15
|
+
locations: Array<{
|
|
16
|
+
path: string;
|
|
17
|
+
proxyPass?: string;
|
|
18
|
+
}>;
|
|
19
|
+
createdBy?: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function normalizeProxyRequest(args: NginxProxySaveArgs, existing?: Record<string, any> | null): NginxProxyRequest;
|
|
22
|
+
export declare function sanitizeNginxServerForAgent(server: any): unknown;
|
|
23
|
+
export declare function sanitizeNginxProxyRequestForAgent(request: NginxProxyRequest): unknown;
|
|
24
|
+
export declare function rollbackNginxProxySave(context: ToolContext, mode: "create" | "update", serverId: string | undefined, saved: Record<string, any> | null, existing: Record<string, any> | null): Promise<Record<string, unknown>>;
|