lean-memory-console 0.2.2__tar.gz → 0.2.3__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 (43) hide show
  1. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/PKG-INFO +2 -2
  2. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/pyproject.toml +3 -3
  3. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/src/lean_memory_console/__init__.py +1 -1
  4. lean_memory_console-0.2.3/src/lean_memory_console/_mcp_compat.py +35 -0
  5. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/src/lean_memory_console/mcp_tools.py +4 -4
  6. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/src/lean_memory_console/observe_mcp.py +3 -4
  7. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/src/lean_memory_console/routes/mcp.py +8 -6
  8. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/test_mcp_parity.py +1 -1
  9. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/test_observe_mcp.py +5 -1
  10. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/.gitignore +0 -0
  11. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/README.md +0 -0
  12. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/deploy/docker-compose.yml +0 -0
  13. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/src/lean_memory_console/app.py +0 -0
  14. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/src/lean_memory_console/cli.py +0 -0
  15. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/src/lean_memory_console/config.py +0 -0
  16. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/src/lean_memory_console/deploy/__init__.py +0 -0
  17. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/src/lean_memory_console/engine.py +0 -0
  18. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/src/lean_memory_console/events.py +0 -0
  19. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/src/lean_memory_console/inspect_sql.py +0 -0
  20. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/src/lean_memory_console/routes/__init__.py +0 -0
  21. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/src/lean_memory_console/routes/data.py +0 -0
  22. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/src/lean_memory_console/routes/review.py +0 -0
  23. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/src/lean_memory_console/routes/views.py +0 -0
  24. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/__init__.py +0 -0
  25. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/conftest.py +0 -0
  26. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/fixtures/__init__.py +0 -0
  27. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/fixtures/build_fixture.py +0 -0
  28. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/fixtures/data_root/.gitignore +0 -0
  29. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/fixtures/data_root/_events.db +0 -0
  30. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/fixtures/data_root/proj-alpha.db +0 -0
  31. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/fixtures/data_root/proj-beta.db +0 -0
  32. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/test_cli.py +0 -0
  33. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/test_config.py +0 -0
  34. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/test_data_plane.py +0 -0
  35. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/test_deploy_artifacts.py +0 -0
  36. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/test_engine.py +0 -0
  37. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/test_events.py +0 -0
  38. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/test_inspect_facts.py +0 -0
  39. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/test_inspect_namespaces.py +0 -0
  40. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/test_plugin_manifest.py +0 -0
  41. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/test_readme_contract.py +0 -0
  42. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/test_review_views.py +0 -0
  43. {lean_memory_console-0.2.2 → lean_memory_console-0.2.3}/tests/test_views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lean-memory-console
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Agent-first read-only verification console for lean-memory
5
5
  Project-URL: Homepage, https://github.com/Wuesteon/lean-memory
6
6
  Project-URL: Repository, https://github.com/Wuesteon/lean-memory
@@ -22,7 +22,7 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
22
  Requires-Python: >=3.10
23
23
  Requires-Dist: fastapi>=0.115
24
24
  Requires-Dist: lean-memory
25
- Requires-Dist: mcp<2,>=1.2
25
+ Requires-Dist: mcp<3,>=1.2
26
26
  Requires-Dist: uvicorn>=0.30
27
27
  Provides-Extra: dev
28
28
  Requires-Dist: anyio>=4; extra == 'dev'
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "lean-memory-console"
7
- version = "0.2.2"
7
+ version = "0.2.3"
8
8
  description = "Agent-first read-only verification console for lean-memory"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -35,8 +35,8 @@ dependencies = [
35
35
  "lean-memory",
36
36
  "fastapi>=0.115",
37
37
  "uvicorn>=0.30",
38
- # <2: mcp 2.0.0 removed mcp.server.fastmcp (see core [mcp] extra note).
39
- "mcp>=1.2,<2",
38
+ # Dual-path (WP12): lean_memory_console._mcp_compat supports 1.x and 2.x.
39
+ "mcp>=1.2,<3",
40
40
  ]
41
41
 
42
42
  [project.optional-dependencies]
@@ -1,3 +1,3 @@
1
1
  """lean-memory-console — agent-first read-only verification console."""
2
2
 
