open-edison 0.1.10__tar.gz → 0.1.15__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.10 → open_edison-0.1.15}/PKG-INFO +5 -2
- {open_edison-0.1.10 → open_edison-0.1.15}/README.md +1 -1
- {open_edison-0.1.10 → open_edison-0.1.15}/config.json +36 -0
- open_edison-0.1.15/prompt_permissions.json +15 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/pyproject.toml +4 -1
- open_edison-0.1.15/resource_permissions.json +15 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/src/cli.py +2 -2
- {open_edison-0.1.10 → open_edison-0.1.15}/src/config.py +53 -1
- open_edison-0.1.15/src/frontend_dist/assets/index-_NTxjOfh.js +51 -0
- open_edison-0.1.15/src/frontend_dist/assets/index-h6k8aL6h.css +1 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/src/frontend_dist/index.html +2 -2
- {open_edison-0.1.10 → open_edison-0.1.15}/src/middleware/data_access_tracker.py +224 -123
- {open_edison-0.1.10 → open_edison-0.1.15}/src/middleware/session_tracking.py +16 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/src/server.py +195 -7
- open_edison-0.1.15/src/telemetry.py +336 -0
- open_edison-0.1.15/tool_permissions.json +260 -0
- open_edison-0.1.10/src/frontend_dist/assets/index-CKkid2y-.js +0 -51
- open_edison-0.1.10/src/frontend_dist/assets/index-CRxojymD.css +0 -1
- {open_edison-0.1.10 → open_edison-0.1.15}/.gitignore +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/LICENSE +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/desktop_ext/README.md +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/docs/README.md +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/docs/architecture/single_user_design.md +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/docs/core/configuration.md +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/docs/core/project_structure.md +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/docs/core/proxy_usage.md +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/docs/deployment/docker.md +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/docs/deployment/local.md +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/docs/development/contributing.md +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/docs/development/development_guide.md +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/docs/development/testing.md +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/docs/quick-reference/api_reference.md +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/docs/quick-reference/config_quick_start.md +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15/frontend/configurations}/prompt_permissions.json +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15/frontend/configurations}/resource_permissions.json +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15/frontend/configurations}/tool_permissions.json +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/src/__init__.py +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/src/__main__.py +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/src/mcp_manager.py +0 -0
- {open_edison-0.1.10 → open_edison-0.1.15}/src/single_user_mcp.py +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.15
|
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
|
@@ -11,6 +11,9 @@ Requires-Dist: fastapi>=0.116.1
|
|
11
11
|
Requires-Dist: fastmcp>=2.10.5
|
12
12
|
Requires-Dist: httpx>=0.28.1
|
13
13
|
Requires-Dist: loguru>=0.7.3
|
14
|
+
Requires-Dist: opentelemetry-api>=1.36.0
|
15
|
+
Requires-Dist: opentelemetry-exporter-otlp>=1.36.0
|
16
|
+
Requires-Dist: opentelemetry-sdk>=1.36.0
|
14
17
|
Requires-Dist: python-dotenv>=1.0.1
|
15
18
|
Requires-Dist: pyyaml>=6.0.2
|
16
19
|
Requires-Dist: sqlalchemy>=2.0.41
|
@@ -111,7 +114,7 @@ The server will be available at `http://localhost:3000`.
|
|
111
114
|
|
112
115
|
```bash
|
113
116
|
# After cloning the repo
|
114
|
-
make
|
117
|
+
make docker_run
|
115
118
|
```
|
116
119
|
|
117
120
|
The MCP server will be available at `http://localhost:3000` and the api + frontend at `http://localhost:3001`.
|
@@ -87,7 +87,7 @@ The server will be available at `http://localhost:3000`.
|
|
87
87
|
|
88
88
|
```bash
|
89
89
|
# After cloning the repo
|
90
|
-
make
|
90
|
+
make docker_run
|
91
91
|
```
|
92
92
|
|
93
93
|
The MCP server will be available at `http://localhost:3000` and the api + frontend at `http://localhost:3001`.
|
@@ -54,6 +54,42 @@
|
|
54
54
|
"env": {},
|
55
55
|
"enabled": false,
|
56
56
|
"roots": []
|
57
|
+
},
|
58
|
+
{
|
59
|
+
"name": "supabase",
|
60
|
+
"command": "",
|
61
|
+
"args": [],
|
62
|
+
"env": {
|
63
|
+
"SUPABASE_URL": "https://your-supabase-url.supabase.co",
|
64
|
+
"SUPABASE_API_KEY": "your-supabase-api-key",
|
65
|
+
"SUPABASE_DATABASE": "your-database-name"
|
66
|
+
},
|
67
|
+
"enabled": false
|
68
|
+
},
|
69
|
+
{
|
70
|
+
"name": "google_drive",
|
71
|
+
"command": "npx",
|
72
|
+
"args": [
|
73
|
+
"-y",
|
74
|
+
"@modelcontextprotocol/server-gdrive"
|
75
|
+
],
|
76
|
+
"env": {
|
77
|
+
"GOOGLE_CLIENT_ID": "your-client-id",
|
78
|
+
"GOOGLE_CLIENT_SECRET": "your-client-secret",
|
79
|
+
"GOOGLE_REFRESH_TOKEN": "your-refresh-token"
|
80
|
+
},
|
81
|
+
"enabled": false
|
82
|
+
},
|
83
|
+
{
|
84
|
+
"name": "atlassian",
|
85
|
+
"command": "npx",
|
86
|
+
"args": [
|
87
|
+
"-y",
|
88
|
+
"mcp-remote",
|
89
|
+
"https://mcp.atlassian.com/v1/sse"
|
90
|
+
],
|
91
|
+
"env": {},
|
92
|
+
"enabled": false
|
57
93
|
}
|
58
94
|
]
|
59
95
|
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
{
|
2
|
+
"_metadata": {
|
3
|
+
"description": "Prompt security classifications for Open Edison data access tracker",
|
4
|
+
"last_updated": "2025-08-07"
|
5
|
+
},
|
6
|
+
"builtin": {
|
7
|
+
"summarize_text": {
|
8
|
+
"enabled": true,
|
9
|
+
"write_operation": false,
|
10
|
+
"read_private_data": false,
|
11
|
+
"read_untrusted_public_data": false
|
12
|
+
}
|
13
|
+
},
|
14
|
+
"sqlite": {}
|
15
|
+
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "open-edison"
|
3
|
-
version = "0.1.
|
3
|
+
version = "0.1.15"
|
4
4
|
description = "Open-source MCP security, aggregation, and monitoring. Single-user, self-hosted MCP proxy."
|
5
5
|
readme = "README.md"
|
6
6
|
authors = [
|
@@ -18,6 +18,9 @@ dependencies = [
|
|
18
18
|
"starlette>=0.47.1",
|
19
19
|
"sqlalchemy>=2.0.41",
|
20
20
|
"aiosqlite>=0.20.0",
|
21
|
+
"opentelemetry-api>=1.36.0",
|
22
|
+
"opentelemetry-sdk>=1.36.0",
|
23
|
+
"opentelemetry-exporter-otlp>=1.36.0",
|
21
24
|
]
|
22
25
|
requires-python = ">= 3.12"
|
23
26
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
{
|
2
|
+
"_metadata": {
|
3
|
+
"description": "Resource security classifications for Open Edison data access tracker",
|
4
|
+
"last_updated": "2025-08-07"
|
5
|
+
},
|
6
|
+
"builtin": {
|
7
|
+
"config://app": {
|
8
|
+
"enabled": true,
|
9
|
+
"write_operation": false,
|
10
|
+
"read_private_data": false,
|
11
|
+
"read_untrusted_public_data": false
|
12
|
+
}
|
13
|
+
},
|
14
|
+
"sqlite": {}
|
15
|
+
}
|
@@ -10,10 +10,10 @@ import argparse
|
|
10
10
|
import asyncio
|
11
11
|
import os
|
12
12
|
import subprocess as _subprocess
|
13
|
+
import sys
|
13
14
|
from contextlib import suppress
|
14
15
|
from pathlib import Path
|
15
16
|
from typing import Any, NoReturn, cast
|
16
|
-
import sys
|
17
17
|
|
18
18
|
from loguru import logger as _log # type: ignore[reportMissingImports]
|
19
19
|
|
@@ -218,7 +218,7 @@ def _run_website(port: int, website_dir: Path | None = None) -> int:
|
|
218
218
|
return 0 if proc is not None else 1
|
219
219
|
|
220
220
|
|
221
|
-
def main(argv: list[str] | None = None) -> NoReturn:
|
221
|
+
def main(argv: list[str] | None = None) -> NoReturn: # noqa: C901
|
222
222
|
args = _parse_args(argv)
|
223
223
|
|
224
224
|
if getattr(args, "command", None) == "website":
|
@@ -11,10 +11,13 @@ import sys
|
|
11
11
|
import tomllib
|
12
12
|
from dataclasses import asdict, dataclass
|
13
13
|
from pathlib import Path
|
14
|
-
from typing import Any
|
14
|
+
from typing import Any, cast
|
15
15
|
|
16
16
|
from loguru import logger as log
|
17
17
|
|
18
|
+
# Default OTLP metrics endpoint for central dev collector.
|
19
|
+
DEFAULT_OTLP_METRICS_ENDPOINT = "https://otel-collector-production-e7a6.up.railway.app/v1/metrics"
|
20
|
+
|
18
21
|
# Get the path to the repository/package root directory (module src/ parent)
|
19
22
|
root_dir = Path(__file__).parent.parent
|
20
23
|
|
@@ -121,6 +124,17 @@ class MCPServerConfig:
|
|
121
124
|
self.env = {}
|
122
125
|
|
123
126
|
|
127
|
+
@dataclass
|
128
|
+
class TelemetryConfig:
|
129
|
+
"""Telemetry configuration"""
|
130
|
+
|
131
|
+
enabled: bool = True
|
132
|
+
# If not provided, exporter may use environment variables or defaults
|
133
|
+
otlp_endpoint: str | None = None
|
134
|
+
headers: dict[str, str] | None = None
|
135
|
+
export_interval_ms: int = 60000
|
136
|
+
|
137
|
+
|
124
138
|
@dataclass
|
125
139
|
class Config:
|
126
140
|
"""Main configuration class"""
|
@@ -128,6 +142,7 @@ class Config:
|
|
128
142
|
server: ServerConfig
|
129
143
|
logging: LoggingConfig
|
130
144
|
mcp_servers: list[MCPServerConfig]
|
145
|
+
telemetry: TelemetryConfig | None = None
|
131
146
|
|
132
147
|
@property
|
133
148
|
def version(self) -> str:
|
@@ -171,6 +186,35 @@ class Config:
|
|
171
186
|
mcp_servers_data = data.get("mcp_servers", []) # type: ignore
|
172
187
|
server_data = data.get("server", {}) # type: ignore
|
173
188
|
logging_data = data.get("logging", {}) # type: ignore
|
189
|
+
telemetry_data_obj: object = data.get("telemetry", {})
|
190
|
+
|
191
|
+
# Parse telemetry config with explicit typing to satisfy strict type checker
|
192
|
+
td: dict[str, object] = {}
|
193
|
+
if isinstance(telemetry_data_obj, dict):
|
194
|
+
for k_any, v_any in cast(dict[Any, Any], telemetry_data_obj).items():
|
195
|
+
td[str(k_any)] = v_any
|
196
|
+
tel_enabled: bool = bool(td.get("enabled", True))
|
197
|
+
otlp_raw: object = td.get("otlp_endpoint")
|
198
|
+
otlp_endpoint: str | None = (
|
199
|
+
str(otlp_raw) if isinstance(otlp_raw, str) and otlp_raw else None
|
200
|
+
)
|
201
|
+
# If not provided in config, use our central dev collector by default
|
202
|
+
if not otlp_endpoint:
|
203
|
+
otlp_endpoint = DEFAULT_OTLP_METRICS_ENDPOINT
|
204
|
+
headers_val: object = td.get("headers")
|
205
|
+
headers_dict: dict[str, str] | None = None
|
206
|
+
if isinstance(headers_val, dict):
|
207
|
+
headers_dict = {}
|
208
|
+
for k_any, v_any in cast(dict[Any, Any], headers_val).items():
|
209
|
+
headers_dict[str(k_any)] = str(v_any)
|
210
|
+
interval_raw: object = td.get("export_interval_ms")
|
211
|
+
export_interval_ms: int = interval_raw if isinstance(interval_raw, int) else 60000
|
212
|
+
telemetry_cfg = TelemetryConfig(
|
213
|
+
enabled=tel_enabled,
|
214
|
+
otlp_endpoint=otlp_endpoint,
|
215
|
+
headers=headers_dict,
|
216
|
+
export_interval_ms=export_interval_ms,
|
217
|
+
)
|
174
218
|
|
175
219
|
return cls(
|
176
220
|
server=ServerConfig(**server_data), # type: ignore
|
@@ -179,6 +223,7 @@ class Config:
|
|
179
223
|
MCPServerConfig(**server_item) # type: ignore
|
180
224
|
for server_item in mcp_servers_data # type: ignore
|
181
225
|
],
|
226
|
+
telemetry=telemetry_cfg,
|
182
227
|
)
|
183
228
|
|
184
229
|
def save(self, config_path: Path | None = None) -> None:
|
@@ -194,6 +239,9 @@ class Config:
|
|
194
239
|
"server": asdict(self.server),
|
195
240
|
"logging": asdict(self.logging),
|
196
241
|
"mcp_servers": [asdict(server) for server in self.mcp_servers],
|
242
|
+
"telemetry": asdict(
|
243
|
+
self.telemetry if self.telemetry is not None else TelemetryConfig()
|
244
|
+
),
|
197
245
|
}
|
198
246
|
|
199
247
|
# Ensure directory exists
|
@@ -217,6 +265,10 @@ class Config:
|
|
217
265
|
enabled=False,
|
218
266
|
)
|
219
267
|
],
|
268
|
+
telemetry=TelemetryConfig(
|
269
|
+
enabled=True,
|
270
|
+
otlp_endpoint=DEFAULT_OTLP_METRICS_ENDPOINT,
|
271
|
+
),
|
220
272
|
)
|
221
273
|
|
222
274
|
|