@qodalis/cli-server-node 1.0.0-beta.1 → 1.0.0-beta.10
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 +1 -1
- package/README.md +348 -74
- package/dist/package.json +77 -0
- package/dist/src/abstractions/cli-command-author.d.ts +2 -0
- package/dist/src/abstractions/cli-command-author.d.ts.map +1 -0
- package/dist/src/abstractions/cli-command-author.js +7 -0
- package/dist/src/abstractions/cli-command-author.js.map +1 -0
- package/dist/src/abstractions/cli-command-parameter-descriptor.d.ts +2 -0
- package/dist/src/abstractions/cli-command-parameter-descriptor.d.ts.map +1 -0
- package/dist/src/abstractions/cli-command-parameter-descriptor.js +6 -0
- package/dist/src/abstractions/cli-command-parameter-descriptor.js.map +1 -0
- package/dist/src/abstractions/cli-command-processor.d.ts +2 -0
- package/dist/src/abstractions/cli-command-processor.d.ts.map +1 -0
- package/dist/src/abstractions/cli-command-processor.js +6 -0
- package/dist/src/abstractions/cli-command-processor.js.map +1 -0
- package/dist/src/abstractions/cli-process-command.d.ts +2 -0
- package/dist/src/abstractions/cli-process-command.d.ts.map +1 -0
- package/dist/src/abstractions/cli-process-command.js.map +1 -0
- package/dist/src/abstractions/index.d.ts +2 -0
- package/dist/src/abstractions/index.d.ts.map +1 -0
- package/dist/src/abstractions/index.js +18 -0
- package/dist/src/abstractions/index.js.map +1 -0
- package/dist/src/auth/cli-server-auth-gate.d.ts +33 -0
- package/dist/src/auth/cli-server-auth-gate.d.ts.map +1 -0
- package/dist/src/auth/cli-server-auth-gate.js +121 -0
- package/dist/src/auth/cli-server-auth-gate.js.map +1 -0
- package/dist/src/auth/cli-server-auth.d.ts +149 -0
- package/dist/src/auth/cli-server-auth.d.ts.map +1 -0
- package/dist/src/auth/cli-server-auth.js +143 -0
- package/dist/src/auth/cli-server-auth.js.map +1 -0
- package/dist/src/auth/index.d.ts +4 -0
- package/dist/src/auth/index.d.ts.map +1 -0
- package/dist/src/auth/index.js +19 -0
- package/dist/src/auth/index.js.map +1 -0
- package/dist/src/auth/ws-upgrade-auth.d.ts +30 -0
- package/dist/src/auth/ws-upgrade-auth.d.ts.map +1 -0
- package/dist/src/auth/ws-upgrade-auth.js +49 -0
- package/dist/src/auth/ws-upgrade-auth.js.map +1 -0
- package/dist/src/controllers/cli-controller.d.ts +11 -0
- package/dist/src/controllers/cli-controller.d.ts.map +1 -0
- package/dist/src/controllers/cli-controller.js +169 -0
- package/dist/src/controllers/cli-controller.js.map +1 -0
- package/dist/src/controllers/cli-version-controller.d.ts +18 -0
- package/dist/src/controllers/cli-version-controller.d.ts.map +1 -0
- package/dist/src/controllers/cli-version-controller.js +81 -0
- package/dist/src/controllers/cli-version-controller.js.map +1 -0
- package/dist/src/controllers/filesystem-controller.d.ts +9 -0
- package/dist/src/controllers/filesystem-controller.d.ts.map +1 -0
- package/dist/src/controllers/filesystem-controller.js +243 -0
- package/dist/src/controllers/filesystem-controller.js.map +1 -0
- package/dist/src/create-cli-server.d.ts +123 -0
- package/dist/src/create-cli-server.d.ts.map +1 -0
- package/dist/src/create-cli-server.js +201 -0
- package/dist/src/create-cli-server.js.map +1 -0
- package/dist/src/extensions/cli-builder.d.ts +54 -0
- package/dist/src/extensions/cli-builder.d.ts.map +1 -0
- package/dist/src/extensions/cli-builder.js +97 -0
- package/dist/src/extensions/cli-builder.js.map +1 -0
- package/dist/src/extensions/index.d.ts.map +1 -0
- package/dist/src/extensions/index.js.map +1 -0
- package/dist/src/filesystem/filesystem-options.d.ts +16 -0
- package/dist/src/filesystem/filesystem-options.d.ts.map +1 -0
- package/dist/src/filesystem/filesystem-options.js +6 -0
- package/dist/src/filesystem/filesystem-options.js.map +1 -0
- package/dist/src/filesystem/filesystem-path-validator.d.ts +15 -0
- package/dist/src/filesystem/filesystem-path-validator.d.ts.map +1 -0
- package/dist/src/filesystem/filesystem-path-validator.js +72 -0
- package/dist/src/filesystem/filesystem-path-validator.js.map +1 -0
- package/dist/src/filesystem/index.d.ts +3 -0
- package/dist/src/filesystem/index.d.ts.map +1 -0
- package/dist/src/filesystem/index.js +8 -0
- package/dist/src/filesystem/index.js.map +1 -0
- package/dist/src/index.d.ts +24 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +121 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/mcp/index.d.ts +10 -0
- package/dist/src/mcp/index.d.ts.map +1 -0
- package/dist/src/mcp/index.js +34 -0
- package/dist/src/mcp/index.js.map +1 -0
- package/dist/src/mcp/mcp-controller.d.ts +54 -0
- package/dist/src/mcp/mcp-controller.d.ts.map +1 -0
- package/dist/src/mcp/mcp-controller.js +358 -0
- package/dist/src/mcp/mcp-controller.js.map +1 -0
- package/dist/src/mcp/mcp-render.d.ts +10 -0
- package/dist/src/mcp/mcp-render.d.ts.map +1 -0
- package/dist/src/mcp/mcp-render.js +66 -0
- package/dist/src/mcp/mcp-render.js.map +1 -0
- package/dist/src/mcp/mcp-schema.d.ts +8 -0
- package/dist/src/mcp/mcp-schema.d.ts.map +1 -0
- package/dist/src/mcp/mcp-schema.js +64 -0
- package/dist/src/mcp/mcp-schema.js.map +1 -0
- package/dist/src/mcp/mcp-types.d.ts +70 -0
- package/dist/src/mcp/mcp-types.d.ts.map +1 -0
- package/dist/src/mcp/mcp-types.js +21 -0
- package/dist/src/mcp/mcp-types.js.map +1 -0
- package/dist/src/mcp/providers/commands-provider.d.ts +30 -0
- package/dist/src/mcp/providers/commands-provider.d.ts.map +1 -0
- package/dist/src/mcp/providers/commands-provider.js +145 -0
- package/dist/src/mcp/providers/commands-provider.js.map +1 -0
- package/dist/src/mcp/providers/data-explorer-provider.d.ts +15 -0
- package/dist/src/mcp/providers/data-explorer-provider.d.ts.map +1 -0
- package/dist/src/mcp/providers/data-explorer-provider.js +83 -0
- package/dist/src/mcp/providers/data-explorer-provider.js.map +1 -0
- package/dist/src/mcp/providers/filesystem-provider.d.ts +15 -0
- package/dist/src/mcp/providers/filesystem-provider.d.ts.map +1 -0
- package/dist/src/mcp/providers/filesystem-provider.js +166 -0
- package/dist/src/mcp/providers/filesystem-provider.js.map +1 -0
- package/dist/src/mcp/providers/jobs-provider.d.ts +23 -0
- package/dist/src/mcp/providers/jobs-provider.d.ts.map +1 -0
- package/dist/src/mcp/providers/jobs-provider.js +121 -0
- package/dist/src/mcp/providers/jobs-provider.js.map +1 -0
- package/dist/src/mcp/providers/server-provider.d.ts +19 -0
- package/dist/src/mcp/providers/server-provider.d.ts.map +1 -0
- package/dist/src/mcp/providers/server-provider.js +73 -0
- package/dist/src/mcp/providers/server-provider.js.map +1 -0
- package/dist/{models → src/models}/cli-server-command-descriptor.d.ts +2 -0
- package/dist/src/models/cli-server-command-descriptor.d.ts.map +1 -0
- package/dist/src/models/cli-server-command-descriptor.js.map +1 -0
- package/dist/src/models/cli-server-output.d.ts +2 -0
- package/dist/src/models/cli-server-output.d.ts.map +1 -0
- package/dist/src/models/cli-server-output.js.map +1 -0
- package/dist/src/models/cli-server-response.d.ts +2 -0
- package/dist/src/models/cli-server-response.d.ts.map +1 -0
- package/dist/src/models/cli-server-response.js.map +1 -0
- package/dist/src/models/index.d.ts.map +1 -0
- package/dist/{models → src/models}/index.js.map +1 -1
- package/dist/{processors → src/processors}/cli-base64-command-processor.d.ts +1 -0
- package/dist/src/processors/cli-base64-command-processor.d.ts.map +1 -0
- package/dist/{processors → src/processors}/cli-base64-command-processor.js +8 -2
- package/dist/src/processors/cli-base64-command-processor.js.map +1 -0
- package/dist/{processors → src/processors}/cli-echo-command-processor.d.ts +2 -0
- package/dist/src/processors/cli-echo-command-processor.d.ts.map +1 -0
- package/dist/src/processors/cli-echo-command-processor.js +20 -0
- package/dist/src/processors/cli-echo-command-processor.js.map +1 -0
- package/dist/{processors → src/processors}/cli-hash-command-processor.d.ts +2 -0
- package/dist/src/processors/cli-hash-command-processor.d.ts.map +1 -0
- package/dist/{processors → src/processors}/cli-hash-command-processor.js +4 -1
- package/dist/src/processors/cli-hash-command-processor.js.map +1 -0
- package/dist/{processors → src/processors}/cli-http-command-processor.d.ts +1 -0
- package/dist/src/processors/cli-http-command-processor.d.ts.map +1 -0
- package/dist/src/processors/cli-http-command-processor.js +161 -0
- package/dist/src/processors/cli-http-command-processor.js.map +1 -0
- package/dist/{processors → src/processors}/cli-status-command-processor.d.ts +1 -0
- package/dist/src/processors/cli-status-command-processor.d.ts.map +1 -0
- package/dist/{processors → src/processors}/cli-status-command-processor.js +1 -0
- package/dist/src/processors/cli-status-command-processor.js.map +1 -0
- package/dist/{processors → src/processors}/cli-system-command-processor.d.ts +1 -0
- package/dist/src/processors/cli-system-command-processor.d.ts.map +1 -0
- package/dist/{processors → src/processors}/cli-system-command-processor.js +1 -0
- package/dist/src/processors/cli-system-command-processor.js.map +1 -0
- package/dist/{processors → src/processors}/index.d.ts +1 -2
- package/dist/src/processors/index.d.ts.map +1 -0
- package/dist/{processors → src/processors}/index.js +2 -3
- package/dist/src/processors/index.js.map +1 -0
- package/dist/{server.d.ts.map → src/server.d.ts.map} +1 -1
- package/dist/{server.js → src/server.js} +22 -7
- package/dist/src/server.js.map +1 -0
- package/dist/src/services/cli-command-executor-service.d.ts +33 -0
- package/dist/src/services/cli-command-executor-service.d.ts.map +1 -0
- package/dist/src/services/cli-command-executor-service.js +77 -0
- package/dist/src/services/cli-command-executor-service.js.map +1 -0
- package/dist/src/services/cli-command-registry.d.ts +25 -0
- package/dist/src/services/cli-command-registry.d.ts.map +1 -0
- package/dist/{services → src/services}/cli-command-registry.js +5 -0
- package/dist/src/services/cli-command-registry.js.map +1 -0
- package/dist/src/services/cli-event-socket-manager.d.ts +77 -0
- package/dist/src/services/cli-event-socket-manager.d.ts.map +1 -0
- package/dist/src/services/cli-event-socket-manager.js +246 -0
- package/dist/src/services/cli-event-socket-manager.js.map +1 -0
- package/dist/src/services/cli-log-socket-manager.d.ts +67 -0
- package/dist/src/services/cli-log-socket-manager.d.ts.map +1 -0
- package/dist/src/services/cli-log-socket-manager.js +225 -0
- package/dist/src/services/cli-log-socket-manager.js.map +1 -0
- package/dist/{services → src/services}/cli-response-builder.d.ts +9 -0
- package/dist/src/services/cli-response-builder.d.ts.map +1 -0
- package/dist/{services → src/services}/cli-response-builder.js +1 -0
- package/dist/src/services/cli-response-builder.js.map +1 -0
- package/dist/src/services/cli-shell-options.d.ts +107 -0
- package/dist/src/services/cli-shell-options.d.ts.map +1 -0
- package/dist/src/services/cli-shell-options.js +139 -0
- package/dist/src/services/cli-shell-options.js.map +1 -0
- package/dist/src/services/cli-shell-session-manager.d.ts +92 -0
- package/dist/src/services/cli-shell-session-manager.d.ts.map +1 -0
- package/dist/src/services/cli-shell-session-manager.js +588 -0
- package/dist/src/services/cli-shell-session-manager.js.map +1 -0
- package/dist/src/services/index.d.ts +8 -0
- package/dist/src/services/index.d.ts.map +1 -0
- package/dist/src/services/index.js +20 -0
- package/dist/src/services/index.js.map +1 -0
- package/dist/src/services/process-tree.d.ts +38 -0
- package/dist/src/services/process-tree.d.ts.map +1 -0
- package/dist/src/services/process-tree.js +249 -0
- package/dist/src/services/process-tree.js.map +1 -0
- package/dist/src/services/session-bound-sockets.d.ts +45 -0
- package/dist/src/services/session-bound-sockets.d.ts.map +1 -0
- package/dist/src/services/session-bound-sockets.js +129 -0
- package/dist/src/services/session-bound-sockets.js.map +1 -0
- package/dist/src/utils/logger.d.ts +11 -0
- package/dist/src/utils/logger.d.ts.map +1 -0
- package/dist/src/utils/logger.js +13 -0
- package/dist/src/utils/logger.js.map +1 -0
- package/package.json +37 -8
- package/dist/abstractions/cli-command-author.d.ts +0 -11
- package/dist/abstractions/cli-command-author.d.ts.map +0 -1
- package/dist/abstractions/cli-command-author.js +0 -14
- package/dist/abstractions/cli-command-author.js.map +0 -1
- package/dist/abstractions/cli-command-parameter-descriptor.d.ts +0 -18
- package/dist/abstractions/cli-command-parameter-descriptor.d.ts.map +0 -1
- package/dist/abstractions/cli-command-parameter-descriptor.js +0 -21
- package/dist/abstractions/cli-command-parameter-descriptor.js.map +0 -1
- package/dist/abstractions/cli-command-processor.d.ts +0 -26
- package/dist/abstractions/cli-command-processor.d.ts.map +0 -1
- package/dist/abstractions/cli-command-processor.js +0 -14
- package/dist/abstractions/cli-command-processor.js.map +0 -1
- package/dist/abstractions/cli-process-command.d.ts +0 -9
- package/dist/abstractions/cli-process-command.d.ts.map +0 -1
- package/dist/abstractions/cli-process-command.js.map +0 -1
- package/dist/abstractions/index.d.ts +0 -5
- package/dist/abstractions/index.d.ts.map +0 -1
- package/dist/abstractions/index.js +0 -11
- package/dist/abstractions/index.js.map +0 -1
- package/dist/controllers/cli-controller.d.ts +0 -4
- package/dist/controllers/cli-controller.d.ts.map +0 -1
- package/dist/controllers/cli-controller.js +0 -42
- package/dist/controllers/cli-controller.js.map +0 -1
- package/dist/create-cli-server.d.ts +0 -25
- package/dist/create-cli-server.d.ts.map +0 -1
- package/dist/create-cli-server.js +0 -35
- package/dist/create-cli-server.js.map +0 -1
- package/dist/extensions/cli-builder.d.ts +0 -9
- package/dist/extensions/cli-builder.d.ts.map +0 -1
- package/dist/extensions/cli-builder.js +0 -18
- package/dist/extensions/cli-builder.js.map +0 -1
- package/dist/extensions/index.d.ts.map +0 -1
- package/dist/extensions/index.js.map +0 -1
- package/dist/index.d.ts +0 -14
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -40
- package/dist/index.js.map +0 -1
- package/dist/models/cli-server-command-descriptor.d.ts.map +0 -1
- package/dist/models/cli-server-command-descriptor.js.map +0 -1
- package/dist/models/cli-server-output.d.ts +0 -23
- package/dist/models/cli-server-output.d.ts.map +0 -1
- package/dist/models/cli-server-output.js.map +0 -1
- package/dist/models/cli-server-response.d.ts +0 -6
- package/dist/models/cli-server-response.d.ts.map +0 -1
- package/dist/models/cli-server-response.js.map +0 -1
- package/dist/models/index.d.ts.map +0 -1
- package/dist/processors/cli-base64-command-processor.d.ts.map +0 -1
- package/dist/processors/cli-base64-command-processor.js.map +0 -1
- package/dist/processors/cli-echo-command-processor.d.ts.map +0 -1
- package/dist/processors/cli-echo-command-processor.js +0 -14
- package/dist/processors/cli-echo-command-processor.js.map +0 -1
- package/dist/processors/cli-hash-command-processor.d.ts.map +0 -1
- package/dist/processors/cli-hash-command-processor.js.map +0 -1
- package/dist/processors/cli-http-command-processor.d.ts.map +0 -1
- package/dist/processors/cli-http-command-processor.js +0 -79
- package/dist/processors/cli-http-command-processor.js.map +0 -1
- package/dist/processors/cli-status-command-processor.d.ts.map +0 -1
- package/dist/processors/cli-status-command-processor.js.map +0 -1
- package/dist/processors/cli-system-command-processor.d.ts.map +0 -1
- package/dist/processors/cli-system-command-processor.js.map +0 -1
- package/dist/processors/cli-uuid-command-processor.d.ts +0 -10
- package/dist/processors/cli-uuid-command-processor.d.ts.map +0 -1
- package/dist/processors/cli-uuid-command-processor.js +0 -27
- package/dist/processors/cli-uuid-command-processor.js.map +0 -1
- package/dist/processors/index.d.ts.map +0 -1
- package/dist/processors/index.js.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/services/cli-command-executor-service.d.ts +0 -12
- package/dist/services/cli-command-executor-service.d.ts.map +0 -1
- package/dist/services/cli-command-executor-service.js +0 -45
- package/dist/services/cli-command-executor-service.js.map +0 -1
- package/dist/services/cli-command-registry.d.ts +0 -14
- package/dist/services/cli-command-registry.d.ts.map +0 -1
- package/dist/services/cli-command-registry.js.map +0 -1
- package/dist/services/cli-event-socket-manager.d.ts +0 -15
- package/dist/services/cli-event-socket-manager.d.ts.map +0 -1
- package/dist/services/cli-event-socket-manager.js +0 -60
- package/dist/services/cli-event-socket-manager.js.map +0 -1
- package/dist/services/cli-response-builder.d.ts.map +0 -1
- package/dist/services/cli-response-builder.js.map +0 -1
- package/dist/services/index.d.ts +0 -5
- package/dist/services/index.d.ts.map +0 -1
- package/dist/services/index.js +0 -12
- package/dist/services/index.js.map +0 -1
- /package/dist/{abstractions → src/abstractions}/cli-process-command.js +0 -0
- /package/dist/{extensions → src/extensions}/index.d.ts +0 -0
- /package/dist/{extensions → src/extensions}/index.js +0 -0
- /package/dist/{models → src/models}/cli-server-command-descriptor.js +0 -0
- /package/dist/{models → src/models}/cli-server-output.js +0 -0
- /package/dist/{models → src/models}/cli-server-response.js +0 -0
- /package/dist/{models → src/models}/index.d.ts +0 -0
- /package/dist/{models → src/models}/index.js +0 -0
- /package/dist/{server.d.ts → src/server.d.ts} +0 -0
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,40 +1,49 @@
|
|
|
1
1
|
# Qodalis CLI Server (Node.js)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Express server that runs server-side commands, files, data sources, jobs and a remote shell for the Qodalis web terminal.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/@qodalis/cli-server-node)
|
|
6
|
+
[](https://www.npmjs.com/package/@qodalis/cli-server-abstractions)
|
|
7
|
+
[](https://github.com/qodalis-solutions/cli-server-node/actions/workflows/build.yml)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
|
|
10
|
+
`@qodalis/cli-server-node` is the Node.js backend of the [Qodalis CLI](https://cli.qodalis.com/docs). You register command processors (classes with a name, parameters and a handler); the browser terminal discovers them over REST and runs them as if they were local commands. Use it as a library inside an existing Express app or run it standalone.
|
|
11
|
+
|
|
12
|
+
| Part of the ecosystem | Repository |
|
|
13
|
+
|---|---|
|
|
14
|
+
| Web terminal (engine, Angular/React/Vue wrappers, plugins) | [qodalis-solutions/web-cli](https://github.com/qodalis-solutions/web-cli) |
|
|
15
|
+
| Node.js server (this repo) | [qodalis-solutions/cli-server-node](https://github.com/qodalis-solutions/cli-server-node) |
|
|
16
|
+
| .NET server (same API) | [qodalis-solutions/cli-server-dotnet](https://github.com/qodalis-solutions/cli-server-dotnet) |
|
|
17
|
+
| Python server (same API) | [qodalis-solutions/cli-server-python](https://github.com/qodalis-solutions/cli-server-python) |
|
|
18
|
+
| Admin dashboard served by the admin plugin | [qodalis-solutions/cli-server-dashboard](https://github.com/qodalis-solutions/cli-server-dashboard) |
|
|
19
|
+
| MCP bridge for Claude Code | [qodalis-solutions/mcp-cli](https://github.com/qodalis-solutions/mcp-cli) |
|
|
20
|
+
|
|
21
|
+
## Quick start
|
|
6
22
|
|
|
7
23
|
```bash
|
|
8
24
|
npm install @qodalis/cli-server-node
|
|
9
25
|
```
|
|
10
26
|
|
|
11
|
-
## Quick Start
|
|
12
|
-
|
|
13
|
-
### As a Library
|
|
14
|
-
|
|
15
27
|
```typescript
|
|
16
28
|
import { createCliServer, CliCommandProcessor, CliProcessCommand } from '@qodalis/cli-server-node';
|
|
17
29
|
|
|
18
|
-
class
|
|
30
|
+
class GreetProcessor extends CliCommandProcessor {
|
|
19
31
|
command = 'greet';
|
|
20
32
|
description = 'Says hello';
|
|
33
|
+
acceptsValue = true;
|
|
21
34
|
|
|
22
35
|
async handleAsync(command: CliProcessCommand): Promise<string> {
|
|
23
|
-
return
|
|
36
|
+
return `Hello, ${command.value ?? 'World'}!`;
|
|
24
37
|
}
|
|
25
38
|
}
|
|
26
39
|
|
|
27
40
|
const { app, eventSocketManager } = createCliServer({
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
},
|
|
41
|
+
allowedOrigins: ['http://localhost:4200'], // the web app hosting the terminal
|
|
42
|
+
configure: (builder) => builder.addProcessor(new GreetProcessor()),
|
|
31
43
|
});
|
|
32
44
|
|
|
33
|
-
const server = app.listen(8047, () =>
|
|
34
|
-
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
eventSocketManager.attach(server);
|
|
45
|
+
const server = app.listen(8047, () => console.log('CLI server on http://localhost:8047'));
|
|
46
|
+
eventSocketManager.attach(server); // WebSockets: events, logs, shell
|
|
38
47
|
|
|
39
48
|
process.on('SIGINT', async () => {
|
|
40
49
|
await eventSocketManager.broadcastDisconnect();
|
|
@@ -43,104 +52,369 @@ process.on('SIGINT', async () => {
|
|
|
43
52
|
});
|
|
44
53
|
```
|
|
45
54
|
|
|
46
|
-
|
|
55
|
+
Point the web terminal at `http://localhost:8047` and type `greet Alice`.
|
|
56
|
+
|
|
57
|
+
Run the standalone server instead (built-in processors plus the weather module):
|
|
47
58
|
|
|
48
59
|
```bash
|
|
49
|
-
npx qodalis-cli-server
|
|
60
|
+
npx -p @qodalis/cli-server-node qodalis-cli-server
|
|
50
61
|
```
|
|
51
62
|
|
|
52
|
-
|
|
63
|
+
| Variable | Default | Description |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `PORT` | `8047` | Listening port |
|
|
66
|
+
| `QCLI_ALLOWED_ORIGINS` | none | Comma-separated origins allowed for CORS and WebSockets |
|
|
67
|
+
| `QCLI_SHELL_TOKEN` | none | Enables the remote shell in token mode |
|
|
53
68
|
|
|
54
|
-
|
|
55
|
-
PORT=9000 npx qodalis-cli-server
|
|
56
|
-
```
|
|
69
|
+
Plugin authors who only need the base types can depend on [`@qodalis/cli-server-abstractions`](packages/abstractions/README.md) (zero dependencies).
|
|
57
70
|
|
|
58
|
-
##
|
|
71
|
+
## Features
|
|
59
72
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
73
|
+
- Command processors with typed parameters, aliases, defaults, sub-commands and modules
|
|
74
|
+
- Plain-text or structured output (tables, lists, JSON, key-value) and SSE streaming execution
|
|
75
|
+
- Versioned REST API compatible with the .NET and Python servers
|
|
76
|
+
- File storage API with pluggable backends (memory, OS, JSON, SQLite, S3)
|
|
77
|
+
- Data explorer over SQL, PostgreSQL, MySQL, SQL Server, MongoDB, Redis and Elasticsearch
|
|
78
|
+
- Background jobs, admin dashboard, users, groups, permissions and API tokens as plugins
|
|
79
|
+
- Remote PTY shell with explicit access modes, limits and process-tree cleanup
|
|
80
|
+
- MCP endpoint that exposes commands, files, data and jobs as tools to AI clients
|
|
81
|
+
- Origin checks, CORS allow-list and trusted-proxy handling
|
|
82
|
+
|
|
83
|
+
## Writing commands
|
|
66
84
|
|
|
67
|
-
|
|
85
|
+
### Processors and parameters
|
|
68
86
|
|
|
69
87
|
```typescript
|
|
70
|
-
import {
|
|
71
|
-
CliCommandProcessor,
|
|
72
|
-
CliCommandParameterDescriptor,
|
|
73
|
-
CliProcessCommand,
|
|
74
|
-
} from '@qodalis/cli-server-node';
|
|
88
|
+
import { CliCommandProcessor, CliCommandParameterDescriptor, CliProcessCommand } from '@qodalis/cli-server-node';
|
|
75
89
|
|
|
76
|
-
class
|
|
90
|
+
class TimeProcessor extends CliCommandProcessor {
|
|
77
91
|
command = 'time';
|
|
78
92
|
description = 'Shows the current server time';
|
|
79
|
-
|
|
80
93
|
parameters = [
|
|
81
|
-
|
|
82
|
-
new CliCommandParameterDescriptor('
|
|
94
|
+
// name description required type aliases
|
|
95
|
+
new CliCommandParameterDescriptor('utc', 'Show UTC time', false, 'boolean'),
|
|
96
|
+
new CliCommandParameterDescriptor('format', 'Output format', false, 'string', ['-f'], 'ISO'),
|
|
83
97
|
];
|
|
84
98
|
|
|
85
99
|
async handleAsync(command: CliProcessCommand): Promise<string> {
|
|
86
|
-
const useUtc = 'utc' in (command.args ?? {});
|
|
87
100
|
const now = new Date();
|
|
88
|
-
return
|
|
101
|
+
return command.args?.utc ? now.toISOString() : now.toLocaleString();
|
|
89
102
|
}
|
|
90
103
|
}
|
|
91
104
|
```
|
|
92
105
|
|
|
93
|
-
|
|
106
|
+
Nest processors with `processors = [new AddProcessor(), new MultiplyProcessor()]` to get `math add --a 1 --b 2`. Implement `handleStructuredAsync` instead of `handleAsync` to return typed outputs.
|
|
107
|
+
|
|
108
|
+
| Member | Default | Description |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| `command`, `description` | required | Name and help text |
|
|
111
|
+
| `handleAsync(command, signal?)` | required | Execution logic, returns text |
|
|
112
|
+
| `handleStructuredAsync(command, signal?)` | none | Returns `{ exitCode, outputs }`; takes precedence over `handleAsync` |
|
|
113
|
+
| `parameters` | none | `CliCommandParameterDescriptor[]` (`string`, `number`, `boolean`, ...) |
|
|
114
|
+
| `processors` | none | Sub-commands |
|
|
115
|
+
| `allowUnlistedCommands` | none | Accept sub-commands not listed in `processors` |
|
|
116
|
+
| `valueRequired` / `acceptsValue` | none | Positional value is required / optional (MCP exposes it as `value`) |
|
|
117
|
+
| `requiredPermissions` | none | Enforced server-side when the users plugin is mounted |
|
|
118
|
+
| `version`, `author` | `'1.0.0'`, library author | Metadata |
|
|
119
|
+
|
|
120
|
+
### Command input
|
|
121
|
+
|
|
122
|
+
| Property | Description |
|
|
123
|
+
|---|---|
|
|
124
|
+
| `command` | Command name |
|
|
125
|
+
| `value` | Positional text as typed (quotes included) |
|
|
126
|
+
| `positionals` | Positional arguments split like a shell (sent by newer clients) |
|
|
127
|
+
| `args` | Named parameters (`--format "HH:mm"`) |
|
|
128
|
+
| `chainCommands` | Sub-command chain (`["add"]` in `math add`) |
|
|
129
|
+
| `rawCommand` | Original input |
|
|
130
|
+
| `data` | Arbitrary payload from the client |
|
|
131
|
+
|
|
132
|
+
Read positional input with `getPositionals(command)` or `getPositionalText(command)`; both fall back to splitting `value` with `splitShellWords`, so quotes never leak into what a processor reads.
|
|
133
|
+
|
|
134
|
+
### Modules
|
|
94
135
|
|
|
95
136
|
```typescript
|
|
96
|
-
|
|
97
|
-
command = 'math';
|
|
98
|
-
description = 'Performs basic math operations';
|
|
99
|
-
allowUnlistedCommands = false;
|
|
100
|
-
|
|
101
|
-
processors = [
|
|
102
|
-
new MathAddProcessor(),
|
|
103
|
-
new MathMultiplyProcessor(),
|
|
104
|
-
];
|
|
137
|
+
import { CliModule, ICliCommandProcessor } from '@qodalis/cli-server-node';
|
|
105
138
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
139
|
+
export class WeatherModule extends CliModule {
|
|
140
|
+
name = 'weather';
|
|
141
|
+
version = '1.0.0';
|
|
142
|
+
description = 'Weather commands';
|
|
143
|
+
processors: ICliCommandProcessor[] = [new WeatherProcessor()];
|
|
109
144
|
}
|
|
145
|
+
|
|
146
|
+
createCliServer({ configure: (builder) => builder.addModule(new WeatherModule()) });
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`plugins/weather/` is a complete reference module (`weather`, `weather current`, `weather forecast`).
|
|
150
|
+
|
|
151
|
+
## Configuration
|
|
152
|
+
|
|
153
|
+
`createCliServer(options)`:
|
|
154
|
+
|
|
155
|
+
| Option | Default | Description |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| `basePath` | `'/api/qcli'` | Extra mount point for the CLI routes; also sets the MCP path (`{basePath}/mcp`) |
|
|
158
|
+
| `allowedOrigins` | none | CORS and WebSocket `Origin` allow-list (`http://host:*` matches any port) |
|
|
159
|
+
| `cors` | from `allowedOrigins` | `true` (any origin), `false`, or a `cors` options object |
|
|
160
|
+
| `trustProxy` | `false` | Number of trusted reverse-proxy hops for `X-Forwarded-*` (`true` = 1) |
|
|
161
|
+
| `enableShell` | `false` | Accept remote shell sessions (see [Remote shell](#remote-shell)) |
|
|
162
|
+
| `shell` | none | Shell access mode, limits, timeouts, `cwd`, `env` |
|
|
163
|
+
| `auth` | none | Auth provider protecting the whole server (for example `usersPlugin.serverAuth`) |
|
|
164
|
+
| `mcp` | off | `true` or `{ tools, exclude, token, instructions, enabled }` (see [MCP](#mcp-endpoint)) |
|
|
165
|
+
| `configure` | none | `(builder) => ...` to register processors, modules, storage and data sources |
|
|
166
|
+
|
|
167
|
+
`configure` receives a `CliBuilder`: `addProcessor`, `addModule`, `setFileStorageProvider`, `addFileSystem`, `addDataExplorerProvider`, `addMcpToolProvider` (all chainable).
|
|
168
|
+
|
|
169
|
+
`createCliServer` returns:
|
|
170
|
+
|
|
171
|
+
| Field | Description |
|
|
172
|
+
|---|---|
|
|
173
|
+
| `app` | The Express app |
|
|
174
|
+
| `registry`, `builder`, `executor` | Processor registry, registration builder, command executor |
|
|
175
|
+
| `eventSocketManager` | `attach(server)` for the WebSockets, `broadcastMessage`, `broadcastDisconnect` |
|
|
176
|
+
| `logSocketManager` | Server log stream socket |
|
|
177
|
+
| `mountPlugin(plugin)` | Mounts a plugin's routes (and dashboard, MCP providers, server auth) |
|
|
178
|
+
| `setAuth(auth)` | Installs or removes the server auth provider |
|
|
179
|
+
| `mcp` | `{ enabled, path, addProvider(provider) }` |
|
|
180
|
+
|
|
181
|
+
Same-origin requests (such as the admin dashboard at `/qcli/admin`) always pass the Origin, CORS and CSRF checks. With `trustProxy` set to n hops, the client IP is the `X-Forwarded-For` entry at index `len - n`; set it to the exact number of proxies you run, otherwise clients can spoof their address.
|
|
182
|
+
|
|
183
|
+
## API
|
|
184
|
+
|
|
185
|
+
| Method | Path | Description |
|
|
186
|
+
|---|---|---|
|
|
187
|
+
| GET | `/api/qcli/versions` | Supported API versions and the preferred one |
|
|
188
|
+
| GET | `/api/v1/qcli/version` | Server version |
|
|
189
|
+
| GET | `/api/v1/qcli/capabilities` | OS, shell availability (`shell`, `shellAuth`), streaming, version |
|
|
190
|
+
| GET | `/api/v1/qcli/commands` | Registered processors |
|
|
191
|
+
| POST | `/api/v1/qcli/execute` | Execute a command |
|
|
192
|
+
| POST | `/api/v1/qcli/execute/stream` | Execute with Server-Sent Events output |
|
|
193
|
+
| GET | `/api/qcli/fs/ls`, `cat`, `stat`, `download` | File storage (when a provider is configured) |
|
|
194
|
+
| POST | `/api/qcli/fs/upload`, `mkdir` | Upload (multipart) / create directory |
|
|
195
|
+
| DELETE | `/api/qcli/fs/rm` | Delete file or directory |
|
|
196
|
+
| GET | `/api/qcli/data-explorer/sources`, `schema` | Data sources and their schema (when sources are registered) |
|
|
197
|
+
| POST | `/api/qcli/data-explorer/execute` | Run a query against a source |
|
|
198
|
+
| POST | `/api/qcli/mcp` | MCP endpoint (when `mcp` is enabled) |
|
|
199
|
+
| WS | `/ws/v1/qcli/events` | Server-push events |
|
|
200
|
+
| WS | `/ws/v1/qcli/logs` | Server log stream |
|
|
201
|
+
| WS | `/ws/v1/qcli/shell` | Interactive PTY shell (when `enableShell` is on) |
|
|
202
|
+
|
|
203
|
+
Every WebSocket is also served without the version (`/ws/qcli/events`, ...). Plugins add their own routes: users (`/api/v1/qcli/sessions`, `/users`, `/groups`, `/tokens`, ...), jobs and admin; see their READMEs.
|
|
204
|
+
|
|
205
|
+
## Plugins
|
|
206
|
+
|
|
207
|
+
| Package | Description |
|
|
208
|
+
|---|---|
|
|
209
|
+
| [`@qodalis/cli-server-plugin-users`](plugins/users/README.md) | Users, groups, permissions, sessions, API tokens, audit log; protects the whole server |
|
|
210
|
+
| [`@qodalis/cli-server-plugin-admin`](plugins/admin/README.md) | Admin dashboard at `/qcli/admin` (status, configuration, logs) |
|
|
211
|
+
| [`@qodalis/cli-server-plugin-jobs`](plugins/jobs/README.md) | Cron and interval background jobs with history and REST management |
|
|
212
|
+
| [`@qodalis/cli-server-plugin-filesystem`](plugins/filesystem/README.md) | File storage abstraction with in-memory and OS providers |
|
|
213
|
+
| [`-filesystem-json`](plugins/filesystem-json/README.md), [`-filesystem-sqlite`](plugins/filesystem-sqlite/README.md), [`-filesystem-s3`](plugins/filesystem-s3/README.md) | JSON file, SQLite and Amazon S3 storage providers |
|
|
214
|
+
| [`@qodalis/cli-server-plugin-data-explorer`](plugins/data-explorer/README.md) | Data explorer core |
|
|
215
|
+
| [`-data-explorer-sql`](plugins/data-explorer-sql/README.md), [`-postgres`](plugins/data-explorer-postgres/README.md), [`-mysql`](plugins/data-explorer-mysql/README.md), [`-mssql`](plugins/data-explorer-mssql/README.md), [`-mongo`](plugins/data-explorer-mongo/README.md), [`-redis`](plugins/data-explorer-redis/README.md), [`-elasticsearch`](plugins/data-explorer-elasticsearch/README.md) | Data explorer providers |
|
|
216
|
+
| [`@qodalis/cli-server-plugin-aws`](plugins/aws/README.md) | AWS commands: S3, EC2, Lambda, CloudWatch, SNS, SQS, IAM, DynamoDB, ECS |
|
|
217
|
+
| [`@qodalis/cli-server-plugin-weather`](plugins/weather/README.md) | Example module |
|
|
218
|
+
|
|
219
|
+
Builder-based plugins are mounted with `mountPlugin`:
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
import { CliUsersBuilder } from '@qodalis/cli-server-plugin-users';
|
|
223
|
+
import { CliJobsBuilder } from '@qodalis/cli-server-plugin-jobs';
|
|
224
|
+
|
|
225
|
+
const { app, eventSocketManager, mountPlugin } = createCliServer({ /* ... */ });
|
|
226
|
+
const broadcast = (msg: Record<string, unknown>) => eventSocketManager.broadcastMessage(msg);
|
|
227
|
+
|
|
228
|
+
mountPlugin(new CliJobsBuilder().addJob(new HealthCheckJob(), { name: 'health', interval: '30s' }).build(broadcast));
|
|
229
|
+
mountPlugin(new CliUsersBuilder().setDefaultAdminPassword(process.env.ADMIN_PASSWORD!).build(broadcast));
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### File storage
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
import { OsFileStorageProvider } from '@qodalis/cli-server-plugin-filesystem';
|
|
236
|
+
|
|
237
|
+
createCliServer({
|
|
238
|
+
configure: (builder) =>
|
|
239
|
+
builder.setFileStorageProvider(new OsFileStorageProvider({ allowedPaths: ['/srv/share'] }), {
|
|
240
|
+
maxUploadBytes: 500 * 1024 * 1024, // default 100 MiB, one file per upload
|
|
241
|
+
}),
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Other providers: `InMemoryFileStorageProvider`, `JsonFileStorageProvider({ filePath })`, `SqliteFileStorageProvider({ dbPath })`, `S3FileStorageProvider({ bucket, region, prefix, credentials })`. Implement `IFileStorageProvider` for your own backend. To mount the router yourself, use `createFilesystemRouter(provider, { maxUploadBytes })`.
|
|
246
|
+
|
|
247
|
+
### Data explorer
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import { SqlDataExplorerProvider } from '@qodalis/cli-server-plugin-data-explorer-sql';
|
|
251
|
+
import { DataExplorerLanguage, DataExplorerOutputFormat } from '@qodalis/cli-server-abstractions';
|
|
252
|
+
|
|
253
|
+
builder.addDataExplorerProvider(new SqlDataExplorerProvider({ type: 'sqlite', filename: './data.db' }), {
|
|
254
|
+
name: 'app-db',
|
|
255
|
+
description: 'Application database',
|
|
256
|
+
language: DataExplorerLanguage.Sql,
|
|
257
|
+
defaultOutputFormat: DataExplorerOutputFormat.Table,
|
|
258
|
+
timeout: 30000,
|
|
259
|
+
maxRows: 1000,
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
The same provider class can be registered several times under different names. Implement `IDataExplorerProvider` for other sources.
|
|
264
|
+
|
|
265
|
+
## Security
|
|
266
|
+
|
|
267
|
+
When the users plugin is mounted (`mountPlugin(usersPlugin)`, or passed as `auth`), every `/api/...` route and WebSocket requires a session or an API token; login, version discovery and capabilities stay public.
|
|
268
|
+
|
|
269
|
+
| Surface | Permission |
|
|
270
|
+
|---|---|
|
|
271
|
+
| `GET /commands` | authenticated |
|
|
272
|
+
| `POST /execute`, `/execute/stream` | `commands:execute` plus the processor's `requiredPermissions` |
|
|
273
|
+
| `POST /api/qcli/mcp` | `commands:execute` (each tool then checks its own) |
|
|
274
|
+
| fs `ls` / `cat` / `stat` / `download` | `files:read` |
|
|
275
|
+
| fs `upload` / `mkdir` / `rm` | `files:write` |
|
|
276
|
+
| data explorer | `data:query` |
|
|
277
|
+
| jobs read / manage | `jobs:read` / `jobs:manage` |
|
|
278
|
+
| events / logs / shell WebSocket | authenticated / `logs:read` / `shell:execute` |
|
|
279
|
+
| admin dashboard | `admin:access` |
|
|
280
|
+
|
|
281
|
+
WebSockets authenticate with a single-use ticket from `POST /api/v1/qcli/sessions/ws-ticket` (`?ticket=<ticket>`). Sockets bound to a session close with 4401 `session ended` on logout, expiry, kick, or when the user is disabled or deleted. Details: [users plugin README](plugins/users/README.md).
|
|
282
|
+
|
|
283
|
+
### Remote shell
|
|
284
|
+
|
|
285
|
+
The PTY shell gives OS-level access, so it is off unless `enableShell: true`, and then exactly one access mode applies:
|
|
286
|
+
|
|
287
|
+
| Mode (`shellAuth`) | When | Client must |
|
|
288
|
+
|---|---|---|
|
|
289
|
+
| `users` | users plugin mounted | connect with a WS ticket of a session holding `shell:execute` |
|
|
290
|
+
| `token` | `shell.token` set | send `Authorization: Bearer <token>` (or the `_header_Authorization` query parameter) |
|
|
291
|
+
| `custom` | `shell.authorize` set | pass `authorize(request, { url, remoteAddress, mode })` |
|
|
292
|
+
| `anonymous` | `shell.allowAnonymous: true` | nothing (a startup warning is logged) |
|
|
293
|
+
| `locked` | none of the above | connections are closed with 4401 |
|
|
294
|
+
|
|
295
|
+
The users plugin wins when mounted; otherwise `token`, then `custom`, then `anonymous`. Every configured check among `token` and `authorize` must pass. Tokens are compared in constant time and never logged.
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
createCliServer({
|
|
299
|
+
enableShell: true,
|
|
300
|
+
shell: { token: process.env.QCLI_SHELL_TOKEN },
|
|
301
|
+
});
|
|
110
302
|
```
|
|
111
303
|
|
|
304
|
+
| `shell` option | Default | Description |
|
|
305
|
+
|---|---|---|
|
|
306
|
+
| `token`, `authorize`, `allowAnonymous` | none | Access mode (see above) |
|
|
307
|
+
| `maxSessionsPerUser` | `3` | Per user (users mode) or per remote address |
|
|
308
|
+
| `maxSessions` | `20` | Total concurrent shells |
|
|
309
|
+
| `idleTimeoutMs` | 15 min | Close after no stdin (`0` = off) |
|
|
310
|
+
| `maxDurationMs` | none | Absolute session limit |
|
|
311
|
+
| `sessionCheckIntervalMs` | `30000` | Users-mode re-check (max 60000) |
|
|
312
|
+
| `cwd`, `shell` | home dir, detected | Working directory and shell binary |
|
|
313
|
+
| `env` | `{}` | `{ allow: string[], set: Record<string, string> }` |
|
|
314
|
+
|
|
315
|
+
- The shell does not inherit the server environment: it gets `PATH`, `HOME`, `USER`, `LANG`, `TERM`, `COLUMNS`, `LINES`, `SHELL`, plus `env.allow` and `env.set`.
|
|
316
|
+
- A shell bound to a users session closes with 4401 when the session ends or `shell:execute` is removed; opens and closes are audited as `shell_opened` / `shell_closed`, never with the command text.
|
|
317
|
+
- When a shell ends, its whole process tree is killed (SIGHUP, SIGTERM, then SIGKILL after 1 s): process group, descendants, Linux session, and every process carrying the shell's `QCLI_SHELL_ID` marker. On Windows only the shell process is killed. Run the server in a container if every process must be contained.
|
|
318
|
+
|
|
319
|
+
| Close code | Reason |
|
|
320
|
+
|---|---|
|
|
321
|
+
| 4401 | login required, session ended, or shell access not configured |
|
|
322
|
+
| 4403 | forbidden (wrong token, `authorize` false, missing `shell:execute`, password change required) |
|
|
323
|
+
| 4404 | shell disabled |
|
|
324
|
+
| 4408 | shell timed out |
|
|
325
|
+
| 4429 | too many shell sessions |
|
|
326
|
+
| 1001 | server shutdown |
|
|
327
|
+
|
|
328
|
+
## MCP endpoint
|
|
329
|
+
|
|
330
|
+
`POST {basePath}/mcp` (default `/api/qcli/mcp`) exposes the server to AI clients such as Claude Code over the [Model Context Protocol](https://modelcontextprotocol.io): stateless Streamable HTTP with JSON responses, methods `initialize`, `ping`, `tools/list`, `tools/call`. It is off by default.
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
const { mcp } = createCliServer({
|
|
334
|
+
mcp: {
|
|
335
|
+
tools: ['weather_*', 'echo'], // allow-list (trailing * = prefix); default: every tool
|
|
336
|
+
exclude: ['fs_delete'], // deny-list applied after `tools`
|
|
337
|
+
token: process.env.MCP_TOKEN, // only without an auth provider: required bearer token
|
|
338
|
+
instructions: 'Each tool runs one command of this server.',
|
|
339
|
+
},
|
|
340
|
+
});
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
| Server setup | Access |
|
|
344
|
+
|---|---|
|
|
345
|
+
| users plugin mounted | session or API token (`qcli_pat_...`) holding `commands:execute`; tools are filtered by the caller's permissions |
|
|
346
|
+
| no auth provider, `mcp.token` set | `Authorization: Bearer <token>` |
|
|
347
|
+
| no auth provider, no token | open, like `/execute` |
|
|
348
|
+
|
|
349
|
+
| Tools | Available when | Permission |
|
|
350
|
+
|---|---|---|
|
|
351
|
+
| `server_info` | always | none |
|
|
352
|
+
| one tool per command (`weather`, `weather_current`, ...) | always | `commands:execute` plus `requiredPermissions` |
|
|
353
|
+
| `fs_list`, `fs_stat`, `fs_read` / `fs_write`, `fs_mkdir`, `fs_delete` | file storage configured | `files:read` / `files:write` |
|
|
354
|
+
| `data_sources`, `data_schema`, `data_query` | data sources registered | `data:query` |
|
|
355
|
+
| `jobs_list`, `jobs_get`, `jobs_history` / `jobs_trigger`, `jobs_pause`, `jobs_resume`, `jobs_stop`, `jobs_cancel` | jobs plugin mounted | `jobs:read` / `jobs:manage` |
|
|
356
|
+
|
|
357
|
+
Command tools run through the same executor as `/execute`; outputs are rendered as text, `isError` is `exitCode != 0`. Add your own tools with `mcp.addProvider(provider)`, `builder.addMcpToolProvider(provider)` or a plugin's `mcpProviders` (use `mcpObjectSchema` to build the input schema). An `Origin` header, when present, must be allowed or same-origin.
|
|
358
|
+
|
|
359
|
+
Connect Claude Code (with the users plugin, create a token with `token create claude` in the web CLI or `POST /api/v1/qcli/tokens`):
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
# directly over HTTP
|
|
363
|
+
claude mcp add --transport http qcli http://localhost:8047/api/qcli/mcp --header "Authorization: Bearer <token>"
|
|
364
|
+
|
|
365
|
+
# or through the @qodalis/mcp-cli bridge
|
|
366
|
+
claude mcp add qcli -e QCLI_URL=http://localhost:8047 -e QCLI_TOKEN=<token> -- npx -y @qodalis/mcp-cli
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
| Symptom | Fix |
|
|
370
|
+
|---|---|
|
|
371
|
+
| `401` | Missing, wrong, expired or revoked token; without the users plugin check `mcp.token` |
|
|
372
|
+
| `403 forbidden: origin not allowed` | Add the client's origin to `allowedOrigins` (Claude Code sends none) |
|
|
373
|
+
| `403 forbidden: missing permission commands:execute` | Grant it to one of the user's groups or the token's scope |
|
|
374
|
+
| `404` | MCP is not enabled or the URL is not `{basePath}/mcp` |
|
|
375
|
+
| `405` | Only `POST` is accepted |
|
|
376
|
+
| Tool missing from `tools/list` | Missing permission, filtered by `tools`/`exclude`, or the feature is not enabled |
|
|
377
|
+
|
|
378
|
+
## Built-in processors
|
|
379
|
+
|
|
380
|
+
| Command | Description |
|
|
381
|
+
|---|---|
|
|
382
|
+
| `echo` | Echoes input text |
|
|
383
|
+
| `status` | Server status (uptime, OS) |
|
|
384
|
+
| `system` | System information (memory, CPU, uptime) |
|
|
385
|
+
| `http` | HTTP `get` / `post` requests |
|
|
386
|
+
| `hash` | MD5, SHA1, SHA256, SHA512 |
|
|
387
|
+
| `base64` | `encode` / `decode` |
|
|
388
|
+
|
|
389
|
+
All are exported (`CliEchoCommandProcessor`, `CliStatusCommandProcessor`, ...) and registered by the standalone server.
|
|
390
|
+
|
|
112
391
|
## Docker
|
|
113
392
|
|
|
114
393
|
```bash
|
|
115
394
|
docker run -p 8047:8047 ghcr.io/qodalis-solutions/cli-server-node
|
|
116
395
|
```
|
|
117
396
|
|
|
118
|
-
The
|
|
397
|
+
The image runs the standalone server and accepts the same environment variables. `docker-compose.yml` builds and runs the demo server (`demo/Dockerfile`) on port 8047.
|
|
119
398
|
|
|
120
|
-
##
|
|
399
|
+
## Development
|
|
121
400
|
|
|
122
401
|
```bash
|
|
123
|
-
cd demo
|
|
124
402
|
npm install
|
|
125
|
-
npm
|
|
126
|
-
#
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
## Project Structure
|
|
403
|
+
npm run build # tsc -> dist/
|
|
404
|
+
npm test # vitest run
|
|
405
|
+
npm run test:watch # vitest in watch mode
|
|
406
|
+
npm run dev # standalone server with watch (tsx)
|
|
130
407
|
|
|
408
|
+
cd demo && npm install && npm start # full demo: all plugins, users (root / admin), MCP, shell
|
|
131
409
|
```
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
create-cli-server.ts # Factory function for standalone/library use
|
|
140
|
-
server.ts # Standalone entry point
|
|
141
|
-
demo/ # Demo app with 5 sample processors
|
|
142
|
-
```
|
|
410
|
+
|
|
411
|
+
| Path | Contents |
|
|
412
|
+
|---|---|
|
|
413
|
+
| `src/` | Server factory, controllers, services, MCP, built-in processors, standalone entry (`server.ts`) |
|
|
414
|
+
| `packages/abstractions/` | `@qodalis/cli-server-abstractions` |
|
|
415
|
+
| `plugins/` | Plugin packages (users, admin, jobs, filesystem, data explorer, aws, weather) |
|
|
416
|
+
| `demo/` | Demo server with custom processors and every plugin |
|
|
143
417
|
|
|
144
418
|
## License
|
|
145
419
|
|
|
146
|
-
MIT
|
|
420
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@qodalis/cli-server-node",
|
|
3
|
+
"version": "1.0.0-beta.10",
|
|
4
|
+
"description": "Node.js CLI server for Qodalis CLI ecosystem — use as a library in existing Express apps or run standalone",
|
|
5
|
+
"main": "dist/src/index.js",
|
|
6
|
+
"types": "dist/src/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"qodalis-cli-server": "dist/src/server.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"!dist/src/__tests__",
|
|
13
|
+
"!dist/plugins",
|
|
14
|
+
"LICENSE",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"start": "tsx src/server.ts",
|
|
20
|
+
"dev": "tsx watch src/server.ts",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"cli",
|
|
26
|
+
"qodalis",
|
|
27
|
+
"terminal",
|
|
28
|
+
"commands",
|
|
29
|
+
"cli-server",
|
|
30
|
+
"command-processor"
|
|
31
|
+
],
|
|
32
|
+
"author": "Nicolae Lupei <nicolae.lupei@qodalis.com>",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/qodalis-solutions/cli-server-node"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://qodalis.com/",
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@qodalis/cli-server-abstractions": "file:packages/abstractions",
|
|
41
|
+
"@qodalis/cli-server-plugin-data-explorer": "file:plugins/data-explorer",
|
|
42
|
+
"@qodalis/cli-server-plugin-filesystem": "file:plugins/filesystem",
|
|
43
|
+
"@qodalis/cli-server-plugin-jobs": "file:plugins/jobs",
|
|
44
|
+
"cors": "^2.8.5",
|
|
45
|
+
"express": "^4.22.3",
|
|
46
|
+
"multer": "^2.5.0",
|
|
47
|
+
"node-pty": "^1.1.0",
|
|
48
|
+
"ws": "^8.22.0"
|
|
49
|
+
},
|
|
50
|
+
"optionalDependencies": {
|
|
51
|
+
"@elastic/elasticsearch": "^8.16.0",
|
|
52
|
+
"@qodalis/cli-server-plugin-filesystem-json": "file:plugins/filesystem-json",
|
|
53
|
+
"@qodalis/cli-server-plugin-filesystem-s3": "file:plugins/filesystem-s3",
|
|
54
|
+
"@qodalis/cli-server-plugin-filesystem-sqlite": "file:plugins/filesystem-sqlite",
|
|
55
|
+
"better-sqlite3": "^13.0.3",
|
|
56
|
+
"ioredis": "^5.4.0",
|
|
57
|
+
"mongodb": "^6.0.0",
|
|
58
|
+
"mssql": "^11.0.0",
|
|
59
|
+
"mysql2": "^3.24.6",
|
|
60
|
+
"pg": "^8.13.0"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
64
|
+
"@types/cors": "^2.8.17",
|
|
65
|
+
"@types/express": "^4.17.21",
|
|
66
|
+
"@types/mssql": "^9.1.9",
|
|
67
|
+
"@types/multer": "^2.0.0",
|
|
68
|
+
"@types/node": "^22.0.0",
|
|
69
|
+
"@types/pg": "^8.0.0",
|
|
70
|
+
"@types/supertest": "^7.2.0",
|
|
71
|
+
"@types/ws": "^8.5.13",
|
|
72
|
+
"supertest": "^7.2.2",
|
|
73
|
+
"tsx": "^4.19.0",
|
|
74
|
+
"typescript": "^5.6.0",
|
|
75
|
+
"vitest": "^4.1.12"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-command-author.d.ts","sourceRoot":"","sources":["../../../src/abstractions/cli-command-author.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultLibraryAuthor = exports.CliCommandAuthor = void 0;
|
|
4
|
+
var cli_server_abstractions_1 = require("@qodalis/cli-server-abstractions");
|
|
5
|
+
Object.defineProperty(exports, "CliCommandAuthor", { enumerable: true, get: function () { return cli_server_abstractions_1.CliCommandAuthor; } });
|
|
6
|
+
Object.defineProperty(exports, "DefaultLibraryAuthor", { enumerable: true, get: function () { return cli_server_abstractions_1.DefaultLibraryAuthor; } });
|
|
7
|
+
//# sourceMappingURL=cli-command-author.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-command-author.js","sourceRoot":"","sources":["../../../src/abstractions/cli-command-author.ts"],"names":[],"mappings":";;;AAAA,4EAA6G;AAAjF,2HAAA,gBAAgB,OAAA;AAAE,+HAAA,oBAAoB,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-command-parameter-descriptor.d.ts","sourceRoot":"","sources":["../../../src/abstractions/cli-command-parameter-descriptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,6BAA6B,EAAE,MAAM,kCAAkC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CliCommandParameterDescriptor = void 0;
|
|
4
|
+
var cli_server_abstractions_1 = require("@qodalis/cli-server-abstractions");
|
|
5
|
+
Object.defineProperty(exports, "CliCommandParameterDescriptor", { enumerable: true, get: function () { return cli_server_abstractions_1.CliCommandParameterDescriptor; } });
|
|
6
|
+
//# sourceMappingURL=cli-command-parameter-descriptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-command-parameter-descriptor.js","sourceRoot":"","sources":["../../../src/abstractions/cli-command-parameter-descriptor.ts"],"names":[],"mappings":";;;AAAA,4EAAiH;AAAxE,wIAAA,6BAA6B,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-command-processor.d.ts","sourceRoot":"","sources":["../../../src/abstractions/cli-command-processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CliCommandProcessor = void 0;
|
|
4
|
+
var cli_server_abstractions_1 = require("@qodalis/cli-server-abstractions");
|
|
5
|
+
Object.defineProperty(exports, "CliCommandProcessor", { enumerable: true, get: function () { return cli_server_abstractions_1.CliCommandProcessor; } });
|
|
6
|
+
//# sourceMappingURL=cli-command-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-command-processor.js","sourceRoot":"","sources":["../../../src/abstractions/cli-command-processor.ts"],"names":[],"mappings":";;;AAAA,4EAA6F;AAA9D,8HAAA,mBAAmB,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-process-command.d.ts","sourceRoot":"","sources":["../../../src/abstractions/cli-process-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC"}
|