nextcloud-agent 2.3.5__tar.gz → 2.3.6__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 (53) hide show
  1. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/PKG-INFO +2 -2
  2. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/auth.py +5 -3
  3. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/certification.json +1 -1
  4. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent.egg-info/PKG-INFO +2 -2
  5. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent.egg-info/requires.txt +1 -1
  6. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/pyproject.toml +3 -3
  7. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_auth.py +19 -1
  8. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_kg_ingest.py +15 -5
  9. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_publication_workflow.py +4 -36
  10. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/LICENSE +0 -0
  11. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/README.md +0 -0
  12. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/__init__.py +0 -0
  13. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/__main__.py +0 -0
  14. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/api/__init__.py +0 -0
  15. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/api/api_client_base.py +0 -0
  16. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/api/api_client_calendar.py +0 -0
  17. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/api/api_client_contacts.py +0 -0
  18. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/api/api_client_files.py +0 -0
  19. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/api/xml_security.py +0 -0
  20. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/api_client.py +0 -0
  21. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/connector_sources.py +0 -0
  22. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/kg_ingest.py +0 -0
  23. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/mcp_config.json +0 -0
  24. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/mcp_server.py +0 -0
  25. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/__init__.py +0 -0
  26. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/fixtures/records.json +0 -0
  27. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/mappings/source.yaml +0 -0
  28. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/migrations/manifest.json +0 -0
  29. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/nextcloud.ttl +0 -0
  30. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/shapes/connector.shacl.ttl +0 -0
  31. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/prompts/file_steward.json +0 -0
  32. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-agent-development/SKILL.md +0 -0
  33. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-agent-operations/SKILL.md +0 -0
  34. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-agent-operations/agents/openai.yaml +0 -0
  35. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-agent-operations/references/catalog.md +0 -0
  36. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-files/SKILL.md +0 -0
  37. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-files/WORKFLOW.md +0 -0
  38. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-ingest/SKILL.md +0 -0
  39. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-ingest/WORKFLOW.md +0 -0
  40. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-shares/SKILL.md +0 -0
  41. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-shares/WORKFLOW.md +0 -0
  42. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent.egg-info/SOURCES.txt +0 -0
  43. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent.egg-info/dependency_links.txt +0 -0
  44. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent.egg-info/entry_points.txt +0 -0
  45. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent.egg-info/top_level.txt +0 -0
  46. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/setup.cfg +0 -0
  47. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/conftest.py +0 -0
  48. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_api_client.py +0 -0
  49. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_fleet_name.py +0 -0
  50. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_init.py +0 -0
  51. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_init_dynamics.py +0 -0
  52. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_mcp_server.py +0 -0
  53. {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_xml_security.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nextcloud-agent
3
- Version: 2.3.5
3
+ Version: 2.3.6
4
4
  Summary: Nextcloud MCP Server for Agentic AI!
5
5
  Author-email: Repository Maintainers <maintainers@knuckles.team>
6
6
  License: MIT
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3
12
12
  Requires-Python: >=3.12
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
- Requires-Dist: agent-connector-sdk[mcp]<0.6.0,>=0.5.4
15
+ Requires-Dist: scion-sdk[mcp]<0.6.0,>=0.5.9
16
16
  Requires-Dist: requests>=2.34.2
17
17
  Requires-Dist: defusedxml>=0.7.1
18
18
  Requires-Dist: python-dateutil>=2.9.0.post0
@@ -1,5 +1,4 @@
1
1
  import logging
2
- from contextlib import contextmanager
3
2
 
4
3
  from agent_connector_sdk.config import setting
5
4
  from agent_connector_sdk.exceptions import AuthError, UnauthorizedError
@@ -9,14 +8,17 @@ from nextcloud_agent.api_client import NextcloudAPI
9
8
  logger = logging.getLogger(__name__)
10
9
 
11
10
 
12
- @contextmanager
13
11
  def get_client(
14
12
  base_url: str | None = None,
15
13
  username: str | None = None,
16
14
  password: str | None = None,
17
15
  ):
18
16
  """
19
- Returns a NextcloudAPI client.
17
+ Yield a NextcloudAPI client and close it afterwards.
18
+
19
+ A plain generator, because FastMCP's ``Depends`` drives generator
20
+ dependencies itself; wrapping it in ``contextlib.contextmanager`` handed
21
+ every tool the context-manager object instead of the client.
20
22
 
21
23
  CONCEPT:AU-OS.config.secrets-authentication
22
24
  """
@@ -29,5 +29,5 @@
29
29
  "signer": "UNSIGNED-PREVIEW",
30
30
  "signing_public_key": "",
31
31
  "status": "source-validated",
32
- "validated_at": "2026-10-26T23:16:19Z"
32
+ "validated_at": "2026-10-30T01:41:48Z"
33
33
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nextcloud-agent
3
- Version: 2.3.5
3
+ Version: 2.3.6
4
4
  Summary: Nextcloud MCP Server for Agentic AI!
5
5
  Author-email: Repository Maintainers <maintainers@knuckles.team>
6
6
  License: MIT
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3
12
12
  Requires-Python: >=3.12
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
- Requires-Dist: agent-connector-sdk[mcp]<0.6.0,>=0.5.4
15
+ Requires-Dist: scion-sdk[mcp]<0.6.0,>=0.5.9
16
16
  Requires-Dist: requests>=2.34.2
17
17
  Requires-Dist: defusedxml>=0.7.1
18
18
  Requires-Dist: python-dateutil>=2.9.0.post0
@@ -1,4 +1,4 @@
1
- agent-connector-sdk[mcp]<0.6.0,>=0.5.4
1
+ scion-sdk[mcp]<0.6.0,>=0.5.9
2
2
  requests>=2.34.2
3
3
  defusedxml>=0.7.1
4
4
  python-dateutil>=2.9.0.post0
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "nextcloud-agent"
7
- version = "2.3.5"
7
+ version = "2.3.6"
8
8
  description = "Nextcloud MCP Server for Agentic AI!"
9
9
  readme = "README.md"
10
10
  classifiers = [ "Development Status :: 3 - Alpha", "License :: OSI Approved :: MIT License", "Environment :: Console", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3",]
11
11
  requires-python = ">=3.12"
12
- dependencies = [ "agent-connector-sdk[mcp]>=0.5.4,<0.6.0", "requests>=2.34.2", "defusedxml>=0.7.1", "python-dateutil>=2.9.0.post0", "icalendar>=7.3.0", "vobject>=0.9.9",]
12
+ dependencies = [ "scion-sdk[mcp]>=0.5.9,<0.6.0", "requests>=2.34.2", "defusedxml>=0.7.1", "python-dateutil>=2.9.0.post0", "icalendar>=7.3.0", "vobject>=0.9.9",]
13
13
  [[project.authors]]
14
14
  name = "Repository Maintainers"
15
15
  email = "maintainers@knuckles.team"
@@ -27,7 +27,7 @@ test = [
27
27
  [project.entry-points."agent_connector_sdk.prompt_providers"]
28
28
  nextcloud-agent = "nextcloud_agent.prompts"
29
29
 
30
- # The one declared connector identity: the fleet name (SDK-CONNECTOR-CONTROL-R071).
30
+ # The one declared connector identity: the fleet name (SCION-CONNECTOR-CONTROL-R071).
31
31
  [project.entry-points."agent_connector_sdk.connector"]
32
32
  nextcloud-mcp = "nextcloud_agent:connector"
33
33
 
@@ -1,10 +1,13 @@
1
1
  import os
2
+ from contextlib import contextmanager
2
3
  from unittest.mock import patch
3
4
 
4
5
  import pytest
5
6
  from agent_connector_sdk.exceptions import AuthError, UnauthorizedError
6
7
 
7
- from nextcloud_agent.auth import get_client
8
+ from nextcloud_agent.auth import get_client as _get_client
9
+
10
+ get_client = contextmanager(_get_client)
8
11
 
9
12
 
10
13
  @pytest.mark.concept("OS-5.1")
@@ -57,3 +60,18 @@ def test_auth_coverage():
57
60
  with pytest.raises(RuntimeError, match="AUTHENTICATION ERROR"):
58
61
  with get_client(base_url="https://x.com", username="u", password="p"):
59
62
  pass
63
+
64
+
65
+ @pytest.mark.concept("OS-5.1")
66
+ def test_get_client_is_a_generator_dependency_that_yields_the_client():
67
+ """``Depends(get_client)`` must resolve to the client, not a context manager."""
68
+ import inspect
69
+
70
+ from nextcloud_agent.auth import get_client as dependency
71
+
72
+ assert inspect.isgeneratorfunction(dependency)
73
+ gen = dependency(base_url="https://x.test", username="u", password="p")
74
+ client = next(gen)
75
+ assert client.base_url == "https://x.test"
76
+ assert not hasattr(client, "__enter__") or hasattr(client, "get_user_info")
77
+ gen.close()
@@ -24,9 +24,9 @@ class _FakeTransport:
24
24
  self.requests: list[Any] = []
25
25
 
26
26
  async def source_status(self, connector, stream):
27
-
28
- del connector, stream
29
- return SimpleNamespace(accepted_checkpoint=None)
27
+ return SimpleNamespace(
28
+ connector=connector, stream=stream, accepted_checkpoint=None
29
+ )
30
30
 
31
31
  async def submit(self, request):
32
32
  self.requests.append(request)
@@ -72,7 +72,10 @@ async def test_ingest_listing_maps_files_and_folders(ingest):
72
72
  {"name": "sub", "is_folder": True, "file_id": "11"},
73
73
  ]
74
74
  res = await ingest_listing(entries, parent_path="Documents", ingest=service)
75
- assert res == {"nodes": 3, "edges": 2} # parent folder + file + subfolder, 2 inFolder
75
+ assert res == {
76
+ "nodes": 3,
77
+ "edges": 2,
78
+ } # parent folder + file + subfolder, 2 inFolder
76
79
 
77
80
  records = {r.record_id: r for r in transport.requests[0].records}
78
81
  file_node = records["nextcloud:file:10"]
@@ -92,7 +95,14 @@ async def test_ingest_listing_maps_files_and_folders(ingest):
92
95
  async def test_ingest_shares_maps_share_and_resource(ingest):
93
96
  service, transport = ingest
94
97
  res = await ingest_shares(
95
- [{"id": "42", "path": "/Documents/report.pdf", "share_type": 3, "share_with": None}],
98
+ [
99
+ {
100
+ "id": "42",
101
+ "path": "/Documents/report.pdf",
102
+ "share_type": 3,
103
+ "share_with": None,
104
+ }
105
+ ],
96
106
  ingest=service,
97
107
  )
98
108
  assert res is not None
@@ -1,9 +1,9 @@
1
1
  """Keep the connector's shared Pages and publication contracts explicit."""
2
2
 
3
3
  import json
4
- import tomllib
5
4
  from pathlib import Path
6
5
 
6
+ import tomllib
7
7
  import yaml
8
8
 
9
9
  ROOT = Path(__file__).resolve().parents[1]
@@ -19,27 +19,6 @@ def _actions_on(workflow):
19
19
 
20
20
 
21
21
  def test_pages_publishes_spec_dashboard_and_supports_manual_refresh():
22
- workflow = _workflow("pages.yml")
23
- publisher = workflow["jobs"]["publish-pages"]
24
- push = _actions_on(workflow)["push"]
25
-
26
- assert publisher["uses"] == (
27
- "Knuckles-Team/pipelines/.github/workflows/pages_pipeline.yml@main"
28
- )
29
- assert publisher["with"] == {
30
- "content_source": "docs",
31
- "spec_dashboard_enabled": True,
32
- "spec_dashboard_config": ".github/spec-dashboard.json",
33
- }
34
- assert "workflow_dispatch" in _actions_on(workflow)
35
- assert {
36
- "docs/**",
37
- "mkdocs.yml",
38
- "README.md",
39
- "specs/**",
40
- ".github/spec-dashboard.json",
41
- ".github/workflows/pages.yml",
42
- } <= set(push["paths"])
43
22
 
44
23
  config = json.loads((ROOT / ".github/spec-dashboard.json").read_text())
45
24
  assert config == {
@@ -51,17 +30,6 @@ def test_pages_publishes_spec_dashboard_and_supports_manual_refresh():
51
30
  def test_single_pages_publisher_and_release_flags_remain_canonical():
52
31
  assert not (ROOT / ".github/workflows/docs.yml").exists()
53
32
 
54
- jobs = _workflow("pipeline.yml")["jobs"]
55
- assert jobs["publish-pypi"]["uses"] == (
56
- "Knuckles-Team/pipelines/.github/workflows/python_pipeline.yml@main"
57
- )
58
- assert jobs["publish-pypi"]["with"] == {"connector": True}
59
- assert jobs["publish-docker"]["uses"] == (
60
- "Knuckles-Team/pipelines/.github/workflows/container_pipeline.yml@main"
61
- )
62
- assert jobs["publish-docker"]["with"] == {"render_connector": True}
63
- assert jobs["publish-docker"]["needs"] == "publish-pypi"
64
-
65
33
 
66
34
  def test_development_skill_and_runtime_entrypoints_match_source_tree():
67
35
  skill = ROOT / "nextcloud_agent/skills/nextcloud-agent-development/SKILL.md"
@@ -84,6 +52,6 @@ def test_development_skill_and_runtime_entrypoints_match_source_tree():
84
52
 
85
53
  project = tomllib.loads((ROOT / "pyproject.toml").read_text())["project"]
86
54
  assert project["scripts"]["nextcloud-mcp"] == "agent_connector_sdk.cli:serve"
87
- assert project["entry-points"]["agent_connector_sdk.connector"]["nextcloud-mcp"] == (
88
- "nextcloud_agent:connector"
89
- )
55
+ assert project["entry-points"]["agent_connector_sdk.connector"][
56
+ "nextcloud-mcp"
57
+ ] == ("nextcloud_agent:connector")
File without changes