iflow-mcp_democratize-technology-chronos-mcp 2.0.0__py3-none-any.whl

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 (68) hide show
  1. chronos_mcp/__init__.py +5 -0
  2. chronos_mcp/__main__.py +9 -0
  3. chronos_mcp/accounts.py +410 -0
  4. chronos_mcp/bulk.py +946 -0
  5. chronos_mcp/caldav_utils.py +149 -0
  6. chronos_mcp/calendars.py +204 -0
  7. chronos_mcp/config.py +187 -0
  8. chronos_mcp/credentials.py +190 -0
  9. chronos_mcp/events.py +515 -0
  10. chronos_mcp/exceptions.py +477 -0
  11. chronos_mcp/journals.py +477 -0
  12. chronos_mcp/logging_config.py +23 -0
  13. chronos_mcp/models.py +202 -0
  14. chronos_mcp/py.typed +0 -0
  15. chronos_mcp/rrule.py +259 -0
  16. chronos_mcp/search.py +315 -0
  17. chronos_mcp/server.py +121 -0
  18. chronos_mcp/tasks.py +518 -0
  19. chronos_mcp/tools/__init__.py +29 -0
  20. chronos_mcp/tools/accounts.py +151 -0
  21. chronos_mcp/tools/base.py +59 -0
  22. chronos_mcp/tools/bulk.py +557 -0
  23. chronos_mcp/tools/calendars.py +142 -0
  24. chronos_mcp/tools/events.py +698 -0
  25. chronos_mcp/tools/journals.py +310 -0
  26. chronos_mcp/tools/tasks.py +414 -0
  27. chronos_mcp/utils.py +163 -0
  28. chronos_mcp/validation.py +636 -0
  29. iflow_mcp_democratize_technology_chronos_mcp-2.0.0.dist-info/METADATA +299 -0
  30. iflow_mcp_democratize_technology_chronos_mcp-2.0.0.dist-info/RECORD +68 -0
  31. iflow_mcp_democratize_technology_chronos_mcp-2.0.0.dist-info/WHEEL +5 -0
  32. iflow_mcp_democratize_technology_chronos_mcp-2.0.0.dist-info/entry_points.txt +2 -0
  33. iflow_mcp_democratize_technology_chronos_mcp-2.0.0.dist-info/licenses/LICENSE +21 -0
  34. iflow_mcp_democratize_technology_chronos_mcp-2.0.0.dist-info/top_level.txt +2 -0
  35. tests/__init__.py +0 -0
  36. tests/conftest.py +91 -0
  37. tests/unit/__init__.py +0 -0
  38. tests/unit/test_accounts.py +380 -0
  39. tests/unit/test_accounts_ssrf.py +134 -0
  40. tests/unit/test_base.py +135 -0
  41. tests/unit/test_bulk.py +380 -0
  42. tests/unit/test_bulk_create.py +408 -0
  43. tests/unit/test_bulk_delete.py +341 -0
  44. tests/unit/test_bulk_resource_limits.py +74 -0
  45. tests/unit/test_caldav_utils.py +300 -0
  46. tests/unit/test_calendars.py +286 -0
  47. tests/unit/test_config.py +111 -0
  48. tests/unit/test_config_validation.py +128 -0
  49. tests/unit/test_credentials_security.py +189 -0
  50. tests/unit/test_cryptography_security.py +178 -0
  51. tests/unit/test_events.py +536 -0
  52. tests/unit/test_exceptions.py +58 -0
  53. tests/unit/test_journals.py +1097 -0
  54. tests/unit/test_models.py +95 -0
  55. tests/unit/test_race_conditions.py +202 -0
  56. tests/unit/test_recurring_events.py +156 -0
  57. tests/unit/test_rrule.py +217 -0
  58. tests/unit/test_search.py +372 -0
  59. tests/unit/test_search_advanced.py +333 -0
  60. tests/unit/test_server_input_validation.py +219 -0
  61. tests/unit/test_ssrf_protection.py +505 -0
  62. tests/unit/test_tasks.py +918 -0
  63. tests/unit/test_thread_safety.py +301 -0
  64. tests/unit/test_tools_journals.py +617 -0
  65. tests/unit/test_tools_tasks.py +968 -0
  66. tests/unit/test_url_validation_security.py +234 -0
  67. tests/unit/test_utils.py +180 -0
  68. tests/unit/test_validation.py +983 -0
