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.
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/PKG-INFO +2 -2
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/auth.py +5 -3
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/certification.json +1 -1
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent.egg-info/PKG-INFO +2 -2
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent.egg-info/requires.txt +1 -1
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/pyproject.toml +3 -3
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_auth.py +19 -1
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_kg_ingest.py +15 -5
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_publication_workflow.py +4 -36
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/LICENSE +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/README.md +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/__init__.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/__main__.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/api/__init__.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/api/api_client_base.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/api/api_client_calendar.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/api/api_client_contacts.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/api/api_client_files.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/api/xml_security.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/api_client.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/connector_sources.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/kg_ingest.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/mcp_config.json +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/mcp_server.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/__init__.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/fixtures/records.json +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/mappings/source.yaml +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/migrations/manifest.json +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/nextcloud.ttl +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/shapes/connector.shacl.ttl +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/prompts/file_steward.json +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-agent-development/SKILL.md +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-agent-operations/SKILL.md +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-agent-operations/agents/openai.yaml +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-agent-operations/references/catalog.md +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-files/SKILL.md +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-files/WORKFLOW.md +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-ingest/SKILL.md +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-ingest/WORKFLOW.md +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-shares/SKILL.md +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-shares/WORKFLOW.md +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent.egg-info/SOURCES.txt +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent.egg-info/dependency_links.txt +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent.egg-info/entry_points.txt +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent.egg-info/top_level.txt +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/setup.cfg +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/conftest.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_api_client.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_fleet_name.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_init.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_init_dynamics.py +0 -0
- {nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/tests/test_mcp_server.py +0 -0
- {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.
|
|
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:
|
|
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
|
-
|
|
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
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nextcloud-agent
|
|
3
|
-
Version: 2.3.
|
|
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:
|
|
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
|
|
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "nextcloud-agent"
|
|
7
|
-
version = "2.3.
|
|
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 = [ "
|
|
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 (
|
|
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
|
-
|
|
29
|
-
|
|
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 == {
|
|
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
|
-
[
|
|
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"][
|
|
88
|
-
"
|
|
89
|
-
)
|
|
55
|
+
assert project["entry-points"]["agent_connector_sdk.connector"][
|
|
56
|
+
"nextcloud-mcp"
|
|
57
|
+
] == ("nextcloud_agent:connector")
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/fixtures/records.json
RENAMED
|
File without changes
|
{nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/mappings/source.yaml
RENAMED
|
File without changes
|
{nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/migrations/manifest.json
RENAMED
|
File without changes
|
|
File without changes
|
{nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/ontology/shapes/connector.shacl.ttl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-files/SKILL.md
RENAMED
|
File without changes
|
{nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-files/WORKFLOW.md
RENAMED
|
File without changes
|
{nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-ingest/SKILL.md
RENAMED
|
File without changes
|
{nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-ingest/WORKFLOW.md
RENAMED
|
File without changes
|
{nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-shares/SKILL.md
RENAMED
|
File without changes
|
{nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent/skills/nextcloud-shares/WORKFLOW.md
RENAMED
|
File without changes
|
|
File without changes
|
{nextcloud_agent-2.3.5 → nextcloud_agent-2.3.6}/nextcloud_agent.egg-info/dependency_links.txt
RENAMED
|
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
|
|
File without changes
|