3
- __version__ = "0.2.2"
3
+ __version__ = "0.2.3"
@@ -0,0 +1,35 @@
1
+ """Dual-path mcp SDK compatibility (WP12): 2.0 renamed FastMCP → MCPServer
2
+ (same decorator API) and moved transport params from the constructor to the
3
+ `streamable_http_app(...)` call. Deliberately duplicated from
4
+ `lean_memory._mcp_compat` rather than imported: console↔core version skew
5
+ makes cross-package private imports fragile."""
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Any
10
+
11
+ try: # mcp >= 2
12
+ from mcp.server.mcpserver import MCPServer as MCPServerType
13
+
14
+ MCP_V2 = True
15
+ except ImportError: # mcp 1.x
16
+ from mcp.server.fastmcp import FastMCP as MCPServerType # type: ignore[assignment]
17
+
18
+ MCP_V2 = False
19
+
20
+
21
+ def make_http_server_and_app(name: str, **transport_kwargs: Any):
22
+ """Build a streamable-HTTP server + its ASGI app under either SDK major.
23
+
24
+ 1.x takes the transport kwargs (stateless_http, json_response,
25
+ streamable_http_path, transport_security) in the FastMCP constructor and a
26
+ bare `streamable_http_app()`; 2.0 takes a bare constructor and passes them
27
+ to `streamable_http_app(...)`. Returns (server, build_app) where build_app
28
+ is a zero-arg callable — tools must be registered on `server` BEFORE
29
+ calling it (both majors snapshot the tool set into the app).
30
+ """
31
+ if MCP_V2:
32
+ server = MCPServerType(name)
33
+ return server, lambda: server.streamable_http_app(**transport_kwargs)
34
+ server = MCPServerType(name, **transport_kwargs)
35
+ return server, lambda: server.streamable_http_app()
@@ -2,7 +2,7 @@
2
2
 
3
3
  The console ships the SAME memory + maintenance tools on both its stdio server
4
4
  (``observe_mcp.py`` — what the plugin runs) and its Docker HTTP mount
5
- (``routes/mcp.py``). Registering them once here, against a passed-in FastMCP + the
5
+ (``routes/mcp.py``). Registering them once here, against a passed-in server + the
6
6
  gateway, keeps tool names, signatures, and return shapes IDENTICAL across the two —
7
7
  and identical to the core stdio server (``lean_memory.mcp_server``), which is the §6.3
8
8
  requirement and the v0.1.3 manifest-parity lesson.
@@ -22,7 +22,7 @@ from __future__ import annotations
22
22
  import json
23
23
  from typing import Any
24
24
 
25
- from mcp.server.fastmcp import FastMCP
25
+ from ._mcp_compat import MCPServerType
26
26
 
27
27
  from .engine import EngineGateway
28
28
 
@@ -61,7 +61,7 @@ Workflow:
61
61
  """
62
62
 
63
63
 
64
- def register_maintenance_tools(mcp: FastMCP, gateway: EngineGateway) -> None:
64
+ def register_maintenance_tools(mcp: MCPServerType, gateway: EngineGateway) -> None:
65
65
  """Register the four §6.3 maintenance tools on `mcp`, routed through `gateway`.
66
66
 
67
67
  Identical names/signatures to the core stdio server: memory_maintenance_run
@@ -120,7 +120,7 @@ def register_maintenance_tools(mcp: FastMCP, gateway: EngineGateway) -> None:
120
120
  return json.loads(json.dumps(result, default=str))
121
121
 
122
122
 
