@yinuo-ngm/mcp-server 0.1.1 → 0.1.3

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 (221) hide show
  1. package/README.md +225 -188
  2. package/lib/audit/audit-event.d.ts +14 -0
  3. package/lib/audit/audit-event.js +2 -0
  4. package/lib/audit/audit-log.service.d.ts +7 -0
  5. package/lib/audit/audit-log.service.js +187 -0
  6. package/lib/audit/redact.d.ts +3 -0
  7. package/lib/audit/redact.js +28 -0
  8. package/lib/catalog/capabilities/blocked-local-actions.d.ts +1 -0
  9. package/lib/catalog/capabilities/blocked-local-actions.js +18 -0
  10. package/lib/catalog/capabilities/frontend-standard.d.ts +2 -0
  11. package/lib/catalog/capabilities/frontend-standard.js +36 -0
  12. package/lib/catalog/capabilities/hub-v2.d.ts +2 -0
  13. package/lib/catalog/capabilities/hub-v2.js +34 -0
  14. package/lib/catalog/capabilities/nginx.d.ts +2 -0
  15. package/lib/catalog/capabilities/nginx.js +23 -0
  16. package/lib/catalog/capabilities/project.d.ts +2 -0
  17. package/lib/catalog/capabilities/project.js +23 -0
  18. package/lib/catalog/capabilities/router.d.ts +2 -0
  19. package/lib/catalog/capabilities/router.js +11 -0
  20. package/lib/catalog/capabilities/runtime.d.ts +2 -0
  21. package/lib/catalog/capabilities/runtime.js +17 -0
  22. package/lib/catalog/capabilities/workspace.d.ts +2 -0
  23. package/lib/catalog/capabilities/workspace.js +23 -0
  24. package/lib/catalog/helpers.d.ts +3 -0
  25. package/lib/catalog/helpers.js +42 -0
  26. package/lib/catalog/index.d.ts +4 -0
  27. package/lib/catalog/index.js +23 -0
  28. package/lib/catalog/tools/frontend-standard.d.ts +2 -0
  29. package/lib/catalog/tools/frontend-standard.js +166 -0
  30. package/lib/catalog/tools/hub-v2-api.d.ts +2 -0
  31. package/lib/catalog/tools/hub-v2-api.js +124 -0
  32. package/lib/catalog/tools/hub-v2-docs.d.ts +2 -0
  33. package/lib/catalog/tools/hub-v2-docs.js +40 -0
  34. package/lib/catalog/tools/nginx.d.ts +2 -0
  35. package/lib/catalog/tools/nginx.js +96 -0
  36. package/lib/catalog/tools/project.d.ts +2 -0
  37. package/lib/catalog/tools/project.js +138 -0
  38. package/lib/catalog/tools/router.d.ts +2 -0
  39. package/lib/catalog/tools/router.js +26 -0
  40. package/lib/catalog/tools/runtime.d.ts +2 -0
  41. package/lib/catalog/tools/runtime.js +47 -0
  42. package/lib/catalog/tools/workspace.d.ts +2 -0
  43. package/lib/catalog/tools/workspace.js +75 -0
  44. package/lib/catalog/types.d.ts +15 -0
  45. package/lib/catalog/types.js +2 -0
  46. package/lib/context/create-tool-context.js +11 -10
  47. package/lib/context/local-server-client.d.ts +2 -0
  48. package/lib/context/local-server-client.js +174 -0
  49. package/lib/context/tool-context.d.ts +36 -0
  50. package/lib/doctor.d.ts +8 -0
  51. package/lib/doctor.js +221 -0
  52. package/lib/errors/error-codes.d.ts +12 -0
  53. package/lib/errors/error-codes.js +14 -0
  54. package/lib/errors/mcp-tool-error.d.ts +8 -0
  55. package/lib/errors/mcp-tool-error.js +14 -0
  56. package/lib/filesystem/project-files.d.ts +18 -0
  57. package/lib/filesystem/project-files.js +112 -0
  58. package/lib/git/local-git-read-service.d.ts +2 -0
  59. package/lib/git/local-git-read-service.js +96 -0
  60. package/lib/index.d.ts +1 -0
  61. package/lib/index.js +4 -0
  62. package/lib/policy/assert-tool-policy.js +10 -1
  63. package/lib/register-tools.js +70 -9
  64. package/lib/registry/tool-names.d.ts +95 -0
  65. package/lib/registry/tool-names.js +97 -0
  66. package/lib/services/path-guard.service.d.ts +4 -0
  67. package/lib/services/path-guard.service.js +75 -0
  68. package/lib/services/permission.service.d.ts +5 -0
  69. package/lib/services/permission.service.js +38 -0
  70. package/lib/services/project-resolver.service.d.ts +32 -0
  71. package/lib/services/project-resolver.service.js +95 -0
  72. package/lib/standard/frontend-standard.default.d.ts +2 -0
  73. package/lib/standard/frontend-standard.default.js +51 -0
  74. package/lib/standard/frontend-standard.schema.d.ts +196 -0
  75. package/lib/standard/frontend-standard.schema.js +61 -0
  76. package/lib/standard/frontend-standard.service.d.ts +79 -0
  77. package/lib/standard/frontend-standard.service.js +115 -0
  78. package/lib/standard/project-scan.d.ts +9 -0
  79. package/lib/standard/project-scan.js +91 -0
  80. package/lib/standard/validators/angular-structure.validator.d.ts +4 -0
  81. package/lib/standard/validators/angular-structure.validator.js +75 -0
  82. package/lib/standard/validators/component.validator.d.ts +4 -0
  83. package/lib/standard/validators/component.validator.js +94 -0
  84. package/lib/standard/validators/git.validator.d.ts +8 -0
  85. package/lib/standard/validators/git.validator.js +32 -0
  86. package/lib/standard/validators/review.validator.d.ts +15 -0
  87. package/lib/standard/validators/review.validator.js +67 -0
  88. package/lib/standard/validators/test.validator.d.ts +19 -0
  89. package/lib/standard/validators/test.validator.js +89 -0
  90. package/lib/tool-catalog.d.ts +2 -0
  91. package/lib/tool-catalog.js +6 -0
  92. package/lib/tools/angular/angular-standard.tools.d.ts +2 -0
  93. package/lib/tools/angular/angular-standard.tools.js +53 -0
  94. package/lib/tools/angular/index.d.ts +1 -0
  95. package/lib/tools/angular/index.js +5 -0
  96. package/lib/tools/capability.tools.d.ts +2 -0
  97. package/lib/tools/capability.tools.js +205 -0
  98. package/lib/tools/controlled/index.d.ts +2 -0
  99. package/lib/tools/controlled/index.js +13 -0
  100. package/lib/tools/controlled/local-server.d.ts +6 -0
  101. package/lib/tools/controlled/local-server.js +17 -0
  102. package/lib/tools/controlled/operation-policy.d.ts +22 -0
  103. package/lib/tools/controlled/operation-policy.js +50 -0
  104. package/lib/tools/controlled/operation-result.d.ts +30 -0
  105. package/lib/tools/controlled/operation-result.js +33 -0
  106. package/lib/tools/controlled/schemas.d.ts +159 -0
  107. package/lib/tools/controlled/schemas.js +49 -0
  108. package/lib/tools/controlled.tools.d.ts +1 -0
  109. package/lib/tools/controlled.tools.js +5 -0
  110. package/lib/tools/file-write.tools.d.ts +2 -0
  111. package/lib/tools/file-write.tools.js +70 -0
  112. package/lib/tools/git.tools.js +109 -8
  113. package/lib/tools/hub-v2/client.d.ts +20 -0
  114. package/lib/tools/hub-v2/client.js +112 -0
  115. package/lib/tools/hub-v2/config/config-paths.d.ts +2 -0
  116. package/lib/tools/hub-v2/config/config-paths.js +17 -0
  117. package/lib/tools/hub-v2/config/env.d.ts +1 -0
  118. package/lib/tools/hub-v2/config/env.js +12 -0
  119. package/lib/tools/hub-v2/config/index.d.ts +8 -0
  120. package/lib/tools/hub-v2/config/index.js +18 -0
  121. package/lib/tools/hub-v2/config/jsonc.d.ts +5 -0
  122. package/lib/tools/hub-v2/config/jsonc.js +86 -0
  123. package/lib/tools/hub-v2/config/load-config.d.ts +18 -0
  124. package/lib/tools/hub-v2/config/load-config.js +93 -0
  125. package/lib/tools/hub-v2/config/project-selector.d.ts +5 -0
  126. package/lib/tools/hub-v2/config/project-selector.js +92 -0
  127. package/lib/tools/hub-v2/config/resolve-context.d.ts +13 -0
  128. package/lib/tools/hub-v2/config/resolve-context.js +33 -0
  129. package/lib/tools/hub-v2/docs.tools.d.ts +2 -0
  130. package/lib/tools/hub-v2/docs.tools.js +215 -0
  131. package/lib/tools/hub-v2/errors.d.ts +8 -0
  132. package/lib/tools/hub-v2/errors.js +27 -0
  133. package/lib/tools/hub-v2/index.d.ts +2 -0
  134. package/lib/tools/hub-v2/index.js +19 -0
  135. package/lib/tools/hub-v2/issues-workflow.tools.d.ts +2 -0
  136. package/lib/tools/hub-v2/issues-workflow.tools.js +199 -0
  137. package/lib/tools/hub-v2/issues.tools.d.ts +2 -0
  138. package/lib/tools/hub-v2/issues.tools.js +244 -0
  139. package/lib/tools/hub-v2/projects.tools.d.ts +2 -0
  140. package/lib/tools/hub-v2/projects.tools.js +41 -0
  141. package/lib/tools/hub-v2/raw.d.ts +8 -0
  142. package/lib/tools/hub-v2/raw.js +33 -0
  143. package/lib/tools/hub-v2/rd.tools.d.ts +2 -0
  144. package/lib/tools/hub-v2/rd.tools.js +361 -0
  145. package/lib/tools/hub-v2/schemas.d.ts +1182 -0
  146. package/lib/tools/hub-v2/schemas.js +318 -0
  147. package/lib/tools/hub-v2/upload.tools.d.ts +2 -0
  148. package/lib/tools/hub-v2/upload.tools.js +198 -0
  149. package/lib/tools/index.d.ts +3 -0
  150. package/lib/tools/index.js +24 -0
  151. package/lib/tools/log.tools.js +33 -6
  152. package/lib/tools/nginx/index.d.ts +1 -0
  153. package/lib/tools/nginx/index.js +5 -0
  154. package/lib/tools/nginx/nginx-control.tools.d.ts +2 -0
  155. package/lib/tools/nginx/nginx-control.tools.js +133 -0
  156. package/lib/tools/nginx/nginx-proxy.d.ts +24 -0
  157. package/lib/tools/nginx/nginx-proxy.js +154 -0
  158. package/lib/tools/nginx.tools.d.ts +2 -0
  159. package/lib/tools/nginx.tools.js +111 -0
  160. package/lib/tools/project/index.d.ts +2 -0
  161. package/lib/tools/project/index.js +7 -0
  162. package/lib/tools/project/launch-status.d.ts +10 -0
  163. package/lib/tools/project/launch-status.js +78 -0
  164. package/lib/tools/project/local-diagnostics.d.ts +19 -0
  165. package/lib/tools/project/local-diagnostics.js +97 -0
  166. package/lib/tools/project/observe-redaction.d.ts +3 -0
  167. package/lib/tools/project/observe-redaction.js +25 -0
  168. package/lib/tools/project/observe-runtime.d.ts +72 -0
  169. package/lib/tools/project/observe-runtime.js +147 -0
  170. package/lib/tools/project/project-control.tools.d.ts +2 -0
  171. package/lib/tools/project/project-control.tools.js +216 -0
  172. package/lib/tools/project/project-observe.tools.d.ts +2 -0
  173. package/lib/tools/project/project-observe.tools.js +191 -0
  174. package/lib/tools/project/runtime-config.d.ts +7 -0
  175. package/lib/tools/project/runtime-config.js +50 -0
  176. package/lib/tools/project-observe.tools.d.ts +1 -0
  177. package/lib/tools/project-observe.tools.js +5 -0
  178. package/lib/tools/project.tools.d.ts +8 -0
  179. package/lib/tools/project.tools.js +97 -6
  180. package/lib/tools/proxy.tools.js +4 -4
  181. package/lib/tools/review/index.d.ts +1 -0
  182. package/lib/tools/review/index.js +5 -0
  183. package/lib/tools/review/review.tools.d.ts +2 -0
  184. package/lib/tools/review/review.tools.js +152 -0
  185. package/lib/tools/runtime/index.d.ts +1 -0
  186. package/lib/tools/runtime/index.js +5 -0
  187. package/lib/tools/runtime/runtime-control.tools.d.ts +2 -0
  188. package/lib/tools/runtime/runtime-control.tools.js +89 -0
  189. package/lib/tools/runtime.tools.js +41 -4
  190. package/lib/tools/standard/index.d.ts +1 -0
  191. package/lib/tools/standard/index.js +5 -0
  192. package/lib/tools/standard/standard.tools.d.ts +2 -0
  193. package/lib/tools/standard/standard.tools.js +91 -0
  194. package/lib/tools/task.tools.js +44 -9
  195. package/lib/tools/test/index.d.ts +1 -0
  196. package/lib/tools/test/index.js +5 -0
  197. package/lib/tools/test/test-standard.tools.d.ts +2 -0
  198. package/lib/tools/test/test-standard.tools.js +51 -0
  199. package/lib/tools/tool-catalog.d.ts +2 -0
  200. package/lib/tools/tool-catalog.js +7 -0
  201. package/lib/tools/workflow/frontend-workflow.tools.d.ts +2 -0
  202. package/lib/tools/workflow/frontend-workflow.tools.js +364 -0
  203. package/lib/tools/workflow/index.d.ts +1 -0
  204. package/lib/tools/workflow/index.js +5 -0
  205. package/lib/tools/workspace-package.d.ts +22 -0
  206. package/lib/tools/workspace-package.js +130 -0
  207. package/lib/tools/workspace.tools.d.ts +7 -0
  208. package/lib/tools/workspace.tools.js +336 -0
  209. package/lib/utils/errors.d.ts +5 -0
  210. package/lib/utils/errors.js +17 -0
  211. package/lib/utils/result.d.ts +20 -2
  212. package/lib/utils/result.js +108 -3
  213. package/lib/workflow/frontend-task.schema.d.ts +83 -0
  214. package/lib/workflow/frontend-task.schema.js +25 -0
  215. package/lib/workflow/frontend-task.service.d.ts +57 -0
  216. package/lib/workflow/frontend-task.service.js +195 -0
  217. package/lib/workflow/workflow-status.d.ts +2 -0
  218. package/lib/workflow/workflow-status.js +14 -0
  219. package/lib/workflow/workflow-transition.d.ts +9 -0
  220. package/lib/workflow/workflow-transition.js +38 -0
  221. package/package.json +10 -4
