synapse-sdk 1.0.0a11__py3-none-any.whl → 2026.1.1b2__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.

Potentially problematic release.


This version of synapse-sdk might be problematic. Click here for more details.

Files changed (261) hide show
  1. synapse_sdk/__init__.py +24 -0
  2. synapse_sdk/cli/__init__.py +9 -8
  3. synapse_sdk/cli/agent/__init__.py +25 -0
  4. synapse_sdk/cli/agent/config.py +104 -0
  5. synapse_sdk/cli/agent/select.py +197 -0
  6. synapse_sdk/cli/auth.py +104 -0
  7. synapse_sdk/cli/main.py +1025 -0
  8. synapse_sdk/cli/plugin/__init__.py +58 -0
  9. synapse_sdk/cli/plugin/create.py +566 -0
  10. synapse_sdk/cli/plugin/job.py +196 -0
  11. synapse_sdk/cli/plugin/publish.py +322 -0
  12. synapse_sdk/cli/plugin/run.py +131 -0
  13. synapse_sdk/cli/plugin/test.py +200 -0
  14. synapse_sdk/clients/README.md +239 -0
  15. synapse_sdk/clients/__init__.py +5 -0
  16. synapse_sdk/clients/_template.py +266 -0
  17. synapse_sdk/clients/agent/__init__.py +84 -29
  18. synapse_sdk/clients/agent/async_ray.py +289 -0
  19. synapse_sdk/clients/agent/container.py +83 -0
  20. synapse_sdk/clients/agent/plugin.py +101 -0
  21. synapse_sdk/clients/agent/ray.py +296 -39
  22. synapse_sdk/clients/backend/__init__.py +152 -12
  23. synapse_sdk/clients/backend/annotation.py +164 -22
  24. synapse_sdk/clients/backend/core.py +101 -0
  25. synapse_sdk/clients/backend/data_collection.py +292 -0
  26. synapse_sdk/clients/backend/hitl.py +87 -0
  27. synapse_sdk/clients/backend/integration.py +374 -46
  28. synapse_sdk/clients/backend/ml.py +134 -22
  29. synapse_sdk/clients/backend/models.py +247 -0
  30. synapse_sdk/clients/base.py +538 -59
  31. synapse_sdk/clients/exceptions.py +35 -7
  32. synapse_sdk/clients/pipeline/__init__.py +5 -0
  33. synapse_sdk/clients/pipeline/client.py +636 -0
  34. synapse_sdk/clients/protocols.py +178 -0
  35. synapse_sdk/clients/utils.py +86 -8
  36. synapse_sdk/clients/validation.py +58 -0
  37. synapse_sdk/enums.py +76 -0
  38. synapse_sdk/exceptions.py +168 -0
  39. synapse_sdk/integrations/__init__.py +74 -0
  40. synapse_sdk/integrations/_base.py +119 -0
  41. synapse_sdk/integrations/_context.py +53 -0
  42. synapse_sdk/integrations/ultralytics/__init__.py +78 -0
  43. synapse_sdk/integrations/ultralytics/_callbacks.py +126 -0
  44. synapse_sdk/integrations/ultralytics/_patches.py +124 -0
  45. synapse_sdk/loggers.py +476 -95
  46. synapse_sdk/mcp/MCP.md +69 -0
  47. synapse_sdk/mcp/__init__.py +48 -0
  48. synapse_sdk/mcp/__main__.py +6 -0
  49. synapse_sdk/mcp/config.py +349 -0
  50. synapse_sdk/mcp/prompts/__init__.py +4 -0
  51. synapse_sdk/mcp/resources/__init__.py +4 -0
  52. synapse_sdk/mcp/server.py +1352 -0
  53. synapse_sdk/mcp/tools/__init__.py +6 -0
  54. synapse_sdk/plugins/__init__.py +133 -9
  55. synapse_sdk/plugins/action.py +229 -0
  56. synapse_sdk/plugins/actions/__init__.py +82 -0
  57. synapse_sdk/plugins/actions/dataset/__init__.py +37 -0
  58. synapse_sdk/plugins/actions/dataset/action.py +471 -0
  59. synapse_sdk/plugins/actions/export/__init__.py +55 -0
  60. synapse_sdk/plugins/actions/export/action.py +183 -0
  61. synapse_sdk/plugins/actions/export/context.py +59 -0
  62. synapse_sdk/plugins/actions/inference/__init__.py +84 -0
  63. synapse_sdk/plugins/actions/inference/action.py +285 -0
  64. synapse_sdk/plugins/actions/inference/context.py +81 -0
  65. synapse_sdk/plugins/actions/inference/deployment.py +322 -0
  66. synapse_sdk/plugins/actions/inference/serve.py +252 -0
  67. synapse_sdk/plugins/actions/train/__init__.py +54 -0
  68. synapse_sdk/plugins/actions/train/action.py +326 -0
  69. synapse_sdk/plugins/actions/train/context.py +57 -0
  70. synapse_sdk/plugins/actions/upload/__init__.py +49 -0
  71. synapse_sdk/plugins/actions/upload/action.py +165 -0
  72. synapse_sdk/plugins/actions/upload/context.py +61 -0
  73. synapse_sdk/plugins/config.py +98 -0
  74. synapse_sdk/plugins/context/__init__.py +109 -0
  75. synapse_sdk/plugins/context/env.py +113 -0
  76. synapse_sdk/plugins/datasets/__init__.py +113 -0
  77. synapse_sdk/plugins/datasets/converters/__init__.py +76 -0
  78. synapse_sdk/plugins/datasets/converters/base.py +347 -0
  79. synapse_sdk/plugins/datasets/converters/yolo/__init__.py +9 -0
  80. synapse_sdk/plugins/datasets/converters/yolo/from_dm.py +468 -0
  81. synapse_sdk/plugins/datasets/converters/yolo/to_dm.py +381 -0
  82. synapse_sdk/plugins/datasets/formats/__init__.py +82 -0
  83. synapse_sdk/plugins/datasets/formats/dm.py +351 -0
  84. synapse_sdk/plugins/datasets/formats/yolo.py +240 -0
  85. synapse_sdk/plugins/decorators.py +83 -0
  86. synapse_sdk/plugins/discovery.py +790 -0
  87. synapse_sdk/plugins/docs/ACTION_DEV_GUIDE.md +933 -0
  88. synapse_sdk/plugins/docs/ARCHITECTURE.md +1225 -0
  89. synapse_sdk/plugins/docs/LOGGING_SYSTEM.md +683 -0
  90. synapse_sdk/plugins/docs/OVERVIEW.md +531 -0
  91. synapse_sdk/plugins/docs/PIPELINE_GUIDE.md +145 -0
  92. synapse_sdk/plugins/docs/README.md +513 -0
  93. synapse_sdk/plugins/docs/STEP.md +656 -0
  94. synapse_sdk/plugins/enums.py +70 -10
  95. synapse_sdk/plugins/errors.py +92 -0
  96. synapse_sdk/plugins/executors/__init__.py +43 -0
  97. synapse_sdk/plugins/executors/local.py +99 -0
  98. synapse_sdk/plugins/executors/ray/__init__.py +18 -0
  99. synapse_sdk/plugins/executors/ray/base.py +282 -0
  100. synapse_sdk/plugins/executors/ray/job.py +298 -0
  101. synapse_sdk/plugins/executors/ray/jobs_api.py +511 -0
  102. synapse_sdk/plugins/executors/ray/packaging.py +137 -0
  103. synapse_sdk/plugins/executors/ray/pipeline.py +792 -0
  104. synapse_sdk/plugins/executors/ray/task.py +257 -0
  105. synapse_sdk/plugins/models/__init__.py +26 -0
  106. synapse_sdk/plugins/models/logger.py +173 -0
  107. synapse_sdk/plugins/models/pipeline.py +25 -0
  108. synapse_sdk/plugins/pipelines/__init__.py +81 -0
  109. synapse_sdk/plugins/pipelines/action_pipeline.py +417 -0
  110. synapse_sdk/plugins/pipelines/context.py +107 -0
  111. synapse_sdk/plugins/pipelines/display.py +311 -0
  112. synapse_sdk/plugins/runner.py +114 -0
  113. synapse_sdk/plugins/schemas/__init__.py +19 -0
  114. synapse_sdk/plugins/schemas/results.py +152 -0
  115. synapse_sdk/plugins/steps/__init__.py +63 -0
  116. synapse_sdk/plugins/steps/base.py +128 -0
  117. synapse_sdk/plugins/steps/context.py +90 -0
  118. synapse_sdk/plugins/steps/orchestrator.py +128 -0
  119. synapse_sdk/plugins/steps/registry.py +103 -0
  120. synapse_sdk/plugins/steps/utils/__init__.py +20 -0
  121. synapse_sdk/plugins/steps/utils/logging.py +85 -0
  122. synapse_sdk/plugins/steps/utils/timing.py +71 -0
  123. synapse_sdk/plugins/steps/utils/validation.py +68 -0
  124. synapse_sdk/plugins/templates/__init__.py +50 -0
  125. synapse_sdk/plugins/templates/base/.gitignore.j2 +26 -0
  126. synapse_sdk/plugins/templates/base/.synapseignore.j2 +11 -0
  127. synapse_sdk/plugins/templates/base/README.md.j2 +26 -0
  128. synapse_sdk/plugins/templates/base/plugin/__init__.py.j2 +1 -0
  129. synapse_sdk/plugins/templates/base/pyproject.toml.j2 +14 -0
  130. synapse_sdk/plugins/templates/base/requirements.txt.j2 +1 -0
  131. synapse_sdk/plugins/templates/custom/plugin/main.py.j2 +18 -0
  132. synapse_sdk/plugins/templates/data_validation/plugin/validate.py.j2 +32 -0
  133. synapse_sdk/plugins/templates/export/plugin/export.py.j2 +36 -0
  134. synapse_sdk/plugins/templates/neural_net/plugin/inference.py.j2 +36 -0
  135. synapse_sdk/plugins/templates/neural_net/plugin/train.py.j2 +33 -0
  136. synapse_sdk/plugins/templates/post_annotation/plugin/post_annotate.py.j2 +32 -0
  137. synapse_sdk/plugins/templates/pre_annotation/plugin/pre_annotate.py.j2 +32 -0
  138. synapse_sdk/plugins/templates/smart_tool/plugin/auto_label.py.j2 +44 -0
  139. synapse_sdk/plugins/templates/upload/plugin/upload.py.j2 +35 -0
  140. synapse_sdk/plugins/testing/__init__.py +25 -0
  141. synapse_sdk/plugins/testing/sample_actions.py +98 -0
  142. synapse_sdk/plugins/types.py +206 -0
  143. synapse_sdk/plugins/upload.py +595 -64
  144. synapse_sdk/plugins/utils.py +325 -37
  145. synapse_sdk/shared/__init__.py +25 -0
  146. synapse_sdk/utils/__init__.py +1 -0
  147. synapse_sdk/utils/auth.py +74 -0
  148. synapse_sdk/utils/file/__init__.py +58 -0
  149. synapse_sdk/utils/file/archive.py +449 -0
  150. synapse_sdk/utils/file/checksum.py +167 -0
  151. synapse_sdk/utils/file/download.py +286 -0
  152. synapse_sdk/utils/file/io.py +129 -0
  153. synapse_sdk/utils/file/requirements.py +36 -0
  154. synapse_sdk/utils/network.py +168 -0
  155. synapse_sdk/utils/storage/__init__.py +238 -0
  156. synapse_sdk/utils/storage/config.py +188 -0
  157. synapse_sdk/utils/storage/errors.py +52 -0
  158. synapse_sdk/utils/storage/providers/__init__.py +13 -0
  159. synapse_sdk/utils/storage/providers/base.py +76 -0
  160. synapse_sdk/utils/storage/providers/gcs.py +168 -0
  161. synapse_sdk/utils/storage/providers/http.py +250 -0
  162. synapse_sdk/utils/storage/providers/local.py +126 -0
  163. synapse_sdk/utils/storage/providers/s3.py +177 -0
  164. synapse_sdk/utils/storage/providers/sftp.py +208 -0
  165. synapse_sdk/utils/storage/registry.py +125 -0
  166. synapse_sdk/utils/websocket.py +99 -0
  167. synapse_sdk-2026.1.1b2.dist-info/METADATA +715 -0
  168. synapse_sdk-2026.1.1b2.dist-info/RECORD +172 -0
  169. {synapse_sdk-1.0.0a11.dist-info → synapse_sdk-2026.1.1b2.dist-info}/WHEEL +1 -1
  170. synapse_sdk-2026.1.1b2.dist-info/licenses/LICENSE +201 -0
  171. locale/en/LC_MESSAGES/messages.mo +0 -0
  172. locale/en/LC_MESSAGES/messages.po +0 -39
  173. locale/ko/LC_MESSAGES/messages.mo +0 -0
  174. locale/ko/LC_MESSAGES/messages.po +0 -34
  175. synapse_sdk/cli/create_plugin.py +0 -10
  176. synapse_sdk/clients/agent/core.py +0 -7
  177. synapse_sdk/clients/agent/service.py +0 -15
  178. synapse_sdk/clients/backend/dataset.py +0 -51
  179. synapse_sdk/clients/ray/__init__.py +0 -6
  180. synapse_sdk/clients/ray/core.py +0 -22
  181. synapse_sdk/clients/ray/serve.py +0 -20
  182. synapse_sdk/i18n.py +0 -35
  183. synapse_sdk/plugins/categories/__init__.py +0 -0
  184. synapse_sdk/plugins/categories/base.py +0 -235
  185. synapse_sdk/plugins/categories/data_validation/__init__.py +0 -0
  186. synapse_sdk/plugins/categories/data_validation/actions/__init__.py +0 -0
  187. synapse_sdk/plugins/categories/data_validation/actions/validation.py +0 -10
  188. synapse_sdk/plugins/categories/data_validation/templates/config.yaml +0 -3
  189. synapse_sdk/plugins/categories/data_validation/templates/plugin/__init__.py +0 -0
  190. synapse_sdk/plugins/categories/data_validation/templates/plugin/validation.py +0 -5
  191. synapse_sdk/plugins/categories/decorators.py +0 -13
  192. synapse_sdk/plugins/categories/export/__init__.py +0 -0
  193. synapse_sdk/plugins/categories/export/actions/__init__.py +0 -0
  194. synapse_sdk/plugins/categories/export/actions/export.py +0 -10
  195. synapse_sdk/plugins/categories/import/__init__.py +0 -0
  196. synapse_sdk/plugins/categories/import/actions/__init__.py +0 -0
  197. synapse_sdk/plugins/categories/import/actions/import.py +0 -10
  198. synapse_sdk/plugins/categories/neural_net/__init__.py +0 -0
  199. synapse_sdk/plugins/categories/neural_net/actions/__init__.py +0 -0
  200. synapse_sdk/plugins/categories/neural_net/actions/deployment.py +0 -45
  201. synapse_sdk/plugins/categories/neural_net/actions/inference.py +0 -18
  202. synapse_sdk/plugins/categories/neural_net/actions/test.py +0 -10
  203. synapse_sdk/plugins/categories/neural_net/actions/train.py +0 -143
  204. synapse_sdk/plugins/categories/neural_net/templates/config.yaml +0 -12
  205. synapse_sdk/plugins/categories/neural_net/templates/plugin/__init__.py +0 -0
  206. synapse_sdk/plugins/categories/neural_net/templates/plugin/inference.py +0 -4
  207. synapse_sdk/plugins/categories/neural_net/templates/plugin/test.py +0 -2
  208. synapse_sdk/plugins/categories/neural_net/templates/plugin/train.py +0 -14
  209. synapse_sdk/plugins/categories/post_annotation/__init__.py +0 -0
  210. synapse_sdk/plugins/categories/post_annotation/actions/__init__.py +0 -0
  211. synapse_sdk/plugins/categories/post_annotation/actions/post_annotation.py +0 -10
  212. synapse_sdk/plugins/categories/post_annotation/templates/config.yaml +0 -3
  213. synapse_sdk/plugins/categories/post_annotation/templates/plugin/__init__.py +0 -0
  214. synapse_sdk/plugins/categories/post_annotation/templates/plugin/post_annotation.py +0 -3
  215. synapse_sdk/plugins/categories/pre_annotation/__init__.py +0 -0
  216. synapse_sdk/plugins/categories/pre_annotation/actions/__init__.py +0 -0
  217. synapse_sdk/plugins/categories/pre_annotation/actions/pre_annotation.py +0 -10
  218. synapse_sdk/plugins/categories/pre_annotation/templates/config.yaml +0 -3
  219. synapse_sdk/plugins/categories/pre_annotation/templates/plugin/__init__.py +0 -0
  220. synapse_sdk/plugins/categories/pre_annotation/templates/plugin/pre_annotation.py +0 -3
  221. synapse_sdk/plugins/categories/registry.py +0 -16
  222. synapse_sdk/plugins/categories/smart_tool/__init__.py +0 -0
  223. synapse_sdk/plugins/categories/smart_tool/actions/__init__.py +0 -0
  224. synapse_sdk/plugins/categories/smart_tool/actions/auto_label.py +0 -37
  225. synapse_sdk/plugins/categories/smart_tool/templates/config.yaml +0 -7
  226. synapse_sdk/plugins/categories/smart_tool/templates/plugin/__init__.py +0 -0
  227. synapse_sdk/plugins/categories/smart_tool/templates/plugin/auto_label.py +0 -11
  228. synapse_sdk/plugins/categories/templates.py +0 -32
  229. synapse_sdk/plugins/cli/__init__.py +0 -21
  230. synapse_sdk/plugins/cli/publish.py +0 -37
  231. synapse_sdk/plugins/cli/run.py +0 -67
  232. synapse_sdk/plugins/exceptions.py +0 -22
  233. synapse_sdk/plugins/models.py +0 -121
  234. synapse_sdk/plugins/templates/cookiecutter.json +0 -11
  235. synapse_sdk/plugins/templates/hooks/post_gen_project.py +0 -3
  236. synapse_sdk/plugins/templates/hooks/pre_prompt.py +0 -21
  237. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.env +0 -24
  238. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.env.dist +0 -24
  239. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.gitignore +0 -27
  240. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.pre-commit-config.yaml +0 -7
  241. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/README.md +0 -5
  242. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/config.yaml +0 -6
  243. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/main.py +0 -4
  244. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/plugin/__init__.py +0 -0
  245. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/pyproject.toml +0 -13
  246. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/requirements.txt +0 -1
  247. synapse_sdk/shared/enums.py +0 -8
  248. synapse_sdk/utils/debug.py +0 -5
  249. synapse_sdk/utils/file.py +0 -87
  250. synapse_sdk/utils/module_loading.py +0 -29
  251. synapse_sdk/utils/pydantic/__init__.py +0 -0
  252. synapse_sdk/utils/pydantic/config.py +0 -4
  253. synapse_sdk/utils/pydantic/errors.py +0 -33
  254. synapse_sdk/utils/pydantic/validators.py +0 -7
  255. synapse_sdk/utils/storage.py +0 -91
  256. synapse_sdk/utils/string.py +0 -11
  257. synapse_sdk-1.0.0a11.dist-info/LICENSE +0 -21
  258. synapse_sdk-1.0.0a11.dist-info/METADATA +0 -43
  259. synapse_sdk-1.0.0a11.dist-info/RECORD +0 -111
  260. {synapse_sdk-1.0.0a11.dist-info → synapse_sdk-2026.1.1b2.dist-info}/entry_points.txt +0 -0
  261. {synapse_sdk-1.0.0a11.dist-info → synapse_sdk-2026.1.1b2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,48 @@
1
+ """Synapse SDK MCP Server.
2
+
3
+ This module provides an MCP (Model Context Protocol) server that enables
4
+ AI assistants to interact with Synapse infrastructure for plugin development,
5
+ execution, debugging, and deployment.
6
+
7
+ Usage:
8
+ # Initialize config (uses existing ~/.synapse/credentials if available)
9
+ synapse mcp init
10
+
11
+ # Run via CLI
12
+ synapse mcp serve
13
+
14
+ # Or run directly
15
+ python -m synapse_sdk.mcp
16
+
17
+ # Cursor: Add to ~/.cursor/mcp.json:
18
+ {
19
+ "mcpServers": {
20
+ "synapse": {
21
+ "command": "uvx",
22
+ "args": ["--from", "synapse-sdk[mcp]", "synapse", "mcp", "serve"]
23
+ }
24
+ }
25
+ }
26
+
27
+ # Claude Code:
28
+ claude mcp add synapse -- uvx --from 'synapse-sdk[mcp]' synapse mcp serve
29
+
30
+ Configuration (~/.synapse/config.yaml):
31
+ default_environment: profile_1
32
+
33
+ environments:
34
+ profile_1:
35
+ backend_url: https://api.synapse.sh
36
+ access_token: your-token
37
+ """
38
+
39
+ from synapse_sdk.mcp.config import ConfigManager, EnvironmentConfig, get_config_manager
40
+ from synapse_sdk.mcp.server import mcp, serve
41
+
42
+ __all__ = [
43
+ 'mcp',
44
+ 'serve',
45
+ 'ConfigManager',
46
+ 'EnvironmentConfig',
47
+ 'get_config_manager',
48
+ ]
@@ -0,0 +1,6 @@
1
+ """Allow running the MCP server as a module: python -m synapse_sdk.mcp"""
2
+
3
+ from synapse_sdk.mcp.server import serve
4
+
5
+ if __name__ == '__main__':
6
+ serve()
@@ -0,0 +1,349 @@
1
+ """MCP Server configuration and environment management."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import sys
7
+ from dataclasses import dataclass, field
8
+ from pathlib import Path
9
+ from typing import Any
10
+
11
+
12
+ @dataclass
13
+ class EnvironmentConfig:
14
+ """Configuration for a single environment."""
15
+
16
+ name: str
17
+ backend_url: str | None = None
18
+ access_token: str | None = None
19
+ tenant: str | None = None
20
+ # Agent info is fetched from backend, but cached here after selection
21
+ agent_id: int | None = None
22
+ agent_name: str | None = None
23
+ agent_url: str | None = None
24
+ agent_token: str | None = None
25
+ plugin_paths: list[str] = field(default_factory=list)
26
+
27
+ def has_backend(self) -> bool:
28
+ """Check if backend is configured."""
29
+ return bool(self.backend_url and self.access_token)
30
+
31
+ def has_agent(self) -> bool:
32
+ """Check if agent is configured."""
33
+ return bool(self.agent_url and self.agent_token)
34
+
35
+ def to_dict(self, include_secrets: bool = False) -> dict[str, Any]:
36
+ """Convert to dictionary, optionally hiding secrets."""
37
+ result = {
38
+ 'name': self.name,
39
+ 'backend_url': self.backend_url,
40
+ 'tenant': self.tenant,
41
+ 'agent_id': self.agent_id,
42
+ 'agent_name': self.agent_name,
43
+ 'agent_url': self.agent_url,
44
+ 'plugin_paths': self.plugin_paths,
45
+ 'has_backend': self.has_backend(),
46
+ 'has_agent': self.has_agent(),
47
+ }
48
+ if include_secrets:
49
+ result['access_token'] = self.access_token
50
+ result['agent_token'] = self.agent_token
51
+ else:
52
+ result['access_token'] = '***' if self.access_token else None
53
+ result['agent_token'] = '***' if self.agent_token else None
54
+ return result
55
+
56
+
57
+ class ConfigManager:
58
+ """Manages MCP server configuration and environment switching."""
59
+
60
+ DEFAULT_CONFIG_PATH = Path.home() / '.synapse' / 'config.json'
61
+
62
+ def __init__(self, config_path: Path | str | None = None):
63
+ self.config_path = Path(config_path) if config_path else self.DEFAULT_CONFIG_PATH
64
+ self._environments: dict[str, EnvironmentConfig] = {}
65
+ self._default_env: str | None = None
66
+ self._active_env: str | None = None
67
+ self._backend_client: Any = None
68
+ self._agent_client: Any = None
69
+ self._load_config()
70
+
71
+ def _load_config(self) -> None:
72
+ """Load configuration from JSON file."""
73
+ if not self.config_path.exists():
74
+ self._log(f'Config file not found: {self.config_path}')
75
+ return
76
+
77
+ try:
78
+ with open(self.config_path) as f:
79
+ data = json.load(f) or {}
80
+
81
+ self._default_env = data.get('default_environment')
82
+
83
+ for name, env_data in data.get('environments', {}).items():
84
+ if env_data is None:
85
+ env_data = {}
86
+ self._environments[name] = EnvironmentConfig(
87
+ name=name,
88
+ backend_url=env_data.get('backend_url'),
89
+ access_token=env_data.get('access_token'),
90
+ tenant=env_data.get('tenant'),
91
+ agent_id=env_data.get('agent_id'),
92
+ agent_name=env_data.get('agent_name'),
93
+ agent_url=env_data.get('agent_url'),
94
+ agent_token=env_data.get('agent_token'),
95
+ plugin_paths=env_data.get('plugin_paths', []),
96
+ )
97
+
98
+ # Set active environment to default
99
+ if self._default_env and self._default_env in self._environments:
100
+ self._active_env = self._default_env
101
+
102
+ self._log(f'Loaded {len(self._environments)} environments from {self.config_path}')
103
+
104
+ except Exception as e:
105
+ self._log(f'Error loading config: {e}')
106
+
107
+ def _save_config(self) -> None:
108
+ """Save current configuration to JSON file."""
109
+ data = {
110
+ 'default_environment': self._default_env,
111
+ 'environments': {},
112
+ }
113
+
114
+ for name, env in self._environments.items():
115
+ env_data: dict[str, Any] = {}
116
+ if env.backend_url:
117
+ env_data['backend_url'] = env.backend_url
118
+ if env.access_token:
119
+ env_data['access_token'] = env.access_token
120
+ if env.tenant:
121
+ env_data['tenant'] = env.tenant
122
+ if env.agent_id:
123
+ env_data['agent_id'] = env.agent_id
124
+ if env.agent_name:
125
+ env_data['agent_name'] = env.agent_name
126
+ if env.agent_url:
127
+ env_data['agent_url'] = env.agent_url
128
+ if env.agent_token:
129
+ env_data['agent_token'] = env.agent_token
130
+ if env.plugin_paths:
131
+ env_data['plugin_paths'] = env.plugin_paths
132
+ data['environments'][name] = env_data
133
+
134
+ # Ensure directory exists
135
+ self.config_path.parent.mkdir(parents=True, exist_ok=True)
136
+
137
+ with open(self.config_path, 'w') as f:
138
+ json.dump(data, f, indent=2)
139
+
140
+ # Set restrictive permissions (owner read/write only)
141
+ self.config_path.chmod(0o600)
142
+
143
+ def _log(self, message: str) -> None:
144
+ """Log to stderr (safe for MCP STDIO transport)."""
145
+ print(f'[synapse-mcp] {message}', file=sys.stderr)
146
+
147
+ def _clear_clients(self) -> None:
148
+ """Clear cached client instances."""
149
+ self._backend_client = None
150
+ self._agent_client = None
151
+
152
+ # Environment management
153
+
154
+ def list_environments(self) -> list[str]:
155
+ """List all configured environment names."""
156
+ return list(self._environments.keys())
157
+
158
+ def get_environment(self, name: str) -> EnvironmentConfig | None:
159
+ """Get environment configuration by name."""
160
+ return self._environments.get(name)
161
+
162
+ def get_active_environment(self) -> EnvironmentConfig | None:
163
+ """Get the currently active environment."""
164
+ if self._active_env:
165
+ return self._environments.get(self._active_env)
166
+ return None
167
+
168
+ def get_active_environment_name(self) -> str | None:
169
+ """Get the name of the currently active environment."""
170
+ return self._active_env
171
+
172
+ def set_active_environment(self, name: str) -> bool:
173
+ """Set the active environment by name."""
174
+ if name not in self._environments:
175
+ return False
176
+ self._active_env = name
177
+ self._clear_clients()
178
+ self._log(f'Switched to environment: {name}')
179
+ return True
180
+
181
+ def add_environment(
182
+ self,
183
+ name: str,
184
+ backend_url: str | None = None,
185
+ access_token: str | None = None,
186
+ tenant: str | None = None,
187
+ plugin_paths: list[str] | None = None,
188
+ set_as_default: bool = False,
189
+ ) -> EnvironmentConfig:
190
+ """Add or update an environment configuration.
191
+
192
+ Note: Agent is configured separately via set_agent() after fetching from backend.
193
+ """
194
+ # Preserve existing agent config if updating
195
+ existing = self._environments.get(name)
196
+ env = EnvironmentConfig(
197
+ name=name,
198
+ backend_url=backend_url,
199
+ access_token=access_token,
200
+ tenant=tenant,
201
+ agent_id=existing.agent_id if existing else None,
202
+ agent_name=existing.agent_name if existing else None,
203
+ agent_url=existing.agent_url if existing else None,
204
+ agent_token=existing.agent_token if existing else None,
205
+ plugin_paths=plugin_paths or [],
206
+ )
207
+ self._environments[name] = env
208
+
209
+ if set_as_default or not self._default_env:
210
+ self._default_env = name
211
+
212
+ if not self._active_env:
213
+ self._active_env = name
214
+
215
+ self._save_config()
216
+ self._log(f'Added environment: {name}')
217
+ return env
218
+
219
+ def set_agent(
220
+ self,
221
+ agent_id: int,
222
+ agent_name: str | None = None,
223
+ agent_url: str | None = None,
224
+ agent_token: str | None = None,
225
+ ) -> bool:
226
+ """Set the agent for the active environment.
227
+
228
+ Args:
229
+ agent_id: Agent ID from backend
230
+ agent_name: Agent name
231
+ agent_url: Agent URL
232
+ agent_token: Agent authentication token
233
+
234
+ Returns:
235
+ True if successful, False if no active environment
236
+ """
237
+ env = self.get_active_environment()
238
+ if not env:
239
+ return False
240
+
241
+ env.agent_id = agent_id
242
+ env.agent_name = agent_name
243
+ env.agent_url = agent_url
244
+ env.agent_token = agent_token
245
+ self._clear_clients()
246
+ self._save_config()
247
+ self._log(f'Set agent {agent_id} ({agent_name}) for environment: {env.name}')
248
+ return True
249
+
250
+ def clear_agent(self) -> bool:
251
+ """Clear the agent for the active environment."""
252
+ env = self.get_active_environment()
253
+ if not env:
254
+ return False
255
+
256
+ env.agent_id = None
257
+ env.agent_name = None
258
+ env.agent_url = None
259
+ env.agent_token = None
260
+ self._clear_clients()
261
+ self._save_config()
262
+ self._log(f'Cleared agent for environment: {env.name}')
263
+ return True
264
+
265
+ def remove_environment(self, name: str) -> bool:
266
+ """Remove an environment configuration."""
267
+ if name not in self._environments:
268
+ return False
269
+
270
+ del self._environments[name]
271
+
272
+ if self._default_env == name:
273
+ self._default_env = next(iter(self._environments), None)
274
+
275
+ if self._active_env == name:
276
+ self._active_env = self._default_env
277
+ self._clear_clients()
278
+
279
+ self._save_config()
280
+ self._log(f'Removed environment: {name}')
281
+ return True
282
+
283
+ # Client access
284
+
285
+ def get_backend_client(self):
286
+ """Get BackendClient for the active environment."""
287
+ env = self.get_active_environment()
288
+ if not env or not env.has_backend():
289
+ return None
290
+
291
+ if self._backend_client is None:
292
+ from synapse_sdk.clients.backend import BackendClient
293
+
294
+ self._backend_client = BackendClient(
295
+ base_url=env.backend_url,
296
+ access_token=env.access_token,
297
+ tenant=env.tenant,
298
+ )
299
+
300
+ return self._backend_client
301
+
302
+ def get_agent_client(self):
303
+ """Get AgentClient for the active environment."""
304
+ env = self.get_active_environment()
305
+ if not env or not env.has_agent():
306
+ return None
307
+
308
+ if self._agent_client is None:
309
+ from synapse_sdk.clients import AgentClient
310
+
311
+ self._agent_client = AgentClient(
312
+ base_url=env.agent_url,
313
+ agent_token=env.agent_token,
314
+ tenant=env.tenant,
315
+ )
316
+
317
+ return self._agent_client
318
+
319
+ # Status
320
+
321
+ def get_status(self) -> dict[str, Any]:
322
+ """Get current configuration status."""
323
+ env = self.get_active_environment()
324
+ return {
325
+ 'config_path': str(self.config_path),
326
+ 'config_exists': self.config_path.exists(),
327
+ 'environments': self.list_environments(),
328
+ 'default_environment': self._default_env,
329
+ 'active_environment': self._active_env,
330
+ 'active_env_details': env.to_dict() if env else None,
331
+ }
332
+
333
+
334
+ # Global config manager instance
335
+ _config_manager: ConfigManager | None = None
336
+
337
+
338
+ def get_config_manager() -> ConfigManager:
339
+ """Get the global ConfigManager instance."""
340
+ global _config_manager
341
+ if _config_manager is None:
342
+ _config_manager = ConfigManager()
343
+ return _config_manager
344
+
345
+
346
+ def reset_config_manager() -> None:
347
+ """Reset the global ConfigManager instance (for testing)."""
348
+ global _config_manager
349
+ _config_manager = None
@@ -0,0 +1,4 @@
1
+ """MCP Prompts for Synapse SDK.
2
+
3
+ Prompts provide workflow templates for common tasks.
4
+ """
@@ -0,0 +1,4 @@
1
+ """MCP Resources for Synapse SDK.
2
+
3
+ Resources provide read-only access to configuration and plugin schemas.
4
+ """