123
- def register_review_prompt(mcp: FastMCP) -> None:
123
+ def register_review_prompt(mcp: MCPServerType) -> None:
124
124
  """Register the `review-memory-maintenance` prompt on a stdio FastMCP (§6.4).
125
125
 
126
126
  The prompt hands the client agent the review workflow but FORBIDS it from deciding
@@ -9,16 +9,15 @@ from __future__ import annotations
9
9
 
10
10
  from typing import Any
11
11
 
12
- from mcp.server.fastmcp import FastMCP
13
-
12
+ from ._mcp_compat import MCPServerType
14
13
  from .config import ConsoleConfig
15
14
  from .engine import EngineGateway
16
15
  from .events import EventLog
17
16
  from .mcp_tools import register_maintenance_tools, register_review_prompt
18
17
 
19
18
 
20
- def build_mcp(gateway: EngineGateway) -> FastMCP:
21
- mcp = FastMCP("lean-memory-console")
19
+ def build_mcp(gateway: EngineGateway) -> MCPServerType:
20
+ mcp = MCPServerType("lean-memory-console")
22
21
 
23
22
  @mcp.tool()
24
23
  async def memory_add(
@@ -49,9 +49,9 @@ from __future__ import annotations
49
49
  import secrets
50
50
  from typing import Any
51
51
 
52
- from mcp.server.fastmcp import FastMCP
53
52
  from mcp.server.transport_security import TransportSecuritySettings
54
53
 
54
+ from .._mcp_compat import MCPServerType, make_http_server_and_app
55
55
  from ..config import ConsoleConfig
56
56
  from ..engine import EngineGateway
57
57
  from ..mcp_tools import register_maintenance_tools
@@ -78,14 +78,16 @@ _ALLOWED_ORIGINS = [
78
78
 
79
79
  def _build_http_mcp(
80
80
  gateway: EngineGateway, extra_allowed_hosts: list[str] | None = None
81
- ) -> FastMCP:
81
+ ) -> tuple[MCPServerType, Any]:
82
82
  # Loopback defaults + any operator-supplied patterns (LM_MCP_ALLOWED_HOSTS),
83
83
  # de-duplicated while preserving order.
84
84
  allowed_hosts = list(_DEFAULT_ALLOWED_HOSTS)
85
85
  for host in extra_allowed_hosts or []:
86
86
  if host not in allowed_hosts:
87
87
  allowed_hosts.append(host)
88
- mcp = FastMCP(
88
+ # The compat factory places the transport kwargs where the installed SDK
89
+ # major wants them (1.x: constructor; 2.x: streamable_http_app call).
90
+ mcp, build_app = make_http_server_and_app(
89
91
  "lean-memory-console",
90
92
  stateless_http=True,
91
93
  json_response=True,
@@ -130,7 +132,7 @@ def _build_http_mcp(
130
132
  # here — MCP prompts are a stdio-client capability; HTTP clients use the tools.
131
133
  register_maintenance_tools(mcp, gateway)
132
134
 
133
- return mcp
135
+ return mcp, build_app
134
136
 
135
137
 
136
138
  def build_mcp_mount(gateway: EngineGateway, config: ConsoleConfig):
@@ -142,8 +144,8 @@ def build_mcp_mount(gateway: EngineGateway, config: ConsoleConfig):
142
144
  enter its ``run()`` in the app lifespan (see module docstring, decision 1) —
143
145
  there is no per-request fallback, because ``run()`` is once-only per instance.
144
146
  """
145
- mcp = _build_http_mcp(gateway, config.mcp_allowed_hosts)
146
- inner = mcp.streamable_http_app()
147
+ mcp, build_app = _build_http_mcp(gateway, config.mcp_allowed_hosts)
148
+ inner = build_app()
147
149
  session_manager = mcp.session_manager # initializes it on the inner app
148
150
  # None when no api_key is configured, so the constant-time compare below
149
151
  # always fails (compare_digest is skipped for a None expected value).
@@ -46,7 +46,7 @@ def test_http_mount_exposes_the_same_tool_set(tmp_path):
46
46
  cfg = ConsoleConfig(data_root=tmp_path, mode="local", models="stub")
47
47
  log = EventLog(tmp_path)
48
48
  gw = EngineGateway(cfg, log)
49
- http_mcp = _build_http_mcp(gw, cfg.mcp_allowed_hosts)
49
+ http_mcp, _build_app = _build_http_mcp(gw, cfg.mcp_allowed_hosts)
50
50
  names = set(_tool_params(http_mcp).keys())
51
51
  gw.close()
52
52
  log.close()
@@ -18,7 +18,11 @@ def wrapper(tmp_path):
18
18
 
19
19
 
20
20
  def _unwrap(result):
21
- """FastMCP call_tool returns (content, structured) or structured dict."""
21
+ """Server-side call_tool return differs per mcp major (WP12): 1.x FastMCP
22
+ returns (content, structured) or a structured dict; 2.0 MCPServer returns
23
+ a CallToolResult carrying `.structured_content`."""
24
+ if hasattr(result, "structured_content"): # mcp >= 2
25
+ return result.structured_content
22
26
  if isinstance(result, tuple):
23
27
  return result[1]
24
28
  return result