linux-mcp-server 0.1.0.dev0__py3-none-any.whl
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/__init__.py +4 -0
- linux_mcp_server/__main__.py +30 -0
- linux_mcp_server/audit.py +285 -0
- linux_mcp_server/logging_config.py +144 -0
- linux_mcp_server/server.py +328 -0
- linux_mcp_server/tools/__init__.py +2 -0
- linux_mcp_server/tools/logs.py +225 -0
- linux_mcp_server/tools/network.py +281 -0
- linux_mcp_server/tools/processes.py +257 -0
- linux_mcp_server/tools/services.py +147 -0
- linux_mcp_server/tools/ssh_executor.py +324 -0
- linux_mcp_server/tools/storage.py +358 -0
- linux_mcp_server/tools/system_info.py +507 -0
- linux_mcp_server/tools/utils.py +27 -0
- linux_mcp_server/tools/validation.py +58 -0
- linux_mcp_server-0.1.0.dev0.dist-info/METADATA +331 -0
- linux_mcp_server-0.1.0.dev0.dist-info/RECORD +20 -0
- linux_mcp_server-0.1.0.dev0.dist-info/WHEEL +4 -0
- linux_mcp_server-0.1.0.dev0.dist-info/entry_points.txt +2 -0
- linux_mcp_server-0.1.0.dev0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: linux-mcp-server
|
|
3
|
+
Version: 0.1.0.dev0
|
|
4
|
+
Summary: MCP server for read-only Linux system administration, diagnostics, and troubleshooting
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Requires-Dist: asyncssh>=2.14.0
|
|
8
|
+
Requires-Dist: mcp>=0.9.0
|
|
9
|
+
Requires-Dist: psutil>=5.9.0
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
12
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
13
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# Linux MCP Server
|
|
17
|
+
|
|
18
|
+
A Model Context Protocol (MCP) server for read-only Linux system administration, diagnostics, and troubleshooting on RHEL-based systems.
|
|
19
|
+
|
|
20
|
+
## Features
|
|
21
|
+
|
|
22
|
+
- **Read-Only Operations**: All tools are strictly read-only for safe diagnostics
|
|
23
|
+
- **Remote SSH Execution**: Execute commands on remote systems via SSH with key-based authentication
|
|
24
|
+
- **Multi-Host Management**: Connect to different remote hosts in the same session
|
|
25
|
+
- **Comprehensive Diagnostics**: System info, services, processes, logs, network, and storage
|
|
26
|
+
- **Configurable Log Access**: Control which log files can be accessed via environment variables
|
|
27
|
+
- **RHEL/systemd Focused**: Optimized for Red Hat Enterprise Linux systems
|
|
28
|
+
|
|
29
|
+
## Architecture Overview
|
|
30
|
+
|
|
31
|
+
```mermaid
|
|
32
|
+
graph TB
|
|
33
|
+
Client["Client Layer<br/>MCP Client (e.g. Claude Desktop)"]
|
|
34
|
+
|
|
35
|
+
subgraph Server["MCP Server"]
|
|
36
|
+
FastMCP[FastMCP Server]
|
|
37
|
+
|
|
38
|
+
subgraph Tools["Tool Categories"]
|
|
39
|
+
direction LR
|
|
40
|
+
subgraph Row1[" "]
|
|
41
|
+
SystemInfo[System Info]
|
|
42
|
+
Services[Services]
|
|
43
|
+
Processes[Processes]
|
|
44
|
+
end
|
|
45
|
+
subgraph Row2[" "]
|
|
46
|
+
Logs[Logs & Audit]
|
|
47
|
+
Network[Network]
|
|
48
|
+
Storage[Storage]
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
Executor[SSH Executor]
|
|
53
|
+
Logger[Audit Logger]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
subgraph Targets["Execution Targets"]
|
|
57
|
+
direction LR
|
|
58
|
+
Local[Local System]
|
|
59
|
+
Remote[Remote Hosts<br/>SSH]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
Client -->|MCP Protocol| FastMCP
|
|
63
|
+
FastMCP --> Tools
|
|
64
|
+
Tools --> Executor
|
|
65
|
+
Executor --> Targets
|
|
66
|
+
|
|
67
|
+
FastMCP -.-> Logger
|
|
68
|
+
Executor -.-> Logger
|
|
69
|
+
|
|
70
|
+
style Client fill:#4a9eff,stroke:#2563eb,color:#fff
|
|
71
|
+
style FastMCP fill:#f59e0b,stroke:#d97706,color:#fff
|
|
72
|
+
style SystemInfo fill:#64748b,stroke:#475569,color:#fff
|
|
73
|
+
style Services fill:#64748b,stroke:#475569,color:#fff
|
|
74
|
+
style Processes fill:#64748b,stroke:#475569,color:#fff
|
|
75
|
+
style Logs fill:#64748b,stroke:#475569,color:#fff
|
|
76
|
+
style Network fill:#64748b,stroke:#475569,color:#fff
|
|
77
|
+
style Storage fill:#64748b,stroke:#475569,color:#fff
|
|
78
|
+
style Executor fill:#10b981,stroke:#059669,color:#fff
|
|
79
|
+
style Logger fill:#8b5cf6,stroke:#7c3aed,color:#fff
|
|
80
|
+
style Local fill:#eab308,stroke:#ca8a04,color:#fff
|
|
81
|
+
style Remote fill:#eab308,stroke:#ca8a04,color:#fff
|
|
82
|
+
style Row1 fill:none,stroke:none
|
|
83
|
+
style Row2 fill:none,stroke:none
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Key Components
|
|
87
|
+
|
|
88
|
+
- **FastMCP Server**: Core MCP protocol server handling tool registration and invocation
|
|
89
|
+
- **Tool Categories**: Six categories of read-only diagnostic tools (system info, services, processes, logs, network, storage)
|
|
90
|
+
- **SSH Executor**: Routes commands to local subprocess or remote SSH execution with connection pooling
|
|
91
|
+
- **Audit Logger**: Comprehensive logging in both human-readable and JSON formats with automatic rotation
|
|
92
|
+
- **Multi-Target Execution**: Single server instance can execute commands on local system or multiple remote hosts
|
|
93
|
+
|
|
94
|
+
## Available Tools
|
|
95
|
+
|
|
96
|
+
### System Information
|
|
97
|
+
- `get_system_info` - OS version, kernel, hostname, uptime
|
|
98
|
+
- `get_cpu_info` - CPU details and load averages
|
|
99
|
+
- `get_memory_info` - RAM usage and swap details
|
|
100
|
+
- `get_disk_usage` - Filesystem usage and mount points
|
|
101
|
+
- `get_hardware_info` - Hardware details (CPU architecture, PCI/USB devices, memory hardware)
|
|
102
|
+
|
|
103
|
+
### Service Management
|
|
104
|
+
- `list_services` - List all systemd services with status
|
|
105
|
+
- `get_service_status` - Detailed status of a specific service
|
|
106
|
+
- `get_service_logs` - Recent logs for a specific service
|
|
107
|
+
|
|
108
|
+
### Process Management
|
|
109
|
+
- `list_processes` - Running processes with CPU/memory usage
|
|
110
|
+
- `get_process_info` - Detailed information about a specific process
|
|
111
|
+
|
|
112
|
+
### Logs & Audit
|
|
113
|
+
- `get_journal_logs` - Query systemd journal with filters
|
|
114
|
+
- `get_audit_logs` - Read audit logs (if available)
|
|
115
|
+
- `read_log_file` - Read specific log file (whitelist-controlled)
|
|
116
|
+
|
|
117
|
+
### Network Diagnostics
|
|
118
|
+
- `get_network_interfaces` - Network interface information
|
|
119
|
+
- `get_network_connections` - Active network connections
|
|
120
|
+
- `get_listening_ports` - Ports listening on the system
|
|
121
|
+
|
|
122
|
+
### Storage & Disk Analysis
|
|
123
|
+
- `list_block_devices` - Block devices and partitions
|
|
124
|
+
- `list_directories_by_size` - List directories sorted by size (largest first) with top N limit
|
|
125
|
+
- `list_directories_by_name` - List all directories sorted alphabetically (A-Z or Z-A)
|
|
126
|
+
- `list_directories_by_modified_date` - List all directories sorted by modification date (newest/oldest first)
|
|
127
|
+
|
|
128
|
+
## Installation
|
|
129
|
+
|
|
130
|
+
### Prerequisites
|
|
131
|
+
- Python 3.10 or higher
|
|
132
|
+
- [uv](https://github.com/astral-sh/uv) package manager
|
|
133
|
+
|
|
134
|
+
### Setup
|
|
135
|
+
|
|
136
|
+
1. Clone the repository:
|
|
137
|
+
```bash
|
|
138
|
+
git clone <repository-url>
|
|
139
|
+
cd linux-mcp-server
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
2. Create virtual environment and install dependencies:
|
|
143
|
+
```bash
|
|
144
|
+
uv venv
|
|
145
|
+
source .venv/bin/activate
|
|
146
|
+
uv pip install -e ".[dev]"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Configuration
|
|
150
|
+
|
|
151
|
+
Configure the server using environment variables:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# Comma-separated list of allowed log file paths
|
|
155
|
+
export LINUX_MCP_ALLOWED_LOG_PATHS="/var/log/messages,/var/log/secure,/var/log/audit/audit.log"
|
|
156
|
+
|
|
157
|
+
# Optional: Set log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
|
158
|
+
export LINUX_MCP_LOG_LEVEL="INFO"
|
|
159
|
+
|
|
160
|
+
# Optional: Custom log directory (default: ~/.local/share/linux-mcp-server/logs/)
|
|
161
|
+
export LINUX_MCP_LOG_DIR="/var/log/linux-mcp-server"
|
|
162
|
+
|
|
163
|
+
# Optional: Log retention in days (default: 10)
|
|
164
|
+
export LINUX_MCP_LOG_RETENTION_DAYS="30"
|
|
165
|
+
|
|
166
|
+
# Optional: Specify SSH private key path (defaults to ~/.ssh/id_ed25519, ~/.ssh/id_rsa, etc.)
|
|
167
|
+
export LINUX_MCP_SSH_KEY_PATH="/path/to/your/private/key"
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Audit Logging
|
|
171
|
+
|
|
172
|
+
The server includes comprehensive audit logging for all operations:
|
|
173
|
+
|
|
174
|
+
**Features:**
|
|
175
|
+
- **Dual Format**: Logs written in both human-readable text and JSON formats
|
|
176
|
+
- **Daily Rotation**: Automatic log rotation at midnight
|
|
177
|
+
- **Configurable Retention**: Keep logs for a specified number of days (default: 10)
|
|
178
|
+
- **Tiered Verbosity**: INFO for operations, DEBUG for detailed diagnostics
|
|
179
|
+
- **Sanitization**: Automatic redaction of sensitive data (passwords, tokens, API keys)
|
|
180
|
+
|
|
181
|
+
**Log Files:**
|
|
182
|
+
- Human-readable: `~/.local/share/linux-mcp-server/logs/server.log`
|
|
183
|
+
- JSON format: `~/.local/share/linux-mcp-server/logs/server.json`
|
|
184
|
+
- Rotated files: `server.log.YYYY-MM-DD` and `server.json.YYYY-MM-DD`
|
|
185
|
+
|
|
186
|
+
**What Gets Logged:**
|
|
187
|
+
- Server startup and shutdown
|
|
188
|
+
- All tool invocations with parameters (sanitized)
|
|
189
|
+
- Tool execution time and completion status
|
|
190
|
+
- SSH connections (success/failure)
|
|
191
|
+
- Remote command execution
|
|
192
|
+
- Error conditions with full context
|
|
193
|
+
|
|
194
|
+
**Log Levels:**
|
|
195
|
+
- `DEBUG`: Detailed flow, connection reuse, function entry/exit, timing details
|
|
196
|
+
- `INFO`: Tool calls, command executions, connection events, operation results
|
|
197
|
+
- `WARNING`: Authentication failures, retryable errors, missing optional data
|
|
198
|
+
- `ERROR`: Failed operations, exceptions, connection failures
|
|
199
|
+
- `CRITICAL`: Server startup/shutdown failures, unrecoverable errors
|
|
200
|
+
|
|
201
|
+
**Example Log Entries:**
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
# Human-readable format (server.log)
|
|
205
|
+
2025-10-10 14:23:45.123 | INFO | server | TOOL_CALL: list_services | host=server1.example.com | username=admin | execution_mode=remote
|
|
206
|
+
2025-10-10 14:23:45.234 | INFO | ssh_executor | SSH_CONNECT: admin@server1.example.com | status=success
|
|
207
|
+
2025-10-10 14:23:45.345 | INFO | ssh_executor | REMOTE_EXEC: systemctl list-units --type=service | host=server1.example.com | exit_code=0
|
|
208
|
+
2025-10-10 14:23:45.456 | INFO | server | TOOL_COMPLETE: list_services | status=success | duration=0.333s
|
|
209
|
+
|
|
210
|
+
# JSON format (server.json)
|
|
211
|
+
{"timestamp": "2025-10-10T14:23:45.123Z", "level": "INFO", "logger": "server", "message": "TOOL_CALL: list_services", "event": "TOOL_CALL", "tool": "list_services", "host": "server1.example.com", "username": "admin", "execution_mode": "remote"}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Remote SSH Execution
|
|
215
|
+
|
|
216
|
+
All tools support optional `host` and `username` parameters for remote execution via SSH:
|
|
217
|
+
|
|
218
|
+
- **Authentication**: SSH key-based authentication only (no password support)
|
|
219
|
+
- **Key Discovery**: Automatically discovers SSH keys from `~/.ssh/` or use `LINUX_MCP_SSH_KEY_PATH`
|
|
220
|
+
- **Connection Pooling**: Reuses SSH connections for efficiency
|
|
221
|
+
- **Multi-Host**: Each tool call can target a different remote host
|
|
222
|
+
|
|
223
|
+
**Requirements**:
|
|
224
|
+
- SSH key-based authentication must be configured on remote hosts
|
|
225
|
+
- Remote user must have appropriate permissions for diagnostic commands
|
|
226
|
+
|
|
227
|
+
**Example Usage**:
|
|
228
|
+
```python
|
|
229
|
+
# Local execution
|
|
230
|
+
await list_services()
|
|
231
|
+
|
|
232
|
+
# Remote execution
|
|
233
|
+
await list_services(host="server1.example.com", username="admin")
|
|
234
|
+
|
|
235
|
+
# Different host in same session
|
|
236
|
+
await get_service_status("nginx", host="server2.example.com", username="sysadmin")
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Usage
|
|
240
|
+
|
|
241
|
+
### Running the Server
|
|
242
|
+
|
|
243
|
+
You can run the server in multiple ways:
|
|
244
|
+
|
|
245
|
+
**Using uv run (recommended for development):**
|
|
246
|
+
```bash
|
|
247
|
+
uv run linux-mcp-server
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Using uvx (recommended for one-off execution without installation):**
|
|
251
|
+
```bash
|
|
252
|
+
uvx --from /path/to/linux-mcp-server linux-mcp-server
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**Traditional Python module execution:**
|
|
256
|
+
```bash
|
|
257
|
+
python -m linux_mcp_server
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Using with Claude Desktop
|
|
261
|
+
|
|
262
|
+
Add to your Claude Desktop configuration (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
|
|
263
|
+
|
|
264
|
+
**Option 1: Using uv run (simpler):**
|
|
265
|
+
```json
|
|
266
|
+
{
|
|
267
|
+
"mcpServers": {
|
|
268
|
+
"linux-diagnostics": {
|
|
269
|
+
"command": "uv",
|
|
270
|
+
"args": [
|
|
271
|
+
"--directory",
|
|
272
|
+
"/path/to/linux-mcp-server",
|
|
273
|
+
"run",
|
|
274
|
+
"linux-mcp-server"
|
|
275
|
+
],
|
|
276
|
+
"env": {
|
|
277
|
+
"LINUX_MCP_ALLOWED_LOG_PATHS": "/var/log/messages,/var/log/secure,/var/log/audit/audit.log"
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Option 2: Using uvx (from local directory):**
|
|
285
|
+
```json
|
|
286
|
+
{
|
|
287
|
+
"mcpServers": {
|
|
288
|
+
"linux-diagnostics": {
|
|
289
|
+
"command": "uvx",
|
|
290
|
+
"args": [
|
|
291
|
+
"--from",
|
|
292
|
+
"/path/to/linux-mcp-server",
|
|
293
|
+
"linux-mcp-server"
|
|
294
|
+
],
|
|
295
|
+
"env": {
|
|
296
|
+
"LINUX_MCP_ALLOWED_LOG_PATHS": "/var/log/messages,/var/log/secure,/var/log/audit/audit.log"
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Development
|
|
304
|
+
|
|
305
|
+
### Running Tests
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
pytest
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Running Tests with Coverage
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
pytest --cov=src --cov-report=html
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Security Considerations
|
|
318
|
+
|
|
319
|
+
- All operations are **read-only**
|
|
320
|
+
- Log file access is controlled via whitelist (`LINUX_MCP_ALLOWED_LOG_PATHS`)
|
|
321
|
+
- **SSH key-based authentication only** - no password support
|
|
322
|
+
- SSH host key verification is disabled for flexibility (use with caution)
|
|
323
|
+
- No arbitrary command execution
|
|
324
|
+
- Input validation on all parameters
|
|
325
|
+
- Requires appropriate system permissions for diagnostics
|
|
326
|
+
- Remote user needs proper sudo/permissions for privileged commands
|
|
327
|
+
|
|
328
|
+
## License
|
|
329
|
+
|
|
330
|
+
MIT License
|
|
331
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
linux_mcp_server/__init__.py,sha256=kqCUoAViNPXAv7NLdtm_QNkRWw3UAUYb-VdtrEirjgw,109
|
|
2
|
+
linux_mcp_server/__main__.py,sha256=KCxRzk4GcqIEhDKHWbsuJZ4OvUnDj0WIDcBcegztF1w,768
|
|
3
|
+
linux_mcp_server/audit.py,sha256=nT6wrc9EbjGRPQYkTexwceDibMDMzmjsrRKtyqbFAlw,7763
|
|
4
|
+
linux_mcp_server/logging_config.py,sha256=4fJbmAhNVHr99721aHIzvfEFjwHAHJYG0nutCu_c9lU,5007
|
|
5
|
+
linux_mcp_server/server.py,sha256=WFvbc4a4IU4sC9JcNeb2BLxQErqGI_-TsdfGXaqw4w4,13646
|
|
6
|
+
linux_mcp_server/tools/__init__.py,sha256=tmts0--UGw0PoDJARq5rurlxNXIdmYQwZddbiViatZY,43
|
|
7
|
+
linux_mcp_server/tools/logs.py,sha256=OT61rh_2LwLTdK0rCm-bQvMQMPBFq-kHmeG5QKsnDUE,7538
|
|
8
|
+
linux_mcp_server/tools/network.py,sha256=TRyDDAouTLoV3xhL1IUJLhlNhzIHnEj_WXwQkrg8XKw,11050
|
|
9
|
+
linux_mcp_server/tools/processes.py,sha256=kDeeQZkuUf-pLU2UA3Aox70-bJjZATnkVmvLbGiCi1Q,10251
|
|
10
|
+
linux_mcp_server/tools/services.py,sha256=IUD0gK-UAljvH11PUW9lgkFyd234EgHOahZgqfLNuHo,5135
|
|
11
|
+
linux_mcp_server/tools/ssh_executor.py,sha256=UBPs9io_T9yF9GNrKIau1yKnWnEOW2QjNw9ZmDwWrV0,11301
|
|
12
|
+
linux_mcp_server/tools/storage.py,sha256=VvOXPuLRHHp_dNAXWev0cVWhswz9qwB8uRZgx3vdQXQ,12977
|
|
13
|
+
linux_mcp_server/tools/system_info.py,sha256=dJJmA3_2KP8yQY2kks8PndGTwS4iWInRc7sSDfoUHLw,19622
|
|
14
|
+
linux_mcp_server/tools/utils.py,sha256=BsrJsHvrdrJKP8-usBtF5KCWU2MKa2P7oEB6MW5hrzY,675
|
|
15
|
+
linux_mcp_server/tools/validation.py,sha256=8EN_Ny9kPVTR0ABoP0GZshuzD-CFAiYk1Qj1Oeiqvm0,1825
|
|
16
|
+
linux_mcp_server-0.1.0.dev0.dist-info/METADATA,sha256=0T5z9LuE4FggUG6V2sqY3lq0oguQanwMHDmidSAMCDg,10972
|
|
17
|
+
linux_mcp_server-0.1.0.dev0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
18
|
+
linux_mcp_server-0.1.0.dev0.dist-info/entry_points.txt,sha256=TVzOzNkzp99ltOQ8SHTA1U-92A_hydczj6EhsqPVChg,67
|
|
19
|
+
linux_mcp_server-0.1.0.dev0.dist-info/licenses/LICENSE,sha256=ji9Aq1nWt4NHP7Abfp-ovzCGgno_QDSAUxDh2dmxyd4,1068
|
|
20
|
+
linux_mcp_server-0.1.0.dev0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Nicolás M.
|
|
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.
|