open-edison 0.1.29__tar.gz → 0.1.34__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.
- {open_edison-0.1.29 → open_edison-0.1.34}/PKG-INFO +4 -3
- {open_edison-0.1.29 → open_edison-0.1.34}/README.md +2 -2
- {open_edison-0.1.29 → open_edison-0.1.34}/docs/core/proxy_usage.md +1 -1
- {open_edison-0.1.29 → open_edison-0.1.34}/docs/deployment/local.md +4 -4
- {open_edison-0.1.29 → open_edison-0.1.34}/docs/development/testing.md +6 -6
- open_edison-0.1.34/hatch_build.py +51 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/pyproject.toml +12 -6
- {open_edison-0.1.29 → open_edison-0.1.34}/src/cli.py +8 -2
- {open_edison-0.1.29 → open_edison-0.1.34}/src/config.py +14 -1
- open_edison-0.1.34/src/frontend_dist/assets/index-BUUcUfTt.js +51 -0
- open_edison-0.1.34/src/frontend_dist/assets/index-o6_8mdM8.css +1 -0
- open_edison-0.1.34/src/frontend_dist/index.html +21 -0
- open_edison-0.1.34/src/frontend_dist/sw.js +71 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/src/server.py +29 -11
- {open_edison-0.1.29 → open_edison-0.1.34}/src/single_user_mcp.py +24 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/.gitignore +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/LICENSE +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/config.json +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/desktop_ext/README.md +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/docs/README.md +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/docs/architecture/single_user_design.md +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/docs/core/configuration.md +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/docs/core/project_structure.md +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/docs/deployment/docker.md +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/docs/development/contributing.md +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/docs/development/development_guide.md +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/docs/quick-reference/api_reference.md +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/docs/quick-reference/config_quick_start.md +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/prompt_permissions.json +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/resource_permissions.json +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/src/__init__.py +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/src/__main__.py +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/src/events.py +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/src/middleware/data_access_tracker.py +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/src/middleware/session_tracking.py +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/src/oauth_manager.py +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/src/permissions.py +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/src/telemetry.py +0 -0
- {open_edison-0.1.29 → open_edison-0.1.34}/tool_permissions.json +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: open-edison
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.34
|
4
4
|
Summary: Open-source MCP security, aggregation, and monitoring. Single-user, self-hosted MCP proxy.
|
5
5
|
Author-email: Hugo Berg <hugo@edison.watch>
|
6
6
|
License-File: LICENSE
|
@@ -9,6 +9,7 @@ Requires-Dist: aiohttp>=3.12.14
|
|
9
9
|
Requires-Dist: aiosqlite>=0.20.0
|
10
10
|
Requires-Dist: fastapi>=0.116.1
|
11
11
|
Requires-Dist: fastmcp>=2.10.5
|
12
|
+
Requires-Dist: hatchling>=1.27.0
|
12
13
|
Requires-Dist: httpx>=0.28.1
|
13
14
|
Requires-Dist: loguru>=0.7.3
|
14
15
|
Requires-Dist: opentelemetry-api>=1.36.0
|
@@ -27,9 +28,9 @@ Description-Content-Type: text/markdown
|
|
27
28
|
|
28
29
|
# OpenEdison 🔒⚡️
|
29
30
|
|
30
|
-
> The
|
31
|
+
> The Secure MCP Control Panel
|
31
32
|
|
32
|
-
Connect AI to your data/software securely without risk of data exfiltration. Gain visibility, block threats, and get alerts on the data your agent is reading/writing.
|
33
|
+
Connect AI to your data/software securely without risk of data exfiltration. Gain visibility, block threats, and get alerts on the data your agent is reading/writing.
|
33
34
|
|
34
35
|
OpenEdison solves the [lethal trifecta problem](https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/), which can cause agent hijacking & data exfiltration by malicious actors.
|
35
36
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# OpenEdison 🔒⚡️
|
2
2
|
|
3
|
-
> The
|
3
|
+
> The Secure MCP Control Panel
|
4
4
|
|
5
|
-
Connect AI to your data/software securely without risk of data exfiltration. Gain visibility, block threats, and get alerts on the data your agent is reading/writing.
|
5
|
+
Connect AI to your data/software securely without risk of data exfiltration. Gain visibility, block threats, and get alerts on the data your agent is reading/writing.
|
6
6
|
|
7
7
|
OpenEdison solves the [lethal trifecta problem](https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/), which can cause agent hijacking & data exfiltration by malicious actors.
|
8
8
|
|
@@ -30,14 +30,14 @@ cd open-edison
|
|
30
30
|
|
31
31
|
### 2. Install Dependencies
|
32
32
|
|
33
|
-
#### Using
|
33
|
+
#### Using UV (Recommended)
|
34
34
|
|
35
35
|
```bash
|
36
|
-
# Install
|
37
|
-
curl -
|
36
|
+
# Install UV if not already installed
|
37
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
38
38
|
|
39
39
|
# Install dependencies
|
40
|
-
|
40
|
+
uv sync
|
41
41
|
```
|
42
42
|
|
43
43
|
#### Using pip/venv
|
@@ -618,18 +618,18 @@ jobs:
|
|
618
618
|
with:
|
619
619
|
python-version: ${{ matrix.python-version }}
|
620
620
|
|
621
|
-
- name: Install
|
621
|
+
- name: Install UV
|
622
622
|
run: |
|
623
|
-
curl -
|
624
|
-
echo "$HOME/.
|
623
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
624
|
+
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
|
625
625
|
|
626
626
|
- name: Install dependencies
|
627
|
-
run:
|
627
|
+
run: uv sync
|
628
628
|
|
629
629
|
- name: Run tests
|
630
630
|
run: |
|
631
|
-
|
632
|
-
|
631
|
+
uv run pytest --cov=src tests/
|
632
|
+
uv run pytest --cov-report=xml
|
633
633
|
|
634
634
|
- name: Upload coverage
|
635
635
|
uses: codecov/codecov-action@v3
|
@@ -0,0 +1,51 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import os
|
4
|
+
import shutil
|
5
|
+
from pathlib import Path
|
6
|
+
|
7
|
+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
8
|
+
|
9
|
+
|
10
|
+
class BuildHook(BuildHookInterface): # type: ignore
|
11
|
+
"""Ensure packaged frontend assets exist in src/frontend_dist before build.
|
12
|
+
|
13
|
+
Behavior:
|
14
|
+
- If src/frontend_dist/index.html exists, do nothing.
|
15
|
+
- Else if frontend/dist/index.html exists, copy it to src/frontend_dist/.
|
16
|
+
- Else raise a clear error instructing to run `make build_package` first.
|
17
|
+
We intentionally DO NOT run npm during packaging to avoid assuming it
|
18
|
+
on build/install environments.
|
19
|
+
"""
|
20
|
+
|
21
|
+
def initialize(self, version: str, build_data: dict) -> None: # noqa: D401 # type: ignore
|
22
|
+
project_root = Path(self.root)
|
23
|
+
src_frontend_dist = project_root / "src" / "frontend_dist"
|
24
|
+
repo_frontend_dist = project_root / "frontend" / "dist"
|
25
|
+
|
26
|
+
# Opt-in enforcement: only enforce when OPEN_EDISON_REQUIRE_FRONTEND=1/true/yes
|
27
|
+
enforce = os.environ.get("OPEN_EDISON_REQUIRE_FRONTEND", "").lower() in {"1", "true", "yes"}
|
28
|
+
if not enforce:
|
29
|
+
self.app.display_info(
|
30
|
+
"Skipping frontend_dist enforcement (set OPEN_EDISON_REQUIRE_FRONTEND=1 to enforce)"
|
31
|
+
)
|
32
|
+
return
|
33
|
+
|
34
|
+
# Fast path: already present in src/
|
35
|
+
if (src_frontend_dist / "index.html").exists():
|
36
|
+
self.app.display_info("frontend_dist already present; skipping build/copy")
|
37
|
+
return
|
38
|
+
|
39
|
+
# Copy from repo frontend/dist if present
|
40
|
+
if (repo_frontend_dist / "index.html").exists():
|
41
|
+
if src_frontend_dist.exists():
|
42
|
+
shutil.rmtree(src_frontend_dist)
|
43
|
+
shutil.copytree(repo_frontend_dist, src_frontend_dist)
|
44
|
+
self.app.display_info("Copied frontend/dist -> src/frontend_dist for packaging")
|
45
|
+
return
|
46
|
+
|
47
|
+
# No assets available; fail fast with guidance
|
48
|
+
raise RuntimeError(
|
49
|
+
"Packaged dashboard (src/frontend_dist) missing and frontend/dist not found. "
|
50
|
+
"Run 'make build_package' to generate assets before packaging/uvx."
|
51
|
+
)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "open-edison"
|
3
|
-
version = "0.1.
|
3
|
+
version = "0.1.34"
|
4
4
|
description = "Open-source MCP security, aggregation, and monitoring. Single-user, self-hosted MCP proxy."
|
5
5
|
readme = "README.md"
|
6
6
|
authors = [
|
@@ -21,6 +21,7 @@ dependencies = [
|
|
21
21
|
"opentelemetry-api>=1.36.0",
|
22
22
|
"opentelemetry-sdk>=1.36.0",
|
23
23
|
"opentelemetry-exporter-otlp>=1.36.0",
|
24
|
+
"hatchling>=1.27.0",
|
24
25
|
]
|
25
26
|
requires-python = ">= 3.12"
|
26
27
|
|
@@ -32,9 +33,8 @@ open_edison = "src.cli:main"
|
|
32
33
|
requires = ["hatchling"]
|
33
34
|
build-backend = "hatchling.build"
|
34
35
|
|
35
|
-
[tool.
|
36
|
+
[tool.uv]
|
36
37
|
managed = true
|
37
|
-
python = "3.12"
|
38
38
|
dev-dependencies = [
|
39
39
|
"basedpyright>=1.21.0",
|
40
40
|
"ruff>=0.12.3",
|
@@ -67,6 +67,9 @@ include = [
|
|
67
67
|
"src/frontend_dist/**",
|
68
68
|
]
|
69
69
|
|
70
|
+
[tool.hatch.build.targets.wheel.hooks.custom]
|
71
|
+
path = "hatch_build.py"
|
72
|
+
|
70
73
|
|
71
74
|
[tool.hatch.build.targets.sdist]
|
72
75
|
include = [
|
@@ -77,10 +80,13 @@ include = [
|
|
77
80
|
"resource_permissions.json",
|
78
81
|
"prompt_permissions.json",
|
79
82
|
"src/**",
|
80
|
-
"docs/**",
|
81
|
-
# Ensure packaged dashboard assets are present when building from sdist
|
82
83
|
"src/frontend_dist/**",
|
84
|
+
"docs/**",
|
83
85
|
]
|
86
|
+
force-include = { "src/frontend_dist" = "src/frontend_dist" }
|
87
|
+
|
88
|
+
[tool.hatch.build.targets.sdist.hooks.custom]
|
89
|
+
path = "hatch_build.py"
|
84
90
|
|
85
91
|
[tool.ruff]
|
86
92
|
line-length = 100
|
@@ -114,4 +120,4 @@ venvPath = ".venv"
|
|
114
120
|
extraPaths = ["src"]
|
115
121
|
|
116
122
|
[tool.vulture]
|
117
|
-
exclude = ["tests", "src/frontend_dist"]
|
123
|
+
exclude = ["tests", "src/frontend_dist"]
|
@@ -17,7 +17,7 @@ from typing import Any, NoReturn, cast
|
|
17
17
|
|
18
18
|
from loguru import logger as _log # type: ignore[reportMissingImports]
|
19
19
|
|
20
|
-
from .config import Config, get_config_dir
|
20
|
+
from .config import Config, get_config_dir, get_config_json_path
|
21
21
|
from .server import OpenEdisonProxy
|
22
22
|
|
23
23
|
log: Any = _log
|
@@ -125,6 +125,12 @@ def _spawn_frontend_dev( # noqa: C901 - pragmatic complexity for env probing
|
|
125
125
|
)
|
126
126
|
# No separate website process needed. Return sentinel port (-1) so caller knows not to warn.
|
127
127
|
return (-1, None)
|
128
|
+
|
129
|
+
if static_dir is None:
|
130
|
+
raise RuntimeError(
|
131
|
+
"No packaged dashboard detected. The website will be served from the frontend directory."
|
132
|
+
)
|
133
|
+
|
128
134
|
pkg_frontend_candidates = [
|
129
135
|
Path(__file__).parent / "frontend", # inside package dir
|
130
136
|
Path(__file__).parent.parent / "frontend", # site-packages root
|
@@ -185,7 +191,7 @@ async def _run_server(args: Any) -> None:
|
|
185
191
|
config_dir = get_config_dir()
|
186
192
|
|
187
193
|
# Load config after setting env override
|
188
|
-
cfg = Config(
|
194
|
+
cfg = Config(get_config_json_path())
|
189
195
|
|
190
196
|
host = getattr(args, "host", None) or cfg.server.host
|
191
197
|
port = getattr(args, "port", None) or cfg.server.port
|
@@ -252,7 +252,20 @@ class Config:
|
|
252
252
|
}
|
253
253
|
|
254
254
|
# Ensure directory exists
|
255
|
-
|
255
|
+
try:
|
256
|
+
config_path.parent.mkdir(parents=True, exist_ok=True)
|
257
|
+
except FileExistsError as e:
|
258
|
+
# If the parent path exists as a file, not a directory, this will fail
|
259
|
+
if config_path.parent.is_file():
|
260
|
+
log.error(
|
261
|
+
f"Config directory path {config_path.parent} exists as a file, not a directory"
|
262
|
+
)
|
263
|
+
log.error("Please remove the file or specify a different config directory")
|
264
|
+
raise FileExistsError(
|
265
|
+
f"Config directory path {config_path.parent} exists as a file, not a directory"
|
266
|
+
) from e
|
267
|
+
log.error(f"Failed to create config directory {config_path.parent}: {e}")
|
268
|
+
raise
|
256
269
|
with open(config_path, "w") as f:
|
257
270
|
json.dump(data, f, indent=2)
|
258
271
|
|