sysflow-mcp 1.0.1__tar.gz

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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Johann Schiffer / NEXUS
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,172 @@
1
+ Metadata-Version: 2.4
2
+ Name: sysflow-mcp
3
+ Version: 1.0.1
4
+ Summary: Safe Linux Sysadmin, Process & Build Automation Engine for AI Agents
5
+ Author: Johann Schiffer
6
+ License: MIT
7
+ Project-URL: Homepage, https://johannschiffer.github.io
8
+ Project-URL: Repository, https://github.com/johannschiffer/sysflow-mcp
9
+ Project-URL: Starter Kit, https://johanld.gumroad.com/l/genesis-starter-kit
10
+ Project-URL: Enterprise Suite, https://johanld.gumroad.com/l/genesis-enterprise-suite
11
+ Keywords: mcp,model-context-protocol,sysadmin,linux,systemd,claude,cursor,monitoring,ai-agent
12
+ Requires-Python: >=3.10
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Provides-Extra: test
16
+ Requires-Dist: pytest>=7; extra == "test"
17
+ Dynamic: license-file
18
+
19
+ # SysFlow MCP (Lite Edition)
20
+
21
+ <a href="https://glama.ai/mcp/servers/@johannschiffer/sysflow-mcp">
22
+ <img width="380" height="200" src="https://glama.ai/mcp/servers/@johannschiffer/sysflow-mcp/badge" alt="sysflow-mcp MCP server" />
23
+ </a>
24
+
25
+
26
+ > **Free:** [Genesis Starter Kit](https://johanld.gumroad.com/l/genesis-starter-kit) (25 `.cursorrules`/`CLAUDE.md` rulesets + MCP configs). Try the [live config builder](https://johannschiffer.github.io).
27
+ > **Full stack:** all six servers in [Genesis Enterprise Suite ($19)](https://johanld.gumroad.com/l/genesis-enterprise-suite).
28
+
29
+
30
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
31
+ [![Python 3.10+](https://img.shields.io/badge/Python-3.10+-brightgreen.svg)](https://python.org)
32
+ [![MCP Compliant](https://img.shields.io/badge/MCP-2024--11--05-purple.svg)](https://modelcontextprotocol.io)
33
+
34
+ **SysFlow MCP** is a lightweight, zero-overhead Model Context Protocol server that gives AI agents in **Claude Desktop**, **Cursor**, **Windsurf**, and **Antigravity** safe, structured access to Linux sysadmin inspection, log tailing, and service health without granting unrestricted root shells or risking interactive terminal freezes.
35
+
36
+ ---
37
+
38
+ ## Run without cloning
39
+
40
+ ```bash
41
+ uvx sysflow-mcp
42
+ ```
43
+
44
+ Claude Desktop / Cursor config entry:
45
+
46
+ ```json
47
+ {
48
+ "mcpServers": {
49
+ "sysflow-mcp": {
50
+ "command": "uvx",
51
+ "args": [
52
+ "--from",
53
+ "git+https://github.com/johannschiffer/sysflow-mcp",
54
+ "sysflow-mcp"
55
+ ]
56
+ }
57
+ }
58
+ }
59
+ ```
60
+
61
+ [![CI](https://github.com/johannschiffer/sysflow-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/johannschiffer/sysflow-mcp/actions/workflows/ci.yml)
62
+
63
+ ## ðŸ–Ĩïļ Why SysFlow MCP?
64
+
65
+ Giving an AI assistant raw terminal execution often ends in frustration:
66
+ 1. **Interactive Terminal Freezes:** Commands like `journalctl`, `systemctl status`, or `git log` default to interactive pagers (`less`), leaving the AI agent permanently hung waiting for user input.
67
+ 2. **Context Window Flooding:** Tailing an unconstrained `/var/log/nginx/access.log` dumps thousands of lines into the LLM prompt, wasting tokens and causing memory errors.
68
+ 3. **Destructive Shell Commands:** Without sandboxing, a hallucinated command can kill critical background daemons or delete workspace assets.
69
+
70
+ **SysFlow** exposes safe, bounded, non-blocking tools specifically tailored for autonomous developer agents.
71
+
72
+ ---
73
+
74
+ ## ⚡ Features (Lite Edition)
75
+
76
+ - 📊 **Resource Healthcheck**: Reports CPU core load averages (1m, 5m, 15m), RAM availability (MB and percentage), and disk partition metrics.
77
+ - 📜 **Safe Log Tailer**: Reads the last N lines (bounded and memory-safe) with optional regex filtering; automatically rejects binary files.
78
+ - ⚙ïļ **Systemd User Service Inspector**: Lists user-level services and timers (`systemctl --user`), highlighting failed units without requiring `sudo`.
79
+ - ðŸŠķ **Zero External Dependencies**: Operates strictly on Python standard library and Linux `/proc` filesystem.
80
+
81
+ ---
82
+
83
+ ## 🚀 Quick Setup in 2 Minutes
84
+
85
+ ### 1. Installation
86
+
87
+ ```bash
88
+ git clone https://github.com/johannschiffer/sysflow-mcp.git
89
+ cd sysflow-mcp
90
+ pip install .
91
+ ```
92
+
93
+ ### 2. Configure Claude Desktop (`claude_desktop_config.json`)
94
+
95
+ On Linux: `~/.config/Claude/claude_desktop_config.json`
96
+ On macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
97
+ On Windows: `%APPDATA%\Claude\claude_desktop_config.json`
98
+
99
+ ```json
100
+ {
101
+ "mcpServers": {
102
+ "sysflow": {
103
+ "command": "python",
104
+ "args": ["-m", "sysflow.server"],
105
+ "cwd": "/path/to/sysflow-mcp"
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### 3. Verify via CLI
112
+
113
+ ```bash
114
+ python -m sysflow.cli resources
115
+ ```
116
+
117
+ ---
118
+
119
+ ## 🛠ïļ MCP Tools Exposed to AI Agents
120
+
121
+ | Tool | Parameters | Description |
122
+ |---|---|---|
123
+ | `check_system_resources` | *(none)* | Returns CPU load, memory usage, and partition disk metrics |
124
+ | `tail_logs` | `filepath`, `lines`, `pattern` | Safely tails recent log lines with optional regex filter |
125
+ | `inspect_systemd_services` | `failed_only` | Lists user-level services, states, and detects failed daemons |
126
+ | `inspect_systemd_timers` | *(none)* | Lists scheduled systemd user timers |
127
+
128
+ ---
129
+
130
+ ## 💎 Need Enterprise Build Sandboxing? Upgrade to SysFlow Pro
131
+
132
+ Looking to automate shell task execution, manage Docker containers, or generate verified systemd units?
133
+
134
+ | Feature | Lite (Open Source) | Enterprise Suite ($19) |
135
+ |---|:---:|:---:|
136
+ | **CPU, RAM & Disk Monitoring** | ✅ | ✅ |
137
+ | **Safe Bounded Log Tailer** | ✅ | ✅ |
138
+ | **Systemd User Service Auditing** | ✅ | ✅ |
139
+ | **Sandboxed Task Runner with Timeouts** *(Anti-freeze)* | ❌ | ✅ |
140
+ | **Docker Container Health & Log Inspector** | ❌ | ✅ |
141
+ | **Verified Systemd Unit File Generator** | ❌ | ✅ |
142
+ | **Listening Socket & Port Conflict Auditor** | ❌ | ✅ |
143
+ | **Production Docker Container** | ❌ | ✅ |
144
+ | **Full Pytest Suite & Sysadmin Automation Guide** | ❌ | ✅ |
145
+
146
+ 👉 **[Get the Genesis Enterprise Suite ($19)](https://johanld.gumroad.com/l/genesis-enterprise-suite)**
147
+
148
+ ---
149
+
150
+ ## 📄 License
151
+
152
+ MIT License. See [LICENSE](LICENSE) for details.
153
+
154
+ ## Recommended Infrastructure
155
+
156
+ VPS hosting that work well with SysFlow MCP. Some links are referral links.
157
+
158
+ - [Hetzner Cloud](https://www.hetzner.com/cloud)
159
+ - [DigitalOcean](https://www.digitalocean.com/)
160
+
161
+ ## Genesis MCP Ecosystem
162
+
163
+ | Module | What it does | Repo |
164
+ |---|---|---|
165
+ | **CrawlEngine MCP** | Anti-bot web scraping, clean Markdown, proxy rotation and TLS evasion | [GitHub](https://github.com/johannschiffer/crawlengine-mcp) |
166
+ | **BrowserBridge MCP** | Deterministic headless browser automation with cryptographic action receipts | [GitHub](https://github.com/johannschiffer/browserbridge-mcp) |
167
+ | **PgSafe MCP** | Zero-trust PostgreSQL/SQLite guard, live PII masking, zero-downtime migration checks | [GitHub](https://github.com/johannschiffer/pgsafe-mcp) |
168
+ | **OmniBridge MCP** | Multi-channel notification and webhook bus with a persistent SQLite WAL queue | [GitHub](https://github.com/johannschiffer/omnibridge-mcp) |
169
+ | **SysFlow MCP** (this repo) | Safe Linux administration plane: systemd, port audit, isolated execution | [GitHub](https://github.com/johannschiffer/sysflow-mcp) |
170
+ | **FastMCP Forge** | Production MCP server scaffolder: stdio, SSE and auth middleware | [GitHub](https://github.com/johannschiffer/fastmcp-forge) |
171
+
172
+ [Live config builder](https://johannschiffer.github.io) | [Starter Kit, free](https://johanld.gumroad.com/l/genesis-starter-kit) | [Enterprise Suite, $19](https://johanld.gumroad.com/l/genesis-enterprise-suite)
@@ -0,0 +1,154 @@
1
+ # SysFlow MCP (Lite Edition)
2
+
3
+ <a href="https://glama.ai/mcp/servers/@johannschiffer/sysflow-mcp">
4
+ <img width="380" height="200" src="https://glama.ai/mcp/servers/@johannschiffer/sysflow-mcp/badge" alt="sysflow-mcp MCP server" />
5
+ </a>
6
+
7
+
8
+ > **Free:** [Genesis Starter Kit](https://johanld.gumroad.com/l/genesis-starter-kit) (25 `.cursorrules`/`CLAUDE.md` rulesets + MCP configs). Try the [live config builder](https://johannschiffer.github.io).
9
+ > **Full stack:** all six servers in [Genesis Enterprise Suite ($19)](https://johanld.gumroad.com/l/genesis-enterprise-suite).
10
+
11
+
12
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
13
+ [![Python 3.10+](https://img.shields.io/badge/Python-3.10+-brightgreen.svg)](https://python.org)
14
+ [![MCP Compliant](https://img.shields.io/badge/MCP-2024--11--05-purple.svg)](https://modelcontextprotocol.io)
15
+
16
+ **SysFlow MCP** is a lightweight, zero-overhead Model Context Protocol server that gives AI agents in **Claude Desktop**, **Cursor**, **Windsurf**, and **Antigravity** safe, structured access to Linux sysadmin inspection, log tailing, and service health without granting unrestricted root shells or risking interactive terminal freezes.
17
+
18
+ ---
19
+
20
+ ## Run without cloning
21
+
22
+ ```bash
23
+ uvx sysflow-mcp
24
+ ```
25
+
26
+ Claude Desktop / Cursor config entry:
27
+
28
+ ```json
29
+ {
30
+ "mcpServers": {
31
+ "sysflow-mcp": {
32
+ "command": "uvx",
33
+ "args": [
34
+ "--from",
35
+ "git+https://github.com/johannschiffer/sysflow-mcp",
36
+ "sysflow-mcp"
37
+ ]
38
+ }
39
+ }
40
+ }
41
+ ```
42
+
43
+ [![CI](https://github.com/johannschiffer/sysflow-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/johannschiffer/sysflow-mcp/actions/workflows/ci.yml)
44
+
45
+ ## ðŸ–Ĩïļ Why SysFlow MCP?
46
+
47
+ Giving an AI assistant raw terminal execution often ends in frustration:
48
+ 1. **Interactive Terminal Freezes:** Commands like `journalctl`, `systemctl status`, or `git log` default to interactive pagers (`less`), leaving the AI agent permanently hung waiting for user input.
49
+ 2. **Context Window Flooding:** Tailing an unconstrained `/var/log/nginx/access.log` dumps thousands of lines into the LLM prompt, wasting tokens and causing memory errors.
50
+ 3. **Destructive Shell Commands:** Without sandboxing, a hallucinated command can kill critical background daemons or delete workspace assets.
51
+
52
+ **SysFlow** exposes safe, bounded, non-blocking tools specifically tailored for autonomous developer agents.
53
+
54
+ ---
55
+
56
+ ## ⚡ Features (Lite Edition)
57
+
58
+ - 📊 **Resource Healthcheck**: Reports CPU core load averages (1m, 5m, 15m), RAM availability (MB and percentage), and disk partition metrics.
59
+ - 📜 **Safe Log Tailer**: Reads the last N lines (bounded and memory-safe) with optional regex filtering; automatically rejects binary files.
60
+ - ⚙ïļ **Systemd User Service Inspector**: Lists user-level services and timers (`systemctl --user`), highlighting failed units without requiring `sudo`.
61
+ - ðŸŠķ **Zero External Dependencies**: Operates strictly on Python standard library and Linux `/proc` filesystem.
62
+
63
+ ---
64
+
65
+ ## 🚀 Quick Setup in 2 Minutes
66
+
67
+ ### 1. Installation
68
+
69
+ ```bash
70
+ git clone https://github.com/johannschiffer/sysflow-mcp.git
71
+ cd sysflow-mcp
72
+ pip install .
73
+ ```
74
+
75
+ ### 2. Configure Claude Desktop (`claude_desktop_config.json`)
76
+
77
+ On Linux: `~/.config/Claude/claude_desktop_config.json`
78
+ On macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
79
+ On Windows: `%APPDATA%\Claude\claude_desktop_config.json`
80
+
81
+ ```json
82
+ {
83
+ "mcpServers": {
84
+ "sysflow": {
85
+ "command": "python",
86
+ "args": ["-m", "sysflow.server"],
87
+ "cwd": "/path/to/sysflow-mcp"
88
+ }
89
+ }
90
+ }
91
+ ```
92
+
93
+ ### 3. Verify via CLI
94
+
95
+ ```bash
96
+ python -m sysflow.cli resources
97
+ ```
98
+
99
+ ---
100
+
101
+ ## 🛠ïļ MCP Tools Exposed to AI Agents
102
+
103
+ | Tool | Parameters | Description |
104
+ |---|---|---|
105
+ | `check_system_resources` | *(none)* | Returns CPU load, memory usage, and partition disk metrics |
106
+ | `tail_logs` | `filepath`, `lines`, `pattern` | Safely tails recent log lines with optional regex filter |
107
+ | `inspect_systemd_services` | `failed_only` | Lists user-level services, states, and detects failed daemons |
108
+ | `inspect_systemd_timers` | *(none)* | Lists scheduled systemd user timers |
109
+
110
+ ---
111
+
112
+ ## 💎 Need Enterprise Build Sandboxing? Upgrade to SysFlow Pro
113
+
114
+ Looking to automate shell task execution, manage Docker containers, or generate verified systemd units?
115
+
116
+ | Feature | Lite (Open Source) | Enterprise Suite ($19) |
117
+ |---|:---:|:---:|
118
+ | **CPU, RAM & Disk Monitoring** | ✅ | ✅ |
119
+ | **Safe Bounded Log Tailer** | ✅ | ✅ |
120
+ | **Systemd User Service Auditing** | ✅ | ✅ |
121
+ | **Sandboxed Task Runner with Timeouts** *(Anti-freeze)* | ❌ | ✅ |
122
+ | **Docker Container Health & Log Inspector** | ❌ | ✅ |
123
+ | **Verified Systemd Unit File Generator** | ❌ | ✅ |
124
+ | **Listening Socket & Port Conflict Auditor** | ❌ | ✅ |
125
+ | **Production Docker Container** | ❌ | ✅ |
126
+ | **Full Pytest Suite & Sysadmin Automation Guide** | ❌ | ✅ |
127
+
128
+ 👉 **[Get the Genesis Enterprise Suite ($19)](https://johanld.gumroad.com/l/genesis-enterprise-suite)**
129
+
130
+ ---
131
+
132
+ ## 📄 License
133
+
134
+ MIT License. See [LICENSE](LICENSE) for details.
135
+
136
+ ## Recommended Infrastructure
137
+
138
+ VPS hosting that work well with SysFlow MCP. Some links are referral links.
139
+
140
+ - [Hetzner Cloud](https://www.hetzner.com/cloud)
141
+ - [DigitalOcean](https://www.digitalocean.com/)
142
+
143
+ ## Genesis MCP Ecosystem
144
+
145
+ | Module | What it does | Repo |
146
+ |---|---|---|
147
+ | **CrawlEngine MCP** | Anti-bot web scraping, clean Markdown, proxy rotation and TLS evasion | [GitHub](https://github.com/johannschiffer/crawlengine-mcp) |
148
+ | **BrowserBridge MCP** | Deterministic headless browser automation with cryptographic action receipts | [GitHub](https://github.com/johannschiffer/browserbridge-mcp) |
149
+ | **PgSafe MCP** | Zero-trust PostgreSQL/SQLite guard, live PII masking, zero-downtime migration checks | [GitHub](https://github.com/johannschiffer/pgsafe-mcp) |
150
+ | **OmniBridge MCP** | Multi-channel notification and webhook bus with a persistent SQLite WAL queue | [GitHub](https://github.com/johannschiffer/omnibridge-mcp) |
151
+ | **SysFlow MCP** (this repo) | Safe Linux administration plane: systemd, port audit, isolated execution | [GitHub](https://github.com/johannschiffer/sysflow-mcp) |
152
+ | **FastMCP Forge** | Production MCP server scaffolder: stdio, SSE and auth middleware | [GitHub](https://github.com/johannschiffer/fastmcp-forge) |
153
+
154
+ [Live config builder](https://johannschiffer.github.io) | [Starter Kit, free](https://johanld.gumroad.com/l/genesis-starter-kit) | [Enterprise Suite, $19](https://johanld.gumroad.com/l/genesis-enterprise-suite)
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "sysflow-mcp"
7
+ version = "1.0.1"
8
+ description = "Safe Linux Sysadmin, Process & Build Automation Engine for AI Agents"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = {text = "MIT"}
12
+ authors = [
13
+ {name = "Johann Schiffer"}
14
+ ]
15
+ keywords = ["mcp", "model-context-protocol", "sysadmin", "linux", "systemd", "claude", "cursor", "monitoring", "ai-agent"]
16
+ dependencies = []
17
+
18
+ [project.optional-dependencies]
19
+ test = ["pytest>=7"]
20
+
21
+ [project.scripts]
22
+ sysflow-mcp = "sysflow.server:main"
23
+ sysflow-cli = "sysflow.cli:main"
24
+
25
+ [tool.setuptools.packages.find]
26
+ include = ["sysflow*"]
27
+
28
+ [project.urls]
29
+ Homepage = "https://johannschiffer.github.io"
30
+ Repository = "https://github.com/johannschiffer/sysflow-mcp"
31
+ "Starter Kit" = "https://johanld.gumroad.com/l/genesis-starter-kit"
32
+ "Enterprise Suite" = "https://johanld.gumroad.com/l/genesis-enterprise-suite"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,8 @@
1
+ """
2
+ SysFlow MCP (Lite Edition)
3
+ Safe Linux Sysadmin, Process & Build Automation Engine for AI Agents.
4
+ """
5
+
6
+ __version__ = "1.0.0"
7
+ __author__ = "Johann Schiffer / NEXUS"
8
+ __license__ = "MIT"
@@ -0,0 +1,11 @@
1
+ """Upgrade notice. Printed to stderr so MCP stdio traffic on stdout is never affected."""
2
+ import os
3
+ import sys
4
+
5
+ NOTICE = '[Genesis MCP Ecosystem] Free Starter Kit (25+ .cursorrules & Blueprints): https://johanld.gumroad.com/l/genesis-starter-kit | Enterprise Pro Suite (6 Pro Servers + Docker Stack): https://johanld.gumroad.com/l/genesis-enterprise-suite | Config Builder: https://johannschiffer.github.io/'
6
+
7
+
8
+ def print_upgrade_notice():
9
+ if os.environ.get("GENESIS_NO_NOTICE") == "1":
10
+ return
11
+ print(NOTICE, file=sys.stderr)
@@ -0,0 +1,61 @@
1
+ """
2
+ SysFlow CLI testing utility.
3
+ Usage:
4
+ python -m sysflow.cli resources
5
+ python -m sysflow.cli tail /var/log/syslog --lines 20
6
+ python -m sysflow.cli systemd --failed
7
+ """
8
+
9
+ import argparse
10
+ import json
11
+ import sys
12
+ from .monitors.resources import ResourceMonitor
13
+ from .monitors.logs import LogTailer
14
+ from .monitors.systemd import SystemdInspector
15
+
16
+ def main():
17
+ from ._genesis import NOTICE
18
+ parser = argparse.ArgumentParser(description="SysFlow CLI utility", epilog=NOTICE, formatter_class=argparse.RawDescriptionHelpFormatter)
19
+ subparsers = parser.add_subparsers(dest="command", help="Sub-commands")
20
+
21
+ subparsers.add_parser("resources", help="Check system CPU, RAM, and disk utilization")
22
+
23
+ tail_parser = subparsers.add_parser("tail", help="Tail recent lines from log file")
24
+ tail_parser.add_argument("file", help="Path to log file")
25
+ tail_parser.add_argument("--lines", type=int, default=50, help="Number of lines")
26
+ tail_parser.add_argument("--pattern", help="Regex filter pattern")
27
+
28
+ systemd_parser = subparsers.add_parser("systemd", help="Inspect systemd --user units")
29
+ systemd_parser.add_argument("--failed", action="store_true", help="Only show failed units")
30
+
31
+ args = parser.parse_args()
32
+
33
+ if args.command == "resources":
34
+ stats = ResourceMonitor.get_system_stats()
35
+ print(json.dumps(stats, indent=2))
36
+
37
+ elif args.command == "tail":
38
+ res = LogTailer.tail(args.file, lines=args.lines, pattern=args.pattern)
39
+ print(json.dumps(res, indent=2))
40
+
41
+ elif args.command == "systemd":
42
+ res = SystemdInspector.list_user_units(failed_only=args.failed)
43
+ print(json.dumps(res, indent=2))
44
+
45
+ else:
46
+ parser.print_help()
47
+
48
+
49
+
50
+ _main_impl = main
51
+
52
+
53
+ def main():
54
+ from ._genesis import print_upgrade_notice
55
+ try:
56
+ return _main_impl()
57
+ finally:
58
+ print_upgrade_notice()
59
+
60
+ if __name__ == "__main__":
61
+ main()
@@ -0,0 +1,71 @@
1
+ """
2
+ Safe Log File Reader & Tailer.
3
+ Tails recent log entries efficiently, filters by regex patterns, and guards against binary files.
4
+ """
5
+ import os
6
+ import re
7
+ from typing import Dict, Any, List, Optional
8
+
9
+ class LogTailer:
10
+ @staticmethod
11
+ def is_binary_file(filepath: str, check_bytes: int = 1024) -> bool:
12
+ """Heuristic check to prevent reading binary files."""
13
+ try:
14
+ with open(filepath, "rb") as f:
15
+ chunk = f.read(check_bytes)
16
+ return b"\x00" in chunk
17
+ except Exception:
18
+ return True
19
+
20
+ @classmethod
21
+ def tail(cls, filepath: str, lines: int = 50, pattern: Optional[str] = None, max_lines: int = 500) -> Dict[str, Any]:
22
+ target_path = os.path.abspath(filepath)
23
+ if not os.path.isfile(target_path):
24
+ return {
25
+ "success": False,
26
+ "error": f"File does not exist or is not a regular file: '{target_path}'"
27
+ }
28
+
29
+ if cls.is_binary_file(target_path):
30
+ return {
31
+ "success": False,
32
+ "error": f"Target file appears to be a binary file: '{target_path}'"
33
+ }
34
+
35
+ capped_lines = min(max_lines, max(1, lines))
36
+ file_size = os.path.getsize(target_path)
37
+
38
+ # Efficiently read from end of file for large files
39
+ chunk_size = 8192
40
+ collected_lines: List[str] = []
41
+
42
+ try:
43
+ with open(target_path, "r", encoding="utf-8", errors="replace") as f:
44
+ if file_size < 100 * 1024: # Under 100KB, read directly
45
+ all_lines = f.readlines()
46
+ collected_lines = all_lines[-capped_lines:]
47
+ else:
48
+ # Seek backwards from end
49
+ f.seek(max(0, file_size - (capped_lines * 500)))
50
+ f.readline() # Discard partial line
51
+ collected_lines = f.readlines()[-capped_lines:]
52
+ except Exception as e:
53
+ return {"success": False, "error": f"Error reading log file: {str(e)}"}
54
+
55
+ clean_lines = [l.rstrip("\r\n") for l in collected_lines]
56
+
57
+ # Optional regex filter
58
+ if pattern:
59
+ try:
60
+ regex = re.compile(pattern, re.IGNORECASE)
61
+ clean_lines = [l for l in clean_lines if regex.search(l)]
62
+ except re.error as e:
63
+ return {"success": False, "error": f"Invalid regex pattern: {str(e)}"}
64
+
65
+ return {
66
+ "success": True,
67
+ "filepath": target_path,
68
+ "file_size_bytes": file_size,
69
+ "lines_returned": len(clean_lines),
70
+ "lines": clean_lines
71
+ }
@@ -0,0 +1,76 @@
1
+ """
2
+ System Resource Monitor.
3
+ Gathers CPU load average, RAM utilization, disk usage, and host details without root.
4
+ """
5
+ import os
6
+ import shutil
7
+ import platform
8
+ from typing import Dict, Any
9
+
10
+ class ResourceMonitor:
11
+ @staticmethod
12
+ def get_system_stats() -> Dict[str, Any]:
13
+ # 1. CPU
14
+ cpu_count = os.cpu_count() or 1
15
+ load_1, load_5, load_15 = (0.0, 0.0, 0.0)
16
+ try:
17
+ load_1, load_5, load_15 = os.getloadavg()
18
+ except (AttributeError, OSError):
19
+ pass
20
+
21
+ # 2. Disk
22
+ disk_total, disk_used, disk_free = (0, 0, 0)
23
+ disk_pct = 0.0
24
+ try:
25
+ usage = shutil.disk_usage("/")
26
+ disk_total = round(usage.total / (1024 ** 3), 2) # GB
27
+ disk_used = round(usage.used / (1024 ** 3), 2)
28
+ disk_free = round(usage.free / (1024 ** 3), 2)
29
+ disk_pct = round((usage.used / usage.total) * 100, 1)
30
+ except Exception:
31
+ pass
32
+
33
+ # 3. RAM (Linux /proc/meminfo)
34
+ mem_total_mb = 0
35
+ mem_avail_mb = 0
36
+ mem_pct = 0.0
37
+ if os.path.exists("/proc/meminfo"):
38
+ try:
39
+ mem_dict = {}
40
+ with open("/proc/meminfo", "r") as f:
41
+ for line in f:
42
+ parts = line.split(":")
43
+ if len(parts) == 2:
44
+ key = parts[0].strip()
45
+ val = parts[1].split()[0].strip()
46
+ mem_dict[key] = int(val)
47
+ total_kb = mem_dict.get("MemTotal", 0)
48
+ avail_kb = mem_dict.get("MemAvailable", mem_dict.get("MemFree", 0))
49
+ mem_total_mb = round(total_kb / 1024, 1)
50
+ mem_avail_mb = round(avail_kb / 1024, 1)
51
+ if total_kb > 0:
52
+ mem_pct = round(((total_kb - avail_kb) / total_kb) * 100, 1)
53
+ except Exception:
54
+ pass
55
+
56
+ return {
57
+ "platform": f"{platform.system()} {platform.release()} ({platform.machine()})",
58
+ "cpu": {
59
+ "cores": cpu_count,
60
+ "load_average_1m": round(load_1, 2),
61
+ "load_average_5m": round(load_5, 2),
62
+ "load_average_15m": round(load_15, 2),
63
+ "load_per_core_1m": round(load_1 / cpu_count, 2)
64
+ },
65
+ "memory": {
66
+ "total_mb": mem_total_mb,
67
+ "available_mb": mem_avail_mb,
68
+ "used_percentage": mem_pct
69
+ },
70
+ "disk": {
71
+ "total_gb": disk_total,
72
+ "used_gb": disk_used,
73
+ "free_gb": disk_free,
74
+ "used_percentage": disk_pct
75
+ }
76
+ }
@@ -0,0 +1,55 @@
1
+ """
2
+ Systemd User Service & Timer Inspector.
3
+ Inspects systemd --user units, detects failed services, and monitors timers without root.
4
+ """
5
+ import subprocess
6
+ from typing import Dict, Any, List
7
+
8
+ class SystemdInspector:
9
+ @staticmethod
10
+ def list_user_units(failed_only: bool = False) -> Dict[str, Any]:
11
+ cmd = ["systemctl", "--user", "list-units", "--type=service", "--no-pager", "--no-legend"]
12
+ if failed_only:
13
+ cmd.append("--state=failed")
14
+
15
+ try:
16
+ res = subprocess.run(cmd, capture_output=True, text=True, timeout=5)
17
+ units: List[Dict[str, str]] = []
18
+
19
+ for line in res.stdout.strip().split("\n"):
20
+ line = line.strip()
21
+ if not line:
22
+ continue
23
+ parts = line.split(maxsplit=4)
24
+ if len(parts) >= 4:
25
+ units.append({
26
+ "unit": parts[0].replace("●", "").strip(),
27
+ "load": parts[1],
28
+ "active": parts[2],
29
+ "sub": parts[3],
30
+ "description": parts[4] if len(parts) > 4 else ""
31
+ })
32
+
33
+ return {
34
+ "success": True,
35
+ "count": len(units),
36
+ "failed_only": failed_only,
37
+ "units": units
38
+ }
39
+ except Exception as e:
40
+ return {"success": False, "error": f"Error querying systemctl: {str(e)}"}
41
+
42
+ @staticmethod
43
+ def list_user_timers() -> Dict[str, Any]:
44
+ cmd = ["systemctl", "--user", "list-timers", "--no-pager", "--no-legend"]
45
+ try:
46
+ res = subprocess.run(cmd, capture_output=True, text=True, timeout=5)
47
+ timers = []
48
+ for line in res.stdout.strip().split("\n"):
49
+ line = line.strip()
50
+ if not line:
51
+ continue
52
+ timers.append(line)
53
+ return {"success": True, "count": len(timers), "timers": timers}
54
+ except Exception as e:
55
+ return {"success": False, "error": f"Error querying systemd timers: {str(e)}"}
@@ -0,0 +1,193 @@
1
+ """
2
+ SysFlow MCP: Model Context Protocol Server (Lite Edition)
3
+ Implements standard JSON-RPC 2.0 stdio transport for safe system inspection and log monitoring.
4
+ """
5
+
6
+ import sys
7
+ import json
8
+ import logging
9
+ from typing import Dict, Any, List, Optional
10
+ from .monitors.resources import ResourceMonitor
11
+ from .monitors.logs import LogTailer
12
+ from .monitors.systemd import SystemdInspector
13
+
14
+ logging.basicConfig(
15
+ level=logging.INFO,
16
+ format="%(asctime)s [%(levelname)s] [SysFlow] %(message)s",
17
+ stream=sys.stderr
18
+ )
19
+ logger = logging.getLogger("SysFlowServer")
20
+
21
+ class SysFlowMCPServer:
22
+ def __init__(self):
23
+ self.server_name = "sysflow-mcp"
24
+ self.server_version = "1.0.1"
25
+
26
+ def get_tools_definition(self) -> List[Dict[str, Any]]:
27
+ return [
28
+ {
29
+ "name": "check_system_resources",
30
+ "description": "Inspect CPU load average, RAM utilization, and disk partition space.",
31
+ "inputSchema": {"type": "object", "properties": {}}
32
+ },
33
+ {
34
+ "name": "tail_logs",
35
+ "description": "Safely read recent lines from a log or text file with optional regex filtering.",
36
+ "inputSchema": {
37
+ "type": "object",
38
+ "properties": {
39
+ "filepath": {"type": "string", "description": "Absolute or relative path to log file"},
40
+ "lines": {"type": "integer", "description": "Number of recent lines to retrieve (default: 50, max: 500)"},
41
+ "pattern": {"type": "string", "description": "Optional regex pattern to filter lines"}
42
+ },
43
+ "required": ["filepath"]
44
+ }
45
+ },
46
+ {
47
+ "name": "inspect_systemd_services",
48
+ "description": "List systemd --user services, active states, and detect failed background units.",
49
+ "inputSchema": {
50
+ "type": "object",
51
+ "properties": {
52
+ "failed_only": {"type": "boolean", "description": "Only return units in failed state (default: false)"}
53
+ }
54
+ }
55
+ },
56
+ {
57
+ "name": "inspect_systemd_timers",
58
+ "description": "List systemd --user scheduled timers and their next trigger times.",
59
+ "inputSchema": {"type": "object", "properties": {}}
60
+ }
61
+ ]
62
+
63
+ def handle_tool_call(self, name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
64
+ if name == "check_system_resources":
65
+ return {
66
+ "success": True,
67
+ "resources": ResourceMonitor.get_system_stats()
68
+ }
69
+
70
+ elif name == "tail_logs":
71
+ filepath = arguments.get("filepath", "")
72
+ lines = arguments.get("lines", 50)
73
+ pattern = arguments.get("pattern")
74
+ return LogTailer.tail(filepath, lines=lines, pattern=pattern)
75
+
76
+ elif name == "inspect_systemd_services":
77
+ failed_only = arguments.get("failed_only", False)
78
+ return SystemdInspector.list_user_units(failed_only=failed_only)
79
+
80
+ elif name == "inspect_systemd_timers":
81
+ return SystemdInspector.list_user_timers()
82
+
83
+ else:
84
+ raise ValueError(f"Unknown tool: {name}")
85
+
86
+ def handle_request(self, request: Dict[str, Any]) -> Optional[Dict[str, Any]]:
87
+ req_id = request.get("id")
88
+ method = request.get("method")
89
+ params = request.get("params", {})
90
+
91
+ if req_id is None:
92
+ if method == "notifications/initialized":
93
+ logger.info("Client completed initialization handshake.")
94
+ return None
95
+
96
+ if method == "initialize":
97
+ return {
98
+ "jsonrpc": "2.0",
99
+ "id": req_id,
100
+ "result": {
101
+ "protocolVersion": "2024-11-05",
102
+ "capabilities": {"tools": {}},
103
+ "serverInfo": {
104
+ "name": self.server_name,
105
+ "version": self.server_version
106
+ }
107
+ }
108
+ }
109
+
110
+ elif method == "ping":
111
+ return {"jsonrpc": "2.0", "id": req_id, "result": {}}
112
+
113
+ elif method == "tools/list":
114
+ return {
115
+ "jsonrpc": "2.0",
116
+ "id": req_id,
117
+ "result": {"tools": self.get_tools_definition()}
118
+ }
119
+
120
+ elif method == "tools/call":
121
+ tool_name = params.get("name")
122
+ tool_args = params.get("arguments", {})
123
+ try:
124
+ output = self.handle_tool_call(tool_name, tool_args)
125
+ return {
126
+ "jsonrpc": "2.0",
127
+ "id": req_id,
128
+ "result": {
129
+ "content": [
130
+ {
131
+ "type": "text",
132
+ "text": json.dumps(output, indent=2, ensure_ascii=False)
133
+ }
134
+ ],
135
+ "isError": not output.get("success", True) if "success" in output else False
136
+ }
137
+ }
138
+ except Exception as e:
139
+ logger.error(f"Error calling tool {tool_name}: {e}")
140
+ return {
141
+ "jsonrpc": "2.0",
142
+ "id": req_id,
143
+ "error": {"code": -32000, "message": str(e)}
144
+ }
145
+ else:
146
+ return {
147
+ "jsonrpc": "2.0",
148
+ "id": req_id,
149
+ "error": {"code": -32601, "message": f"Method not found: {method}"}
150
+ }
151
+
152
+ def run_stdio(self):
153
+ from ._genesis import print_upgrade_notice
154
+ print_upgrade_notice()
155
+ logger.info(f"Starting {self.server_name} v{self.server_version} stdio listener...")
156
+ for line in sys.stdin:
157
+ line = line.strip()
158
+ if not line:
159
+ continue
160
+ try:
161
+ request = json.loads(line)
162
+ response = self.handle_request(request)
163
+ if response is not None:
164
+ sys.stdout.write(json.dumps(response) + "\n")
165
+ sys.stdout.flush()
166
+ except Exception as e:
167
+ logger.error(f"Error processing stdio line: {e}")
168
+
169
+ def main():
170
+ import argparse
171
+ from ._genesis import NOTICE
172
+ parser = argparse.ArgumentParser(
173
+ prog="sysflow-mcp",
174
+ description="SysFlow MCP: Safe Linux Sysadmin, Process & Build Automation Engine for AI Agents",
175
+ epilog=NOTICE,
176
+ formatter_class=argparse.RawDescriptionHelpFormatter
177
+ )
178
+ parser.add_argument("-v", "--version", action="version", version="%(prog)s 1.0.1")
179
+ args, unknown = parser.parse_known_args()
180
+ server = SysFlowMCPServer()
181
+ server.run_stdio()
182
+
183
+ _main_impl = main
184
+
185
+ def main():
186
+ from ._genesis import print_upgrade_notice
187
+ try:
188
+ return _main_impl()
189
+ finally:
190
+ print_upgrade_notice()
191
+
192
+ if __name__ == "__main__":
193
+ main()
@@ -0,0 +1,172 @@
1
+ Metadata-Version: 2.4
2
+ Name: sysflow-mcp
3
+ Version: 1.0.1
4
+ Summary: Safe Linux Sysadmin, Process & Build Automation Engine for AI Agents
5
+ Author: Johann Schiffer
6
+ License: MIT
7
+ Project-URL: Homepage, https://johannschiffer.github.io
8
+ Project-URL: Repository, https://github.com/johannschiffer/sysflow-mcp
9
+ Project-URL: Starter Kit, https://johanld.gumroad.com/l/genesis-starter-kit
10
+ Project-URL: Enterprise Suite, https://johanld.gumroad.com/l/genesis-enterprise-suite
11
+ Keywords: mcp,model-context-protocol,sysadmin,linux,systemd,claude,cursor,monitoring,ai-agent
12
+ Requires-Python: >=3.10
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Provides-Extra: test
16
+ Requires-Dist: pytest>=7; extra == "test"
17
+ Dynamic: license-file
18
+
19
+ # SysFlow MCP (Lite Edition)
20
+
21
+ <a href="https://glama.ai/mcp/servers/@johannschiffer/sysflow-mcp">
22
+ <img width="380" height="200" src="https://glama.ai/mcp/servers/@johannschiffer/sysflow-mcp/badge" alt="sysflow-mcp MCP server" />
23
+ </a>
24
+
25
+
26
+ > **Free:** [Genesis Starter Kit](https://johanld.gumroad.com/l/genesis-starter-kit) (25 `.cursorrules`/`CLAUDE.md` rulesets + MCP configs). Try the [live config builder](https://johannschiffer.github.io).
27
+ > **Full stack:** all six servers in [Genesis Enterprise Suite ($19)](https://johanld.gumroad.com/l/genesis-enterprise-suite).
28
+
29
+
30
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
31
+ [![Python 3.10+](https://img.shields.io/badge/Python-3.10+-brightgreen.svg)](https://python.org)
32
+ [![MCP Compliant](https://img.shields.io/badge/MCP-2024--11--05-purple.svg)](https://modelcontextprotocol.io)
33
+
34
+ **SysFlow MCP** is a lightweight, zero-overhead Model Context Protocol server that gives AI agents in **Claude Desktop**, **Cursor**, **Windsurf**, and **Antigravity** safe, structured access to Linux sysadmin inspection, log tailing, and service health without granting unrestricted root shells or risking interactive terminal freezes.
35
+
36
+ ---
37
+
38
+ ## Run without cloning
39
+
40
+ ```bash
41
+ uvx sysflow-mcp
42
+ ```
43
+
44
+ Claude Desktop / Cursor config entry:
45
+
46
+ ```json
47
+ {
48
+ "mcpServers": {
49
+ "sysflow-mcp": {
50
+ "command": "uvx",
51
+ "args": [
52
+ "--from",
53
+ "git+https://github.com/johannschiffer/sysflow-mcp",
54
+ "sysflow-mcp"
55
+ ]
56
+ }
57
+ }
58
+ }
59
+ ```
60
+
61
+ [![CI](https://github.com/johannschiffer/sysflow-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/johannschiffer/sysflow-mcp/actions/workflows/ci.yml)
62
+
63
+ ## ðŸ–Ĩïļ Why SysFlow MCP?
64
+
65
+ Giving an AI assistant raw terminal execution often ends in frustration:
66
+ 1. **Interactive Terminal Freezes:** Commands like `journalctl`, `systemctl status`, or `git log` default to interactive pagers (`less`), leaving the AI agent permanently hung waiting for user input.
67
+ 2. **Context Window Flooding:** Tailing an unconstrained `/var/log/nginx/access.log` dumps thousands of lines into the LLM prompt, wasting tokens and causing memory errors.
68
+ 3. **Destructive Shell Commands:** Without sandboxing, a hallucinated command can kill critical background daemons or delete workspace assets.
69
+
70
+ **SysFlow** exposes safe, bounded, non-blocking tools specifically tailored for autonomous developer agents.
71
+
72
+ ---
73
+
74
+ ## ⚡ Features (Lite Edition)
75
+
76
+ - 📊 **Resource Healthcheck**: Reports CPU core load averages (1m, 5m, 15m), RAM availability (MB and percentage), and disk partition metrics.
77
+ - 📜 **Safe Log Tailer**: Reads the last N lines (bounded and memory-safe) with optional regex filtering; automatically rejects binary files.
78
+ - ⚙ïļ **Systemd User Service Inspector**: Lists user-level services and timers (`systemctl --user`), highlighting failed units without requiring `sudo`.
79
+ - ðŸŠķ **Zero External Dependencies**: Operates strictly on Python standard library and Linux `/proc` filesystem.
80
+
81
+ ---
82
+
83
+ ## 🚀 Quick Setup in 2 Minutes
84
+
85
+ ### 1. Installation
86
+
87
+ ```bash
88
+ git clone https://github.com/johannschiffer/sysflow-mcp.git
89
+ cd sysflow-mcp
90
+ pip install .
91
+ ```
92
+
93
+ ### 2. Configure Claude Desktop (`claude_desktop_config.json`)
94
+
95
+ On Linux: `~/.config/Claude/claude_desktop_config.json`
96
+ On macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
97
+ On Windows: `%APPDATA%\Claude\claude_desktop_config.json`
98
+
99
+ ```json
100
+ {
101
+ "mcpServers": {
102
+ "sysflow": {
103
+ "command": "python",
104
+ "args": ["-m", "sysflow.server"],
105
+ "cwd": "/path/to/sysflow-mcp"
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### 3. Verify via CLI
112
+
113
+ ```bash
114
+ python -m sysflow.cli resources
115
+ ```
116
+
117
+ ---
118
+
119
+ ## 🛠ïļ MCP Tools Exposed to AI Agents
120
+
121
+ | Tool | Parameters | Description |
122
+ |---|---|---|
123
+ | `check_system_resources` | *(none)* | Returns CPU load, memory usage, and partition disk metrics |
124
+ | `tail_logs` | `filepath`, `lines`, `pattern` | Safely tails recent log lines with optional regex filter |
125
+ | `inspect_systemd_services` | `failed_only` | Lists user-level services, states, and detects failed daemons |
126
+ | `inspect_systemd_timers` | *(none)* | Lists scheduled systemd user timers |
127
+
128
+ ---
129
+
130
+ ## 💎 Need Enterprise Build Sandboxing? Upgrade to SysFlow Pro
131
+
132
+ Looking to automate shell task execution, manage Docker containers, or generate verified systemd units?
133
+
134
+ | Feature | Lite (Open Source) | Enterprise Suite ($19) |
135
+ |---|:---:|:---:|
136
+ | **CPU, RAM & Disk Monitoring** | ✅ | ✅ |
137
+ | **Safe Bounded Log Tailer** | ✅ | ✅ |
138
+ | **Systemd User Service Auditing** | ✅ | ✅ |
139
+ | **Sandboxed Task Runner with Timeouts** *(Anti-freeze)* | ❌ | ✅ |
140
+ | **Docker Container Health & Log Inspector** | ❌ | ✅ |
141
+ | **Verified Systemd Unit File Generator** | ❌ | ✅ |
142
+ | **Listening Socket & Port Conflict Auditor** | ❌ | ✅ |
143
+ | **Production Docker Container** | ❌ | ✅ |
144
+ | **Full Pytest Suite & Sysadmin Automation Guide** | ❌ | ✅ |
145
+
146
+ 👉 **[Get the Genesis Enterprise Suite ($19)](https://johanld.gumroad.com/l/genesis-enterprise-suite)**
147
+
148
+ ---
149
+
150
+ ## 📄 License
151
+
152
+ MIT License. See [LICENSE](LICENSE) for details.
153
+
154
+ ## Recommended Infrastructure
155
+
156
+ VPS hosting that work well with SysFlow MCP. Some links are referral links.
157
+
158
+ - [Hetzner Cloud](https://www.hetzner.com/cloud)
159
+ - [DigitalOcean](https://www.digitalocean.com/)
160
+
161
+ ## Genesis MCP Ecosystem
162
+
163
+ | Module | What it does | Repo |
164
+ |---|---|---|
165
+ | **CrawlEngine MCP** | Anti-bot web scraping, clean Markdown, proxy rotation and TLS evasion | [GitHub](https://github.com/johannschiffer/crawlengine-mcp) |
166
+ | **BrowserBridge MCP** | Deterministic headless browser automation with cryptographic action receipts | [GitHub](https://github.com/johannschiffer/browserbridge-mcp) |
167
+ | **PgSafe MCP** | Zero-trust PostgreSQL/SQLite guard, live PII masking, zero-downtime migration checks | [GitHub](https://github.com/johannschiffer/pgsafe-mcp) |
168
+ | **OmniBridge MCP** | Multi-channel notification and webhook bus with a persistent SQLite WAL queue | [GitHub](https://github.com/johannschiffer/omnibridge-mcp) |
169
+ | **SysFlow MCP** (this repo) | Safe Linux administration plane: systemd, port audit, isolated execution | [GitHub](https://github.com/johannschiffer/sysflow-mcp) |
170
+ | **FastMCP Forge** | Production MCP server scaffolder: stdio, SSE and auth middleware | [GitHub](https://github.com/johannschiffer/fastmcp-forge) |
171
+
172
+ [Live config builder](https://johannschiffer.github.io) | [Starter Kit, free](https://johanld.gumroad.com/l/genesis-starter-kit) | [Enterprise Suite, $19](https://johanld.gumroad.com/l/genesis-enterprise-suite)
@@ -0,0 +1,17 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ sysflow/__init__.py
5
+ sysflow/_genesis.py
6
+ sysflow/cli.py
7
+ sysflow/server.py
8
+ sysflow/monitors/logs.py
9
+ sysflow/monitors/resources.py
10
+ sysflow/monitors/systemd.py
11
+ sysflow_mcp.egg-info/PKG-INFO
12
+ sysflow_mcp.egg-info/SOURCES.txt
13
+ sysflow_mcp.egg-info/dependency_links.txt
14
+ sysflow_mcp.egg-info/entry_points.txt
15
+ sysflow_mcp.egg-info/requires.txt
16
+ sysflow_mcp.egg-info/top_level.txt
17
+ tests/test_genesis_entrypoints.py
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ sysflow-cli = sysflow.cli:main
3
+ sysflow-mcp = sysflow.server:main
@@ -0,0 +1,3 @@
1
+
2
+ [test]
3
+ pytest>=7
@@ -0,0 +1 @@
1
+ sysflow
@@ -0,0 +1,25 @@
1
+ import importlib
2
+ import io
3
+ import os
4
+ import sys
5
+
6
+
7
+ def test_script_target_is_callable():
8
+ mod = importlib.import_module('sysflow.server')
9
+ assert callable(getattr(mod, 'main'))
10
+
11
+
12
+ def test_upgrade_notice_goes_to_stderr(capsys, monkeypatch):
13
+ monkeypatch.delenv('GENESIS_NO_NOTICE', raising=False)
14
+ from sysflow._genesis import print_upgrade_notice
15
+ print_upgrade_notice()
16
+ out = capsys.readouterr()
17
+ assert out.out == ''
18
+ assert 'gumroad.com' in out.err
19
+
20
+
21
+ def test_upgrade_notice_can_be_silenced(capsys, monkeypatch):
22
+ monkeypatch.setenv('GENESIS_NO_NOTICE', '1')
23
+ from sysflow._genesis import print_upgrade_notice
24
+ print_upgrade_notice()
25
+ assert capsys.readouterr().err == ''