answer42 0.2.7__tar.gz → 0.2.9__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.
Files changed (59) hide show
  1. {answer42-0.2.7 → answer42-0.2.9}/PKG-INFO +1 -1
  2. {answer42-0.2.7 → answer42-0.2.9}/pyproject.toml +1 -1
  3. answer42-0.2.9/src/mcp_1c/__init__.py +22 -0
  4. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/server.py +38 -9
  5. answer42-0.2.7/src/mcp_1c/__init__.py +0 -4
  6. {answer42-0.2.7 → answer42-0.2.9}/.gitignore +0 -0
  7. {answer42-0.2.7 → answer42-0.2.9}/LICENSE +0 -0
  8. {answer42-0.2.7 → answer42-0.2.9}/README.md +0 -0
  9. {answer42-0.2.7 → answer42-0.2.9}/credentials.example.json +0 -0
  10. {answer42-0.2.7 → answer42-0.2.9}/docs/agent-installation.md +0 -0
  11. {answer42-0.2.7 → answer42-0.2.9}/docs/architecture.md +0 -0
  12. {answer42-0.2.7 → answer42-0.2.9}/docs/assets/answer42-logo.png +0 -0
  13. {answer42-0.2.7 → answer42-0.2.9}/docs/assets/platform42-logo.svg +0 -0
  14. {answer42-0.2.7 → answer42-0.2.9}/docs/installation.md +0 -0
  15. {answer42-0.2.7 → answer42-0.2.9}/scripts/build_cf.py +0 -0
  16. {answer42-0.2.7 → answer42-0.2.9}/scripts/build_pages.py +0 -0
  17. {answer42-0.2.7 → answer42-0.2.9}/scripts/e2e_stable.py +0 -0
  18. {answer42-0.2.7 → answer42-0.2.9}/scripts/openclaw_mcp_autoreload.py +0 -0
  19. {answer42-0.2.7 → answer42-0.2.9}/scripts/rag_cli.py +0 -0
  20. {answer42-0.2.7 → answer42-0.2.9}/src/cf/ConfigDumpInfo.xml +0 -0
  21. {answer42-0.2.7 → answer42-0.2.9}/src/cf/Configuration.xml +0 -0
  22. {answer42-0.2.7 → answer42-0.2.9}/src/cf/DataProcessors/MCPTestManager/Ext/ObjectModule.bsl +0 -0
  23. {answer42-0.2.7 → answer42-0.2.9}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260/Ext/Form/Module.bsl" +0 -0
  24. {answer42-0.2.7 → answer42-0.2.9}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260/Ext/Form.xml" +0 -0
  25. {answer42-0.2.7 → answer42-0.2.9}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260.xml" +0 -0
  26. {answer42-0.2.7 → answer42-0.2.9}/src/cf/DataProcessors/MCPTestManager.xml +0 -0
  27. {answer42-0.2.7 → answer42-0.2.9}/src/cf/Ext/ManagedApplicationModule.bsl +0 -0
  28. {answer42-0.2.7 → answer42-0.2.9}/src/cf/Languages//320/240/321/203/321/201/321/201/320/272/320/270/320/271.xml" +0 -0
  29. {answer42-0.2.7 → answer42-0.2.9}/src/client_cf/Catalogs//320/237/320/241_/320/222/320/273/320/260/320/264/320/265/320/273/320/265/321/206.xml" +0 -0
  30. {answer42-0.2.7 → answer42-0.2.9}/src/client_cf/Catalogs//320/237/320/241_/320/241/320/277/321/200/320/260/320/262/320/276/321/207/320/275/320/270/320/2721.xml" +0 -0
  31. {answer42-0.2.7 → answer42-0.2.9}/src/client_cf/ConfigDumpInfo.xml +0 -0
  32. {answer42-0.2.7 → answer42-0.2.9}/src/client_cf/Configuration.xml +0 -0
  33. {answer42-0.2.7 → answer42-0.2.9}/src/client_cf/Languages//320/240/321/203/321/201/321/201/320/272/320/270/320/271.xml" +0 -0
  34. {answer42-0.2.7 → answer42-0.2.9}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Ext/ManagerModule.bsl" +0 -0
  35. {answer42-0.2.7 → answer42-0.2.9}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Ext/ObjectModule.bsl" +0 -0
  36. {answer42-0.2.7 → answer42-0.2.9}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Templates//320/236/321/201/320/275/320/276/320/262/320/275/320/260/321/217/320/241/321/205/320/265/320/274/320/260/320/232/320/276/320/274/320/277/320/276/320/275/320/276/320/262/320/272/320/270/320/224/320/260/320/275/320/275/321/213/321/205/Ext/Template.xml" +0 -0
  37. {answer42-0.2.7 → answer42-0.2.9}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Templates//320/236/321/201/320/275/320/276/320/262/320/275/320/260/321/217/320/241/321/205/320/265/320/274/320/260/320/232/320/276/320/274/320/277/320/276/320/275/320/276/320/262/320/272/320/270/320/224/320/260/320/275/320/275/321/213/321/205.xml" +0 -0
  38. {answer42-0.2.7 → answer42-0.2.9}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262.xml" +0 -0
  39. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/assets/MCPTestClient.cf +0 -0
  40. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/assets/MCPTestManager.cf +0 -0
  41. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/assets/__init__.py +0 -0
  42. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/assets/skills/answer42/SKILL.md +0 -0
  43. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/assets/skills/answer42-rag/SKILL.md +0 -0
  44. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/bridge.py +0 -0
  45. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/credentials.py +0 -0
  46. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/os_support.py +0 -0
  47. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/platform.py +0 -0
  48. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/protocol.py +0 -0
  49. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/rag/__init__.py +0 -0
  50. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/rag/detect.py +0 -0
  51. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/rag/model.py +0 -0
  52. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/rag/parsers.py +0 -0
  53. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/rag/service.py +0 -0
  54. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/rag/store.py +0 -0
  55. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/recorder.py +0 -0
  56. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/release_helper.py +0 -0
  57. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/runtime.py +0 -0
  58. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/skill_installer.py +0 -0
  59. {answer42-0.2.7 → answer42-0.2.9}/src/mcp_1c/window_control.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: answer42
