mcp-yieldshell 0.1.7__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.
@@ -0,0 +1 @@
1
+ """YieldShell MCP — A drop-in shell MCP that auto-yields long-running commands."""
@@ -0,0 +1,17 @@
1
+ """CLI entrypoint: start the YieldShell MCP stdio server."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from .config import Config
6
+ from .server import create_server
7
+
8
+
9
+ def main() -> None:
10
+ """Start the YieldShell MCP server on stdio."""
11
+ config = Config()
12
+ server = create_server(config)
13
+ server.run(transport="stdio")
14
+
15
+
16
+ if __name__ == "__main__":
17
+ main()
@@ -0,0 +1,66 @@
1
+ """Configuration parsed from environment variables at server startup."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import re
7
+
8
+
9
+ class Config:
10
+ def __init__(self) -> None:
11
+ self.default_cwd: str = os.environ.get("YIELDSHELL_DEFAULT_CWD", os.getcwd())
12
+ self.allowed_cwd_roots: list[str] = _parse_pathsep(
13
+ os.environ.get("YIELDSHELL_ALLOWED_CWDS", "")
14
+ )
15
+ self.max_output_bytes: int = _parse_int(
16
+ os.environ.get("YIELDSHELL_MAX_OUTPUT_BYTES", ""), 20000
17
+ )
18
+ self.max_processes: int = _parse_int(
19
+ os.environ.get("YIELDSHELL_MAX_PROCESSES", ""), 50
20
+ )
21
+ self.default_yield_ms: int = _parse_int(
22
+ os.environ.get("YIELDSHELL_DEFAULT_YIELD_MS", ""), 5000
23
+ )
24
+ self.max_yield_ms: int = _parse_int(
25
+ os.environ.get("YIELDSHELL_MAX_YIELD_MS", ""), 300000
26
+ )
27
+ self.default_timeout_ms: int = _parse_int(
28
+ os.environ.get("YIELDSHELL_DEFAULT_TIMEOUT_MS", ""), 0
29
+ )
30
+ self.deny_command_regex: re.Pattern[str] | None = _parse_regex(
31
+ os.environ.get("YIELDSHELL_DENY_COMMAND_REGEX", "")
32
+ )
33
+ self.allow_command_regex: re.Pattern[str] | None = _parse_regex(
34
+ os.environ.get("YIELDSHELL_ALLOW_COMMAND_REGEX", "")
35
+ )
36
+ self.redact_env_regex: re.Pattern[str] = _parse_regex_required(
37
+ os.environ.get("YIELDSHELL_REDACT_ENV_REGEX", ""),
38
+ r"TOKEN|KEY|SECRET|PASSWORD",
39
+ )
40
+
41
+
42
+ def _parse_pathsep(value: str) -> list[str]:
43
+ if not value:
44
+ return []
45
+ return [p for p in value.split(os.pathsep) if p]
46
+
47
+
48
+ def _parse_int(value: str, default: int) -> int:
49
+ if not value:
50
+ return default
51
+ try:
52
+ return int(value)
53
+ except ValueError:
54
+ return default
55
+
56
+
57
+ def _parse_regex(value: str) -> re.Pattern[str] | None:
58
+ if not value:
59
+ return None
60
+ return re.compile(value)
61
+
62
+
63
+ def _parse_regex_required(value: str, default: str) -> re.Pattern[str]:
64
+ if not value:
65
+ return re.compile(default)
66
+ return re.compile(value)
@@ -0,0 +1 @@
1
+ """Process management sub-package."""