nextcloud-agent 2.3.3__tar.gz → 2.3.5__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 (65) hide show
  1. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/PKG-INFO +3 -9
  2. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/README.md +0 -2
  3. nextcloud_agent-2.3.5/nextcloud_agent/__init__.py +11 -0
  4. nextcloud_agent-2.3.5/nextcloud_agent/__main__.py +4 -0
  5. nextcloud_agent-2.3.5/nextcloud_agent/connector_sources.py +82 -0
  6. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/kg_ingest.py +5 -59
  7. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/mcp_server.py +0 -68
  8. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/ontology/certification.json +6 -6
  9. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/ontology/mappings/source.yaml +1 -1
  10. nextcloud_agent-2.3.5/nextcloud_agent/skills/nextcloud-agent-development/SKILL.md +123 -0
  11. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent.egg-info/PKG-INFO +3 -9
  12. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent.egg-info/SOURCES.txt +2 -7
  13. nextcloud_agent-2.3.5/nextcloud_agent.egg-info/entry_points.txt +8 -0
  14. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent.egg-info/requires.txt +1 -7
  15. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent.egg-info/top_level.txt +0 -1
  16. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/pyproject.toml +14 -14
  17. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/tests/test_fleet_name.py +1 -1
  18. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/tests/test_init.py +2 -2
  19. nextcloud_agent-2.3.5/tests/test_mcp_server.py +52 -0
  20. nextcloud_agent-2.3.5/tests/test_publication_workflow.py +89 -0
  21. nextcloud_agent-2.3.3/nextcloud_agent/__init__.py +0 -1
  22. nextcloud_agent-2.3.3/nextcloud_agent/__main__.py +0 -4
  23. nextcloud_agent-2.3.3/nextcloud_agent/connector_sources.py +0 -114
  24. nextcloud_agent-2.3.3/nextcloud_agent/connectors/__init__.py +0 -0
  25. nextcloud_agent-2.3.3/nextcloud_agent/prompts/__init__.py +0 -0
  26. nextcloud_agent-2.3.3/nextcloud_agent/skills/__init__.py +0 -0
  27. nextcloud_agent-2.3.3/nextcloud_agent.egg-info/entry_points.txt +0 -14
  28. nextcloud_agent-2.3.3/scripts/security_sanitizer.py +0 -318
  29. nextcloud_agent-2.3.3/scripts/verify_api_integration.py +0 -320
  30. nextcloud_agent-2.3.3/tests/test_cli_server.py +0 -18
  31. nextcloud_agent-2.3.3/tests/test_default_content_surfaces.py +0 -43
  32. nextcloud_agent-2.3.3/tests/test_mcp_server.py +0 -100
  33. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/LICENSE +0 -0
  34. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/api/__init__.py +0 -0
  35. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/api/api_client_base.py +0 -0
  36. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/api/api_client_calendar.py +0 -0
  37. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/api/api_client_contacts.py +0 -0
  38. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/api/api_client_files.py +0 -0
  39. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/api/xml_security.py +0 -0
  40. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/api_client.py +0 -0
  41. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/auth.py +0 -0
  42. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/mcp_config.json +0 -0
  43. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/ontology/__init__.py +0 -0
  44. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/ontology/fixtures/records.json +0 -0
  45. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/ontology/migrations/manifest.json +0 -0
  46. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/ontology/nextcloud.ttl +0 -0
  47. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/ontology/shapes/connector.shacl.ttl +0 -0
  48. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/prompts/file_steward.json +0 -0
  49. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/skills/nextcloud-agent-operations/SKILL.md +0 -0
  50. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/skills/nextcloud-agent-operations/agents/openai.yaml +0 -0
  51. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/skills/nextcloud-agent-operations/references/catalog.md +0 -0
  52. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/skills/nextcloud-files/SKILL.md +0 -0
  53. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/skills/nextcloud-files/WORKFLOW.md +0 -0
  54. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/skills/nextcloud-ingest/SKILL.md +0 -0
  55. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/skills/nextcloud-ingest/WORKFLOW.md +0 -0
  56. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/skills/nextcloud-shares/SKILL.md +0 -0
  57. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent/skills/nextcloud-shares/WORKFLOW.md +0 -0
  58. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/nextcloud_agent.egg-info/dependency_links.txt +0 -0
  59. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/setup.cfg +0 -0
  60. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/tests/conftest.py +0 -0
  61. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/tests/test_api_client.py +0 -0
  62. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/tests/test_auth.py +0 -0
  63. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/tests/test_init_dynamics.py +0 -0
  64. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/tests/test_kg_ingest.py +0 -0
  65. {nextcloud_agent-2.3.3 → nextcloud_agent-2.3.5}/tests/test_xml_security.py +0 -0
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nextcloud-agent
3
- Version: 2.3.3
3
+ Version: 2.3.5
4
4
  Summary: Nextcloud MCP Server for Agentic AI!
