@yinuo-ngm/mcp-server 0.1.1
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/LICENSE +15 -0
- package/README.md +188 -0
- package/lib/context/create-tool-context.d.ts +2 -0
- package/lib/context/create-tool-context.js +66 -0
- package/lib/context/tool-context.d.ts +22 -0
- package/lib/context/tool-context.js +2 -0
- package/lib/create-mcp-server.d.ts +3 -0
- package/lib/create-mcp-server.js +10 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +28 -0
- package/lib/policy/assert-tool-policy.d.ts +2 -0
- package/lib/policy/assert-tool-policy.js +8 -0
- package/lib/policy/tool-policy.d.ts +3 -0
- package/lib/policy/tool-policy.js +14 -0
- package/lib/register-tools.d.ts +3 -0
- package/lib/register-tools.js +28 -0
- package/lib/tools/git.tools.d.ts +2 -0
- package/lib/tools/git.tools.js +36 -0
- package/lib/tools/index.d.ts +12 -0
- package/lib/tools/index.js +19 -0
- package/lib/tools/log.tools.d.ts +2 -0
- package/lib/tools/log.tools.js +75 -0
- package/lib/tools/project.tools.d.ts +18 -0
- package/lib/tools/project.tools.js +129 -0
- package/lib/tools/proxy.tools.d.ts +2 -0
- package/lib/tools/proxy.tools.js +46 -0
- package/lib/tools/runtime.tools.d.ts +2 -0
- package/lib/tools/runtime.tools.js +65 -0
- package/lib/tools/task.tools.d.ts +2 -0
- package/lib/tools/task.tools.js +39 -0
- package/lib/utils/errors.d.ts +1 -0
- package/lib/utils/errors.js +9 -0
- package/lib/utils/result.d.ts +19 -0
- package/lib/utils/result.js +21 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ZhangJing
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose
|
|
6
|
+
with or without fee is hereby granted, provided that the above copyright notice
|
|
7
|
+
and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
11
|
+
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
13
|
+
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
14
|
+
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
|
15
|
+
THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
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.
|
|
@@ -0,0 +1,66 @@
|
|
|
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.createToolContext = createToolContext;
|
|
37
|
+
const os = __importStar(require("os"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const core_1 = require("@yinuo-ngm/core");
|
|
40
|
+
const gitStub = {
|
|
41
|
+
async status() {
|
|
42
|
+
throw new Error("Git service is not implemented in core yet");
|
|
43
|
+
},
|
|
44
|
+
async diff() {
|
|
45
|
+
throw new Error("Git service is not implemented in core yet");
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
async function createToolContext() {
|
|
49
|
+
const dataDir = process.env.NGM_DATA_DIR || path.join(os.homedir(), ".ng-manager");
|
|
50
|
+
const workspaceRoot = process.env.NGM_WORKSPACE_ROOT || process.cwd();
|
|
51
|
+
const core = await (0, core_1.createCoreApp)({
|
|
52
|
+
dataDir,
|
|
53
|
+
sysLogCapacity: 3000,
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
workspaceRoot,
|
|
57
|
+
dataDir,
|
|
58
|
+
services: {
|
|
59
|
+
core,
|
|
60
|
+
git: gitStub,
|
|
61
|
+
},
|
|
62
|
+
async dispose() {
|
|
63
|
+
await core.dispose();
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CoreApp } from "@yinuo-ngm/core";
|
|
2
|
+
export type GitReadService = {
|
|
3
|
+
status(input: {
|
|
4
|
+
projectId?: string;
|
|
5
|
+
projectPath?: string;
|
|
6
|
+
}): Promise<unknown>;
|
|
7
|
+
diff(input: {
|
|
8
|
+
projectId?: string;
|
|
9
|
+
projectPath?: string;
|
|
10
|
+
maxBytes?: number;
|
|
11
|
+
}): Promise<unknown>;
|
|
12
|
+
};
|
|
13
|
+
export type ToolServices = {
|
|
14
|
+
core: CoreApp;
|
|
15
|
+
git: GitReadService;
|
|
16
|
+
};
|
|
17
|
+
export type ToolContext = {
|
|
18
|
+
workspaceRoot: string;
|
|
19
|
+
dataDir: string;
|
|
20
|
+
services: ToolServices;
|
|
21
|
+
dispose(): Promise<void>;
|
|
22
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createMcpServer = createMcpServer;
|
|
4
|
+
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
5
|
+
const register_tools_1 = require("./register-tools");
|
|
6
|
+
function createMcpServer(context) {
|
|
7
|
+
const server = new mcp_js_1.McpServer({ name: "ng-manager", version: "0.1.0" }, { capabilities: { tools: {} } });
|
|
8
|
+
(0, register_tools_1.registerTools)(server, context);
|
|
9
|
+
return server;
|
|
10
|
+
}
|
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.main = main;
|
|
5
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
6
|
+
const create_tool_context_1 = require("./context/create-tool-context");
|
|
7
|
+
const create_mcp_server_1 = require("./create-mcp-server");
|
|
8
|
+
const errors_1 = require("./utils/errors");
|
|
9
|
+
async function main() {
|
|
10
|
+
const context = await (0, create_tool_context_1.createToolContext)();
|
|
11
|
+
const server = (0, create_mcp_server_1.createMcpServer)(context);
|
|
12
|
+
const cleanup = async () => {
|
|
13
|
+
await context.dispose();
|
|
14
|
+
};
|
|
15
|
+
process.once("SIGINT", () => {
|
|
16
|
+
void cleanup().finally(() => process.exit(0));
|
|
17
|
+
});
|
|
18
|
+
process.once("SIGTERM", () => {
|
|
19
|
+
void cleanup().finally(() => process.exit(0));
|
|
20
|
+
});
|
|
21
|
+
await server.connect(new stdio_js_1.StdioServerTransport());
|
|
22
|
+
}
|
|
23
|
+
if (require.main === module) {
|
|
24
|
+
main().catch((error) => {
|
|
25
|
+
process.stderr.write(`${(0, errors_1.errorMessage)(error)}\n`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertToolPolicy = assertToolPolicy;
|
|
4
|
+
function assertToolPolicy(policy, toolName, riskLevel) {
|
|
5
|
+
if (!policy[riskLevel]) {
|
|
6
|
+
throw new Error(`Tool ${toolName} is blocked by policy: ${riskLevel} tools are disabled`);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDefaultToolPolicy = createDefaultToolPolicy;
|
|
4
|
+
function envFlag(name) {
|
|
5
|
+
return String(process.env[name] ?? "").trim().toLowerCase() === "true";
|
|
6
|
+
}
|
|
7
|
+
function createDefaultToolPolicy() {
|
|
8
|
+
return {
|
|
9
|
+
read: true,
|
|
10
|
+
write: envFlag("NGM_MCP_ALLOW_WRITE"),
|
|
11
|
+
execute: envFlag("NGM_MCP_ALLOW_EXECUTE"),
|
|
12
|
+
dangerous: envFlag("NGM_MCP_ALLOW_DANGEROUS"),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerTools = registerTools;
|
|
4
|
+
const assert_tool_policy_1 = require("./policy/assert-tool-policy");
|
|
5
|
+
const tool_policy_1 = require("./policy/tool-policy");
|
|
6
|
+
const tools_1 = require("./tools");
|
|
7
|
+
const errors_1 = require("./utils/errors");
|
|
8
|
+
const result_1 = require("./utils/result");
|
|
9
|
+
function registerTools(server, context) {
|
|
10
|
+
const policy = (0, tool_policy_1.createDefaultToolPolicy)();
|
|
11
|
+
const registerTool = server.registerTool.bind(server);
|
|
12
|
+
for (const tool of (0, tools_1.allTools)()) {
|
|
13
|
+
registerTool(tool.name, {
|
|
14
|
+
description: tool.description,
|
|
15
|
+
inputSchema: tool.inputSchema,
|
|
16
|
+
}, async (args) => {
|
|
17
|
+
try {
|
|
18
|
+
(0, assert_tool_policy_1.assertToolPolicy)(policy, tool.name, tool.riskLevel);
|
|
19
|
+
const parsed = tool.inputSchema.parse(args);
|
|
20
|
+
const result = await tool.handler(parsed, context);
|
|
21
|
+
return (0, result_1.toMcpTextResult)(result);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
return (0, result_1.toMcpTextResult)((0, result_1.fail)(tool.name, (0, errors_1.errorMessage)(error)));
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.gitTools = gitTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const result_1 = require("../utils/result");
|
|
6
|
+
const gitProjectSchema = zod_1.z.object({
|
|
7
|
+
projectId: zod_1.z.string().trim().min(1).optional(),
|
|
8
|
+
projectPath: zod_1.z.string().trim().min(1).optional(),
|
|
9
|
+
}).strict();
|
|
10
|
+
const gitDiffSchema = gitProjectSchema.extend({
|
|
11
|
+
maxBytes: zod_1.z.number().int().min(1).max(200000).optional(),
|
|
12
|
+
}).strict();
|
|
13
|
+
function gitTools() {
|
|
14
|
+
return [
|
|
15
|
+
{
|
|
16
|
+
name: "ngm.git.status",
|
|
17
|
+
description: "Read Git working tree status for a project. This MVP uses a core Git service stub.",
|
|
18
|
+
riskLevel: "read",
|
|
19
|
+
inputSchema: gitProjectSchema,
|
|
20
|
+
async handler(args, context) {
|
|
21
|
+
const data = await context.services.git.status(args);
|
|
22
|
+
return (0, result_1.ok)("ngm.git.status", data);
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: "ngm.git.diff",
|
|
27
|
+
description: "Read Git diff for a project. This MVP uses a core Git service stub.",
|
|
28
|
+
riskLevel: "read",
|
|
29
|
+
inputSchema: gitDiffSchema,
|
|
30
|
+
async handler(args, context) {
|
|
31
|
+
const data = await context.services.git.diff(args);
|
|
32
|
+
return (0, result_1.ok)("ngm.git.diff", data);
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { ToolContext } from "../context/tool-context";
|
|
3
|
+
import type { ToolRiskLevel } from "../policy/tool-policy";
|
|
4
|
+
import type { ToolResult } from "../utils/result";
|
|
5
|
+
export type McpToolDefinition<TSchema extends z.AnyZodObject = z.AnyZodObject> = {
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
riskLevel: ToolRiskLevel;
|
|
9
|
+
inputSchema: TSchema;
|
|
10
|
+
handler(args: z.infer<TSchema>, context: ToolContext): Promise<ToolResult> | ToolResult;
|
|
11
|
+
};
|
|
12
|
+
export declare function allTools(): McpToolDefinition[];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.allTools = allTools;
|
|
4
|
+
const git_tools_1 = require("./git.tools");
|
|
5
|
+
const log_tools_1 = require("./log.tools");
|
|
6
|
+
const project_tools_1 = require("./project.tools");
|
|
7
|
+
const proxy_tools_1 = require("./proxy.tools");
|
|
8
|
+
const runtime_tools_1 = require("./runtime.tools");
|
|
9
|
+
const task_tools_1 = require("./task.tools");
|
|
10
|
+
function allTools() {
|
|
11
|
+
return [
|
|
12
|
+
...(0, project_tools_1.projectTools)(),
|
|
13
|
+
...(0, task_tools_1.taskTools)(),
|
|
14
|
+
...(0, log_tools_1.logTools)(),
|
|
15
|
+
...(0, git_tools_1.gitTools)(),
|
|
16
|
+
...(0, runtime_tools_1.runtimeTools)(),
|
|
17
|
+
...(0, proxy_tools_1.proxyTools)(),
|
|
18
|
+
];
|
|
19
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logTools = logTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const result_1 = require("../utils/result");
|
|
6
|
+
const logTailSchema = zod_1.z.object({
|
|
7
|
+
runId: zod_1.z.string().trim().min(1).optional(),
|
|
8
|
+
taskId: zod_1.z.string().trim().min(1).optional(),
|
|
9
|
+
tail: zod_1.z.number().int().min(1).max(500).optional(),
|
|
10
|
+
}).strict();
|
|
11
|
+
const logSearchSchema = zod_1.z.object({
|
|
12
|
+
query: zod_1.z.string().trim().min(1),
|
|
13
|
+
limit: zod_1.z.number().int().min(1).max(200).optional(),
|
|
14
|
+
source: zod_1.z.string().trim().min(1).optional(),
|
|
15
|
+
scope: zod_1.z.string().trim().min(1).optional(),
|
|
16
|
+
}).strict();
|
|
17
|
+
function clampTail(value) {
|
|
18
|
+
return Math.min(Math.max(value ?? 100, 1), 500);
|
|
19
|
+
}
|
|
20
|
+
function clampSearchLimit(value) {
|
|
21
|
+
return Math.min(Math.max(value ?? 50, 1), 200);
|
|
22
|
+
}
|
|
23
|
+
function logTools() {
|
|
24
|
+
return [
|
|
25
|
+
{
|
|
26
|
+
name: "ngm.log.tail",
|
|
27
|
+
description: "Read recent task logs by runId or taskId.",
|
|
28
|
+
riskLevel: "read",
|
|
29
|
+
inputSchema: logTailSchema,
|
|
30
|
+
async handler(args, context) {
|
|
31
|
+
const tail = clampTail(args.tail);
|
|
32
|
+
let runId = args.runId;
|
|
33
|
+
if (!runId && args.taskId) {
|
|
34
|
+
const snapshot = await context.services.core.task.getSnapshotByTaskId(args.taskId);
|
|
35
|
+
runId = snapshot?.runId;
|
|
36
|
+
}
|
|
37
|
+
if (!runId) {
|
|
38
|
+
throw new Error("runId or taskId is required");
|
|
39
|
+
}
|
|
40
|
+
const lines = await context.services.core.task.getTailLogsByRun(runId, tail);
|
|
41
|
+
return (0, result_1.ok)("ngm.log.tail", {
|
|
42
|
+
runId,
|
|
43
|
+
tail,
|
|
44
|
+
lines,
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: "ngm.log.search",
|
|
50
|
+
description: "Search recent ng-manager system logs by keyword.",
|
|
51
|
+
riskLevel: "read",
|
|
52
|
+
inputSchema: logSearchSchema,
|
|
53
|
+
async handler(args, context) {
|
|
54
|
+
const limit = clampSearchLimit(args.limit);
|
|
55
|
+
const filter = {
|
|
56
|
+
...(args.source ? { source: args.source } : {}),
|
|
57
|
+
...(args.scope ? { scope: args.scope } : {}),
|
|
58
|
+
};
|
|
59
|
+
const needle = args.query.toLowerCase();
|
|
60
|
+
const entries = context.services.core.sysLog
|
|
61
|
+
.query(filter, { limit: 10000 })
|
|
62
|
+
.filter((entry) => {
|
|
63
|
+
const text = `${entry.text} ${JSON.stringify(entry.data ?? {})}`.toLowerCase();
|
|
64
|
+
return text.includes(needle);
|
|
65
|
+
})
|
|
66
|
+
.slice(0, limit);
|
|
67
|
+
return (0, result_1.ok)("ngm.log.search", {
|
|
68
|
+
query: args.query,
|
|
69
|
+
limit,
|
|
70
|
+
entries,
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Project } from "@yinuo-ngm/project";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { ToolContext } from "../context/tool-context";
|
|
4
|
+
import type { McpToolDefinition } from "./index";
|
|
5
|
+
export declare const projectLocatorSchema: z.ZodObject<{
|
|
6
|
+
projectId: z.ZodOptional<z.ZodString>;
|
|
7
|
+
projectPath: z.ZodOptional<z.ZodString>;
|
|
8
|
+
}, "strict", z.ZodTypeAny, {
|
|
9
|
+
projectId?: string | undefined;
|
|
10
|
+
projectPath?: string | undefined;
|
|
11
|
+
}, {
|
|
12
|
+
projectId?: string | undefined;
|
|
13
|
+
projectPath?: string | undefined;
|
|
14
|
+
}>;
|
|
15
|
+
type ProjectLocator = z.infer<typeof projectLocatorSchema>;
|
|
16
|
+
export declare function resolveProject(context: ToolContext, locator: ProjectLocator): Promise<Project>;
|
|
17
|
+
export declare function projectTools(): McpToolDefinition[];
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,129 @@
|
|
|
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.projectLocatorSchema = void 0;
|
|
37
|
+
exports.resolveProject = resolveProject;
|
|
38
|
+
exports.projectTools = projectTools;
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const zod_1 = require("zod");
|
|
41
|
+
const result_1 = require("../utils/result");
|
|
42
|
+
exports.projectLocatorSchema = zod_1.z.object({
|
|
43
|
+
projectId: zod_1.z.string().trim().min(1).optional(),
|
|
44
|
+
projectPath: zod_1.z.string().trim().min(1).optional(),
|
|
45
|
+
}).strict();
|
|
46
|
+
async function resolveProject(context, locator) {
|
|
47
|
+
if (locator.projectId) {
|
|
48
|
+
return context.services.core.project.get(locator.projectId);
|
|
49
|
+
}
|
|
50
|
+
if (locator.projectPath) {
|
|
51
|
+
const projects = await context.services.core.project.list();
|
|
52
|
+
const requestedPath = normalizeFsPath(locator.projectPath);
|
|
53
|
+
const project = projects.find((item) => normalizeFsPath(item.root) === requestedPath);
|
|
54
|
+
if (project) {
|
|
55
|
+
return project;
|
|
56
|
+
}
|
|
57
|
+
throw new Error(`Project not found for path: ${locator.projectPath}`);
|
|
58
|
+
}
|
|
59
|
+
throw new Error("projectId or projectPath is required");
|
|
60
|
+
}
|
|
61
|
+
function normalizeFsPath(value) {
|
|
62
|
+
const resolved = path.resolve(value);
|
|
63
|
+
return process.platform === "win32" ? resolved.replace(/\\/g, "/").toLowerCase() : resolved;
|
|
64
|
+
}
|
|
65
|
+
function toProjectSummary(project) {
|
|
66
|
+
return {
|
|
67
|
+
id: project.id,
|
|
68
|
+
name: project.name,
|
|
69
|
+
root: project.root,
|
|
70
|
+
createdAt: project.createdAt,
|
|
71
|
+
updatedAt: project.updatedAt,
|
|
72
|
+
scripts: project.scripts,
|
|
73
|
+
packageManager: project.packageManager,
|
|
74
|
+
runtime: project.runtime,
|
|
75
|
+
nodeVersion: project.nodeVersion,
|
|
76
|
+
framework: project.framework,
|
|
77
|
+
env: project.env,
|
|
78
|
+
isFavorite: project.isFavorite,
|
|
79
|
+
lastOpened: project.lastOpened,
|
|
80
|
+
repoUrl: project.repoUrl,
|
|
81
|
+
repoPageUrl: project.repoPageUrl,
|
|
82
|
+
assets: project.assets,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function toProjectScripts(project) {
|
|
86
|
+
return {
|
|
87
|
+
id: project.id,
|
|
88
|
+
name: project.name,
|
|
89
|
+
root: project.root,
|
|
90
|
+
scripts: project.scripts ?? {},
|
|
91
|
+
packageManager: project.packageManager,
|
|
92
|
+
nodeVersion: project.nodeVersion,
|
|
93
|
+
runtime: project.runtime,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function projectTools() {
|
|
97
|
+
return [
|
|
98
|
+
{
|
|
99
|
+
name: "ngm.project.list",
|
|
100
|
+
description: "List projects managed by ng-manager.",
|
|
101
|
+
riskLevel: "read",
|
|
102
|
+
inputSchema: zod_1.z.object({}).strict(),
|
|
103
|
+
async handler(_args, context) {
|
|
104
|
+
const projects = await context.services.core.project.list();
|
|
105
|
+
return (0, result_1.ok)("ngm.project.list", projects.map(toProjectSummary));
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "ngm.project.get",
|
|
110
|
+
description: "Get one ng-manager project by projectId or projectPath.",
|
|
111
|
+
riskLevel: "read",
|
|
112
|
+
inputSchema: exports.projectLocatorSchema,
|
|
113
|
+
async handler(args, context) {
|
|
114
|
+
const project = await resolveProject(context, args);
|
|
115
|
+
return (0, result_1.ok)("ngm.project.get", toProjectSummary(project));
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: "ngm.project.getScripts",
|
|
120
|
+
description: "Get package scripts and runtime hints for one ng-manager project.",
|
|
121
|
+
riskLevel: "read",
|
|
122
|
+
inputSchema: exports.projectLocatorSchema,
|
|
123
|
+
async handler(args, context) {
|
|
124
|
+
const project = await resolveProject(context, args);
|
|
125
|
+
return (0, result_1.ok)("ngm.project.getScripts", toProjectScripts(project));
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
];
|
|
129
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.proxyTools = proxyTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const result_1 = require("../utils/result");
|
|
6
|
+
const proxyValidateSchema = zod_1.z.object({
|
|
7
|
+
configText: zod_1.z.string().optional(),
|
|
8
|
+
}).strict();
|
|
9
|
+
function proxyTools() {
|
|
10
|
+
return [
|
|
11
|
+
{
|
|
12
|
+
name: "ngm.proxy.list",
|
|
13
|
+
description: "List current ng-manager Nginx/proxy binding, status, servers, and upstreams.",
|
|
14
|
+
riskLevel: "read",
|
|
15
|
+
inputSchema: zod_1.z.object({}).strict(),
|
|
16
|
+
async handler(_args, context) {
|
|
17
|
+
const nginx = context.services.core.nginx;
|
|
18
|
+
const instance = nginx.service.getInstance();
|
|
19
|
+
const [status, servers, upstreams] = await Promise.all([
|
|
20
|
+
nginx.service.getStatus().catch((error) => ({
|
|
21
|
+
isRunning: false,
|
|
22
|
+
error: error instanceof Error ? error.message : String(error),
|
|
23
|
+
})),
|
|
24
|
+
nginx.server.getAllServers().catch(() => []),
|
|
25
|
+
nginx.module.getUpstreams().catch(() => []),
|
|
26
|
+
]);
|
|
27
|
+
return (0, result_1.ok)("ngm.proxy.list", {
|
|
28
|
+
instance,
|
|
29
|
+
status,
|
|
30
|
+
servers,
|
|
31
|
+
upstreams,
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: "ngm.proxy.validate",
|
|
37
|
+
description: "Validate the current or supplied ng-manager Nginx/proxy config without reload.",
|
|
38
|
+
riskLevel: "read",
|
|
39
|
+
inputSchema: proxyValidateSchema,
|
|
40
|
+
async handler(args, context) {
|
|
41
|
+
const validation = await context.services.core.nginx.config.validateConfig(args.configText);
|
|
42
|
+
return (0, result_1.ok)("ngm.proxy.validate", validation);
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runtimeTools = runtimeTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const project_tools_1 = require("./project.tools");
|
|
6
|
+
const result_1 = require("../utils/result");
|
|
7
|
+
function normalizePackageManager(value) {
|
|
8
|
+
return value === "pnpm" || value === "yarn" ? value : "npm";
|
|
9
|
+
}
|
|
10
|
+
function runtimeConfigForProject(project) {
|
|
11
|
+
if (project.runtime) {
|
|
12
|
+
return {
|
|
13
|
+
...project.runtime,
|
|
14
|
+
packageManager: normalizePackageManager(project.runtime.packageManager ?? project.packageManager),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
if (project.nodeVersion) {
|
|
18
|
+
return {
|
|
19
|
+
type: "managed",
|
|
20
|
+
version: project.nodeVersion,
|
|
21
|
+
packageManager: normalizePackageManager(project.packageManager),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
type: "system",
|
|
26
|
+
packageManager: normalizePackageManager(project.packageManager),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function runtimeTools() {
|
|
30
|
+
return [
|
|
31
|
+
{
|
|
32
|
+
name: "ngm.runtime.list",
|
|
33
|
+
description: "List Node runtimes known to ng-manager.",
|
|
34
|
+
riskLevel: "read",
|
|
35
|
+
inputSchema: zod_1.z.object({}).strict(),
|
|
36
|
+
async handler(_args, context) {
|
|
37
|
+
const runtimes = await context.services.core.nodeRuntime.listRuntimes();
|
|
38
|
+
return (0, result_1.ok)("ngm.runtime.list", runtimes);
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "ngm.runtime.resolveForProject",
|
|
43
|
+
description: "Resolve the Node runtime ng-manager would use for a project.",
|
|
44
|
+
riskLevel: "read",
|
|
45
|
+
inputSchema: project_tools_1.projectLocatorSchema,
|
|
46
|
+
async handler(args, context) {
|
|
47
|
+
const project = await (0, project_tools_1.resolveProject)(context, args);
|
|
48
|
+
const requestedRuntime = runtimeConfigForProject(project);
|
|
49
|
+
const resolvedRuntime = await context.services.core.nodeRuntime.resolveRuntime(requestedRuntime);
|
|
50
|
+
return (0, result_1.ok)("ngm.runtime.resolveForProject", {
|
|
51
|
+
project: {
|
|
52
|
+
id: project.id,
|
|
53
|
+
name: project.name,
|
|
54
|
+
root: project.root,
|
|
55
|
+
packageManager: project.packageManager,
|
|
56
|
+
nodeVersion: project.nodeVersion,
|
|
57
|
+
runtime: project.runtime,
|
|
58
|
+
},
|
|
59
|
+
requestedRuntime,
|
|
60
|
+
resolvedRuntime,
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.taskTools = taskTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const result_1 = require("../utils/result");
|
|
6
|
+
const taskListSchema = zod_1.z.object({
|
|
7
|
+
projectId: zod_1.z.string().trim().min(1).optional(),
|
|
8
|
+
}).strict();
|
|
9
|
+
const taskStatusSchema = zod_1.z.object({
|
|
10
|
+
taskId: zod_1.z.string().trim().min(1),
|
|
11
|
+
}).strict();
|
|
12
|
+
function taskTools() {
|
|
13
|
+
return [
|
|
14
|
+
{
|
|
15
|
+
name: "ngm.task.list",
|
|
16
|
+
description: "List registered task views for a project, or active tasks when projectId is omitted.",
|
|
17
|
+
riskLevel: "read",
|
|
18
|
+
inputSchema: taskListSchema,
|
|
19
|
+
async handler(args, context) {
|
|
20
|
+
if (args.projectId) {
|
|
21
|
+
const rows = await context.services.core.task.listViewsByProject(args.projectId);
|
|
22
|
+
return (0, result_1.ok)("ngm.task.list", rows);
|
|
23
|
+
}
|
|
24
|
+
const activeTasks = await context.services.core.task.listActive();
|
|
25
|
+
return (0, result_1.ok)("ngm.task.list", activeTasks);
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: "ngm.task.getStatus",
|
|
30
|
+
description: "Get the runtime status for a registered task.",
|
|
31
|
+
riskLevel: "read",
|
|
32
|
+
inputSchema: taskStatusSchema,
|
|
33
|
+
async handler(args, context) {
|
|
34
|
+
const runtime = await context.services.core.task.status(args.taskId);
|
|
35
|
+
return (0, result_1.ok)("ngm.task.getStatus", runtime);
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function errorMessage(error: unknown): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.errorMessage = errorMessage;
|
|
4
|
+
function errorMessage(error) {
|
|
5
|
+
if (error instanceof Error && error.message) {
|
|
6
|
+
return error.message;
|
|
7
|
+
}
|
|
8
|
+
return String(error ?? "Unknown error");
|
|
9
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type ToolSuccessResult<T = unknown> = {
|
|
2
|
+
ok: true;
|
|
3
|
+
tool: string;
|
|
4
|
+
data: T;
|
|
5
|
+
};
|
|
6
|
+
export type ToolErrorResult = {
|
|
7
|
+
ok: false;
|
|
8
|
+
tool: string;
|
|
9
|
+
error: string;
|
|
10
|
+
};
|
|
11
|
+
export type ToolResult<T = unknown> = ToolSuccessResult<T> | ToolErrorResult;
|
|
12
|
+
export declare function ok<T>(tool: string, data: T): ToolSuccessResult<T>;
|
|
13
|
+
export declare function fail(tool: string, error: string): ToolErrorResult;
|
|
14
|
+
export declare function toMcpTextResult(result: ToolResult): {
|
|
15
|
+
content: Array<{
|
|
16
|
+
type: "text";
|
|
17
|
+
text: string;
|
|
18
|
+
}>;
|
|
19
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ok = ok;
|
|
4
|
+
exports.fail = fail;
|
|
5
|
+
exports.toMcpTextResult = toMcpTextResult;
|
|
6
|
+
function ok(tool, data) {
|
|
7
|
+
return { ok: true, tool, data };
|
|
8
|
+
}
|
|
9
|
+
function fail(tool, error) {
|
|
10
|
+
return { ok: false, tool, error };
|
|
11
|
+
}
|
|
12
|
+
function toMcpTextResult(result) {
|
|
13
|
+
return {
|
|
14
|
+
content: [
|
|
15
|
+
{
|
|
16
|
+
type: "text",
|
|
17
|
+
text: JSON.stringify(result, null, 2),
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yinuo-ngm/mcp-server",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Local MCP stdio server for ng-manager core capabilities.",
|
|
5
|
+
"author": "ZhangJing <892295834@qq.com>",
|
|
6
|
+
"license": "ISC",
|
|
7
|
+
"bin": {
|
|
8
|
+
"ngm-mcp-server": "lib/index.js"
|
|
9
|
+
},
|
|
10
|
+
"main": "lib/index.js",
|
|
11
|
+
"types": "lib/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./lib/index.d.ts",
|
|
15
|
+
"default": "./lib/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"lib"
|
|
20
|
+
],
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=18"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"dev": "tsx watch src/index.ts",
|
|
26
|
+
"build": "tsc -b tsconfig.json",
|
|
27
|
+
"start": "node lib/index.js"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
31
|
+
"@yinuo-ngm/core": "^0.1.14",
|
|
32
|
+
"zod": "^3.25.76"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"tsx": "^4.21.0"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"gitHead": "f64135f6db80de6928bc0b83c29c26e408e9fcfb"
|
|
41
|
+
}
|