3
- Version: 0.2.7
3
+ Version: 0.2.9
4
4
  Summary: Answer42 — The Answer to Life, Universe, and 1C — UI Driver. MCP-powered 1C:Enterprise UI automation: click, fill, navigate, test, and introspect managed forms through the test-client API
5
5
  Author: Marvin (AI Assistant), 42Clouds, and contributors
6
6
  Author-email: "Kosolapov Stanislav (proDOOMman)" <prodoomman@gmail.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "answer42"
3
- version = "0.2.7"
3
+ version = "0.2.9"
4
4
  description = "Answer42 — The Answer to Life, Universe, and 1C — UI Driver. MCP-powered 1C:Enterprise UI automation: click, fill, navigate, test, and introspect managed forms through the test-client API"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -0,0 +1,22 @@
1
+ """MCP server for 1C:Enterprise test manager automation."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+ from pathlib import Path
5
+ import tomllib
6
+
7
+ __all__ = ["__version__"]
8
+
9
+
10
+ def _version_from_pyproject() -> str:
11
+ pyproject = Path(__file__).resolve().parents[2] / "pyproject.toml"
12
+ try:
13
+ data = tomllib.loads(pyproject.read_text(encoding="utf-8"))
14
+ return str(data.get("project", {}).get("version") or "0+unknown")
15
+ except Exception:
16
+ return "0+unknown"
17
+
18
+
19
+ try:
20
+ __version__ = version("answer42")
21
+ except PackageNotFoundError:
22
+ __version__ = _version_from_pyproject()
@@ -25,6 +25,7 @@ from typing import Annotated, Any
25
25
 
26
26
  from mcp.server.fastmcp import FastMCP
27
27
 
28
+ from . import __version__
28
29
  from . import os_support
29
30
  from . import platform as _platform
30
31
  from . import runtime
@@ -40,6 +41,7 @@ from .recorder import RecordingSession
40
41
  mcp = FastMCP("Answer42")
41
42
  _RAG = RagService()
42
43
  _RAG_ENABLED = os.getenv("ONEC_MCP_DISABLE_RAG", "").strip().lower() not in {"1", "true", "yes", "on"}
44
+ _CREDENTIAL_STORE_ENABLED = os.getenv("ONEC_MCP_DISABLE_CREDENTIAL_STORE", "").strip().lower() not in {"1", "true", "yes", "on"}
43
45
  DEFAULT_SESSION = "default"
44
46
  STATE_FILE = os_support.runtime_path("ONEC_MCP_SESSION_STATE", "sessions.json")
45
47
  AUTORELOAD_PID_FILE = os_support.runtime_path("ONEC_MCP_AUTORELOAD_PID_FILE", "answer42-autoreload.pid")
@@ -2023,9 +2025,21 @@ def export_eventlog(
2023
2025
  return {"path": str(exported), "format": fmt, "eventlog_dir": str(eventlog_path)}
2024
2026
 
2025
2027
 
2028
+ def _credential_store_disabled_error() -> RuntimeError:
2029
+ return RuntimeError("Credential store is disabled by --disable-credential-store or ONEC_MCP_DISABLE_CREDENTIAL_STORE.")
2030
+
2031
+
2032
+ def _lookup_credentials(base_url: str) -> dict[str, str] | None:
2033
+ if not _CREDENTIAL_STORE_ENABLED:
2034
+ return None
2035
+ return _credentials_store().lookup(base_url)
2036
+
2037
+
2026
2038
  @mcp.tool()
2027
2039
  def credentials_check(base_url: str) -> dict[str, object]:
2028
2040
  """Check whether credentials exist for a base URL without returning secrets."""
2041
+ if not _CREDENTIAL_STORE_ENABLED:
2042
+ return {"base_url": base_url, "found": False, "disabled": True}
2029
2043
  credentials = _credentials_store().lookup(base_url)
2030
2044
  if credentials is None:
2031
2045
  return {"base_url": base_url, "found": False}
@@ -2047,6 +2061,8 @@ def credentials_save(
2047
2061
  login/password pairs so that ``start_session`` can pick them up automatically
2048
2062
  without exposing secrets in MCP tool-call arguments.
2049
2063
  """