5
- Author-email: Project Maintainers <maintainers@users.noreply.github.com>
5
+ Author-email: Repository Maintainers <maintainers@knuckles.team>
6
6
  License: MIT
7
7
  Classifier: Development Status :: 3 - Alpha
8
8
  Classifier: License :: OSI Approved :: MIT License
@@ -12,16 +12,12 @@ 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]<1.0.0,>=0.4.1
15
+ Requires-Dist: agent-connector-sdk[mcp]<0.6.0,>=0.5.4
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
19
19
  Requires-Dist: icalendar>=7.3.0
20
20
  Requires-Dist: vobject>=0.9.9
21
- Provides-Extra: mcp
22
- Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1; extra == "mcp"
23
- Provides-Extra: all
24
- Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1; extra == "all"
25
21
  Provides-Extra: test
26
22
  Requires-Dist: pytest-xdist>=3.8.0; extra == "test"
27
23
  Requires-Dist: pytest>=9.1.1; extra == "test"
@@ -51,8 +47,6 @@ Dynamic: license-file
51
47
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/nextcloud-agent)
52
48
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/nextcloud-agent)
53
49
 
54
- *Version: 2.3.3*
55
-
56
50
  > **Documentation** — Installation, deployment, usage across the API, CLI, and MCP
57
51
  > interfaces, and guidance for provisioning the backing Nextcloud instance are
58
52
  > maintained in the [official documentation](https://knuckles-team.github.io/nextcloud-agent/).
@@ -20,8 +20,6 @@
20
20
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/nextcloud-agent)
21
21
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/nextcloud-agent)
22
22
 
23
- *Version: 2.3.3*
24
-
25
23
  > **Documentation** — Installation, deployment, usage across the API, CLI, and MCP
26
24
  > interfaces, and guidance for provisioning the backing Nextcloud instance are
