ssot-mcp 0.1.2.dev1__tar.gz → 0.1.3.dev1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ssot-mcp
3
- Version: 0.1.2.dev1
3
+ Version: 0.1.3.dev1
4
4
  Summary: MCP server for optional SSOT pull-worker control-plane coordination.
5
5
  Author-email: Jacob Stewart <jacob@swarmauri.com>
6
6
  License-Expression: Apache-2.0
@@ -28,7 +28,7 @@ Classifier: Topic :: Utilities
28
28
  Requires-Python: <3.15,>=3.10
29
29
  Description-Content-Type: text/markdown
30
30
  Requires-Dist: mcp>=1.0
31
- Requires-Dist: ssot-core<0.3.0,>=0.2.20.dev1
31
+ Requires-Dist: ssot-core<0.3.0,>=0.2.21.dev1
32
32
 
33
33
  <div align="center">
34
34
  <h1>ssot-mcp</h1>
@@ -122,8 +122,9 @@ Workers and MCP clients should not hand-edit `.ssot/registry.json`. When a clien
122
122
  - `registry_entity_unlink`
123
123
  - `get_ssot_cli_surface`
124
124
  - `run_ssot_cli`
125
+ - mirrored `ssot_cli__*` tools for each live CLI command path
125
126
 
126
- The structured entity tools use the same core registry mutation APIs as the CLI, validate before saving, and emit `registry_updated` events. `run_ssot_cli` delegates to the repo-local CLI parser in process and supports global flags, help/version requests, commands, subcommands, command flags, and subcommand flags as argv tokens.
127
+ The structured entity tools use the same core registry mutation APIs as the CLI, validate before saving, and emit `registry_updated` events. `get_ssot_cli_surface` exposes the live parser inventory, `run_ssot_cli` remains the generic delegation fallback, and `ssot-mcp` also registers mirrored `ssot_cli__*` MCP tools for every current CLI command path. Together they keep the CLI and MCP surfaces aligned across global flags, help/version requests, commands, subcommands, command flags, and subcommand flags.
127
128
 
128
129
  ## Pull-worker campaign model
129
130
 
@@ -90,8 +90,9 @@ Workers and MCP clients should not hand-edit `.ssot/registry.json`. When a clien
90
90
  - `registry_entity_unlink`
91
91
  - `get_ssot_cli_surface`
92
92
  - `run_ssot_cli`
93
+ - mirrored `ssot_cli__*` tools for each live CLI command path
93
94
 
94
- The structured entity tools use the same core registry mutation APIs as the CLI, validate before saving, and emit `registry_updated` events. `run_ssot_cli` delegates to the repo-local CLI parser in process and supports global flags, help/version requests, commands, subcommands, command flags, and subcommand flags as argv tokens.
95
+ The structured entity tools use the same core registry mutation APIs as the CLI, validate before saving, and emit `registry_updated` events. `get_ssot_cli_surface` exposes the live parser inventory, `run_ssot_cli` remains the generic delegation fallback, and `ssot-mcp` also registers mirrored `ssot_cli__*` MCP tools for every current CLI command path. Together they keep the CLI and MCP surfaces aligned across global flags, help/version requests, commands, subcommands, command flags, and subcommand flags.
95
96
 
96
97
  ## Pull-worker campaign model
97
98
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ssot-mcp"
7
- version = "0.1.2.dev1"
7
+ version = "0.1.3.dev1"
8
8
  description = "MCP server for optional SSOT pull-worker control-plane coordination."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10,<3.15"
@@ -12,7 +12,7 @@ license = "Apache-2.0"
12
12
  authors = [{ name = "Jacob Stewart", email = "jacob@swarmauri.com" }]
13
13
  dependencies = [
14
14
  "mcp>=1.0",
15
- "ssot-core>=0.2.20.dev1,<0.3.0",
15
+ "ssot-core>=0.2.21.dev1,<0.3.0",
16
16
  ]
17
17
  keywords = ["ssot", "mcp", "model-context-protocol", "codex", "workers", "leases", "control-plane", "registry", "developer-tools", "automation"]