2064
+ if not _CREDENTIAL_STORE_ENABLED:
2065
+ raise _credential_store_disabled_error()
2050
2066
  updated = _credentials_store().upsert(url, username, password)
2051
2067
  return {
2052
2068
  "url": url,
@@ -2060,6 +2076,8 @@ def credentials_remove(
2060
2076
  url: Annotated[str, "Exact URL pattern to remove from the credentials store"],
2061
2077
  ) -> dict[str, object]:
2062
2078
  """Remove a credential entry from the local store by exact URL match."""
2079
+ if not _CREDENTIAL_STORE_ENABLED:
2080
+ raise _credential_store_disabled_error()
2063
2081
  removed = _credentials_store().remove(url)
2064
2082
  return {"url": url, "removed": removed}
2065
2083
 
@@ -2067,6 +2085,8 @@ def credentials_remove(
2067
2085
  @mcp.tool()
2068
2086
  def credentials_list() -> list[dict[str, str]]:
2069
2087
  """List configured credential URL patterns (no usernames or passwords)."""
2088
+ if not _CREDENTIAL_STORE_ENABLED:
2089
+ return []
2070
2090
  return _credentials_store().list_entries()
2071
2091
 
2072
2092
 
@@ -2332,7 +2352,7 @@ async def _connect_test_client_impl(
2332
2352
  raise ValueError("base_url or connection_value is required")
2333
2353
  r_base = r_value
2334
2354
  if not r_user and not r_pass:
2335
- credentials = _credentials_store().lookup(r_base)
2355
+ credentials = _lookup_credentials(r_base)
2336
2356
  if credentials:
2337
2357
  r_user = credentials["username"]
2338
2358
  r_pass = credentials["password"]
@@ -2398,7 +2418,7 @@ async def _connect_test_client_impl(
2398
2418
  target_connection_mode = mode
2399
2419
 
2400
2420
  if not r_user and not r_pass and r_base:
2401
- credentials = _credentials_store().lookup(r_base)
2421
+ credentials = _lookup_credentials(r_base)
2402
2422
  if credentials:
2403
2423
  r_user = credentials["username"]
2404
2424
  r_pass = credentials["password"]
@@ -4063,15 +4083,17 @@ async def _run() -> None:
4063
4083
  _SESSIONS.clear()
4064
4084
 
4065
4085
 
4066
- def main() -> None:
4067
- global _RAG_ENABLED
4086
+ def main(argv: list[str] | None = None) -> None:
4087
+ global _RAG_ENABLED, _CREDENTIAL_STORE_ENABLED
4068
4088
 
4069
- if len(sys.argv) > 1 and sys.argv[1] in {"install-skills", "skills-install"}:
4070
- raise SystemExit(skill_installer.main(sys.argv[2:]))
4071
- if len(sys.argv) > 1 and sys.argv[1] in {"release", "release-pypi"}:
4072
- raise SystemExit(release_helper.main(sys.argv[2:]))
4089
+ argv = list(sys.argv[1:] if argv is None else argv)
4090
+ if argv and argv[0] in {"install-skills", "skills-install"}:
4091
+ raise SystemExit(skill_installer.main(argv[1:]))
4092
+ if argv and argv[0] in {"release", "release-pypi"}:
4093
+ raise SystemExit(release_helper.main(argv[1:]))
4073
4094
 
4074
4095
  parser = argparse.ArgumentParser(description="MCP server for 1C:Enterprise test manager")
4096
+ parser.add_argument("--version", action="version", version=f"answer42 {__version__}")
4075
4097
  parser.add_argument("--log-level", default=os.getenv("ONEC_MCP_LOG_LEVEL", "INFO"))
4076
4098
  parser.add_argument(
4077
4099
  "--disable-rag",
@@ -4079,6 +4101,12 @@ def main() -> None:
4079
4101
  default=os.getenv("ONEC_MCP_DISABLE_RAG", "").strip().lower() in {"1", "true", "yes", "on"},
4080
4102
  help="disable built-in Answer42 RAG tools and RAG enrichment",
4081
4103
  )
4104
+ parser.add_argument(
4105
+ "--disable-credential-store",
4106
+ action="store_true",
4107
+ default=os.getenv("ONEC_MCP_DISABLE_CREDENTIAL_STORE", "").strip().lower() in {"1", "true", "yes", "on"},
4108
+ help="disable loading, saving and automatic lookup of credentials from the local credential store",
4109
+ )
4082
4110
  parser.add_argument(
4083
4111
  "--rag-source-dir",
4084
4112
  action="append",
@@ -4114,9 +4142,10 @@ def main() -> None:
4114
4142
  default=float(os.getenv("ONEC_MCP_DEV_RESTART_TIMEOUT", "30")),
4115
4143
  help="seconds of no file changes before the OpenClaw MCP autoreload watchdog triggers reload",
4116
4144
  )
4117
- args = parser.parse_args()
4145
+ args = parser.parse_args(argv)
4118
4146
 
4119
4147
  _RAG_ENABLED = not args.disable_rag
4148
+ _CREDENTIAL_STORE_ENABLED = not args.disable_credential_store
4120
4149
  logging.basicConfig(level=getattr(logging, args.log_level.upper(), logging.INFO))
4121
4150
  if _RAG_ENABLED:
4122
4151
  _register_startup_rag_source_dirs(args.rag_source_dir or [], args.rag_source_prefix, not args.rag_source_no_recursive, args.rag_source_max_depth)
@@ -1,4 +0,0 @@
1
- """MCP server for 1C:Enterprise test manager automation."""
2
-
3
- __all__ = ["__version__"]
4
- __version__ = "0.1.0"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes