llng-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/.github/workflows/ci.yml +77 -0
  2. package/.prettierrc +7 -0
  3. package/LICENSE +661 -0
  4. package/README.md +502 -0
  5. package/dist/__tests__/api-transport.test.d.ts +1 -0
  6. package/dist/__tests__/api-transport.test.js +577 -0
  7. package/dist/__tests__/api-transport.test.js.map +1 -0
  8. package/dist/__tests__/config.test.d.ts +1 -0
  9. package/dist/__tests__/config.test.js +472 -0
  10. package/dist/__tests__/config.test.js.map +1 -0
  11. package/dist/__tests__/integration/api-mode.test.d.ts +1 -0
  12. package/dist/__tests__/integration/api-mode.test.js +199 -0
  13. package/dist/__tests__/integration/api-mode.test.js.map +1 -0
  14. package/dist/__tests__/integration/oidc-rp.test.d.ts +1 -0
  15. package/dist/__tests__/integration/oidc-rp.test.js +120 -0
  16. package/dist/__tests__/integration/oidc-rp.test.js.map +1 -0
  17. package/dist/__tests__/integration/ssh-mode.test.d.ts +1 -0
  18. package/dist/__tests__/integration/ssh-mode.test.js +101 -0
  19. package/dist/__tests__/integration/ssh-mode.test.js.map +1 -0
  20. package/dist/__tests__/k8s-transport.test.d.ts +1 -0
  21. package/dist/__tests__/k8s-transport.test.js +254 -0
  22. package/dist/__tests__/k8s-transport.test.js.map +1 -0
  23. package/dist/__tests__/oidc-tools.test.d.ts +1 -0
  24. package/dist/__tests__/oidc-tools.test.js +457 -0
  25. package/dist/__tests__/oidc-tools.test.js.map +1 -0
  26. package/dist/__tests__/registry.test.d.ts +1 -0
  27. package/dist/__tests__/registry.test.js +96 -0
  28. package/dist/__tests__/registry.test.js.map +1 -0
  29. package/dist/__tests__/ssh-transport.test.d.ts +1 -0
  30. package/dist/__tests__/ssh-transport.test.js +618 -0
  31. package/dist/__tests__/ssh-transport.test.js.map +1 -0
  32. package/dist/__tests__/tools.test.d.ts +1 -0
  33. package/dist/__tests__/tools.test.js +525 -0
  34. package/dist/__tests__/tools.test.js.map +1 -0
  35. package/dist/config.d.ts +65 -0
  36. package/dist/config.js +506 -0
  37. package/dist/config.js.map +1 -0
  38. package/dist/index.d.ts +2 -0
  39. package/dist/index.js +42 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/resources/documentation.d.ts +5 -0
  42. package/dist/resources/documentation.js +56 -0
  43. package/dist/resources/documentation.js.map +1 -0
  44. package/dist/tools/cli-utilities.d.ts +3 -0
  45. package/dist/tools/cli-utilities.js +187 -0
  46. package/dist/tools/cli-utilities.js.map +1 -0
  47. package/dist/tools/config.d.ts +6 -0
  48. package/dist/tools/config.js +326 -0
  49. package/dist/tools/config.js.map +1 -0
  50. package/dist/tools/consents.d.ts +3 -0
  51. package/dist/tools/consents.js +39 -0
  52. package/dist/tools/consents.js.map +1 -0
  53. package/dist/tools/instances.d.ts +3 -0
  54. package/dist/tools/instances.js +14 -0
  55. package/dist/tools/instances.js.map +1 -0
  56. package/dist/tools/oidc-rp.d.ts +6 -0
  57. package/dist/tools/oidc-rp.js +246 -0
  58. package/dist/tools/oidc-rp.js.map +1 -0
  59. package/dist/tools/oidc.d.ts +3 -0
  60. package/dist/tools/oidc.js +343 -0
  61. package/dist/tools/oidc.js.map +1 -0
  62. package/dist/tools/secondfactors.d.ts +3 -0
  63. package/dist/tools/secondfactors.js +62 -0
  64. package/dist/tools/secondfactors.js.map +1 -0
  65. package/dist/tools/sessions.d.ts +6 -0
  66. package/dist/tools/sessions.js +300 -0
  67. package/dist/tools/sessions.js.map +1 -0
  68. package/dist/transport/api.d.ts +35 -0
  69. package/dist/transport/api.js +327 -0
  70. package/dist/transport/api.js.map +1 -0
  71. package/dist/transport/interface.d.ts +50 -0
  72. package/dist/transport/interface.js +2 -0
  73. package/dist/transport/interface.js.map +1 -0
  74. package/dist/transport/k8s.d.ts +41 -0
  75. package/dist/transport/k8s.js +303 -0
  76. package/dist/transport/k8s.js.map +1 -0
  77. package/dist/transport/registry.d.ts +20 -0
  78. package/dist/transport/registry.js +91 -0
  79. package/dist/transport/registry.js.map +1 -0
  80. package/dist/transport/ssh.d.ts +37 -0
  81. package/dist/transport/ssh.js +353 -0
  82. package/dist/transport/ssh.js.map +1 -0
  83. package/docker-compose.test.yml +16 -0
  84. package/eslint.config.js +21 -0
  85. package/package.json +38 -0
  86. package/src/__tests__/api-transport.test.ts +746 -0
  87. package/src/__tests__/config.test.ts +587 -0
  88. package/src/__tests__/integration/api-mode.test.ts +229 -0
  89. package/src/__tests__/integration/oidc-rp.test.ts +138 -0
  90. package/src/__tests__/integration/ssh-mode.test.ts +113 -0
  91. package/src/__tests__/k8s-transport.test.ts +342 -0
  92. package/src/__tests__/oidc-tools.test.ts +554 -0
  93. package/src/__tests__/registry.test.ts +110 -0
  94. package/src/__tests__/ssh-transport.test.ts +805 -0
  95. package/src/__tests__/tools.test.ts +735 -0
  96. package/src/config.ts +605 -0
  97. package/src/index.ts +48 -0
  98. package/src/resources/documentation.ts +65 -0
  99. package/src/tools/cli-utilities.ts +207 -0
  100. package/src/tools/config.ts +382 -0
  101. package/src/tools/consents.ts +50 -0
  102. package/src/tools/instances.ts +21 -0
  103. package/src/tools/oidc-rp.ts +299 -0
  104. package/src/tools/oidc.ts +434 -0
  105. package/src/tools/secondfactors.ts +78 -0
  106. package/src/tools/sessions.ts +342 -0
  107. package/src/transport/api.ts +429 -0
  108. package/src/transport/interface.ts +58 -0
  109. package/src/transport/k8s.ts +367 -0
  110. package/src/transport/registry.ts +105 -0
  111. package/src/transport/ssh.ts +430 -0
  112. package/tsconfig.json +16 -0
  113. package/vitest.config.ts +8 -0
  114. package/vitest.integration.config.ts +9 -0