18
18
  classifiers = [
@@ -6,6 +6,56 @@ from typing import Any
6
6
  from . import resources, tools
7
7
 
8
8
 
9
+ def _make_cli_mirror_tool(path: str):
10
+ prefix = path.split()
11
+
12
+ def cli_mirror_tool(
13
+ repo: str | None = None,
14
+ global_args: list[str] | None = None,
15
+ args: list[str] | None = None,
16
+ ) -> dict[str, Any]:
17
+ """Run one fixed ssot-registry command path through MCP.
18
+
19
+ `global_args` are inserted before the fixed command path so callers can
20
+ supply root-level flags such as `--output-format`.
21
+ `args` are appended after the fixed command path for command and
22
+ subcommand flags plus positional arguments.
23
+ """
24
+
25
+ argv: list[str] = []
26
+ if global_args:
27
+ argv.extend(global_args)
28
+ argv.extend(prefix)
29
+ if args:
30
+ argv.extend(args)
31
+ return tools.run_ssot_cli(repo=repo, args=argv)
32
+
33
+ cli_mirror_tool.__name__ = tools.mcp_cli_tool_name_for_path(path)
34
+ return cli_mirror_tool
35
+
36
+
37
+ def _register_cli_mirror_tools(mcp: Any) -> None:
38
+ surface = tools.get_ssot_cli_surface()
39
+ mcp.tool(
40
+ name=tools.MCP_CLI_ROOT_TOOL_NAME,
41
+ title="ssot-registry root",
42
+ description="Mirror of the root ssot-registry CLI surface through MCP. Pass argv tokens after `ssot-registry` in `args`.",
43
+ )(tools.run_ssot_cli)
44
+
45
+ for path in surface["subcommand_paths"]:
46
+ flags = surface["flags_by_path"].get(path, [])
47
+ flags_text = ", ".join(f"`{flag}`" for flag in flags) if flags else "none"
48
+ mcp.tool(
49
+ name=surface["tool_name_by_path"][path],
50
+ title=f"ssot-registry {path}",
51
+ description=(
52
+ f"Mirror of `ssot-registry {path}` through MCP. "
53
+ f"Supported path-local flags: {flags_text}. "
54
+ "Pass root/global flags in `global_args` and path-local flags or positionals in `args`."
55
+ ),
56
+ )(_make_cli_mirror_tool(path))
57
+
58
+
9
59
  def build_server() -> Any:
10
60
  try:
11
61
  from mcp.server.fastmcp import FastMCP
@@ -36,6 +86,7 @@ def build_server() -> Any:
36
86
  mcp.tool()(tools.registry_entity_link)
37
87
  mcp.tool()(tools.registry_entity_unlink)
38
88
  mcp.tool()(tools.run_ssot_cli)
89
+ _register_cli_mirror_tools(mcp)
39
90
 
40
91
  mcp.resource("ssot://registry/{repo}")(resources.registry_resource)
41
92
  mcp.resource("ssot://campaign/{repo}/{campaign_id}")(resources.campaign_status_resource)
@@ -25,6 +25,7 @@ from ssot_registry.control.service import ControlPlane
25
25
 
26
26
  _PINNED_REPO: Path | None = None
27
27
  _CLI_LOCK = RLock()
28
+ MCP_CLI_ROOT_TOOL_NAME = "ssot_cli__root"
28
29
 
29
30
 
30
31
  def configure_repo(repo: str | Path | None) -> None:
@@ -139,6 +140,17 @@ def _cli_surface() -> dict[str, Any]:
139
140
  }
140
141
 
141
142
 
143
+ def mcp_cli_tool_name_for_path(path: str) -> str:
144
+ tokens = [token.strip().lower().replace("-", "_") for token in path.split() if token.strip()]
145
+ if not tokens:
146
+ return MCP_CLI_ROOT_TOOL_NAME
147
+ return "ssot_cli__" + "__".join(tokens)
148
+
149
+
150
+ def _mcp_cli_tool_map(surface: dict[str, Any]) -> dict[str, str]:
151
+ return {path: mcp_cli_tool_name_for_path(path) for path in surface["subcommand_paths"]}
152
+
153
+
142
154
  def _is_cli_metadata_request(args: list[str]) -> bool:
143
155
  return not args or any(token in {"-h", "--help", "--version"} for token in args)
144
156
 
@@ -283,7 +295,12 @@ def get_ssot_cli_surface(repo: str | None = None) -> dict[str, Any]:
283
295
  if repo is not None or _PINNED_REPO is not None:
284
296
  _resolve_repo_for_cli(repo, ["--help"])
285
297
  surface = _cli_surface()
286
- return {"passed": True, **surface}
298
+ return {
299
+ "passed": True,
300
+ **surface,
301
+ "root_tool_name": MCP_CLI_ROOT_TOOL_NAME,
302
+ "tool_name_by_path": _mcp_cli_tool_map(surface),
303
+ }
287
304
 
288
305
 
289
306
  def get_blocked_transitions(repo: str | None = None, campaign_id: str | None = None, status: str | None = "open") -> dict[str, Any]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ssot-mcp
3
- Version: 0.1.2.dev1
3
+ Version: 0.1.3.dev1
4
4
  Summary: MCP server for optional SSOT pull-worker control-plane coordination.
5
5
  Author-email: Jacob Stewart <jacob@swarmauri.com>
6
6
  License-Expression: Apache-2.0
@@ -28,7 +28,7 @@ Classifier: Topic :: Utilities
28
28
  Requires-Python: <3.15,>=3.10
29
29
  Description-Content-Type: text/markdown
30
30
  Requires-Dist: mcp>=1.0
31
- Requires-Dist: ssot-core<0.3.0,>=0.2.20.dev1
31
+ Requires-Dist: ssot-core<0.3.0,>=0.2.21.dev1
32
32
 
33
33
  <div align="center">
34
34
  <h1>ssot-mcp</h1>
@@ -122,8 +122,9 @@ Workers and MCP clients should not hand-edit `.ssot/registry.json`. When a clien
122
122
  - `registry_entity_unlink`
123
123
  - `get_ssot_cli_surface`
124
124
  - `run_ssot_cli`
125
+ - mirrored `ssot_cli__*` tools for each live CLI command path
125
126
 
126
- The structured entity tools use the same core registry mutation APIs as the CLI, validate before saving, and emit `registry_updated` events. `run_ssot_cli` delegates to the repo-local CLI parser in process and supports global flags, help/version requests, commands, subcommands, command flags, and subcommand flags as argv tokens.
127
+ The structured entity tools use the same core registry mutation APIs as the CLI, validate before saving, and emit `registry_updated` events. `get_ssot_cli_surface` exposes the live parser inventory, `run_ssot_cli` remains the generic delegation fallback, and `ssot-mcp` also registers mirrored `ssot_cli__*` MCP tools for every current CLI command path. Together they keep the CLI and MCP surfaces aligned across global flags, help/version requests, commands, subcommands, command flags, and subcommand flags.
127
128
 
128
129
  ## Pull-worker campaign model
129
130
 
@@ -0,0 +1,2 @@
1
+ mcp>=1.0
2
+ ssot-core<0.3.0,>=0.2.21.dev1
@@ -1,2 +0,0 @@
1
- mcp>=1.0
2
- ssot-core<0.3.0,>=0.2.20.dev1
File without changes