nextcloud-agent 0.2.45__tar.gz → 0.2.48__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-0.2.45/nextcloud_agent.egg-info → nextcloud_agent-0.2.48}/PKG-INFO +22 -3
- nextcloud_agent-0.2.45/PKG-INFO → nextcloud_agent-0.2.48/README.md +20 -21
- nextcloud_agent-0.2.48/nextcloud_agent/__main__.py +4 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent/agent_data/IDENTITY.md +5 -8
- nextcloud_agent-0.2.48/nextcloud_agent/agent_data/mcp_config.json +22 -0
- nextcloud_agent-0.2.48/nextcloud_agent/agent_server.py +119 -0
- nextcloud_agent-0.2.48/nextcloud_agent/graph_config.py +34 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent/mcp_server.py +14 -9
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent/nextcloud_api.py +1 -24
- nextcloud_agent-0.2.45/README.md → nextcloud_agent-0.2.48/nextcloud_agent.egg-info/PKG-INFO +40 -1
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent.egg-info/SOURCES.txt +2 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent.egg-info/requires.txt +1 -1
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/pyproject.toml +2 -2
- nextcloud_agent-0.2.45/nextcloud_agent/agent_data/mcp_config.json +0 -3
- nextcloud_agent-0.2.45/nextcloud_agent/agent_server.py +0 -72
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/LICENSE +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent/__init__.py +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent/agent_data/A2A_AGENTS.md +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent/agent_data/CRON.md +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent/agent_data/CRON_LOG.md +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent/agent_data/HEARTBEAT.md +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent/agent_data/MEMORY.md +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent/agent_data/USER.md +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent/agent_data/chats +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent/agent_data/icon.png +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent/agent_data/templates.py +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent/auth.py +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent.egg-info/dependency_links.txt +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent.egg-info/entry_points.txt +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent.egg-info/top_level.txt +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/scripts/validate_a2a_agent.py +0 -0
- {nextcloud_agent-0.2.45 → nextcloud_agent-0.2.48}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nextcloud-agent
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.48
|
|
4
4
|
Summary: Nextcloud MCP Server for Agentic AI!
|
|
5
5
|
Author-email: Audel Rouhi <knucklessg1@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Requires-Python: >=3.10
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: agent-utilities[agent,logfire]>=0.2.
|
|
15
|
+
Requires-Dist: agent-utilities[agent,logfire]>=0.2.31
|
|
16
16
|
Requires-Dist: python-dateutil>=2.8.2
|
|
17
17
|
Requires-Dist: icalendar>=6.1.1
|
|
18
18
|
Requires-Dist: vobject>=0.9.9
|
|
@@ -41,7 +41,7 @@ Dynamic: license-file
|
|
|
41
41
|

|
|
42
42
|