@@ -0,0 +1,142 @@
1
+ """
2
+ Calendar management tools for Chronos MCP
3
+ """
4
+
5
+ import uuid
6
+ from typing import Any, Dict, Optional
7
+
8
+ from pydantic import Field
9
+
10
+ from ..exceptions import (
11
+ CalendarNotFoundError,
12
+ ChronosError,
13
+ ErrorSanitizer,
14
+ ValidationError,
15
+ )
16
+ from ..logging_config import setup_logging
17
+ from ..validation import InputValidator
18
+ from .base import create_success_response, handle_tool_errors
19
+
20
+ logger = setup_logging()
21
+
22
+ # Module-level managers dictionary for dependency injection
23
+ _managers = {}
24
+
25
+
26
+ # Calendar tool functions - defined as standalone functions for importability
27
+ async def list_calendars(
28
+ account: Optional[str] = Field(
29
+ None, description="Account alias (uses default if not specified)"
30
+ ),
31
+ ) -> Dict[str, Any]:
32
+ """List all calendars for an account"""
33
+ calendars = _managers["calendar_manager"].list_calendars(account)
34
+
35
+ return {
36
+ "calendars": [
37
+ {
38
+ "uid": cal.uid,
39
+ "name": cal.name,
40
+ "description": cal.description,
41
+ "color": cal.color,
42
+ "url": cal.url,
43
+ "account": cal.account_alias,
44
+ }
45
+ for cal in calendars
46
+ ],
47
+ "total": len(calendars),
48
+ "account": account or _managers["config_manager"].config.default_account,
49
+ }
50
+
51
+
52
+ async def create_calendar(
53
+ name: str = Field(..., description="Calendar name"),
54
+ description: Optional[str] = Field(None, description="Calendar description"),
55
+ color: Optional[str] = Field(None, description="Calendar color (hex format)"),
56
+ account: Optional[str] = Field(
57
+ None, description="Account alias (uses default if not specified)"
58
+ ),
59
+ ) -> Dict[str, Any]:
60
+ """Create a new calendar"""
61
+ try:
62
+ # Validate inputs
63
+ name = InputValidator.validate_text_field(name, "calendar_name", required=True)
64
+ if description:
65
+ description = InputValidator.validate_text_field(description, "description")
66
+ if color and not InputValidator.PATTERNS["color"].match(color):
67
+ raise ValidationError(
68
+ "Invalid color format. Must be hex color like #FF0000"
69
+ )
70
+ if account:
71
+ account = InputValidator.validate_text_field(
72
+ account, "alias", required=False
73
+ )
74
+ except ValidationError as e:
75
+ return {"success": False, "error": str(e)}
76
+
77
+ calendar = _managers["calendar_manager"].create_calendar(
78
+ name, description, color, account
79
+ )
80
+
81
+ if calendar:
82
+ return {
83
+ "success": True,
84
+ "calendar": {
85
+ "uid": calendar.uid,
86
+ "name": calendar.name,
87
+ "url": calendar.url,
88
+ },
89
+ }
90
+ else:
91
+ return {"success": False, "error": "Failed to create calendar"}
92
+
93
+
94
+ @handle_tool_errors
95
+ async def delete_calendar(
96
+ calendar_uid: str = Field(..., description="Calendar UID to delete"),
97
+ account: Optional[str] = Field(
98
+ None, description="Account alias (uses default if not specified)"
99
+ ),
100
+ request_id: str = None,
101
+ ) -> Dict[str, Any]:
102
+ """Delete a calendar"""
103
+ # Validate inputs
104
+ calendar_uid = InputValidator.validate_uid(calendar_uid)
105
+ if account:
106
+ account = InputValidator.validate_text_field(account, "alias", required=False)
107
+
108
+ _managers["calendar_manager"].delete_calendar(
109
+ calendar_uid, account, request_id=request_id
110
+ )
111
+
112
+ return create_success_response(
113
+ message=f"Calendar '{calendar_uid}' deleted successfully",
114
+ request_id=request_id,
115
+ )
116
+
117
+
118
+ def register_calendar_tools(mcp, managers):
119
+ """Register calendar management tools with the MCP server"""
120
+
121
+ # Update module-level managers for dependency injection
122
+ _managers.update(managers)
123
+
124
+ # Register all calendar tools with the MCP server
125
+ mcp.tool(list_calendars)
126
+ mcp.tool(create_calendar)
127
+ mcp.tool(delete_calendar)
128
+
129
+
130
+ # Add .fn attribute to each function for backwards compatibility with tests
131
+ list_calendars.fn = list_calendars
132
+ create_calendar.fn = create_calendar
133
+ delete_calendar.fn = delete_calendar
134
+
135
+
136
+ # Export all tools for backwards compatibility
137
+ __all__ = [
138
+ "list_calendars",
139
+ "create_calendar",
140
+ "delete_calendar",
141
+ "register_calendar_tools",
142
+ ]