linux-mcp-server 0.1.0a1__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.
- linux_mcp_server-0.1.0a1/.codecov.yml +38 -0
- linux_mcp_server-0.1.0a1/.github/workflows/build-publish.yml +75 -0
- linux_mcp_server-0.1.0a1/.github/workflows/ci.yml +122 -0
- linux_mcp_server-0.1.0a1/.gitignore +52 -0
- linux_mcp_server-0.1.0a1/CONTRIBUTING.md +350 -0
- linux_mcp_server-0.1.0a1/DEBUGGING.md +133 -0
- linux_mcp_server-0.1.0a1/LICENSE +201 -0
- linux_mcp_server-0.1.0a1/PKG-INFO +344 -0
- linux_mcp_server-0.1.0a1/README.md +315 -0
- linux_mcp_server-0.1.0a1/USAGE.md +350 -0
- linux_mcp_server-0.1.0a1/claude_desktop_config.example.json +19 -0
- linux_mcp_server-0.1.0a1/example_config.sh +66 -0
- linux_mcp_server-0.1.0a1/pyproject.toml +165 -0
- linux_mcp_server-0.1.0a1/renovate.json +4 -0
- linux_mcp_server-0.1.0a1/src/linux_mcp_server/__init__.py +1 -0
- linux_mcp_server-0.1.0a1/src/linux_mcp_server/__main__.py +30 -0
- linux_mcp_server-0.1.0a1/src/linux_mcp_server/audit.py +290 -0
- linux_mcp_server-0.1.0a1/src/linux_mcp_server/logging_config.py +176 -0
- linux_mcp_server-0.1.0a1/src/linux_mcp_server/server.py +444 -0
- linux_mcp_server-0.1.0a1/src/linux_mcp_server/tools/__init__.py +1 -0
- linux_mcp_server-0.1.0a1/src/linux_mcp_server/tools/logs.py +224 -0
- linux_mcp_server-0.1.0a1/src/linux_mcp_server/tools/network.py +279 -0
- linux_mcp_server-0.1.0a1/src/linux_mcp_server/tools/processes.py +274 -0
- linux_mcp_server-0.1.0a1/src/linux_mcp_server/tools/services.py +147 -0
- linux_mcp_server-0.1.0a1/src/linux_mcp_server/tools/ssh_executor.py +333 -0
- linux_mcp_server-0.1.0a1/src/linux_mcp_server/tools/storage.py +359 -0
- linux_mcp_server-0.1.0a1/src/linux_mcp_server/tools/system_info.py +520 -0
- linux_mcp_server-0.1.0a1/src/linux_mcp_server/tools/utils.py +26 -0
- linux_mcp_server-0.1.0a1/src/linux_mcp_server/tools/validation.py +57 -0
- linux_mcp_server-0.1.0a1/tests/__init__.py +1 -0
- linux_mcp_server-0.1.0a1/tests/test_audit.py +306 -0
- linux_mcp_server-0.1.0a1/tests/test_logging_config.py +209 -0
- linux_mcp_server-0.1.0a1/tests/test_processes.py +50 -0
- linux_mcp_server-0.1.0a1/tests/test_server.py +44 -0
- linux_mcp_server-0.1.0a1/tests/test_services.py +115 -0
- linux_mcp_server-0.1.0a1/tests/test_ssh_executor.py +314 -0
- linux_mcp_server-0.1.0a1/tests/test_storage.py +351 -0
- linux_mcp_server-0.1.0a1/tests/test_system_info.py +72 -0
- linux_mcp_server-0.1.0a1/tests/test_validation.py +161 -0
- linux_mcp_server-0.1.0a1/uv.lock +1335 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
codecov:
|
|
2
|
+
notify:
|
|
3
|
+
after_n_builds: 2
|
|
4
|
+
wait_for_ci: false
|
|
5
|
+
|
|
6
|
+
require_ci_to_pass: false
|
|
7
|
+
token: 74bc381b-9c5f-44c1-9efa-af57d5f3fe50 # notsecret # repo-scoped, upload-only, stability in fork PRs
|
|
8
|
+
|
|
9
|
+
coverage:
|
|
10
|
+
range: 40..100
|
|
11
|
+
status:
|
|
12
|
+
project:
|
|
13
|
+
default:
|
|
14
|
+
target: 60%
|
|
15
|
+
threshold: 10%
|
|
16
|
+
app:
|
|
17
|
+
target: 60%
|
|
18
|
+
threshold: 10%
|
|
19
|
+
paths:
|
|
20
|
+
- src/
|
|
21
|
+
tests:
|
|
22
|
+
target: 100%
|
|
23
|
+
paths:
|
|
24
|
+
- tests/
|
|
25
|
+
|
|
26
|
+
patch:
|
|
27
|
+
default:
|
|
28
|
+
target: 100%
|
|
29
|
+
threshold: 10%
|
|
30
|
+
app:
|
|
31
|
+
target: 100%
|
|
32
|
+
threshold: 10%
|
|
33
|
+
paths:
|
|
34
|
+
- src/
|
|
35
|
+
tests:
|
|
36
|
+
target: 100%
|
|
37
|
+
paths:
|
|
38
|
+
- tests/
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
name: Build and publish
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
tags:
|
|
5
|
+
- '*'
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
name: Build sdist and wheel
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout
|
|
17
|
+
uses: actions/checkout@v5.0.0
|
|
18
|
+
with:
|
|
19
|
+
fetch-depth: 0
|
|
20
|
+
|
|
21
|
+
- name: Show environment
|
|
22
|
+
run: |
|
|
23
|
+
set -x
|
|
24
|
+
python -VV
|
|
25
|
+
python -m site
|
|
26
|
+
ls -ld $(python -c "import site; print(site.getsitepackages()[0])")
|
|
27
|
+
git tag --list --sort=-refname --format='%(refname:short) %(objectname:short)'
|
|
28
|
+
whoami
|
|
29
|
+
|
|
30
|
+
- name: Install build tools
|
|
31
|
+
run: |
|
|
32
|
+
python -m pip install --upgrade pip
|
|
33
|
+
python -m pip install build
|
|
34
|
+
|
|
35
|
+
- name: Build
|
|
36
|
+
run: python -m build --sdist --wheel
|
|
37
|
+
|
|
38
|
+
- name: Upload artifacts
|
|
39
|
+
uses: actions/upload-artifact@v4.6.2
|
|
40
|
+
with:
|
|
41
|
+
name: artifacts
|
|
42
|
+
path: dist
|
|
43
|
+
if-no-files-found: error
|
|
44
|
+
|
|
45
|
+
publish:
|
|
46
|
+
name: Publish to PyPI
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
needs:
|
|
49
|
+
- build
|
|
50
|
+
|
|
51
|
+
environment:
|
|
52
|
+
name: pypi
|
|
53
|
+
url: https://pypi.org/p/linux-mcp-server
|
|
54
|
+
|
|
55
|
+
permissions:
|
|
56
|
+
id-token: write
|
|
57
|
+
|
|
58
|
+
steps:
|
|
59
|
+
- name: Download artifacts
|
|
60
|
+
uses: actions/download-artifact@v5.0.0
|
|
61
|
+
with:
|
|
62
|
+
name: artifacts
|
|
63
|
+
path: dist
|
|
64
|
+
|
|
65
|
+
- name: Show environment
|
|
66
|
+
run: |
|
|
67
|
+
set -x
|
|
68
|
+
python -VV
|
|
69
|
+
python -m site
|
|
70
|
+
ls -ld $(python -c "import site; print(site.getsitepackages()[0])")
|
|
71
|
+
ls -l dist/
|
|
72
|
+
whoami
|
|
73
|
+
|
|
74
|
+
- name: Publish to PyPI
|
|
75
|
+
uses: pypa/gh-action-pypi-publish@v1.13.0
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches:
|
|
5
|
+
- main
|
|
6
|
+
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
env:
|
|
13
|
+
PIP_DISABLE_PIP_VERSION_CHECK: 1
|
|
14
|
+
COVERAGE_IGOR_VERBOSE: 1
|
|
15
|
+
FORCE_COLOR: 1 # Get colored pytest output
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
sanity:
|
|
20
|
+
name: Sanity - ${{ matrix.test.name }}
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
|
|
23
|
+
strategy:
|
|
24
|
+
fail-fast: false
|
|
25
|
+
matrix:
|
|
26
|
+
test:
|
|
27
|
+
- name: Type
|
|
28
|
+
step_name: Check types
|
|
29
|
+
command: pyright
|
|
30
|
+
|
|
31
|
+
- name: Lint
|
|
32
|
+
step_name: Run lint
|
|
33
|
+
command: ruff check --diff
|
|
34
|
+
|
|
35
|
+
- name: Format
|
|
36
|
+
step_name: Run format check
|
|
37
|
+
command: ruff format --diff
|
|
38
|
+
|
|
39
|
+
steps:
|
|
40
|
+
- name: Checkout
|
|
41
|
+
uses: actions/checkout@v5.0.0
|
|
42
|
+
|
|
43
|
+
- name: Install Python
|
|
44
|
+
uses: actions/setup-python@v6.0.0
|
|
45
|
+
with:
|
|
46
|
+
python-version-file: pyproject.toml
|
|
47
|
+
|
|
48
|
+
- name: Install uv
|
|
49
|
+
uses: astral-sh/setup-uv@v7.1.0
|
|
50
|
+
with:
|
|
51
|
+
enable-cache: true
|
|
52
|
+
prune-cache: false
|
|
53
|
+
|
|
54
|
+
- name: Install dependencies
|
|
55
|
+
run: uv sync --locked --group lint
|
|
56
|
+
|
|
57
|
+
- name: "Show environment"
|
|
58
|
+
run: |
|
|
59
|
+
python -VV
|
|
60
|
+
python -m site
|
|
61
|
+
uv --version
|
|
62
|
+
env | sort
|
|
63
|
+
ls -ld $(python -c "import site; print(site.getsitepackages()[0])")
|
|
64
|
+
whoami
|
|
65
|
+
|
|
66
|
+
- name: ${{ matrix.test.step_name }}
|
|
67
|
+
run: uv run --locked ${{ matrix.test.command }}
|
|
68
|
+
|
|
69
|
+
tests:
|
|
70
|
+
name: Unit - ${{ matrix.python-version }}
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
|
|
73
|
+
strategy:
|
|
74
|
+
fail-fast: true
|
|
75
|
+
matrix:
|
|
76
|
+
python-version:
|
|
77
|
+
- "3.10"
|
|
78
|
+
- "3.11"
|
|
79
|
+
- "3.12"
|
|
80
|
+
- "3.13"
|
|
81
|
+
- "3.13t"
|
|
82
|
+
- "3.14"
|
|
83
|
+
- "3.14t"
|
|
84
|
+
|
|
85
|
+
steps:
|
|
86
|
+
- name: Checkout
|
|
87
|
+
uses: actions/checkout@v5.0.0
|
|
88
|
+
|
|
89
|
+
- name: Install Python
|
|
90
|
+
uses: actions/setup-python@v6.0.0
|
|
91
|
+
with:
|
|
92
|
+
python-version-file: pyproject.toml
|
|
93
|
+
|
|
94
|
+
- name: Install uv
|
|
95
|
+
uses: astral-sh/setup-uv@v7.1.0
|
|
96
|
+
with:
|
|
97
|
+
enable-cache: true
|
|
98
|
+
prune-cache: false
|
|
99
|
+
|
|
100
|
+
- name: Install dependencies
|
|
101
|
+
run: uv sync --locked --group test
|
|
102
|
+
|
|
103
|
+
- name: Show environment
|
|
104
|
+
run: |
|
|
105
|
+
set -x
|
|
106
|
+
python -VV
|
|
107
|
+
python -m site
|
|
108
|
+
uv --version
|
|
109
|
+
ls -ld $(python -c "import site; print(site.getsitepackages()[0])")
|
|
110
|
+
whoami
|
|
111
|
+
|
|
112
|
+
- name: Run tests
|
|
113
|
+
run: uv run --locked pytest --cov-report=xml
|
|
114
|
+
|
|
115
|
+
- name: Upload coverage report
|
|
116
|
+
uses: codecov/codecov-action@v5.5.1
|
|
117
|
+
with:
|
|
118
|
+
env_vars: OS,PYTHON
|
|
119
|
+
disable_search: true
|
|
120
|
+
files: coverage/coverage.xml
|
|
121
|
+
fail_ci_if_error: true
|
|
122
|
+
flags: unittests
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
|
|
23
|
+
# Virtual environments
|
|
24
|
+
.venv/
|
|
25
|
+
venv/
|
|
26
|
+
ENV/
|
|
27
|
+
env/
|
|
28
|
+
|
|
29
|
+
# Testing
|
|
30
|
+
.pytest_cache/
|
|
31
|
+
.coverage
|
|
32
|
+
coverage/
|
|
33
|
+
htmlcov/
|
|
34
|
+
.tox/
|
|
35
|
+
|
|
36
|
+
# IDEs
|
|
37
|
+
.vscode/
|
|
38
|
+
.idea/
|
|
39
|
+
*.swp
|
|
40
|
+
*.swo
|
|
41
|
+
*~
|
|
42
|
+
|
|
43
|
+
# OS
|
|
44
|
+
.DS_Store
|
|
45
|
+
Thumbs.db
|
|
46
|
+
|
|
47
|
+
# uv
|
|
48
|
+
.uv/
|
|
49
|
+
|
|
50
|
+
# Configuration files (user-specific)
|
|
51
|
+
config.sh
|
|
52
|
+
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# Contributing to Linux MCP Server
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing! This document provides guidelines for contributing to the Linux MCP Server project.
|
|
4
|
+
|
|
5
|
+
## Development Setup
|
|
6
|
+
|
|
7
|
+
1. **Clone the repository:**
|
|
8
|
+
```bash
|
|
9
|
+
git clone <repository-url>
|
|
10
|
+
cd linux-mcp-server
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. **Set up development environment:**
|
|
14
|
+
```bash
|
|
15
|
+
uv venv
|
|
16
|
+
source .venv/bin/activate
|
|
17
|
+
uv sync --editable --group dev
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
3. **Verify setup:**
|
|
21
|
+
```bash
|
|
22
|
+
pytest
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Development Workflow
|
|
26
|
+
|
|
27
|
+
We follow Test-Driven Development (TDD) principles:
|
|
28
|
+
|
|
29
|
+
### 1. RED - Write a Failing Test
|
|
30
|
+
```python
|
|
31
|
+
# tests/test_new_feature.py
|
|
32
|
+
import pytest
|
|
33
|
+
from linux_mcp_server.tools import new_module
|
|
34
|
+
|
|
35
|
+
@pytest.mark.asyncio
|
|
36
|
+
async def test_new_feature():
|
|
37
|
+
result = await new_module.new_function()
|
|
38
|
+
assert "expected" in result
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 2. GREEN - Implement Minimal Code to Pass
|
|
42
|
+
```python
|
|
43
|
+
# src/linux_mcp_server/tools/new_module.py
|
|
44
|
+
async def new_function():
|
|
45
|
+
return "expected result"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 3. REFACTOR - Improve Code Quality
|
|
49
|
+
- Improve readability
|
|
50
|
+
- Remove duplication
|
|
51
|
+
- Ensure all tests still pass
|
|
52
|
+
|
|
53
|
+
### 4. Commit
|
|
54
|
+
```bash
|
|
55
|
+
git add .
|
|
56
|
+
git commit -m "feat: add new feature
|
|
57
|
+
|
|
58
|
+
- Detailed description of what was added
|
|
59
|
+
- Tests included
|
|
60
|
+
- All tests passing"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Code Standards
|
|
64
|
+
|
|
65
|
+
### Style Guidelines
|
|
66
|
+
- Follow PEP 8 for Python code
|
|
67
|
+
- Use type hints for function parameters and return values
|
|
68
|
+
- Use async/await for I/O operations
|
|
69
|
+
- Maximum line length: 100 characters
|
|
70
|
+
|
|
71
|
+
### Documentation
|
|
72
|
+
- Add docstrings to all public functions
|
|
73
|
+
- Use clear, descriptive variable names
|
|
74
|
+
- Comment complex logic
|
|
75
|
+
|
|
76
|
+
### Testing
|
|
77
|
+
- Write tests for all new features
|
|
78
|
+
- Maintain test coverage above 80%
|
|
79
|
+
- Use descriptive test names that explain what is being tested
|
|
80
|
+
|
|
81
|
+
## Adding New Tools
|
|
82
|
+
|
|
83
|
+
When adding a new diagnostic tool:
|
|
84
|
+
|
|
85
|
+
1. **Create the tool function in appropriate module:**
|
|
86
|
+
```python
|
|
87
|
+
# src/linux_mcp_server/tools/my_tool.py
|
|
88
|
+
import typing as t Optional
|
|
89
|
+
from .ssh_executor import execute_command
|
|
90
|
+
|
|
91
|
+
async def my_diagnostic_function(
|
|
92
|
+
host: Optional[str] = None,
|
|
93
|
+
username: Optional[str] = None
|
|
94
|
+
) -> str:
|
|
95
|
+
"""
|
|
96
|
+
Brief description of what this tool does.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
host: Optional remote host to connect to via SSH
|
|
100
|
+
username: Optional SSH username (required if host is provided)
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Formatted string with diagnostic information
|
|
104
|
+
"""
|
|
105
|
+
try:
|
|
106
|
+
# Implementation using execute_command for local/remote execution
|
|
107
|
+
returncode, stdout, stderr = await execute_command(
|
|
108
|
+
["your", "command"],
|
|
109
|
+
host=host,
|
|
110
|
+
username=username
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
if returncode != 0:
|
|
114
|
+
return f"Error: {stderr}"
|
|
115
|
+
|
|
116
|
+
return stdout
|
|
117
|
+
except Exception as e:
|
|
118
|
+
return f"Error: {str(e)}"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
2. **Register the tool in server.py using FastMCP decorator:**
|
|
122
|
+
```python
|
|
123
|
+
# Import your tool module at the top
|
|
124
|
+
from .tools import my_tool
|
|
125
|
+
|
|
126
|
+
# Add decorated function
|
|
127
|
+
@mcp.tool()
|
|
128
|
+
async def my_tool_name(
|
|
129
|
+
param1: str,
|
|
130
|
+
host: Optional[str] = None,
|
|
131
|
+
username: Optional[str] = None
|
|
132
|
+
) -> str:
|
|
133
|
+
"""Description for LLM to understand the tool.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
param1: Description of the parameter
|
|
137
|
+
host: Remote host to connect to via SSH (optional)
|
|
138
|
+
username: SSH username for remote host (required if host is provided)
|
|
139
|
+
"""
|
|
140
|
+
return await _execute_tool(
|
|
141
|
+
"my_tool_name",
|
|
142
|
+
my_tool.my_diagnostic_function,
|
|
143
|
+
param1=param1,
|
|
144
|
+
host=host,
|
|
145
|
+
username=username
|
|
146
|
+
)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
3. **Write tests:**
|
|
150
|
+
```python
|
|
151
|
+
# tests/test_my_tool.py
|
|
152
|
+
import pytest
|
|
153
|
+
from linux_mcp_server.tools import my_tool
|
|
154
|
+
|
|
155
|
+
@pytest.mark.asyncio
|
|
156
|
+
async def test_my_tool():
|
|
157
|
+
result = await my_tool.my_diagnostic_function()
|
|
158
|
+
assert isinstance(result, str)
|
|
159
|
+
assert "expected content" in result.lower()
|
|
160
|
+
|
|
161
|
+
# Test server integration
|
|
162
|
+
@pytest.mark.asyncio
|
|
163
|
+
async def test_server_has_my_tool():
|
|
164
|
+
from linux_mcp_server.server import mcp
|
|
165
|
+
tools = await mcp.list_tools()
|
|
166
|
+
tool_names = [t.name for t in tools]
|
|
167
|
+
assert "my_tool_name" in tool_names
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
4. **Update documentation:**
|
|
171
|
+
- Add tool description to README.md
|
|
172
|
+
- Add usage examples to USAGE.md
|
|
173
|
+
|
|
174
|
+
## Commit Message Format
|
|
175
|
+
|
|
176
|
+
We use [Conventional Commits](https://www.conventionalcommits.org/):
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
<type>(<scope>): <subject>
|
|
180
|
+
|
|
181
|
+
<body>
|
|
182
|
+
|
|
183
|
+
<footer>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Types:
|
|
187
|
+
- `feat`: New feature
|
|
188
|
+
- `fix`: Bug fix
|
|
189
|
+
- `docs`: Documentation only changes
|
|
190
|
+
- `test`: Adding missing tests
|
|
191
|
+
- `refactor`: Code change that neither fixes a bug nor adds a feature
|
|
192
|
+
- `perf`: Performance improvement
|
|
193
|
+
- `chore`: Changes to build process or auxiliary tools
|
|
194
|
+
|
|
195
|
+
### Examples:
|
|
196
|
+
```
|
|
197
|
+
feat(tools): add disk smart status tool
|
|
198
|
+
|
|
199
|
+
- Implement smart status checking
|
|
200
|
+
- Add tests for SMART data parsing
|
|
201
|
+
- Update documentation
|
|
202
|
+
|
|
203
|
+
Closes #123
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
fix(network): handle missing network interfaces gracefully
|
|
208
|
+
|
|
209
|
+
Previously crashed when network interface disappeared
|
|
210
|
+
during enumeration. Now catches exception and continues.
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Security Guidelines
|
|
214
|
+
|
|
215
|
+
### Read-Only Operations
|
|
216
|
+
- All tools MUST be read-only
|
|
217
|
+
- Never implement any function that modifies system state
|
|
218
|
+
- Use subprocess with caution; validate all inputs
|
|
219
|
+
|
|
220
|
+
### Input Validation
|
|
221
|
+
- Always validate user input
|
|
222
|
+
- Use whitelists for file paths (see `read_log_file`)
|
|
223
|
+
- Sanitize parameters passed to shell commands
|
|
224
|
+
|
|
225
|
+
### Error Handling
|
|
226
|
+
- Never expose sensitive information in error messages
|
|
227
|
+
- Catch broad exceptions at the function level
|
|
228
|
+
- Return user-friendly error messages
|
|
229
|
+
|
|
230
|
+
## Testing Guidelines
|
|
231
|
+
|
|
232
|
+
### Unit Tests
|
|
233
|
+
Test individual functions in isolation:
|
|
234
|
+
```python
|
|
235
|
+
@pytest.mark.asyncio
|
|
236
|
+
async def test_function_returns_correct_format():
|
|
237
|
+
result = await module.function()
|
|
238
|
+
assert isinstance(result, str)
|
|
239
|
+
assert "expected" in result
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Integration Tests
|
|
243
|
+
Test that tools work with the MCP server:
|
|
244
|
+
```python
|
|
245
|
+
@pytest.mark.asyncio
|
|
246
|
+
async def test_server_has_tool():
|
|
247
|
+
from linux_mcp_server.server import mcp
|
|
248
|
+
tools = await mcp.list_tools()
|
|
249
|
+
tool_names = [t.name for t in tools]
|
|
250
|
+
assert "tool_name" in tool_names
|
|
251
|
+
|
|
252
|
+
@pytest.mark.asyncio
|
|
253
|
+
async def test_server_calls_tool():
|
|
254
|
+
from linux_mcp_server.server import mcp
|
|
255
|
+
result = await mcp.call_tool("tool_name", {})
|
|
256
|
+
assert isinstance(result, str)
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Running Tests
|
|
260
|
+
```bash
|
|
261
|
+
# Run all tests
|
|
262
|
+
pytest
|
|
263
|
+
|
|
264
|
+
# Run specific test file
|
|
265
|
+
pytest tests/test_services.py
|
|
266
|
+
|
|
267
|
+
# Run with coverage
|
|
268
|
+
pytest --cov=src --cov-report=html
|
|
269
|
+
|
|
270
|
+
# Run with verbose output
|
|
271
|
+
pytest -v
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Documentation
|
|
275
|
+
|
|
276
|
+
### Code Documentation
|
|
277
|
+
- Use docstrings for all public functions
|
|
278
|
+
- Include parameter descriptions
|
|
279
|
+
- Document return values
|
|
280
|
+
- Add usage examples for complex functions
|
|
281
|
+
|
|
282
|
+
### User Documentation
|
|
283
|
+
- Update README.md for new features
|
|
284
|
+
- Add examples to USAGE.md
|
|
285
|
+
- Document configuration options
|
|
286
|
+
- Include troubleshooting tips
|
|
287
|
+
|
|
288
|
+
## Pull Request Process
|
|
289
|
+
|
|
290
|
+
1. **Create a feature branch:**
|
|
291
|
+
```bash
|
|
292
|
+
git checkout -b feature/my-new-feature
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
2. **Make changes following TDD:**
|
|
296
|
+
- Write tests first
|
|
297
|
+
- Implement feature
|
|
298
|
+
- Ensure all tests pass
|
|
299
|
+
|
|
300
|
+
3. **Update documentation:**
|
|
301
|
+
- Update README.md if needed
|
|
302
|
+
- Update USAGE.md with examples
|
|
303
|
+
- Update CONTRIBUTING.md if changing development process
|
|
304
|
+
|
|
305
|
+
4. **Run all tests:**
|
|
306
|
+
```bash
|
|
307
|
+
pytest
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
5. **Commit with conventional commit messages:**
|
|
311
|
+
```bash
|
|
312
|
+
git commit -m "feat: add new diagnostic tool"
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
6. **Push and create pull request:**
|
|
316
|
+
```bash
|
|
317
|
+
git push origin feature/my-new-feature
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
7. **PR Description should include:**
|
|
321
|
+
- What the change does
|
|
322
|
+
- Why it's needed
|
|
323
|
+
- How to test it
|
|
324
|
+
- Screenshots/examples if applicable
|
|
325
|
+
|
|
326
|
+
## Code Review Checklist
|
|
327
|
+
|
|
328
|
+
- [ ] Tests added and passing
|
|
329
|
+
- [ ] Code follows style guidelines
|
|
330
|
+
- [ ] Documentation updated
|
|
331
|
+
- [ ] Commit messages follow conventional format
|
|
332
|
+
- [ ] No security vulnerabilities introduced
|
|
333
|
+
- [ ] All operations are read-only
|
|
334
|
+
- [ ] Error handling is appropriate
|
|
335
|
+
- [ ] Input validation is present
|
|
336
|
+
|
|
337
|
+
## Questions or Issues?
|
|
338
|
+
|
|
339
|
+
- Open an issue on GitHub
|
|
340
|
+
- Check existing issues first
|
|
341
|
+
- Provide detailed information:
|
|
342
|
+
- System information (OS, version)
|
|
343
|
+
- Steps to reproduce
|
|
344
|
+
- Expected vs actual behavior
|
|
345
|
+
- Relevant logs
|
|
346
|
+
|
|
347
|
+
## License
|
|
348
|
+
|
|
349
|
+
By contributing, you agree that your contributions will be licensed under the Apache 2.0 License.
|
|
350
|
+
|