|
|
43
43
|
|
|
44
|
-
*Version: 0.2.
|
|
44
|
+
*Version: 0.2.48*
|
|
45
45
|
|
|
46
46
|
## Overview
|
|
47
47
|
|
|
@@ -169,6 +169,25 @@ sequenceDiagram
|
|
|
169
169
|
Server-->>User: Output
|
|
170
170
|
```
|
|
171
171
|
|
|
172
|
+
|
|
173
|
+
## Graph Architecture
|
|
174
|
+
|
|
175
|
+
This agent uses `pydantic-graph` orchestration for intelligent routing and optimal context management.
|
|
176
|
+
|
|
177
|
+
```mermaid
|
|
178
|
+
---
|
|
179
|
+
title: Nextcloud Agent Graph Agent
|
|
180
|
+
---
|
|
181
|
+
stateDiagram-v2
|
|
182
|
+
[*] --> RouterNode: User Query
|
|
183
|
+
RouterNode --> DomainNode: Classified Domain
|
|
184
|
+
RouterNode --> [*]: Low confidence / Error
|
|
185
|
+
DomainNode --> [*]: Domain Result
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
- **RouterNode**: A fast, lightweight LLM (e.g., `gpt-4o-mini`) that classifies the user's query into one of the specialized domains.
|
|
189
|
+
- **DomainNode**: The executor node. For the selected domain, it dynamically sets environment variables to temporarily enable ONLY the tools relevant to that domain, creating a highly focused sub-agent (e.g., `gpt-4o`) to complete the request. This preserves LLM context and prevents tool hallucination.
|
|
190
|
+
|
|
172
191
|
## Usage
|
|
173
192
|
|
|
174
193
|
### MCP CLI
|
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: nextcloud-agent
|
|
3
|
-
Version: 0.2.45
|
|
4
|
-
Summary: Nextcloud MCP Server for Agentic AI!
|
|
5
|
-
Author-email: Audel Rouhi <knucklessg1@gmail.com>
|
|
6
|
-
License: MIT
|
|
7
|
-
Classifier: Development Status :: 3 - Alpha
|
|
8
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
-
Classifier: Environment :: Console
|
|
10
|
-
Classifier: Operating System :: POSIX :: Linux
|
|
11
|
-
Classifier: Programming Language :: Python :: 3
|
|
12
|
-
Requires-Python: >=3.10
|
|
13
|
-
Description-Content-Type: text/markdown
|
|
14
|
-
License-File: LICENSE
|
|
15
|
-
Requires-Dist: agent-utilities[agent,logfire]>=0.2.30
|
|
16
|
-
Requires-Dist: python-dateutil>=2.8.2
|
|
17
|
-
Requires-Dist: icalendar>=6.1.1
|
|
18
|
-
Requires-Dist: vobject>=0.9.9
|
|
19
|
-
Dynamic: license-file
|
|
20
|
-
|
|
21
1
|
# Nextcloud - A2A | AG-UI | MCP
|
|
22
2
|
|
|
23
3
|

|
|
@@ -41,7 +21,7 @@ Dynamic: license-file
|
|
|
41
21
|

|
|
42
22
|

