ellmos-servercommander-mcp 0.1.0-alpha.4 → 0.1.0-alpha.6

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/KONZEPT.md CHANGED
@@ -83,9 +83,9 @@ endpoints = [
83
83
 
84
84
  ## Quellmodule
85
85
 
86
- | Modul | Quellpfad | LoC | Dependencies |
86
+ | Modul | Herkunft | LoC | Dependencies |
87
87
  |---|---|---|---|
88
- | deploy.py | `.TOPICS/.UMBRUCH/deploy.py` | ~221 | paramiko (SFTP) |
89
- | cli.py (Mail) | `.TOPICS/.UMBRUCH/cli.py` | ~516 | stdlib (imaplib, smtplib) |
90
- | traffic_analyzer.py | `.TOPICS/.UMBRUCH/traffic_analyzer.py` | ~300 | stdlib |
88
+ | deploy.py | interne Extraktionsnotiz | ~221 | paramiko (SFTP) |
89
+ | cli.py (Mail) | interne Extraktionsnotiz | ~516 | stdlib (imaplib, smtplib) |
90
+ | traffic_analyzer.py | interne Extraktionsnotiz | ~300 | stdlib |
91
91
  | health.py | neu | ~50 | stdlib (urllib) |
package/README.md CHANGED
@@ -8,33 +8,47 @@ Alpha MCP server for server operations: deployment dry-runs, mail status, access
8
8
 
9
9
  German README: [README_de.md](README_de.md)
10
10
 
11
+ *Part of the [ellmos-ai](https://github.com/ellmos-ai) family.*
12
+
13
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
14
+ [![npm version](https://img.shields.io/npm/v/ellmos-servercommander-mcp.svg)](https://www.npmjs.com/package/ellmos-servercommander-mcp)
15
+ [![Python](https://img.shields.io/badge/python-%3E%3D3.10-blue.svg)](https://www.python.org/)
16
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](https://nodejs.org/)
17
+ [![MCP](https://img.shields.io/badge/MCP-stdio-blueviolet.svg)](https://modelcontextprotocol.io/)
18
+ [![Status: alpha](https://img.shields.io/badge/status-alpha-orange.svg)](https://www.npmjs.com/package/ellmos-servercommander-mcp)
19
+
20
+ **Discoverability:** Published on [npm](https://www.npmjs.com/package/ellmos-servercommander-mcp) as `ellmos-servercommander-mcp` and maintained in the [`ellmos-ai`](https://github.com/ellmos-ai) organization.
21
+
11
22
  ## Status
12
23
 
13
24
  - Transport: stdio via the Python MCP SDK
14
25
  - Package status: public alpha package under `ellmos-ai`
15
- - Current core: MCP tool listing, MCP tool dispatch, config loading, `sc_logs_analyze`, `sc_health_check`
16
- - Safe alpha handlers: `sc_deploy` builds local SHA256 manifests in dry-run mode; `sc_mail_*` does not perform IMAP/SMTP operations yet
26
+ - Current core: MCP tool listing, MCP tool dispatch, config loading, HTTP health checks, richer access-log analysis
27
+ - Safe alpha handlers: `sc_deploy` builds local SHA256 manifests and configuration diagnostics in dry-run mode; `sc_mail_*` reports mail configuration gaps without IMAP/SMTP operations
17
28
  - i18n: localized MCP tool descriptions, input-schema field descriptions, and unknown-tool errors for `en`, `de`, `es`, `zh`, `ja`, `ru` with English fallback
18
29
 
19
30
  ## Install
20
31
 
21
32
  The npm package contains a Node wrapper that starts the Python server. You still need Python 3.10+ and the Python package `mcp>=1.0.0`.
22
33
 
34
+ ### Option 1: Install From npm
35
+
23
36
  ```powershell
24
37
  npm install -g ellmos-servercommander-mcp@alpha
25
38
  ellmos-servercommander
26
39
  ```
27
40
 
28
- For local development:
41
+ ### Option 2: Install From Source
29
42
 
30
43
  ```powershell
31
- cd "C:\Users\User\OneDrive\.TOPICS\.AI\.MCP\ellmos-servercommander-mcp"
44
+ git clone https://github.com/ellmos-ai/ellmos-servercommander-mcp.git
45
+ cd ellmos-servercommander-mcp
32
46
  $env:PYTHONIOENCODING = "utf-8"
33
47
  python -m pip install -e ".[dev]"
34
48
  python -m pytest -q
35
49
  ```
36
50
 
37
- Do not create a `.venv` inside a OneDrive-synced folder. If you need an isolated environment, create it outside OneDrive.
51
+ Avoid creating a `.venv` inside cloud-synced folders if your sync client locks files. If you need an isolated environment, create it outside that folder.
38
52
 
39
53
  ## Start From Source
40
54
 
@@ -43,7 +57,39 @@ $env:PYTHONPATH = "src"
43
57
  python -m servercommander.server
44
58
  ```
45
59
 
46
- ## Configuration
60
+ ## MCP Client Configuration
61
+
62
+ ### Global npm Install
63
+
64
+ ```json
65
+ {
66
+ "mcpServers": {
67
+ "servercommander": {
68
+ "command": "ellmos-servercommander"
69
+ }
70
+ }
71
+ }
72
+ ```
73
+
74
+ ### Source Checkout
75
+
76
+ ```json
77
+ {
78
+ "mcpServers": {
79
+ "servercommander": {
80
+ "command": "python",
81
+ "args": ["-m", "servercommander.server"],
82
+ "env": {
83
+ "PYTHONPATH": "/absolute/path/to/ellmos-servercommander-mcp/src"
84
+ }
85
+ }
86
+ }
87
+ }
88
+ ```
89
+
90
+ Replace `/absolute/path/to/ellmos-servercommander-mcp` with your local checkout path.
91
+
92
+ ## Server Configuration
47
93
 
48
94
  Example: [config/servercommander.example.toml](config/servercommander.example.toml)
49
95
 
@@ -66,10 +112,10 @@ Secrets should be referenced through environment variables, for example `$MAIL_P
66
112
  ## Tools
67
113
 
68
114
  - `sc_health_check`: checks HTTP endpoints and reports status code plus latency
69
- - `sc_logs_analyze`: analyzes Apache/Nginx access logs from inline text or a local file
70
- - `sc_deploy`: creates a deployment plan with a local SHA256 manifest, but does not upload yet
71
- - `sc_deploy_status`: shows configured deploy profiles and the current alpha history status
72
- - `sc_mail_list`, `sc_mail_read`, `sc_mail_send`, `sc_mail_search`: safe alpha status responses without IMAP/SMTP connections
115
+ - `sc_logs_analyze`: analyzes Apache/Nginx access logs from inline text or a local file, including status classes, bytes, referers, error paths, and suspicious request markers
116
+ - `sc_deploy`: creates a deployment plan with a local SHA256 manifest and profile diagnostics, but does not upload yet
117
+ - `sc_deploy_status`: shows configured deploy profiles, selected-profile diagnostics, and the current alpha history status
118
+ - `sc_mail_list`, `sc_mail_read`, `sc_mail_send`, `sc_mail_search`: safe alpha status responses with mail configuration diagnostics and no IMAP/SMTP connections
73
119
 
74
120
  ## Development
75
121
 
@@ -81,4 +127,4 @@ npm run smoke
81
127
  npm pack --dry-run
82
128
  ```
83
129
 
84
- Next useful step: extract real SFTP, IMAP/SMTP, and extended traffic-analysis modules from `.UMBRUCH` into credential-free adapters with local tests.
130
+ Next useful step: add explicitly configured execution adapters for SFTP and IMAP/SMTP, keep dry-run defaults, and extend log analysis with persisted reports.
package/README_de.md CHANGED
@@ -8,33 +8,47 @@ Alpha-MCP-Server für Server-Operationen: Deployment-Dry-runs, Mail-Status, Acce
8
8
 
9
9
  Englische Standard-README: [README.md](README.md)
10
10
 
11
+ *Teil der [ellmos-ai](https://github.com/ellmos-ai)-Familie.*
12
+
13
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
14
+ [![npm version](https://img.shields.io/npm/v/ellmos-servercommander-mcp.svg)](https://www.npmjs.com/package/ellmos-servercommander-mcp)
15
+ [![Python](https://img.shields.io/badge/python-%3E%3D3.10-blue.svg)](https://www.python.org/)
16
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](https://nodejs.org/)
17
+ [![MCP](https://img.shields.io/badge/MCP-stdio-blueviolet.svg)](https://modelcontextprotocol.io/)
18
+ [![Status: alpha](https://img.shields.io/badge/status-alpha-orange.svg)](https://www.npmjs.com/package/ellmos-servercommander-mcp)
19
+
20
+ **Auffindbarkeit:** Veröffentlicht auf [npm](https://www.npmjs.com/package/ellmos-servercommander-mcp) als `ellmos-servercommander-mcp` und gepflegt in der Organisation [`ellmos-ai`](https://github.com/ellmos-ai).
21
+
11
22
  ## Status
12
23
 
13
24
  - Transport: stdio über das Python-MCP-SDK
14
25
  - Paketstatus: öffentliches Alpha-Paket unter `ellmos-ai`
15
- - Aktiver Kern: MCP-Tool-Liste, MCP-Tool-Dispatch, Config-Lader, `sc_logs_analyze`, `sc_health_check`
16
- - Sichere Alpha-Handler: `sc_deploy` erstellt lokale SHA256-Manifeste im Dry-run, `sc_mail_*` führt noch keine IMAP/SMTP-Aktionen aus
26
+ - Aktiver Kern: MCP-Tool-Liste, MCP-Tool-Dispatch, Config-Lader, HTTP-Health-Checks, erweiterte Access-Log-Analyse
27
+ - Sichere Alpha-Handler: `sc_deploy` erstellt lokale SHA256-Manifeste und Konfigurationsdiagnosen im Dry-run, `sc_mail_*` meldet Mail-Konfigurationslücken ohne IMAP/SMTP-Aktionen
17
28
  - i18n: lokalisierte MCP-Tool-Beschreibungen, Input-Schema-Feldbeschreibungen und Unknown-Tool-Fehler für `en`, `de`, `es`, `zh`, `ja`, `ru` mit Englisch-Fallback
18
29
 
19
30
  ## Installation
20
31
 
21
32
  Das npm-Paket enthält einen Node-Wrapper, der den Python-Server startet. Voraussetzung bleibt Python 3.10+ mit installiertem Python-Paket `mcp>=1.0.0`.
22
33
 
34
+ ### Option 1: Installation per npm
35
+
23
36
  ```powershell
24
37
  npm install -g ellmos-servercommander-mcp@alpha
25
38
  ellmos-servercommander
26
39
  ```
27
40
 
28
- Für lokale Entwicklung:
41
+ ### Option 2: Installation aus dem Quellcode
29
42
 
30
43
  ```powershell
31
- cd "C:\Users\User\OneDrive\.TOPICS\.AI\.MCP\ellmos-servercommander-mcp"
44
+ git clone https://github.com/ellmos-ai/ellmos-servercommander-mcp.git
45
+ cd ellmos-servercommander-mcp
32
46
  $env:PYTHONIOENCODING = "utf-8"
33
47
  python -m pip install -e ".[dev]"
34
48
  python -m pytest -q
35
49
  ```
36
50
 
37
- Keine `.venv` im OneDrive-Ordner anlegen. Falls eine isolierte Umgebung gebraucht wird, außerhalb von OneDrive erstellen.
51
+ Keine `.venv` in cloud-synchronisierten Ordnern anlegen, wenn der Sync-Client Dateien sperrt. Falls eine isolierte Umgebung gebraucht wird, außerhalb dieses Ordners erstellen.
38
52
 
39
53
  ## Start Aus Dem Quellbaum
40
54
 
@@ -43,7 +57,39 @@ $env:PYTHONPATH = "src"
43
57
  python -m servercommander.server
44
58
  ```
45
59
 
46
- ## Konfiguration
60
+ ## MCP-Client-Konfiguration
61
+
62
+ ### Globale npm-Installation
63
+
64
+ ```json
65
+ {
66
+ "mcpServers": {
67
+ "servercommander": {
68
+ "command": "ellmos-servercommander"
69
+ }
70
+ }
71
+ }
72
+ ```
73
+
74
+ ### Quellcode-Checkout
75
+
76
+ ```json
77
+ {
78
+ "mcpServers": {
79
+ "servercommander": {
80
+ "command": "python",
81
+ "args": ["-m", "servercommander.server"],
82
+ "env": {
83
+ "PYTHONPATH": "/absolute/path/to/ellmos-servercommander-mcp/src"
84
+ }
85
+ }
86
+ }
87
+ }
88
+ ```
89
+
90
+ `/absolute/path/to/ellmos-servercommander-mcp` durch den eigenen lokalen Checkout-Pfad ersetzen.
91
+
92
+ ## Server-Konfiguration
47
93
 
48
94
  Beispiel: [config/servercommander.example.toml](config/servercommander.example.toml)
49
95
 
@@ -66,10 +112,10 @@ Secrets sollen als Umgebungsvariablen referenziert werden, zum Beispiel `$MAIL_P
66
112
  ## Tools
67
113
 
68
114
  - `sc_health_check`: prüft HTTP-Endpunkte und meldet Status-Code plus Latenz
69
- - `sc_logs_analyze`: analysiert Apache-/Nginx-Access-Logs aus Text oder Datei
70
- - `sc_deploy`: erstellt einen Deployment-Plan mit lokalem SHA256-Manifest, führt aber noch keinen Upload aus
71
- - `sc_deploy_status`: zeigt konfigurierte Deploy-Profile und den aktuellen Alpha-History-Status
72
- - `sc_mail_list`, `sc_mail_read`, `sc_mail_send`, `sc_mail_search`: sichere Alpha-Statusantworten ohne IMAP/SMTP-Verbindung
115
+ - `sc_logs_analyze`: analysiert Apache-/Nginx-Access-Logs aus Text oder Datei, inklusive Statusklassen, Bytes, Referern, Fehlerpfaden und verdächtigen Request-Markern
116
+ - `sc_deploy`: erstellt einen Deployment-Plan mit lokalem SHA256-Manifest und Profildiagnose, führt aber noch keinen Upload aus
117
+ - `sc_deploy_status`: zeigt konfigurierte Deploy-Profile, ausgewählte Profildiagnosen und den aktuellen Alpha-History-Status
118
+ - `sc_mail_list`, `sc_mail_read`, `sc_mail_send`, `sc_mail_search`: sichere Alpha-Statusantworten mit Mail-Konfigurationsdiagnosen und ohne IMAP/SMTP-Verbindung
73
119
 
74
120
  ## Entwicklung
75
121
 
@@ -81,4 +127,4 @@ npm run smoke
81
127
  npm pack --dry-run
82
128
  ```
83
129
 
84
- Der nächste sinnvolle Schritt ist die Extraktion der echten SFTP-, IMAP/SMTP- und erweiterten Traffic-Module aus `.UMBRUCH` in credential-freie Adapter mit lokalen Tests.
130
+ Der nächste sinnvolle Schritt ist, explizit konfigurierte Ausführungsadapter für SFTP und IMAP/SMTP zu ergänzen, Dry-run als Standard beizubehalten und Log-Analysen um persistierte Reports zu erweitern.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ellmos-servercommander-mcp",
3
- "version": "0.1.0-alpha.4",
3
+ "version": "0.1.0-alpha.6",
4
4
  "description": "Alpha MCP server for server operations: deploy dry-runs, mail status, log analysis, and health checks.",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "ellmos-servercommander-mcp"
7
- version = "0.1.0a4"
7
+ version = "0.1.0a6"
8
8
  description = "MCP server for server operations: deploy, mail, log analysis, health checks."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1,3 +1,3 @@
1
1
  """ellmos-servercommander-mcp - server operations via MCP."""
2
2
 
3
- __version__ = "0.1.0a4"
3
+ __version__ = "0.1.0a6"
@@ -33,6 +33,7 @@ async def sc_deploy(
33
33
  "local_path": local_path or profile_config.get("local_path"),
34
34
  "remote_path": remote_path or profile_config.get("remote_path"),
35
35
  "protocol": profile_config.get("protocol", "sftp"),
36
+ "port": profile_config.get("port", 22),
36
37
  }
37
38
  missing = [key for key in ("host", "user", "local_path", "remote_path") if not plan.get(key)]
38
39
  manifest = _build_manifest(plan["local_path"]) if plan.get("local_path") else None
@@ -43,6 +44,7 @@ async def sc_deploy(
43
44
  "missing": missing,
44
45
  "plan": plan,
45
46
  "manifest": manifest,
47
+ "diagnostics": _deploy_diagnostics(profile_config, plan, manifest),
46
48
  }
47
49
 
48
50
 
@@ -58,6 +60,7 @@ async def sc_deploy_status(
58
60
  "message": "Deployment history storage is not implemented yet.",
59
61
  "profiles": profiles,
60
62
  "selected_profile": selected,
63
+ "diagnostics": _deploy_diagnostics(selected or {}, selected or {}, None) if profile else None,
61
64
  }
62
65
 
63
66
 
@@ -98,3 +101,24 @@ def _file_entry(path: Path, root: Path) -> dict[str, Any]:
98
101
  "size": path.stat().st_size,
99
102
  "sha256": digest.hexdigest(),
100
103
  }
104
+
105
+
106
+ def _deploy_diagnostics(profile_config: dict[str, Any], plan: dict[str, Any], manifest: dict[str, Any] | None) -> dict[str, Any]:
107
+ protocol = str(plan.get("protocol") or "sftp").lower()
108
+ auth_methods = []
109
+ if profile_config.get("key_path"):
110
+ auth_methods.append("key_path")
111
+ if profile_config.get("password"):
112
+ auth_methods.append("password")
113
+ if not auth_methods:
114
+ auth_methods.append("agent_or_prompt")
115
+ local_status = manifest.get("status") if manifest else "not_checked"
116
+ return {
117
+ "protocol_supported": protocol == "sftp",
118
+ "protocol": protocol,
119
+ "port": int(plan.get("port") or 22),
120
+ "auth_methods_configured": auth_methods,
121
+ "local_status": local_status,
122
+ "execution_enabled": False,
123
+ "next_step": "Review the dry-run plan and enable a future SFTP executor only after credential handling is finalized.",
124
+ }
@@ -18,6 +18,7 @@ LOG_PATTERN = re.compile(
18
18
  )
19
19
 
20
20
  BOT_MARKERS = ("bot", "crawler", "spider", "slurp", "bingpreview")
21
+ SUSPICIOUS_MARKERS = ("../", "%2e%2e", "/wp-admin", "/.env", "/phpmyadmin", "/admin", "/login")
21
22
 
22
23
 
23
24
  async def sc_logs_analyze(
@@ -36,8 +37,13 @@ async def sc_logs_analyze(
36
37
  status_classes: Counter[str] = Counter()
37
38
  method_counts: Counter[str] = Counter()
38
39
  path_counts: Counter[str] = Counter()
40
+ error_path_counts: Counter[str] = Counter()
39
41
  agent_counts: Counter[str] = Counter()
42
+ referer_counts: Counter[str] = Counter()
43
+ hosts: set[str] = set()
44
+ total_bytes = 0
40
45
  bot_requests = 0
46
+ suspicious_requests = 0
41
47
  parsed_lines = 0
42
48
 
43
49
  for line in lines:
@@ -45,28 +51,49 @@ async def sc_logs_analyze(
45
51
  if not match:
46
52
  continue
47
53
  parsed_lines += 1
54
+ hosts.add(match.group("host"))
48
55
  status = match.group("status")
49
56
  status_counts[status] += 1
50
57
  status_classes[f"{status[0]}xx"] += 1
51
58
  method_counts[match.group("method")] += 1
52
- path_counts[match.group("path")] += 1
59
+ path = match.group("path")
60
+ path_counts[path] += 1
61
+ if int(status) >= 400:
62
+ error_path_counts[path] += 1
63
+ size = match.group("size")
64
+ if size.isdigit():
65
+ total_bytes += int(size)
66
+ referer = match.group("referer") or ""
67
+ if referer and referer != "-":
68
+ referer_counts[referer] += 1
53
69
  agent = match.group("agent") or ""
54
70
  if agent:
55
71
  agent_counts[agent] += 1
56
72
  if any(marker in agent.lower() for marker in BOT_MARKERS):
57
73
  bot_requests += 1
74
+ if any(marker in path.lower() for marker in SUSPICIOUS_MARKERS):
75
+ suspicious_requests += 1
76
+
77
+ error_count = sum(count for status, count in status_counts.items() if int(status) >= 400)
78
+ error_rate = round(error_count / parsed_lines, 4) if parsed_lines else 0.0
58
79
 
59
80
  return {
60
81
  "status": "ok",
61
82
  "total_lines": len(lines),
62
83
  "parsed_lines": parsed_lines,
63
84
  "unparsed_lines": len(lines) - parsed_lines,
85
+ "unique_hosts": len(hosts),
86
+ "total_bytes": total_bytes,
87
+ "error_rate": error_rate,
64
88
  "status_counts": dict(status_counts),
65
89
  "status_classes": dict(status_classes),
66
90
  "method_counts": dict(method_counts),
67
91
  "top_paths": path_counts.most_common(int(top_paths)),
92
+ "top_error_paths": error_path_counts.most_common(int(top_paths)),
93
+ "top_referers": referer_counts.most_common(10),
68
94
  "top_agents": agent_counts.most_common(10),
69
95
  "bot_requests": bot_requests,
96
+ "suspicious_requests": suspicious_requests,
70
97
  }
71
98
 
72
99
 
@@ -40,11 +40,27 @@ def _mail_alpha_response(config: ServerCommanderConfig, action: str, request: di
40
40
  mail = config.mail
41
41
  username = resolve_env_value(mail.get("username", ""))
42
42
  password = resolve_env_value(mail.get("password", ""))
43
- configured = bool(mail.get("imap_host") and mail.get("smtp_host") and username and password)
43
+ checks = {
44
+ "imap_host": bool(mail.get("imap_host")),
45
+ "smtp_host": bool(mail.get("smtp_host")),
46
+ "username": bool(username),
47
+ "password": bool(password),
48
+ }
49
+ configured = all(checks.values())
50
+ missing = [key for key, ok in checks.items() if not ok]
44
51
  return {
45
52
  "status": "not_implemented",
46
53
  "action": action,
47
54
  "configured": configured,
55
+ "missing": missing,
56
+ "checks": checks,
57
+ "capabilities": {
58
+ "list": False,
59
+ "read": False,
60
+ "send": False,
61
+ "search": False,
62
+ "config_diagnostics": True,
63
+ },
48
64
  "request": request,
49
65
  "message": "IMAP/SMTP execution is not implemented in the alpha server.",
50
66
  }