@@ -0,0 +1,353 @@
1
+ import { spawn } from "child_process";
2
+ import { resolvePaths } from "../config.js";
3
+ export class SshTransport {
4
+ config;
5
+ paths;
6
+ constructor(config) {
7
+ this.config = config;
8
+ this.paths = resolvePaths(config.binPrefix, config.cliPath, config.sessionsPath, config.configEditorPath);
9
+ }
10
+ async exec(args, env) {
11
+ return new Promise((resolve, reject) => {
12
+ let cmd;
13
+ let cmdArgs;
14
+ if (this.config.host) {
15
+ // SSH mode
16
+ cmd = "ssh";
17
+ cmdArgs = [];
18
+ if (this.config.port) {
19
+ cmdArgs.push("-p", this.config.port.toString());
20
+ }
21
+ const hostSpec = this.config.user
22
+ ? `${this.config.user}@${this.config.host}`
23
+ : this.config.host;
24
+ cmdArgs.push(hostSpec);
25
+ // Build the remote command
26
+ let remoteCmd = args.map((arg) => this.shellQuote(arg)).join(" ");
27
+ // If env vars are provided, prefix with env command
28
+ if (env) {
29
+ const envPrefix = Object.entries(env)
30
+ .map(([k, v]) => `${k}=${this.shellQuote(v)}`)
31
+ .join(" ");
32
+ remoteCmd = `env ${envPrefix} ${remoteCmd}`;
33
+ }
34
+ // Insert remoteCommand between sudo and the LLNG command
35
+ if (this.config.remoteCommand) {
36
+ remoteCmd = `${this.config.remoteCommand} ${remoteCmd}`;
37
+ }
38
+ if (this.config.sudo) {
39
+ remoteCmd = `sudo -u ${this.shellQuote(this.config.sudo)} ${remoteCmd}`;
40
+ }
41
+ cmdArgs.push(remoteCmd);
42
+ }
43
+ else {
44
+ // Local mode
45
+ if (this.config.sudo) {
46
+ cmd = "sudo";
47
+ cmdArgs = ["-u", this.config.sudo];
48
+ if (this.config.remoteCommand) {
49
+ cmdArgs.push(...this.config.remoteCommand.split(" "), ...args);
50
+ }
51
+ else {
52
+ cmdArgs.push(...args);
53
+ }
54
+ }
55
+ else if (this.config.remoteCommand) {
56
+ const parts = this.config.remoteCommand.split(" ");
57
+ cmd = parts[0];
58
+ cmdArgs = [...parts.slice(1), ...args];
59
+ }
60
+ else {
61
+ cmd = args[0];
62
+ cmdArgs = args.slice(1);
63
+ }
64
+ }
65
+ const spawnOpts = env ? { env: { ...process.env, ...env } } : undefined;
66
+ const proc = spawn(cmd, cmdArgs, spawnOpts);
67
+ let stdout = "";
68
+ proc.stdout.on("data", (data) => {
69
+ stdout += data.toString();
70
+ });
71
+ proc.stderr.on("data", () => {
72
+ // stderr is consumed but not exposed to clients for security
73
+ });
74
+ proc.on("close", (code) => {
75
+ if (code !== 0) {
76
+ reject(new Error(`Command failed with exit code ${code}`));
77
+ }
78
+ else {
79
+ resolve(stdout);
80
+ }
81
+ });
82
+ proc.on("error", () => {
83
+ reject(new Error("Command execution failed"));
84
+ });
85
+ });
86
+ }
87
+ async execWithStdin(args, input) {
88
+ return new Promise((resolve, reject) => {
89
+ let cmd;
90
+ let cmdArgs;
91
+ if (this.config.host) {
92
+ // SSH mode
93
+ cmd = "ssh";
94
+ cmdArgs = [];
95
+ if (this.config.port) {
96
+ cmdArgs.push("-p", this.config.port.toString());
97
+ }
98
+ const hostSpec = this.config.user
99
+ ? `${this.config.user}@${this.config.host}`
100
+ : this.config.host;
101
+ cmdArgs.push(hostSpec);
102
+ // Build the remote command
103
+ let remoteCmd = args.map((arg) => this.shellQuote(arg)).join(" ");
104
+ if (this.config.remoteCommand) {
105
+ remoteCmd = `${this.config.remoteCommand} ${remoteCmd}`;
106
+ }
107
+ if (this.config.sudo) {
108
+ remoteCmd = `sudo -u ${this.shellQuote(this.config.sudo)} ${remoteCmd}`;
109
+ }
110
+ cmdArgs.push(remoteCmd);
111
+ }
112
+ else {
113
+ // Local mode
114
+ if (this.config.sudo) {
115
+ cmd = "sudo";
116
+ cmdArgs = ["-u", this.config.sudo];
117
+ if (this.config.remoteCommand) {
118
+ cmdArgs.push(...this.config.remoteCommand.split(" "), ...args);
119
+ }
120
+ else {
121
+ cmdArgs.push(...args);
122
+ }
123
+ }
124
+ else if (this.config.remoteCommand) {
125
+ const parts = this.config.remoteCommand.split(" ");
126
+ cmd = parts[0];
127
+ cmdArgs = [...parts.slice(1), ...args];
128
+ }
129
+ else {
130
+ cmd = args[0];
131
+ cmdArgs = args.slice(1);
132
+ }
133
+ }
134
+ const proc = spawn(cmd, cmdArgs);
135
+ let stdout = "";
136
+ proc.stdout.on("data", (data) => {
137
+ stdout += data.toString();
138
+ });
139
+ proc.stderr.on("data", () => {
140
+ // stderr is consumed but not exposed to clients for security
141
+ });
142
+ proc.on("close", (code) => {
143
+ if (code !== 0) {
144
+ reject(new Error(`Command failed with exit code ${code}`));
145
+ }
146
+ else {
147
+ resolve(stdout);
148
+ }
149
+ });
150
+ proc.on("error", () => {
151
+ reject(new Error("Command execution failed"));
152
+ });
153
+ // Write input to stdin
154
+ proc.stdin.write(input);
155
+ proc.stdin.end();
156
+ });
157
+ }
158
+ shellQuote(arg) {
159
+ // Simple shell quoting - escape single quotes and wrap in single quotes
160
+ return `'${arg.replace(/'/g, "'\\''")}'`;
161
+ }
162
+ async execCli(subArgs) {
163
+ return this.exec([this.paths.cliPath, ...subArgs]);
164
+ }
165
+ async execSessions(subArgs) {
166
+ return this.exec([this.paths.sessionsPath, ...subArgs]);
167
+ }
168
+ async execConfigEditor(subArgs) {
169
+ return this.exec([this.paths.configEditorPath, ...subArgs], { EDITOR: "cat" });
170
+ }
171
+ pushSessionGetOptions(args, options) {
172
+ if (!options)
173
+ return;
174
+ if (options.persistent) {
175
+ args.push("--persistent");
176
+ }
177
+ if (options.hash) {
178
+ args.push("--hash");
179
+ }
180
+ if (options.refreshTokens) {
181
+ args.push("--refresh-tokens");
182
+ }
183
+ if (options.backend) {
184
+ args.push("--backend", options.backend);
185
+ }
186
+ }
187
+ // Config methods
188
+ async configInfo() {
189
+ const output = await this.execCli(["info"]);
190
+ // Parse text output like "Num : 1\nAuthor : The LemonLDAP::NG team\n..."
191
+ const lines = output.trim().split("\n");
192
+ const data = {};
193
+ for (const line of lines) {
194
+ const match = line.match(/^(\S+)\s*:\s*(.*)$/);
195
+ if (match) {
196
+ data[match[1]] = match[2];
197
+ }
198
+ }
199
+ return {
200
+ cfgNum: parseInt(data["Num"] || "0", 10),
201
+ cfgAuthor: data["Author"] || "",
202
+ cfgDate: data["Date"] || "",
203
+ cfgLog: data["Log"],
204
+ };
205
+ }
206
+ async configGet(keys) {
207
+ const output = await this.execCli(["-json", "get", ...keys]);
208
+ return JSON.parse(output);
209
+ }
210
+ async configSet(pairs, log) {
211
+ const args = ["set", "-yes", "1"];
212
+ for (const [key, value] of Object.entries(pairs)) {
213
+ args.push(key, String(value));
214
+ }
215
+ if (log) {
216
+ args.push("-log", log);
217
+ }
218
+ await this.execCli(args);
219
+ }
220
+ async configAddKey(key, subkey, value) {
221
+ await this.execCli(["addKey", key, subkey, value]);
222
+ }
223
+ async configDelKey(key, subkey) {
224
+ await this.execCli(["delKey", key, subkey]);
225
+ }
226
+ async configSave() {
227
+ return await this.execCli(["save"]);
228
+ }
229
+ async configRestore(json) {
230
+ await this.execWithStdin([this.paths.cliPath, "restore", "-yes", "1", "-"], json);
231
+ }
232
+ async configMerge(json) {
233
+ await this.execWithStdin([this.paths.cliPath, "merge", "-yes", "1", "-"], json);
234
+ }
235
+ async configRollback() {
236
+ await this.execCli(["rollback", "-yes", "1"]);
237
+ }
238
+ async configUpdateCache() {
239
+ await this.execCli(["update-cache"]);
240
+ }
241
+ async configTestEmail(destination) {
242
+ await this.execCli(["test-email", destination]);
243
+ }
244
+ // Session methods
245
+ async sessionGet(id, options) {
246
+ const args = ["get", id];
247
+ this.pushSessionGetOptions(args, options);
248
+ const output = await this.execSessions(args);
249
+ return JSON.parse(output);
250
+ }
251
+ async sessionSearch(filters) {
252
+ const args = ["search"];
253
+ if (filters.where) {
254
+ for (const [field, value] of Object.entries(filters.where)) {
255
+ args.push("--where", `${field}=${value}`);
256
+ }
257
+ }
258
+ if (filters.select && filters.select.length > 0) {
259
+ args.push("--select", filters.select.join(","));
260
+ }
261
+ if (filters.backend) {
262
+ args.push("--backend", filters.backend);
263
+ }
264
+ if (filters.count) {
265
+ args.push("--count");
266
+ }
267
+ if (filters.refreshTokens) {
268
+ args.push("--refresh-tokens");
269
+ }
270
+ if (filters.persistent) {
271
+ args.push("--persistent");
272
+ }
273
+ if (filters.hash) {
274
+ args.push("--hash");
275
+ }
276
+ if (filters.idOnly) {
277
+ args.push("--id-only");
278
+ }
279
+ const output = await this.execSessions(args);
280
+ return JSON.parse(output);
281
+ }
282
+ async sessionDelete(ids, options) {
283
+ if (options?.where) {
284
+ // Where-based deletion uses lemonldap-ng-sessions delete
285
+ const args = ["delete"];
286
+ for (const [field, value] of Object.entries(options.where)) {
287
+ args.push("--where", `${field}=${value}`);
288
+ }
289
+ this.pushSessionGetOptions(args, options);
290
+ await this.execSessions(args);
291
+ }
292
+ else {
293
+ // ID-based deletion uses llngDeleteSession
294
+ const deleteScriptPath = this.config.deleteSessionPath ||
295
+ this.paths.cliPath.replace("lemonldap-ng-cli", "llngDeleteSession");
296
+ for (const id of ids) {
297
+ const args = [deleteScriptPath, id];
298
+ this.pushSessionGetOptions(args, options);
299
+ await this.exec(args);
300
+ }
301
+ }
302
+ }
303
+ async sessionSetKey(id, pairs, options) {
304
+ const args = ["setKey", id];
305
+ for (const [key, value] of Object.entries(pairs)) {
306
+ args.push(key, String(value));
307
+ }
308
+ this.pushSessionGetOptions(args, options);
309
+ await this.execSessions(args);
310
+ }
311
+ async sessionDelKey(id, keys, options) {
312
+ const args = ["delKey", id, ...keys];
313
+ this.pushSessionGetOptions(args, options);
314
+ await this.execSessions(args);
315
+ }
316
+ async sessionBackup(backend, refreshTokens, persistent) {
317
+ // Return all sessions as JSON via search with no filters
318
+ const args = ["search"];
319
+ if (backend) {
320
+ args.push("--backend", backend);
321
+ }
322
+ if (refreshTokens) {
323
+ args.push("--refresh-tokens");
324
+ }
325
+ if (persistent) {
326
+ args.push("--persistent");
327
+ }
328
+ const output = await this.execSessions(args);
329
+ return output;
330
+ }
331
+ // 2FA methods
332
+ async secondFactorsGet(_user) {
333
+ throw new Error("secondFactorsGet is not supported via CLI. Use API mode.");
334
+ }
335
+ async secondFactorsDelete(_user, _ids) {
336
+ throw new Error("secondFactorsDelete is not supported via CLI. Use API mode.");
337
+ }
338
+ async secondFactorsDelType(_user, _type) {
339
+ throw new Error("secondFactorsDelType is not supported via CLI. Use API mode.");
340
+ }
341
+ // Consents methods
342
+ async consentsGet(_user) {
343
+ throw new Error("consentsGet is not supported via CLI. Use API mode.");
344
+ }
345
+ async consentsDelete(_user, _ids) {
346
+ throw new Error("consentsDelete is not supported via CLI. Use API mode.");
347
+ }
348
+ async execScript(scriptName, args) {
349
+ const prefix = this.config.binPrefix || "/usr/share/lemonldap-ng/bin";
350
+ return this.exec([`${prefix}/${scriptName}`, ...args]);
351
+ }
352
+ }
353
+ //# sourceMappingURL=ssh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh.js","sourceRoot":"","sources":["../../src/transport/ssh.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ services:
2
+ llng:
3
+ image: yadd/lemonldap-ng-full
4
+ ports:
5
+ - "19876:80"
6
+ environment:
7
+ - SSODOMAIN=example.com
8
+ - PORTAL=http://auth.example.com
9
+ - LOGLEVEL=debug
10
+ - LOGGER=stderr
11
+ healthcheck:
12
+ test: ["CMD", "curl", "-f", "http://localhost/"]
13
+ interval: 5s
14
+ timeout: 3s
15
+ retries: 20
16
+ start_period: 10s
@@ -0,0 +1,21 @@
1
+ import eslint from "@eslint/js";
2
+ import tseslint from "typescript-eslint";
3
+ import eslintConfigPrettier from "eslint-config-prettier";
4
+
5
+ export default tseslint.config(
6
+ eslint.configs.recommended,
7
+ ...tseslint.configs.recommended,
8
+ eslintConfigPrettier,
9
+ {
10
+ ignores: ["dist/", "node_modules/"],
11
+ },
12
+ {
13
+ rules: {
14
+ "@typescript-eslint/no-explicit-any": "off",
15
+ "@typescript-eslint/no-unused-vars": [
16
+ "error",
17
+ { argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
18
+ ],
19
+ },
20
+ },
21
+ );
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "llng-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP Server for Lemonldap-NG",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "llng-mcp": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/index.js",
13
+ "dev": "tsc --watch",
14
+ "test": "vitest run",
15
+ "test:watch": "vitest",
16
+ "test:integration": "vitest run --config vitest.integration.config.ts",
17
+ "lint": "eslint src/",
18
+ "lint:fix": "eslint src/ --fix",
19
+ "format": "prettier --write 'src/**/*.ts'",
20
+ "format:check": "prettier --check 'src/**/*.ts'"
21
+ },
22
+ "dependencies": {
23
+ "@modelcontextprotocol/sdk": "^1.12.1"
24
+ },
25
+ "devDependencies": {
26
+ "@eslint/js": "^9.39.2",
27
+ "@types/node": "^22.0.0",
28
+ "eslint": "^9.39.2",
29
+ "eslint-config-prettier": "^10.1.8",
30
+ "prettier": "^3.8.1",
31
+ "typescript": "^5.7.0",
32
+ "typescript-eslint": "^8.54.0",
33
+ "vitest": "^4.0.18"
34
+ },
35
+ "engines": {
36
+ "node": ">=20"
37
+ }
38
+ }