package/README.md CHANGED
@@ -1,188 +1,225 @@
1
- # @yinuo-ngm/mcp-server
2
-
3
- Local MCP stdio server for ng-manager core capabilities.
4
-
5
- This package is an AI Agent adapter layer. It is not a business core, not a Fastify replacement, not an Electron lifecycle manager, and not a general shell execution entrypoint.
6
-
7
- ## Positioning
8
-
9
- The intended boundary is:
10
-
11
- ```text
12
- MCP client -> packages/mcp-server -> ToolContext.services -> packages/core
13
- ```
14
-
15
- MCP tools must not call the local Fastify HTTP API. HTTP routes, Electron IPC, CLI commands, and MCP tools should all adapt the same core services.
16
-
17
- ## Safety
18
-
19
- Tools are assigned one risk level:
20
-
21
- ```text
22
- read
23
- write
24
- execute
25
- dangerous
26
- ```
27
-
28
- Default policy:
29
-
30
- ```text
31
- read allowed
32
- write blocked
33
- execute blocked
34
- dangerous blocked
35
- ```
36
-
37
- This MVP only registers read tools. It does not implement arbitrary shell execution, task start/stop/restart, git pull/checkout/commit/reset, proxy reload, runtime install/remove, file deletion, or system environment mutation.
38
-
39
- ## Environment
40
-
41
- ```text
42
- NGM_DATA_DIR ng-manager data directory. Defaults to ~/.ng-manager.
43
- NGM_WORKSPACE_ROOT Optional workspace hint. Defaults to process.cwd().
44
- NGM_MCP_ALLOW_WRITE Future policy flag for write tools. Defaults to false.
45
- NGM_MCP_ALLOW_EXECUTE Future policy flag for execute tools. Defaults to false.
46
- NGM_MCP_ALLOW_DANGEROUS Future policy flag for dangerous tools. Defaults to false.
47
- ```
48
-
49
- ## Commands
50
-
51
- From the repository root:
52
-
53
- ```bash
54
- npm run mcp:dev
55
- npm run mcp:build
56
- npm run mcp:start
57
- ```
58
-
59
- Direct workspace commands:
60
-
61
- ```bash
62
- npm run dev -w @yinuo-ngm/mcp-server
63
- npm run build -w @yinuo-ngm/mcp-server
64
- npm run start -w @yinuo-ngm/mcp-server
65
- ```
66
-
67
- The server uses stdio transport only. It does not listen on an HTTP port, and stdout is reserved for the MCP protocol.
68
-
69
- ## MCP Client Configuration
70
-
71
- Built output:
72
-
73
- ```json
74
- {
75
- "mcpServers": {
76
- "ng-manager": {
77
- "command": "node",
78
- "args": [
79
- "D:/ng-manager/packages/mcp-server/lib/index.js"
80
- ],
81
- "env": {
82
- "NGM_DATA_DIR": "C:/Users/you/.ng-manager",
83
- "NGM_WORKSPACE_ROOT": "D:/ng-manager",
84
- "NGM_MCP_ALLOW_WRITE": "false",
85
- "NGM_MCP_ALLOW_EXECUTE": "false",
86
- "NGM_MCP_ALLOW_DANGEROUS": "false"
87
- }
88
- }
89
- }
90
- }
91
- ```
92
-
93
- Development:
94
-
95
- ```json
96
- {
97
- "mcpServers": {
98
- "ng-manager": {
99
- "command": "npm",
100
- "args": [
101
- "run",
102
- "dev",
103
- "-w",
104
- "@yinuo-ngm/mcp-server"
105
- ],
106
- "env": {
107
- "NGM_DATA_DIR": "C:/Users/you/.ng-manager",
108
- "NGM_WORKSPACE_ROOT": "D:/ng-manager"
109
- }
110
- }
111
- }
112
- }
113
- ```
114
-
115
- ## Tools
116
-
117
- Project:
118
-
119
- ```text
120
- ngm.project.list
121
- ngm.project.get
122
- ngm.project.getScripts
123
- ```
124
-
125
- Task:
126
-
127
- ```text
128
- ngm.task.list
129
- ngm.task.getStatus
130
- ```
131
-
132
- Log:
133
-
134
- ```text
135
- ngm.log.tail
136
- ngm.log.search
137
- ```
138
-
139
- Git:
140
-
141
- ```text
142
- ngm.git.status
143
- ngm.git.diff
144
- ```
145
-
146
- The Git tools are registered in this MVP but return a clear "not implemented in core yet" error through the Git service stub. A future phase should add a read-only Git service to `packages/core` first.
147
-
148
- Runtime:
149
-
150
- ```text
151
- ngm.runtime.list
152
- ngm.runtime.resolveForProject
153
- ```
154
-
155
- Proxy:
156
-
157
- ```text
158
- ngm.proxy.list
159
- ngm.proxy.validate
160
- ```
161
-
162
- In this package, "proxy" means ng-manager's current Nginx/proxy management domain, not the operating system global proxy.
163
-
164
- ## Result Shape
165
-
166
- All tools return structured JSON as text content:
167
-
168
- ```json
169
- {
170
- "ok": true,
171
- "tool": "ngm.project.list",
172
- "data": []
173
- }
174
- ```
175
-
176
- Errors use:
177
-
178
- ```json
179
- {
180
- "ok": false,
181
- "tool": "ngm.project.get",
182
- "error": "projectId or projectPath is required"
183
- }
184
- ```
185
-
186
- ## Replacing Stubs
187
-
188
- Add missing capabilities to `packages/core` first, then replace the corresponding service inside `ToolContext.services`. MCP tools should remain thin adapters that validate input, enforce policy, call core services, and cap output size.
1
+ # @yinuo-ngm/mcp-server
2
+
3
+ Local MCP Server for ng-manager.
4
+
5
+ Provides MCP tools that expose ng-manager capabilities to AI Agents such as Codex, OpenCode, Claude Code, Cursor, and other MCP-compatible clients.
6
+
7
+ The MCP server is an adapter layer only. Business logic belongs in `packages/core`.
8
+
9
+ ---
10
+
11
+ ## Architecture
12
+
13
+ ```text
14
+ AI Agent
15
+
16
+ MCP Client
17
+
18
+ packages/mcp-server
19
+
20
+ ToolContext.services
21
+
22
+ packages/core
23
+
24
+ Local Services
25
+ ```
26
+
27
+ Principles:
28
+
29
+ - MCP tools are thin adapters
30
+ - No duplicated business logic
31
+ - No Fastify dependency
32
+ - No Electron dependency
33
+ - Reuse the same core services as CLI, UI, and Local Server
34
+
35
+ ---
36
+
37
+ ## Quick Start
38
+
39
+ Repository root:
40
+
41
+ ```bash
42
+ npm run mcp:dev
43
+ npm run mcp:build
44
+ npm run mcp:start
45
+ ```
46
+
47
+ Workspace commands:
48
+
49
+ ```bash
50
+ npm run dev -w @yinuo-ngm/mcp-server
51
+ npm run build -w @yinuo-ngm/mcp-server
52
+ npm run start -w @yinuo-ngm/mcp-server
53
+ ```
54
+
55
+ CLI:
56
+
57
+ ```bash
58
+ ngm mcp
59
+ ```
60
+
61
+ Diagnostics:
62
+
63
+ ```bash
64
+ ngm mcp doctor
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Environment Variables
70
+
71
+ | Variable | Description |
72
+ |-----------|-------------|
73
+ | NGM_DATA_DIR | ng-manager data directory |
74
+ | NGM_MCP_ALLOW_WRITE | Enable write tools |
75
+ | NGM_MCP_ALLOW_EXECUTE | Enable execute tools |
76
+ | NGM_MCP_ALLOW_DANGEROUS | Enable dangerous tools |
77
+ | NGM_MCP_ALLOW_HUB | Enable Hub V2 write operations |
78
+ | NGM_MCP_MAX_RESULT_CHARS | MCP response size limit |
79
+
80
+ ---
81
+
82
+ ## MCP Client Example
83
+
84
+ ```json
85
+ {
86
+ "mcpServers": {
87
+ "ng-manager": {
88
+ "command": "node",
89
+ "args": [
90
+ "packages/mcp-server/lib/index.js"
91
+ ],
92
+ "env": {
93
+ "NGM_DATA_DIR": "~/.ng-manager"
94
+ }
95
+ }
96
+ }
97
+ }
98
+ ```
99
+
100
+ ---
101
+
102
+ ## Tool Categories
103
+
104
+ ### Workspace
105
+
106
+ - Workspace discovery
107
+ - Package metadata
108
+ - Capability routing
109
+ - Context generation
110
+
111
+ ### Project
112
+
113
+ - Project metadata
114
+ - Package.json access
115
+ - Script discovery
116
+ - Task status and logs
117
+
118
+ ### Runtime
119
+
120
+ - Node runtime discovery
121
+ - Runtime resolution
122
+ - Project runtime configuration
123
+
124
+ ### Nginx
125
+
126
+ - Status inspection
127
+ - Configuration validation
128
+ - Proxy management
129
+
130
+ ### Git
131
+
132
+ - Status and diff
133
+ - Commit message generation
134
+ - Review assistance
135
+
136
+ ### Frontend Workflow
137
+
138
+ - Standards validation
139
+ - Review scanning
140
+ - Task planning
141
+ - Delivery reports
142
+
143
+ ### Hub V2
144
+
145
+ - Documents
146
+ - Issues
147
+ - RD workflows
148
+ - File uploads
149
+
150
+ ---
151
+
152
+ ## Safety Model
153
+
154
+ Risk levels:
155
+
156
+ ```text
157
+ read
158
+ write
159
+ execute
160
+ dangerous
161
+ ```
162
+
163
+ Default policy:
164
+
165
+ ```text
166
+ read allowed
167
+ write blocked
168
+ execute blocked
169
+ dangerous blocked
170
+ ```
171
+
172
+ Write and execute operations require:
173
+
174
+ - `confirm=true`
175
+ - Matching environment flag enabled
176
+ - Policy validation passed
177
+
178
+ The MCP server does not provide:
179
+
180
+ - Arbitrary shell execution
181
+ - Arbitrary file system access
182
+ - System environment mutation
183
+ - Remote client command execution
184
+
185
+ ---
186
+
187
+ ## Documentation
188
+
189
+ Detailed documentation is maintained under:
190
+
191
+ ```text
192
+ packages/mcp-server/docs/
193
+ ```
194
+
195
+ Recommended structure:
196
+
197
+ ```text
198
+ docs/
199
+ ├─ architecture.md
200
+ ├─ security.md
201
+ ├─ configuration.md
202
+ └─ tools/
203
+ ├─ ngm-workspace.md
204
+ ├─ ngm-project.md
205
+ ├─ ngm-runtime.md
206
+ ├─ ngm-nginx.md
207
+ ├─ ngm-git.md
208
+ └─ hub-v2.md
209
+ ```
210
+
211
+ ---
212
+
213
+ ## Design Goal
214
+
215
+ ng-manager MCP Server is the unified AI integration layer for local-first engineering workflows.
216
+
217
+ ```text
218
+ AI Agent
219
+
220
+ MCP
221
+
222
+ ng-manager Core
223
+
224
+ Local Control Plane
225
+ ```
@@ -0,0 +1,14 @@
1
+ import type { ToolRiskLevel } from "../policy/tool-policy";
2
+ import type { ToolResult } from "../utils/result";
3
+ export type AuditToolEvent = {
4
+ tool: string;
5
+ riskLevel: ToolRiskLevel;
6
+ args?: unknown;
7
+ result?: ToolResult;
8
+ error?: unknown;
9
+ durationMs: number;
10
+ };
11
+ export type AuditWarning = {
12
+ code: "AUDIT_LOG_WRITE_FAILED";
13
+ message: string;
14
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ import type { ToolRiskLevel } from "../policy/tool-policy";
2
+ import type { ToolContext } from "../context/tool-context";
3
+ import type { AuditToolEvent, AuditWarning } from "./audit-event";
4
+ export declare function summarizeAuditArgs(args: unknown): Record<string, unknown>;
5
+ export declare function writeAuditLog(context: ToolContext, event: AuditToolEvent): Promise<void>;
6
+ export declare function shouldAuditTool(toolName: string, riskLevel: ToolRiskLevel): boolean;
7
+ export declare function auditWarning(error: unknown): AuditWarning;
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.summarizeAuditArgs = summarizeAuditArgs;
37
+ exports.writeAuditLog = writeAuditLog;
38
+ exports.shouldAuditTool = shouldAuditTool;
39
+ exports.auditWarning = auditWarning;
40
+ const fs = __importStar(require("fs/promises"));
41
+ const path = __importStar(require("path"));
42
+ const project_files_1 = require("../filesystem/project-files");
43
+ const redact_1 = require("./redact");
44
+ function isRecord(value) {
45
+ return typeof value === "object" && value !== null && !Array.isArray(value);
46
+ }
47
+ function getString(value, key) {
48
+ return isRecord(value) && typeof value[key] === "string" ? value[key] : undefined;
49
+ }
50
+ function normalizePath(value) {
51
+ const resolved = path.resolve(value);
52
+ return process.platform === "win32" ? resolved.replace(/\\/g, "/").toLowerCase() : resolved;
53
+ }
54
+ async function registeredProjectByPath(context, projectPath) {
55
+ const list = context.services.core?.project?.list;
56
+ if (typeof list !== "function")
57
+ return null;
58
+ let projects;
59
+ try {
60
+ projects = await list.call(context.services.core.project);
61
+ }
62
+ catch {
63
+ return null;
64
+ }
65
+ if (!Array.isArray(projects))
66
+ return null;
67
+ const requested = normalizePath(projectPath);
68
+ const matched = projects.find((project) => typeof project?.root === "string" && normalizePath(project.root) === requested);
69
+ return matched ? {
70
+ projectId: typeof matched.id === "string" ? matched.id : undefined,
71
+ projectName: typeof matched.name === "string" ? matched.name : undefined,
72
+ projectRoot: path.resolve(matched.root),
73
+ } : null;
74
+ }
75
+ async function resolveAuditProjectRoot(context, args) {
76
+ const projectId = getString(args, "projectId");
77
+ if (projectId) {
78
+ const project = await context.services.core.project.get(projectId);
79
+ return {
80
+ projectId: project.id,
81
+ projectName: project.name,
82
+ projectRoot: path.resolve(project.root),
83
+ };
84
+ }
85
+ const projectPath = getString(args, "projectPath");
86
+ if (projectPath) {
87
+ const requestedRoot = path.resolve(projectPath);
88
+ const registered = await registeredProjectByPath(context, requestedRoot);
89
+ if (registered)
90
+ return registered;
91
+ throw new Error("Audit projectPath must match a registered project root");
92
+ }
93
+ return {
94
+ projectRoot: path.resolve(context.workspaceRoot),
95
+ };
96
+ }
97
+ function byteLength(value) {
98
+ return typeof value === "string" ? Buffer.byteLength(value, "utf-8") : undefined;
99
+ }
100
+ function shortText(value, maxChars = 200) {
101
+ if (typeof value !== "string")
102
+ return undefined;
103
+ const redacted = (0, redact_1.redactText)(value);
104
+ return redacted.length > maxChars ? `${redacted.slice(0, maxChars)}...` : redacted;
105
+ }
106
+ function summarizeAuditArgs(args) {
107
+ const source = isRecord(args) ? args : {};
108
+ const out = {};
109
+ for (const key of ["projectId", "projectPath", "taskId"]) {
110
+ const value = getString(source, key);
111
+ if (value)
112
+ out[key] = value;
113
+ }
114
+ for (const key of ["confirm", "dryRun", "overwrite"]) {
115
+ if (typeof source[key] === "boolean")
116
+ out[key] = source[key];
117
+ }
118
+ const title = shortText(source.title);
119
+ if (title)
120
+ out.title = title;
121
+ const patchBytes = byteLength(source.patch);
122
+ if (patchBytes !== undefined)
123
+ out.patchBytes = patchBytes;
124
+ const contextBytes = byteLength(source.context);
125
+ if (contextBytes !== undefined)
126
+ out.contextBytes = contextBytes;
127
+ const markdownBytes = byteLength(source.markdown);
128
+ if (markdownBytes !== undefined)
129
+ out.markdownBytes = markdownBytes;
130
+ const summaryBytes = byteLength(source.summary);
131
+ if (summaryBytes !== undefined)
132
+ out.summaryBytes = summaryBytes;
133
+ return out;
134
+ }
135
+ function resultStatus(result, error) {
136
+ if (error) {
137
+ const message = error instanceof Error ? error.message : String(error);
138
+ return message.includes("blocked by policy") ? "blocked" : "failed";
139
+ }
140
+ if (!result)
141
+ return "unknown";
142
+ if (!result.ok)
143
+ return "failed";
144
+ const data = isRecord(result.data) ? result.data : {};
145
+ const operation = isRecord(data.operation) ? data.operation : undefined;
146
+ return typeof operation?.status === "string" ? operation.status : "ok";
147
+ }
148
+ function changedFilesFromResult(result) {
149
+ if (!result?.ok || !isRecord(result.data))
150
+ return [];
151
+ const value = result.data.changedFiles;
152
+ if (!Array.isArray(value))
153
+ return [];
154
+ return value.filter((item) => typeof item === "string").slice(0, 100);
155
+ }
156
+ function todayFileName(now = new Date()) {
157
+ return `mcp-${now.toISOString().slice(0, 10)}.jsonl`;
158
+ }
159
+ async function writeAuditLog(context, event) {
160
+ const args = isRecord(event.args) ? event.args : {};
161
+ const project = await resolveAuditProjectRoot(context, args);
162
+ const auditPath = (0, project_files_1.resolveNgManagerPath)(project.projectRoot, "audit", todayFileName());
163
+ const entry = {
164
+ time: new Date().toISOString(),
165
+ tool: event.tool,
166
+ riskLevel: event.riskLevel,
167
+ projectId: getString(args, "projectId") ?? project.projectId,
168
+ projectRoot: project.projectRoot,
169
+ taskId: getString(args, "taskId"),
170
+ status: resultStatus(event.result, event.error),
171
+ changedFiles: changedFilesFromResult(event.result),
172
+ durationMs: event.durationMs,
173
+ error: event.error ? (0, redact_1.redactValue)(event.error instanceof Error ? event.error.message : String(event.error)) : undefined,
174
+ argsSummary: summarizeAuditArgs(event.args),
175
+ };
176
+ await fs.mkdir(path.dirname(auditPath), { recursive: true });
177
+ await fs.appendFile(auditPath, `${JSON.stringify(entry)}\n`, "utf-8");
178
+ }
179
+ function shouldAuditTool(toolName, riskLevel) {
180
+ return riskLevel !== "read" || toolName.startsWith("ngm_workflow_");
181
+ }
182
+ function auditWarning(error) {
183
+ return {
184
+ code: "AUDIT_LOG_WRITE_FAILED",
185
+ message: error instanceof Error ? error.message : String(error),
186
+ };
187
+ }
@@ -0,0 +1,3 @@
1
+ export declare const SENSITIVE_KEY_RE: RegExp;
2
+ export declare function redactText(value: string): string;
3
+ export declare function redactValue(value: unknown): unknown;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SENSITIVE_KEY_RE = void 0;
4
+ exports.redactText = redactText;
5
+ exports.redactValue = redactValue;
6
+ exports.SENSITIVE_KEY_RE = /(authorization|cookie|token|password|passwd|secret|api[-_]?key|access[-_]?token|refresh[-_]?token|private[-_]?key|env)/i;
7
+ function redactText(value) {
8
+ return value
9
+ .replace(/(^|\n)([A-Z0-9_]*(?:TOKEN|PASSWORD|PASSWD|SECRET|API_KEY|ACCESS_TOKEN|REFRESH_TOKEN|AUTHORIZATION|COOKIE)[A-Z0-9_]*\s*=\s*)[^\r\n]+/gi, "$1$2[REDACTED]")
10
+ .replace(/(^|\n)(\s*[A-Za-z0-9_.-]*\.env\s*[:=]\s*)[^\r\n]+/gi, "$1$2[REDACTED]")
11
+ .replace(/(authorization\s*[:=]\s*)(bearer\s+)?[^\s,;]+/gi, "$1[REDACTED]")
12
+ .replace(/(cookie\s*[:=]\s*)[^\r\n]+/gi, "$1[REDACTED]")
13
+ .replace(/((?:token|password|passwd|secret|api[-_]?key|access[-_]?token|refresh[-_]?token|private[-_]?key)\s*[:=]\s*)("[^"]*"|'[^']*'|[^\s,;&]+)/gi, "$1[REDACTED]")
14
+ .replace(/([?&](?:token|password|passwd|secret|api[-_]?key|access[-_]?token|refresh[-_]?token)=)[^&\s]+/gi, "$1[REDACTED]");
15
+ }
16
+ function redactValue(value) {
17
+ if (typeof value === "string")
18
+ return redactText(value);
19
+ if (Array.isArray(value))
20
+ return value.map(redactValue);
21
+ if (typeof value !== "object" || value === null)
22
+ return value;
23
+ const out = {};
24
+ for (const [key, item] of Object.entries(value)) {
25
+ out[key] = exports.SENSITIVE_KEY_RE.test(key) ? "[REDACTED]" : redactValue(item);
26
+ }
27
+ return out;
28
+ }
@@ -0,0 +1 @@
1
+ export declare const blockedLocalActions: string[];