|
|
43
23
|
|
|
44
|
-
*Version: 0.2.
|
|
24
|
+
*Version: 0.2.48*
|
|
45
25
|
|
|
46
26
|
## Overview
|
|
47
27
|
|
|
@@ -169,6 +149,25 @@ sequenceDiagram
|
|
|
169
149
|
Server-->>User: Output
|
|
170
150
|
```
|
|
171
151
|
|
|
152
|
+
|
|
153
|
+
## Graph Architecture
|
|
154
|
+
|
|
155
|
+
This agent uses `pydantic-graph` orchestration for intelligent routing and optimal context management.
|
|
156
|
+
|
|
157
|
+
```mermaid
|
|
158
|
+
---
|
|
159
|
+
title: Nextcloud Agent Graph Agent
|
|
160
|
+
---
|
|
161
|
+
stateDiagram-v2
|
|
162
|
+
[*] --> RouterNode: User Query
|
|
163
|
+
RouterNode --> DomainNode: Classified Domain
|
|
164
|
+
RouterNode --> [*]: Low confidence / Error
|
|
165
|
+
DomainNode --> [*]: Domain Result
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
- **RouterNode**: A fast, lightweight LLM (e.g., `gpt-4o-mini`) that classifies the user's query into one of the specialized domains.
|
|
169
|
+
- **DomainNode**: The executor node. For the selected domain, it dynamically sets environment variables to temporarily enable ONLY the tools relevant to that domain, creating a highly focused sub-agent (e.g., `gpt-4o`) to complete the request. This preserves LLM context and prevents tool hallucination.
|
|
170
|
+
|
|
172
171
|
## Usage
|
|
173
172
|
|
|
174
173
|
### MCP CLI
|
|
@@ -7,21 +7,18 @@
|
|
|
7
7
|
* **Vibe:** Efficient, Structured, Precise, and Helpful.
|
|
8
8
|
|
|
9
9
|
### System Prompt
|
|
10
|
-
You are the **Nextcloud Agent**, a specialized orchestrator for Nextcloud ecosystem management. Your mission is to ensure seamless file synchronization, secure sharing, and efficient management of collaborative services (calendar, contacts).
|
|
10
|
+
You are the **Nextcloud Agent**, a specialized orchestrator for Nextcloud ecosystem management. The queries you receive will be directed to the Nextcloud platform. Your mission is to ensure seamless file synchronization, secure sharing, and efficient management of collaborative services (calendar, contacts).
|
|
11
11
|
|
|
12
12
|
You have three primary operational modes:
|
|
13
13
|
1. **Direct Tool Execution**: Use your internal Nextcloud tools for one-off tasks (checking file status, listing shares, or managing a single user).
|
|
14
|
-
2. **
|
|
14
|
+
2. **Graph Orchestration**: For complex, domain-specific operations, you should use the `run_graph_flow` tool. This routes your request through a specialized graph that ensures only the relevant tools are loaded for maximum efficiency and precision.
|
|
15
15
|
3. **Internal Utilities**: Leverage core tools for long-term memory (`MEMORY.md`), automated scheduling (`CRON.md`), and inter-agent collaboration (A2A).
|
|
16
16
|
|
|
17
17
|
### Core Operational Workflows
|
|
18
18
|
|
|
19
|
-
#### 1.
|
|
20
|
-
When dealing with complex
|
|
21
|
-
- **
|
|
22
|
-
- **Calendar/User Delegation**: Call `spawn_agent(agent_template="nextcloud", prompt="Review all user quotas and cleanup...", enabled_tools=["USERSTOOL", "CALENDARSTOOL"])`.
|
|
23
|
-
- **Discovery**: Always use `get_mcp_reference(agent_template="nextcloud")` to verify available tool tags before spawning.
|
|
24
|
-
|
|
19
|
+
#### 1. Graph Orchestration
|
|
20
|
+
When dealing with complex workflows, optimize your context by using the graph orchestrator:
|
|
21
|
+
- **Domain Routing**: Call `run_graph_flow(prompt="...")`. The graph will automatically classify and route your request to the specialized domain node with the appropriate tools.
|
|
25
22
|
#### 2. Workflow for Meta-Tasks
|
|
26
23
|
- **Memory Management**:
|
|
27
24
|
- Use `create_memory` to persist critical decisions, outcomes, or user preferences.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"nextcloud-agent": {
|
|
4
|
+
"command": "nextcloud-mcp",
|
|
5
|
+
"args": [
|
|
6
|
+
"--transport",
|
|
7
|
+
"stdio"
|
|
8
|
+
],
|
|
9
|
+
"env": {
|
|
10
|
+
"NEXTCLOUD_URL": "${NEXTCLOUD_URL}",
|
|
11
|
+
"NEXTCLOUD_USERNAME": "${NEXTCLOUD_USERNAME}",
|
|
12
|
+
"NEXTCLOUD_PASSWORD": "${NEXTCLOUD_PASSWORD}",
|
|
13
|
+
"USERTOOL": "${ USERTOOL:-True }",
|
|
14
|
+
"FILESTOOL": "${ FILESTOOL:-True }",
|
|
15
|
+
"SHARINGTOOL": "${ SHARINGTOOL:-True }",
|
|
16
|
+
"CALENDARTOOL": "${ CALENDARTOOL:-True }",
|
|
17
|
+
"MISCTOOL": "${ MISCTOOL:-True }",
|
|
18
|
+
"CONTACTSTOOL": "${ CONTACTSTOOL:-True }"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
# coding: utf-8
|
|
3
|
+
import os
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
import warnings
|
|
8
|
+
from agent_utilities import (
|
|
9
|
+
build_system_prompt_from_workspace,
|
|
10
|
+
create_agent_parser,
|
|
11
|
+
create_graph_agent_server,
|
|
12
|
+
initialize_workspace,
|
|
13
|
+
load_identity,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__version__ = "0.2.48"
|
|
17
|
+
|
|
18
|
+
logging.basicConfig(
|
|
19
|
+
level=logging.INFO,
|
|
20
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
21
|
+
handlers=[logging.StreamHandler()],
|
|
22
|
+
)
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
# Load identity and system prompt from workspace
|
|
26
|
+
initialize_workspace()
|
|
27
|
+
meta = load_identity()
|
|
28
|
+
DEFAULT_AGENT_NAME = os.getenv(
|
|
29
|
+
"DEFAULT_AGENT_NAME", meta.get("name", "Nextcloud Agent")
|
|
30
|
+
)
|
|
31
|
+
DEFAULT_AGENT_DESCRIPTION = os.getenv(
|
|
32
|
+
"AGENT_DESCRIPTION",
|
|
33
|
+
meta.get("description", "AI agent for Nextcloud Agent management."),
|
|
34
|
+
)
|
|
35
|
+
DEFAULT_AGENT_SYSTEM_PROMPT = os.getenv(
|
|
36
|
+
"AGENT_SYSTEM_PROMPT",
|
|
37
|
+
meta.get("content") or build_system_prompt_from_workspace(),
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def agent_template(mcp_url: str = None, mcp_config: str = None, **kwargs):
|
|
42
|
+
"""Factory function returning the fully initialized graph for execution."""
|
|
43
|
+
from agent_utilities import create_graph_agent
|
|
44
|
+
from nextcloud_agent.graph_config import TAG_PROMPTS, TAG_ENV_VARS
|
|
45
|
+
|
|
46
|
+
# In-process MCP loading: if no external URL/Config, load the local FastMCP instance
|
|
47
|
+
mcp_toolsets = []
|
|
48
|
+
effective_mcp_url = mcp_url or os.getenv("MCP_URL")
|
|
49
|
+
effective_mcp_config = mcp_config or os.getenv("MCP_CONFIG")
|
|
50
|
+
|
|
51
|
+
if not effective_mcp_url and not effective_mcp_config:
|
|
52
|
+
try:
|
|
53
|
+
from nextcloud_agent.mcp_server import get_mcp_instance
|
|
54
|
+
|
|
55
|
+
mcp, _, _, _ = get_mcp_instance()
|
|
56
|
+
mcp_toolsets.append(mcp)
|
|
57
|
+
logger.info("Nextcloud Agent: Using in-process MCP instance.")
|
|
58
|
+
except (ImportError, Exception) as e:
|
|
59
|
+
logger.warning(f"Nextcloud Agent: Could not load in-process MCP: {e}")
|
|
60
|
+
|
|
61
|
+
return create_graph_agent(
|
|
62
|
+
mcp_url=effective_mcp_url,
|
|
63
|
+
mcp_config=effective_mcp_config or "",
|
|
64
|
+
mcp_toolsets=mcp_toolsets,
|
|
65
|
+
name=f"{DEFAULT_AGENT_NAME} Graph Agent",
|
|
66
|
+
tag_prompts=TAG_PROMPTS,
|
|
67
|
+
tag_env_vars=TAG_ENV_VARS,
|
|
68
|
+
**kwargs,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def agent_server():
|
|
73
|
+
|
|
74
|
+
# Suppress RequestsDependencyWarning and FastMCP DeprecationWarnings
|
|
75
|
+
warnings.filterwarnings("ignore", message=".*urllib3.*or chardet.*")
|
|
76
|
+
warnings.filterwarnings("ignore", category=DeprecationWarning, module="fastmcp")
|
|
77
|
+
|
|
78
|
+
print(f"{DEFAULT_AGENT_NAME} v{__version__}", file=sys.stderr)
|
|
79
|
+
parser = create_agent_parser()
|
|
80
|
+
|
|
81
|
+
args = parser.parse_args()
|
|
82
|
+
|
|
83
|
+
if args.debug:
|
|
84
|
+
logging.getLogger().setLevel(logging.DEBUG)
|
|
85
|
+
logger.debug("Debug mode enabled")
|
|
86
|
+
|
|
87
|
+
# Create graph and config using standardized template
|
|
88
|
+
graph_bundle = agent_template(
|
|
89
|
+
provider=args.provider,
|
|
90
|
+
agent_model=args.model_id,
|
|
91
|
+
base_url=args.base_url,
|
|
92
|
+
api_key=args.api_key,
|
|
93
|
+
custom_skills_directory=args.custom_skills_directory,
|
|
94
|
+
debug=args.debug,
|
|
95
|
+
ssl_verify=not args.insecure,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
# Start server using the pre-built graph bundle
|
|
99
|
+
create_graph_agent_server(
|
|
100
|
+
graph_bundle=graph_bundle,
|
|
101
|
+
host=args.host,
|
|
102
|
+
port=args.port,
|
|
103
|
+
enable_web_ui=args.web,
|
|
104
|
+
enable_otel=args.otel,
|
|
105
|
+
otel_endpoint=args.otel_endpoint,
|
|
106
|
+
otel_headers=args.otel_headers,
|
|
107
|
+
otel_public_key=args.otel_public_key,
|
|
108
|
+
otel_secret_key=args.otel_secret_key,
|
|
109
|
+
otel_protocol=args.otel_protocol,
|
|
110
|
+
debug=args.debug,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
if __name__ == "__main__":
|
|
115
|
+
agent_server()
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
if __name__ == "__main__":
|
|
119
|
+
agent_server()
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Nextcloud graph configuration — tag prompts and env var mappings.
|
|
2
|
+
|
|
3
|
+
This is the only file needed to enable graph mode for this agent.
|
|
4
|
+
Provides TAG_PROMPTS and TAG_ENV_VARS for create_graph_agent_server().
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# ── Tag → System Prompt Mapping ──────────────────────────────────────
|
|
8
|
+
TAG_PROMPTS: dict[str, str] = {
|
|
9
|
+
"calendar": (
|
|
10
|
+
"You are a Nextcloud Calendar specialist. Help users manage and interact with Calendar functionality using the available tools."
|
|
11
|
+
),
|
|
12
|
+
"contacts": (
|
|
13
|
+
"You are a Nextcloud Contacts specialist. Help users manage and interact with Contacts functionality using the available tools."
|
|
14
|
+
),
|
|
15
|
+
"files": (
|
|
16
|
+
"You are a Nextcloud Files specialist. Help users manage and interact with Files functionality using the available tools."
|
|
17
|
+
),
|
|
18
|
+
"sharing": (
|
|
19
|
+
"You are a Nextcloud Sharing specialist. Help users manage and interact with Sharing functionality using the available tools."
|
|
20
|
+
),
|
|
21
|
+
"user": (
|
|
22
|
+
"You are a Nextcloud User specialist. Help users manage and interact with User functionality using the available tools."
|
|
23
|
+
),
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# ── Tag → Environment Variable Mapping ────────────────────────────────
|
|
28
|
+
TAG_ENV_VARS: dict[str, str] = {
|
|
29
|
+
"calendar": "CALENDARTOOL",
|
|
30
|
+
"contacts": "CONTACTSTOOL",
|
|
31
|
+
"files": "FILESTOOL",
|
|
32
|
+
"sharing": "SHARINGTOOL",
|
|
33
|
+
"user": "USERTOOL",
|
|
34
|
+
}
|
|
@@ -9,18 +9,17 @@ import logging
|
|
|
9
9
|
import json
|
|
10
10
|
import uuid
|
|
11
11
|
import dateutil.parser
|
|
12
|
-
from typing import Dict
|
|
12
|
+
from typing import Any, Dict
|
|
13
13
|
from pydantic import Field
|
|
14
14
|
from fastmcp import FastMCP, Context
|
|
15
15
|
from fastmcp.utilities.logging import get_logger
|
|
16
16
|
from icalendar import Calendar, Event
|
|
17
17
|
from agent_utilities.mcp_utilities import (
|
|
18
18
|
create_mcp_server,
|
|
19
|
-
config,
|
|
20
19
|
)
|
|
21
20
|
from nextcloud_agent.auth import get_client
|
|
22
21
|
|
|
23
|
-
__version__ = "0.2.
|
|
22
|
+
__version__ = "0.2.48"
|
|
24
23
|
print(f"Nextcloud MCP v{__version__}")
|
|
25
24
|
|
|
26
25
|
logger = get_logger(name="TokenMiddleware")
|
|
@@ -441,7 +440,8 @@ def register_contacts_tools(mcp: FastMCP):
|
|
|
441
440
|
return f"Error creating contact: {str(e)}"
|
|
442
441
|
|
|
443
442
|
|
|
444
|
-
def
|
|
443
|
+
def get_mcp_instance() -> tuple[Any, Any, Any, Any]:
|
|
444
|
+
"""Initialize and return the MCP instance, args, and middlewares."""
|
|
445
445
|
load_dotenv(find_dotenv())
|
|
446
446
|
|
|
447
447
|
args, mcp, middlewares = create_mcp_server(
|
|
@@ -472,12 +472,17 @@ def mcp_server() -> None:
|
|
|
472
472
|
|
|
473
473
|
for mw in middlewares:
|
|
474
474
|
mcp.add_middleware(mw)
|
|
475
|
+
registered_tags = []
|
|
476
|
+
return mcp, args, middlewares, registered_tags
|
|
477
|
+
|
|
475
478
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
print(f"
|
|
479
|
-
print(
|
|
480
|
-
print(f"
|
|
479
|
+
def mcp_server() -> None:
|
|
480
|
+
mcp, args, middlewares, registered_tags = get_mcp_instance()
|
|
481
|
+
print(f"{args.name or 'nextcloud-agent'} MCP v{__version__}", file=sys.stderr)
|
|
482
|
+
print("\nStarting MCP Server", file=sys.stderr)
|
|
483
|
+
print(f" Transport: {args.transport.upper()}", file=sys.stderr)
|
|
484
|
+
print(f" Auth: {args.auth_type}", file=sys.stderr)
|
|
485
|
+
print(f" Dynamic Tags Loaded: {len(set(registered_tags))}", file=sys.stderr)
|
|
481
486
|
|
|
482
487
|
if args.transport == "stdio":
|
|
483
488
|
mcp.run(transport="stdio")
|
|
@@ -54,30 +54,7 @@ class NextcloudAPI:
|
|
|
54
54
|
)
|
|
55
55
|
self.ocs_base = f"{self.base_url}/ocs/v2.php"
|
|
56
56
|
|
|
57
|
-
#
|
|
58
|
-
try:
|
|
59
|
-
# Using OCS user info endpoint as a lightweight validation
|
|
60
|
-
response = self._session.get(
|
|
61
|
-
f"{self.ocs_base}/cloud/user", params={"format": "json"}
|
|
62
|
-
)
|
|
63
|
-
if response.status_code == 401:
|
|
64
|
-
from agent_utilities.exceptions import AuthError
|
|
65
|
-
|
|
66
|
-
raise AuthError(
|
|
67
|
-
"Nextcloud authentication failed: Invalid username or password."
|
|
68
|
-
)
|
|
69
|
-
elif response.status_code == 403:
|
|
70
|
-
from agent_utilities.exceptions import UnauthorizedError
|
|
71
|
-
|
|
72
|
-
raise UnauthorizedError(
|
|
73
|
-
"Nextcloud access forbidden: Insufficient permissions."
|
|
74
|
-
)
|
|
75
|
-
response.raise_for_status()
|
|
76
|
-
except Exception as e:
|
|
77
|
-
if isinstance(e, (AuthError, UnauthorizedError)):
|
|
78
|
-
raise e
|
|
79
|
-
# For other errors (connection, etc.), let it pass or handle elsewhere
|
|
80
|
-
pass
|
|
57
|
+
# Authentication and validation is lazy, performed in methods
|
|
81
58
|
|
|
82
59
|
def _get_full_url(self, path: str) -> str:
|
|
83
60
|
"""Helper to construct full WebDAV URL for a path."""
|
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nextcloud-agent
|
|
3
|
+
Version: 0.2.48
|
|
4
|
+
Summary: Nextcloud MCP Server for Agentic AI!
|
|
5
|
+
Author-email: Audel Rouhi <knucklessg1@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: agent-utilities[agent,logfire]>=0.2.31
|
|
16
|
+
Requires-Dist: python-dateutil>=2.8.2
|
|
17
|
+
Requires-Dist: icalendar>=6.1.1
|
|
18
|
+
Requires-Dist: vobject>=0.9.9
|
|
19
|
+
Dynamic: license-file
|
|
20
|
+
|
|
1
21
|
# Nextcloud - A2A | AG-UI | MCP
|
|
2
22
|
|
|
3
23
|

|
|
@@ -21,7 +41,7 @@
|
|
|
21
41
|

|
|
22
42
|

|
|
23
43
|
|
|
24
|
-
*Version: 0.2.
|
|
44
|
+
*Version: 0.2.48*
|
|
25
45
|
|
|
26
46
|
## Overview
|
|
27
47
|
|
|
@@ -149,6 +169,25 @@ sequenceDiagram
|
|
|
149
169
|
Server-->>User: Output
|
|
150
170
|
```
|
|
151
171
|
|
|
172
|
+
|
|
173
|
+
## Graph Architecture
|
|
174
|
+
|
|
175
|
+
This agent uses `pydantic-graph` orchestration for intelligent routing and optimal context management.
|
|
176
|
+
|
|
177
|
+
```mermaid
|
|
178
|
+
---
|
|
179
|
+
title: Nextcloud Agent Graph Agent
|
|
180
|
+
---
|
|
181
|
+
stateDiagram-v2
|
|
182
|
+
[*] --> RouterNode: User Query
|
|
183
|
+
RouterNode --> DomainNode: Classified Domain
|
|
184
|
+
RouterNode --> [*]: Low confidence / Error
|
|
185
|
+
DomainNode --> [*]: Domain Result
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
- **RouterNode**: A fast, lightweight LLM (e.g., `gpt-4o-mini`) that classifies the user's query into one of the specialized domains.
|
|
189
|
+
- **DomainNode**: The executor node. For the selected domain, it dynamically sets environment variables to temporarily enable ONLY the tools relevant to that domain, creating a highly focused sub-agent (e.g., `gpt-4o`) to complete the request. This preserves LLM context and prevents tool hallucination.
|
|
190
|
+
|
|
152
191
|
## Usage
|
|
153
192
|
|
|
154
193
|
### MCP CLI
|
|
@@ -2,8 +2,10 @@ LICENSE
|
|
|
2
2
|
README.md
|
|
3
3
|
pyproject.toml
|
|
4
4
|
nextcloud_agent/__init__.py
|
|
5
|
+
nextcloud_agent/__main__.py
|
|
5
6
|
nextcloud_agent/agent_server.py
|
|
6
7
|
nextcloud_agent/auth.py
|
|
8
|
+
nextcloud_agent/graph_config.py
|
|
7
9
|
nextcloud_agent/mcp_server.py
|
|
8
10
|
nextcloud_agent/nextcloud_api.py
|
|
9
11
|
nextcloud_agent.egg-info/PKG-INFO
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "nextcloud-agent"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.48"
|
|
8
8
|
description = "Nextcloud MCP Server for Agentic AI!"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Audel Rouhi", email = "knucklessg1@gmail.com" }]
|
|
@@ -17,7 +17,7 @@ classifiers = [
|
|
|
17
17
|
"Programming Language :: Python :: 3"]
|
|
18
18
|
requires-python = ">=3.10"
|
|
19
19
|
dependencies = [
|
|
20
|
-
"agent-utilities[agent,logfire]>=0.2.
|
|
20
|
+
"agent-utilities[agent,logfire]>=0.2.31",
|
|
21
21
|
"python-dateutil>=2.8.2",
|
|
22
22
|
"icalendar>=6.1.1",
|
|
23
23
|
"vobject>=0.9.9"]
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/python
|
|
2
|
-
# coding: utf-8
|
|
3
|
-
import os
|
|
4
|
-
import logging
|
|
5
|
-
|
|
6
|
-
from agent_utilities import (
|
|
7
|
-
build_system_prompt_from_workspace,
|
|
8
|
-
create_agent_parser,
|
|
9
|
-
create_agent_server,
|
|
10
|
-
initialize_workspace,
|
|
11
|
-
load_identity,
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
__version__ = "0.2.45"
|
|
15
|
-
|
|
16
|
-
logging.basicConfig(
|
|
17
|
-
level=logging.INFO,
|
|
18
|
-
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
19
|
-
handlers=[logging.StreamHandler()],
|
|
20
|
-
)
|
|
21
|
-
logger = logging.getLogger(__name__)
|
|
22
|
-
|
|
23
|
-
# Load identity and system prompt from workspace
|
|
24
|
-
initialize_workspace()
|
|
25
|
-
meta = load_identity()
|
|
26
|
-
DEFAULT_AGENT_NAME = os.getenv(
|
|
27
|
-
"DEFAULT_AGENT_NAME", meta.get("name", "Nextcloud Agent")
|
|
28
|
-
)
|
|
29
|
-
DEFAULT_AGENT_DESCRIPTION = os.getenv(
|
|
30
|
-
"AGENT_DESCRIPTION",
|
|
31
|
-
meta.get("description", "AI agent for Nextcloud Agent management."),
|
|
32
|
-
)
|
|
33
|
-
DEFAULT_AGENT_SYSTEM_PROMPT = os.getenv(
|
|
34
|
-
"AGENT_SYSTEM_PROMPT",
|
|
35
|
-
meta.get("content") or build_system_prompt_from_workspace(),
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def agent_server():
|
|
40
|
-
print(f"{DEFAULT_AGENT_NAME} v{__version__}")
|
|
41
|
-
parser = create_agent_parser()
|
|
42
|
-
|
|
43
|
-
args = parser.parse_args()
|
|
44
|
-
|
|
45
|
-
if args.debug:
|
|
46
|
-
logging.getLogger().setLevel(logging.DEBUG)
|
|
47
|
-
logger.debug("Debug mode enabled")
|
|
48
|
-
|
|
49
|
-
create_agent_server(
|
|
50
|
-
provider=args.provider,
|
|
51
|
-
model_id=args.model_id,
|
|
52
|
-
base_url=args.base_url,
|
|
53
|
-
api_key=args.api_key,
|
|
54
|
-
custom_skills_directory=args.custom_skills_directory,
|
|
55
|
-
debug=args.debug,
|
|
56
|
-
host=args.host,
|
|
57
|
-
port=args.port,
|
|
58
|
-
enable_web_ui=args.web,
|
|
59
|
-
ssl_verify=not args.insecure,
|
|
60
|
-
name=DEFAULT_AGENT_NAME,
|
|
61
|
-
system_prompt=DEFAULT_AGENT_SYSTEM_PROMPT,
|
|
62
|
-
enable_otel=args.otel,
|
|
63
|
-
otel_endpoint=args.otel_endpoint,
|
|
64
|
-
otel_headers=args.otel_headers,
|
|
65
|
-
otel_public_key=args.otel_public_key,
|
|
66
|
-
otel_secret_key=args.otel_secret_key,
|
|
67
|
-
otel_protocol=args.otel_protocol,
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if __name__ == "__main__":
|
|
72
|
-
agent_server()
|
|
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-0.2.45 → nextcloud_agent-0.2.48}/nextcloud_agent.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|