27
25
  > maintained in the [official documentation](https://knuckles-team.github.io/nextcloud-agent/).
@@ -0,0 +1,11 @@
1
+ from agent_connector_sdk.connector import Connector
2
+
3
+ from nextcloud_agent.api_client import NextcloudAPI
4
+ from nextcloud_agent.auth import get_client
5
+
6
+ connector = Connector(
7
+ api=NextcloudAPI,
8
+ get_client=get_client,
9
+ tools="nextcloud_agent.mcp_server",
10
+ instructions="nextcloud-agent MCP Server — Condensed Action-Routed Tools.",
11
+ )
@@ -0,0 +1,4 @@
1
+ from agent_connector_sdk import run
2
+
3
+ if __name__ == "__main__":
4
+ run()
@@ -0,0 +1,82 @@
1
+ """Data sources of this connector, declared by tool name (generated by connector-ontology-map migrate).
2
+
3
+ Served live as ``connector://resources``. Regenerate by editing the declarations, not the tools.
4
+ """
5
+
6
+ # ruff: noqa: E501
7
+ from __future__ import annotations
8
+
9
+ from typing import Any
10
+
11
+ from agent_connector_sdk.ingest.live_declaration import source_meta
12
+
13
+ SOURCES: tuple[Any, ...] = (
14
+ source_meta(
15
+ tool="nextcloud_list_files",
16
+ source_id="nextcloud-files",
17
+ record_type="File",
18
+ id_field="file_id",
19
+ cursor_field="last_modified",
20
+ preset={
21
+ "doc_type": "file",
22
+ "params_style": "args",
23
+ },
24
+ records_path="",
25
+ server="nextcloud-mcp",
26
+ text_field="name",
27
+ title_field="name",
28
+ ),
29
+ )
30
+
31
+ SCHEMA_VERSION = 2
32
+
33
+ FIELD_SETS: dict[str, dict[str, str]] = {
34
+ "fields_1": {
35
+ "mimeType": "xsd:string",
36
+ "modifiedAt": "xsd:string",
37
+ "path": "xsd:string",
38
+ "sizeBytes": "xsd:integer",
39
+ },
40
+ }
41
+
42
+ SCHEMA_MAPPINGS: dict[str, Any] = {
43
+ "CalendarEvent": {
44
+ "field_sets": ["fields_1"],
45
+ "ontology_class": "Event",
46
+ },
47
+ "File": {
48
+ "field_sets": ["fields_1"],
49
+ "ontology_class": "File",
50
+ },
51
+ "Folder": {
52
+ "field_sets": ["fields_1"],
53
+ "ontology_class": None,
54
+ },
55
+ "Share": {
56
+ "field_sets": ["fields_1"],
57
+ "ontology_class": None,
58
+ },
59
+ }
60
+
61
+ RESOURCES: tuple[dict[str, str], ...] = (
62
+ {
63
+ "id_prefix": "calendarevent",
64
+ "label": "Calendar Event",
65
+ "name": "CalendarEvent",
66
+ },
67
+ {
68
+ "id_prefix": "file",
69
+ "label": "Nextcloud File",
70
+ "name": "File",
71
+ },
72
+ {
73
+ "id_prefix": "folder",
74
+ "label": "Nextcloud Folder",
75
+ "name": "Folder",
76
+ },
77
+ {
78
+ "id_prefix": "share",
79
+ "label": "Nextcloud Share",
80
+ "name": "Share",
81
+ },
82
+ )
@@ -17,65 +17,11 @@ import posixpath
17
17
  from typing import Any
18
18
 
19
19
  from agent_connector_sdk.ingest import (
20
- ChangeSet,
21
- Entity,
22
- IngestBinding,
23
- IngestError,
24
20
  KnowledgeIngest,
25
- Relationship,
26
- current_ingest,
21
+ SourceStream,
27
22
  )
28
23
 
29
- _BINDING = IngestBinding(connector="nextcloud-mcp", stream="nextcloud")
30
-
31
- _ENTITY_RESERVED_KEYS = frozenset({"id", "node_type"})
32
- _RELATIONSHIP_RESERVED_KEYS = frozenset({"source", "target", "relationship"})
33
-
34
-
35
- def _to_entity(record: dict[str, Any]) -> Entity:
36
- return Entity(
37
- id=record.get("id"),
38
- node_type=record.get("node_type"),
39
- properties={
40
- key: value
41
- for key, value in record.items()
42
- if key not in _ENTITY_RESERVED_KEYS
43
- },
44
- )
45
-
46
-
47
- def _to_relationship(record: dict[str, Any]) -> Relationship:
48
- properties = {
49
- key: value
50
- for key, value in record.items()
51
- if key not in _RELATIONSHIP_RESERVED_KEYS
52
- }
53
- return Relationship(
54
- source=record["source"],
55
- target=record["target"],
56
- relationship=record["relationship"],
57
- properties=properties or None,
58
- )
59
-
60
-
61
- async def _ingest(
62
- entities: list[dict[str, Any]],
63
- relationships: list[dict[str, Any]] | None = None,
64
- *,
65
- ingest: KnowledgeIngest | None = None,
66
- ) -> dict[str, int]:
67
- """Route typed nodes/edges through the SDK ingest facade (injectable for tests)."""
68
- if not entities:
69
- raise IngestError("ingest needs at least one entity")
70
- change_set = ChangeSet(
71
- entities=tuple(_to_entity(entity) for entity in entities),
72
- relationships=tuple(
73
- _to_relationship(relationship) for relationship in relationships or ()
74
- ),
75
- )
76
- service = ingest or current_ingest()
77
- receipt = await service.submit(_BINDING, change_set)
78
- return {"nodes": receipt.affected_count, "edges": receipt.relationship_count}
24
+ STREAM = SourceStream.for_package(__package__.split(".")[0], "nextcloud")
79
25
 
80
26
 
81
27
  async def ingest_listing(
@@ -143,7 +89,7 @@ async def ingest_listing(
143
89
  {"source": node["id"], "target": parent_id, "relationship": "inFolder"}
144
90
  )
145
91
 
146
- return await _ingest(entities, relationships, ingest=ingest)
92
+ return await STREAM.entities(entities, relationships, ingest=ingest)
147
93
 
148
94
 
149
95
  async def ingest_shares(
@@ -192,7 +138,7 @@ async def ingest_shares(
192
138
  )
193
139
  if not entities:
194
140
  return None
195
- return await _ingest(entities, relationships, ingest=ingest)
141
+ return await STREAM.entities(entities, relationships, ingest=ingest)
196
142
 
197
143
 
198
144
  async def ingest_calendar_events(
@@ -218,4 +164,4 @@ async def ingest_calendar_events(
218
164
  )
219
165
  if not entities:
220
166
  return None
221
- return await _ingest(entities, None, ingest=ingest)
167
+ return await STREAM.entities(entities, None, ingest=ingest)
@@ -3,7 +3,6 @@ import warnings
3
3
 
4
4
  from fastmcp import Context, FastMCP
5
5
  from fastmcp.dependencies import Depends
6
- from fastmcp.utilities.logging import get_logger
7
6
  from pydantic import Field
8
7
 
9
8
  # Filter RequestsDependencyWarning early to prevent log spam
@@ -19,26 +18,12 @@ with warnings.catch_warnings():
19
18
  warnings.filterwarnings("ignore", message=".*urllib3.*or chardet.*")
20
19
  warnings.filterwarnings("ignore", message=".*urllib3.*or charset_normalizer.*")
21
20
 
22
- import logging
23
- import sys
24
- from typing import Any
25
21
 
26
- from agent_connector_sdk.config import load_config
27
22
  from agent_connector_sdk.mcp.action_dispatch import resolve_action
28
23
  from agent_connector_sdk.mcp.concurrency import run_blocking
29
- from agent_connector_sdk.mcp.server import create_mcp_server
30
- from agent_connector_sdk.mcp.tool_surface import register_tool_surface
31
- from starlette.requests import Request
32
- from starlette.responses import JSONResponse
33
24
 
34
- from nextcloud_agent.api_client import NextcloudAPI
35
25
  from nextcloud_agent.auth import get_client
36
26
 
37
- __version__ = "2.3.3"
38
-
39
- logger = get_logger(name="nextcloud-agent")
40
- logger.setLevel(logging.INFO)
41
-
42
27
 
43
28
  def register_files_tools(mcp: FastMCP):
44
29
  """
@@ -303,56 +288,3 @@ def register_contacts_tools(mcp: FastMCP):
303
288
  if action == "create_contact":
304
289
  return await run_blocking(client.create_contact, **kwargs)
305
290
  raise ValueError(f"Unknown action: {action}")
306
-
307
-
308
- def get_mcp_instance() -> tuple[Any, ...]:
309
- """
310
- Initialize and return the MCP instance.
311
- """
312
- load_config()
313
- args, mcp, middlewares = create_mcp_server(
314
- name="nextcloud-agent MCP",
315
- version=__version__,
316
- instructions="nextcloud-agent MCP Server — Condensed Action-Routed Tools.",
317
- )
318
-
319
- @mcp.custom_route("/health", methods=["GET"])
320
- async def health_check(request: Request) -> JSONResponse:
321
- return JSONResponse({"status": "OK"})
322
-
323
- register_tool_surface(
324
- mcp,
325
- client_cls=NextcloudAPI,
326
- get_client=get_client,
327
- service="nextcloud-agent",
328
- tools_module=sys.modules[__name__],
329
- )
330
-
331
- for mw in middlewares:
332
- mcp.add_middleware(mw)
333
- return mcp, args, middlewares
334
-
335
-
336
- def mcp_server() -> None:
337
- """
338
- Launch the MCP server process.
339
- """
340
- mcp, args, middlewares = get_mcp_instance()
341
- print(f"nextcloud-agent MCP v{__version__}", file=sys.stderr)
342
- print("\nStarting MCP Server", file=sys.stderr)
343
- print(f" Transport: {args.transport.upper()}", file=sys.stderr)
344
- print(f" Auth: {args.auth_type}", file=sys.stderr)
345
-
346
- if args.transport == "stdio":
347
- mcp.run(transport="stdio")
348
- elif args.transport == "streamable-http":
349
- mcp.run(transport="streamable-http", host=args.host, port=args.port)
350
- elif args.transport == "sse":
351
- mcp.run(transport="sse", host=args.host, port=args.port)
352
- else:
353
- logger.error("Invalid transport", extra={"transport": args.transport})
354
- sys.exit(1)
355
-
356
-
357
- if __name__ == "__main__":
358
- mcp_server()
@@ -1,10 +1,10 @@
1
1
  {
2
- "api_version": "arbora.io/v1",
2
+ "api_version": "graphos.io/v1",
3
3
  "artifacts": {
4
4
  "nextcloud_agent/ontology/fixtures/records.json": "aeff7048eae4bc5068dcd2070ad0f0e02b1de63bf9fd5dbecf6a51c5ebd26dc7",
5
- "nextcloud_agent/ontology/mappings/source.yaml": "eac08da9aa72d040d223652f0d55ec6b3847527630fde0291601e1b77b216739",
5
+ "nextcloud_agent/ontology/mappings/source.yaml": "88a1d3c331f53626adcb3998eb8f262a33a59065ad8f99ad70e7a82a14c41d49",
6
6
  "nextcloud_agent/ontology/migrations/manifest.json": "25716b991f14c59cc202177dfa6d410b396e18a5c9accc92238e5433825535e7",
7
- "nextcloud_agent/ontology/nextcloud.ttl": "1f2f60e44e2e7f49bb86365d488668ce08724f114e67364d21ec302fcc516956",
7
+ "nextcloud_agent/ontology/nextcloud.ttl": "19a6a86795f930ab216e58fa59f02aa4f26ccf0cd08a3dee859383b640d1f30f",
8
8
  "nextcloud_agent/ontology/shapes/connector.shacl.ttl": "9a8192289bd6b9a24b4d215cf0fe0391d7e706cf461704dff4c537b5f82724f6"
9
9
  },
10
10
  "checks": {
@@ -15,11 +15,11 @@
15
15
  "synthetic_fixture_contract": "passed"
16
16
  },
17
17
  "compatibility": {
18
- "agent_connector_sdk": ">=2.5.0,<3",
18
+ "agent_utilities": ">=2.5.0,<3",
19
19
  "bundle_schema": "2",
20
20
  "epistemic_graph": ">=2.27.0,<3"
21
21
  },
22
- "connector": "nextcloud-mcp",
22
+ "connector": "nextcloud-agent",
23
23
  "kind": "ConnectorSourceAttestation",
24
24
  "live_certified": false,
25
25
  "mode": "offline-source",
@@ -29,5 +29,5 @@
29
29
  "signer": "UNSIGNED-PREVIEW",
30
30
  "signing_public_key": "",
31
31
  "status": "source-validated",
32
- "validated_at": "2026-08-26T13:42:55Z"
32
+ "validated_at": "2026-10-26T23:16:19Z"
33
33
  }
@@ -1,5 +1,5 @@
1
1
  schema_version: '1'
2
- connector: nextcloud-agent
2
+ connector: nextcloud-mcp
3
3
  ontology_source: nextcloud
4
4
  sync:
5
5
  - preset: nextcloud-files
@@ -0,0 +1,123 @@
1
+ ---
2
+ name: nextcloud-agent-development
3
+ skill_type: skill
4
+ description: >-
5
+ Develop and verify nextcloud-agent as a connector-owned package while preserving
6
+ its SDK Connector wiring, action-routed MCP tools, Nextcloud authentication and
7
+ TLS boundary, packaged content, and source-backed spec-delivery publication.
8
+ ---
9
+
10
+ # Nextcloud Agent Development
11
+
12
+ Use this skill for changes to the `nextcloud-agent` connector. The package owns
13
+ Nextcloud API calls, mappings, MCP tools, and connector content; it does not own
14
+ the connector SDK, Arbora admission, the shared Pages renderer, or Pipelines
15
+ hooks.
16
+
17
+ ## Repository map and runtime boundary
18
+
19
+ - `nextcloud_agent/__init__.py` creates the SDK `Connector` with `NextcloudAPI`,
20
+ `get_client`, and `nextcloud_agent.mcp_server` as its tool module. Preserve this
21
+ wiring when changing a client or tool.
22
+ - `nextcloud_agent/mcp_server.py` registers the condensed action-routed tools
23
+ `nextcloud_files`, `nextcloud_user`, `nextcloud_sharing`, `nextcloud_calendar`,
24
+ and `nextcloud_contacts`. Their action lists and client calls are the runtime
25
+ contract; the domain clients live under `nextcloud_agent/api/` and are composed
26
+ by `nextcloud_agent/api/__init__.py`.
27
+ - `nextcloud_agent/auth.py` reads `NEXTCLOUD_URL`, `NEXTCLOUD_USERNAME`, and
28
+ `NEXTCLOUD_PASSWORD` through the SDK setting boundary. The API client resolves
29
+ the named `nextcloud` TLS profile through the SDK and configures a verified,
30
+ same-origin requests session; preserve that transport boundary and its cleanup.
31
+ - `nextcloud_agent/ontology/`, `nextcloud_agent/prompts/`, and
32
+ `nextcloud_agent/skills/` contain connector content. The package-data table in
33
+ `pyproject.toml` declares those trees plus `agent_data/**` and `connectors/**`;
34
+ inspect a built wheel when changing packaged content.
35
+ - The current `pyproject.toml` declares `nextcloud-mcp` as its console script and
36
+ `nextcloud-mcp` as its connector identity. Older README, AGENTS, and deployment
37
+ examples mention a `nextcloud-agent` console script and `agent_server.py`, but
38
+ those are not declared or present in this source tree. Do not invent that
39
+ runtime or rewrite it as part of a Pages/skill change.
40
+
41
+ ## Rapid delivery: the 5-minute contract
42
+
43
+ 1. Read the owning `specs/` row and this repository's `AGENTS.md` before editing.
44
+ 2. Inspect the active client/tool path and focused tests before changing API
45
+ behavior, auth, ontology content, or packaged skills.
46
+ 3. Prefer the smallest connector-owned change. Preserve action names, parameter
47
+ schemas, SDK `Connector` wiring, Nextcloud credentials, TLS verification,
48
+ same-origin checks, and package-data declarations unless the owning requirement
49
+ changes them.
50
+ 4. Run focused tests through the narrow test-slot wrapper, then run the repository
51
+ pre-commit and pre-push gates without bypasses.
52
+ 5. For public packaged content, bump the patch version and refresh `uv.lock`
53
+ together; inspect the built wheel for the new skill.
54
+ 6. Treat Pages as a separate proof: after the exact main SHA has a successful
55
+ Pages run, check `/spec-delivery/`, its `index.html`, and `snapshot.json` over
56
+ HTTPS and record the revision from the snapshot.
57
+
58
+ ## Focused development commands
59
+
60
+ From the repository root:
61
+
62
+ ```bash
63
+ uv sync --locked
64
+
65
+ /var/tmp/arbora-delivery/scale/run-narrow-test-slot.sh \
66
+ uv run --locked --extra test pytest -q \
67
+ tests/test_init.py \
68
+ tests/test_init_dynamics.py \
69
+ tests/test_auth.py \
70
+ tests/test_api_client.py \
71
+ tests/test_mcp_server.py \
72
+ tests/test_kg_ingest.py \
73
+ tests/test_xml_security.py \
74
+ tests/test_fleet_name.py \
75
+ tests/test_publication_workflow.py
76
+
77
+ uvx pre-commit run --all-files
78
+ uvx pre-commit run --all-files --hook-stage pre-push
79
+ ```
80
+
81
+ These checks cover SDK server construction, runtime entry points, action
82
+ dispatch, authentication, XML security, ingestion, fleet identity, and the
83
+ Pages/release contract. Do not replace them with a live Nextcloud call or a
84
+ credential-bearing test.
85
+
86
+ ## Pages and package publication
87
+
88
+ `.github/workflows/pages.yml` is the one Pages caller. It invokes the shared
89
+ Pipelines `pages_pipeline.yml@main` with `content_source: docs` and the version 1
90
+ `.github/spec-dashboard.json` source declaration for `specs/*/status.json`.
91
+ Keep manual dispatch and the docs/spec/config/workflow path filters. The old direct
92
+ `mkdocs gh-deploy` publisher must not be restored because it would compete with the
93
+ shared dashboard build.
94
+
95
+ After a merge, verify the exact main SHA in the successful Pages run and probe:
96
+
97
+ ```bash
98
+ curl -fsSI https://knuckles-team.github.io/nextcloud-agent/
99
+ curl -fsSI https://knuckles-team.github.io/nextcloud-agent/spec-delivery/
100
+ curl -fsSI https://knuckles-team.github.io/nextcloud-agent/spec-delivery/index.html
101
+ curl -fsS https://knuckles-team.github.io/nextcloud-agent/spec-delivery/snapshot.json
102
+ ```
103
+
104
+ Keep `.github/workflows/pipeline.yml` on the shared `connector: true` and
105
+ `render_connector: true` flags. Central generation owns generated connector
106
+ manifests and release container artifacts; preserve this package's existing
107
+ runtime, auth, and port semantics and inspect generated output before making
108
+ claims.
109
+
110
+ ## Change discipline
111
+
112
+ - Keep Nextcloud API calls, request models, ontology mappings, MCP schemas, and
113
+ ingestion declarations under this repository's `CONN-NEXTCLOUD-AGENT-*` boundary.
114
+ SDK transport and central renderer behavior belong to their owner repositories.
115
+ - Use `NEXTCLOUD_URL`, `NEXTCLOUD_USERNAME`, and `NEXTCLOUD_PASSWORD` only in
116
+ injected runtime configuration; never print or commit their values. Preserve
117
+ TLS certificate verification, same-origin checks, and the SDK-resolved named
118
+ profile path.
119
+ - For mutations, inspect current state first, require operator approval where the
120
+ existing connector procedure calls for it, and verify the result. Keep KG
121
+ ingestion opt-in and preserve its provenance/tenant contract.
122
+ - Keep generated status changes and central promotion with the Pipelines/status
123
+ owner. Do not claim Pages or public package results from a local build.
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nextcloud-agent
3
- Version: 2.3.3
3
+ Version: 2.3.5
4
4
  Summary: Nextcloud MCP Server for Agentic AI!
5
- Author-email: Project Maintainers <maintainers@users.noreply.github.com>
5
+ Author-email: Repository Maintainers <maintainers@knuckles.team>
6
6
  License: MIT
7
7
  Classifier: Development Status :: 3 - Alpha
8
8
  Classifier: License :: OSI Approved :: MIT License
@@ -12,16 +12,12 @@ 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]<1.0.0,>=0.4.1
15
+ Requires-Dist: agent-connector-sdk[mcp]<0.6.0,>=0.5.4
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
19
19
  Requires-Dist: icalendar>=7.3.0
20
20
  Requires-Dist: vobject>=0.9.9
21
- Provides-Extra: mcp
22
- Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1; extra == "mcp"
23
- Provides-Extra: all
24
- Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1; extra == "all"
25
21
  Provides-Extra: test
26
22
  Requires-Dist: pytest-xdist>=3.8.0; extra == "test"
27
23
  Requires-Dist: pytest>=9.1.1; extra == "test"
@@ -51,8 +47,6 @@ Dynamic: license-file
51
47
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/nextcloud-agent)
52
48
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/nextcloud-agent)
53
49
 
54
- *Version: 2.3.3*
55
-
56
50
  > **Documentation** — Installation, deployment, usage across the API, CLI, and MCP
57
51
  > interfaces, and guidance for provisioning the backing Nextcloud instance are
58
52
  > maintained in the [official documentation](https://knuckles-team.github.io/nextcloud-agent/).
@@ -21,7 +21,6 @@ nextcloud_agent/api/api_client_calendar.py
21
21
  nextcloud_agent/api/api_client_contacts.py
22
22
  nextcloud_agent/api/api_client_files.py
23
23
  nextcloud_agent/api/xml_security.py
24
- nextcloud_agent/connectors/__init__.py
25
24
  nextcloud_agent/ontology/__init__.py
26
25
  nextcloud_agent/ontology/certification.json
27
26
  nextcloud_agent/ontology/nextcloud.ttl
@@ -29,9 +28,8 @@ nextcloud_agent/ontology/fixtures/records.json
29
28
  nextcloud_agent/ontology/mappings/source.yaml
30
29
  nextcloud_agent/ontology/migrations/manifest.json
31
30
  nextcloud_agent/ontology/shapes/connector.shacl.ttl
32
- nextcloud_agent/prompts/__init__.py
33
31
  nextcloud_agent/prompts/file_steward.json
34
- nextcloud_agent/skills/__init__.py
32
+ nextcloud_agent/skills/nextcloud-agent-development/SKILL.md
35
33
  nextcloud_agent/skills/nextcloud-agent-operations/SKILL.md
36
34
  nextcloud_agent/skills/nextcloud-agent-operations/agents/openai.yaml
37
35
  nextcloud_agent/skills/nextcloud-agent-operations/references/catalog.md
@@ -41,16 +39,13 @@ nextcloud_agent/skills/nextcloud-ingest/SKILL.md
41
39
  nextcloud_agent/skills/nextcloud-ingest/WORKFLOW.md
42
40
  nextcloud_agent/skills/nextcloud-shares/SKILL.md
43
41
  nextcloud_agent/skills/nextcloud-shares/WORKFLOW.md
44
- scripts/security_sanitizer.py
45
- scripts/verify_api_integration.py
46
42
  tests/conftest.py
47
43
  tests/test_api_client.py
48
44
  tests/test_auth.py
49
- tests/test_cli_server.py
50
- tests/test_default_content_surfaces.py
51
45
  tests/test_fleet_name.py
52
46
  tests/test_init.py
53
47
  tests/test_init_dynamics.py
54
48
  tests/test_kg_ingest.py
55
49
  tests/test_mcp_server.py
50
+ tests/test_publication_workflow.py
56
51
  tests/test_xml_security.py
@@ -0,0 +1,8 @@
1
+ [agent_connector_sdk.connector]
2
+ nextcloud-mcp = nextcloud_agent:connector
3
+
4
+ [agent_connector_sdk.prompt_providers]
5
+ nextcloud-agent = nextcloud_agent.prompts
6
+
7
+ [console_scripts]
8
+ nextcloud-mcp = agent_connector_sdk.cli:serve
@@ -1,16 +1,10 @@
1
- agent-connector-sdk[mcp]<1.0.0,>=0.4.1
1
+ agent-connector-sdk[mcp]<0.6.0,>=0.5.4
2
2
  requests>=2.34.2
3
3
  defusedxml>=0.7.1
4
4
  python-dateutil>=2.9.0.post0
5
5
  icalendar>=7.3.0
6
6
  vobject>=0.9.9
7
7
 
8
- [all]
9
- agent-connector-sdk[mcp]<1.0.0,>=0.4.1
10
-
11
- [mcp]
12
- agent-connector-sdk[mcp]<1.0.0,>=0.4.1
13
-
14
8
  [test]
15
9
  pytest-xdist>=3.8.0
16
10
  pytest>=9.1.1
@@ -4,6 +4,5 @@ dist-sdist
4
4
  docker
5
5
  docs
6
6
  nextcloud_agent
7
- scripts
8
7
  specs
9
8
  tests