mcp-ticketer 0.1.27__py3-none-any.whl → 0.1.28__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.

Potentially problematic release.


This version of mcp-ticketer might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  """Version information for mcp-ticketer package."""
2
2
 
3
- __version__ = "0.1.27"
3
+ __version__ = "0.1.28"
4
4
  __version_info__ = tuple(int(part) for part in __version__.split("."))
5
5
 
6
6
  # Package metadata
@@ -235,6 +235,64 @@ class AITrackdownAdapter(BaseAdapter[Task]):
235
235
 
236
236
  return ticket
237
237
 
238
+ async def create_epic(self, title: str, description: str = None, **kwargs) -> Epic:
239
+ """Create a new epic.
240
+
241
+ Args:
242
+ title: Epic title
243
+ description: Epic description
244
+ **kwargs: Additional epic properties
245
+
246
+ Returns:
247
+ Created Epic instance
248
+ """
249
+ epic = Epic(
250
+ title=title,
251
+ description=description,
252
+ **kwargs
253
+ )
254
+ return await self.create(epic)
255
+
256
+ async def create_issue(self, title: str, parent_epic: str = None, description: str = None, **kwargs) -> Task:
257
+ """Create a new issue.
258
+
259
+ Args:
260
+ title: Issue title
261
+ parent_epic: Parent epic ID
262
+ description: Issue description
263
+ **kwargs: Additional issue properties
264
+
265
+ Returns:
266
+ Created Task instance (representing an issue)
267
+ """
268
+ task = Task(
269
+ title=title,
270
+ description=description,
271
+ parent_epic=parent_epic,
272
+ **kwargs
273
+ )
274
+ return await self.create(task)
275
+
276
+ async def create_task(self, title: str, parent_id: str, description: str = None, **kwargs) -> Task:
277
+ """Create a new task under an issue.
278
+
279
+ Args:
280
+ title: Task title
281
+ parent_id: Parent issue ID
282
+ description: Task description
283
+ **kwargs: Additional task properties
284
+
285
+ Returns:
286
+ Created Task instance
287
+ """
288
+ task = Task(
289
+ title=title,
290
+ description=description,
291
+ parent_issue=parent_id,
292
+ **kwargs
293
+ )
294
+ return await self.create(task)
295
+
238
296
  async def read(self, ticket_id: str) -> Optional[Union[Task, Epic]]:
239
297
  """Read a task by ID."""
240
298
  if self.tracker:
@@ -973,6 +973,66 @@ class LinearAdapter(BaseAdapter[Task]):
973
973
  created_issue = result["issueCreate"]["issue"]
974
974
  return self._task_from_linear_issue(created_issue)
975
975
 
976
+ async def create_epic(self, title: str, description: str = None, **kwargs) -> Task:
977
+ """Create a new epic (Linear project).
978
+
979
+ Args:
980
+ title: Epic title
981
+ description: Epic description
982
+ **kwargs: Additional epic properties
983
+
984
+ Returns:
985
+ Created Task instance representing the epic
986
+ """
987
+ # In Linear, epics are represented as issues with special labels/properties
988
+ task = Task(
989
+ title=title,
990
+ description=description,
991
+ tags=kwargs.get('tags', []) + ['epic'], # Add epic tag
992
+ **{k: v for k, v in kwargs.items() if k != 'tags'}
993
+ )
994
+ return await self.create(task)
995
+
996
+ async def create_issue(self, title: str, parent_epic: str = None, description: str = None, **kwargs) -> Task:
997
+ """Create a new issue.
998
+
999
+ Args:
1000
+ title: Issue title
1001
+ parent_epic: Parent epic ID
1002
+ description: Issue description
1003
+ **kwargs: Additional issue properties
1004
+
1005
+ Returns:
1006
+ Created Task instance representing the issue
1007
+ """
1008
+ task = Task(
1009
+ title=title,
1010
+ description=description,
1011
+ parent_epic=parent_epic,
1012
+ **kwargs
1013
+ )
1014
+ return await self.create(task)
1015
+
1016
+ async def create_task(self, title: str, parent_id: str, description: str = None, **kwargs) -> Task:
1017
+ """Create a new task under an issue.
1018
+
1019
+ Args:
1020
+ title: Task title
1021
+ parent_id: Parent issue ID
1022
+ description: Task description
1023
+ **kwargs: Additional task properties
1024
+
1025
+ Returns:
1026
+ Created Task instance
1027
+ """
1028
+ task = Task(
1029
+ title=title,
1030
+ description=description,
1031
+ parent_issue=parent_id,
1032
+ **kwargs
1033
+ )
1034
+ return await self.create(task)
1035
+
976
1036
  async def read(self, ticket_id: str) -> Optional[Task]:
977
1037
  """Read a Linear issue by identifier with full details."""
978
1038
  # Validate credentials before attempting operation
@@ -9,7 +9,7 @@ from pathlib import Path
9
9
  from typing import Any, Optional, Union
10
10
 
11
11
  import yaml
12
- from pydantic import BaseModel, Field, root_validator, validator
12
+ from pydantic import BaseModel, Field, field_validator, model_validator
13
13
 
14
14
  logger = logging.getLogger(__name__)
15
15
 
@@ -45,24 +45,27 @@ class GitHubConfig(BaseAdapterConfig):
45
45
  use_projects_v2: bool = False
46
46
  custom_priority_scheme: Optional[dict[str, list[str]]] = None
47
47
 
48
- @validator("token", pre=True, always=True)
49
- def validate_token(self, v):
48
+ @field_validator("token", mode="before")
49
+ @classmethod
50
+ def validate_token(cls, v):
50
51
  if not v:
51
52
  v = os.getenv("GITHUB_TOKEN")
52
53
  if not v:
53
54
  raise ValueError("GitHub token is required")
54
55
  return v
55
56
 
56
- @validator("owner", pre=True, always=True)
57
- def validate_owner(self, v):
57
+ @field_validator("owner", mode="before")
58
+ @classmethod
59
+ def validate_owner(cls, v):
58
60
  if not v:
59
61
  v = os.getenv("GITHUB_OWNER")
60
62
  if not v:
61
63
  raise ValueError("GitHub owner is required")
62
64
  return v
63
65
 
64
- @validator("repo", pre=True, always=True)
65
- def validate_repo(self, v):
66
+ @field_validator("repo", mode="before")
67
+ @classmethod
68
+ def validate_repo(cls, v):
66
69
  if not v:
67
70
  v = os.getenv("GITHUB_REPO")
68
71
  if not v:
@@ -81,24 +84,27 @@ class JiraConfig(BaseAdapterConfig):
81
84
  cloud: bool = True
82
85
  verify_ssl: bool = True
83
86
 
84
- @validator("server", pre=True, always=True)
85
- def validate_server(self, v):
87
+ @field_validator("server", mode="before")
88
+ @classmethod
89
+ def validate_server(cls, v):
86
90
  if not v:
87
91
  v = os.getenv("JIRA_SERVER")
88
92
  if not v:
89
93
  raise ValueError("JIRA server URL is required")
90
94
  return v.rstrip("/")
91
95
 
92
- @validator("email", pre=True, always=True)
93
- def validate_email(self, v):
96
+ @field_validator("email", mode="before")
97
+ @classmethod
98
+ def validate_email(cls, v):
94
99
  if not v:
95
100
  v = os.getenv("JIRA_EMAIL")
96
101
  if not v:
97
102
  raise ValueError("JIRA email is required")
98
103
  return v
99
104
 
100
- @validator("api_token", pre=True, always=True)
101
- def validate_api_token(self, v):
105
+ @field_validator("api_token", mode="before")
106
+ @classmethod
107
+ def validate_api_token(cls, v):
102
108
  if not v:
103
109
  v = os.getenv("JIRA_API_TOKEN")
104
110
  if not v:
@@ -115,8 +121,9 @@ class LinearConfig(BaseAdapterConfig):
115
121
  team_key: str
116
122
  api_url: str = "https://api.linear.app/graphql"
117
123
 
118
- @validator("api_key", pre=True, always=True)
119
- def validate_api_key(self, v):
124
+ @field_validator("api_key", mode="before")
125
+ @classmethod
126
+ def validate_api_key(cls, v):
120
127
  if not v:
121
128
  v = os.getenv("LINEAR_API_KEY")
122
129
  if not v:
@@ -163,23 +170,23 @@ class AppConfig(BaseModel):
163
170
  cache_ttl: int = 300 # Cache TTL in seconds
164
171
  default_adapter: Optional[str] = None
165
172
 
166
- @root_validator(skip_on_failure=True)
167
- def validate_adapters(self, values):
173
+ @model_validator(mode="after")
174
+ def validate_adapters(self):
168
175
  """Validate adapter configurations."""
169
- adapters = values.get("adapters", {})
176
+ adapters = self.adapters
170
177
 
171
178
  if not adapters:
172
179
  logger.warning("No adapters configured")
173
- return values
180
+ return self
174
181
 
175
182
  # Validate default adapter
176
- default_adapter = values.get("default_adapter")
183
+ default_adapter = self.default_adapter
177
184
  if default_adapter and default_adapter not in adapters:
178
185
  raise ValueError(
179
186
  f"Default adapter '{default_adapter}' not found in adapters"
180
187
  )
181
188
 
182
- return values
189
+ return self
183
190
 
184
191
  def get_adapter_config(self, adapter_name: str) -> Optional[BaseAdapterConfig]:
185
192
  """Get configuration for a specific adapter."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-ticketer
3
- Version: 0.1.27
3
+ Version: 0.1.28
4
4
  Summary: Universal ticket management interface for AI agents with MCP support
5
5
  Author-email: MCP Ticketer Team <support@mcp-ticketer.io>
6
6
  Maintainer-email: MCP Ticketer Team <support@mcp-ticketer.io>
@@ -1,12 +1,12 @@
1
1
  mcp_ticketer/__init__.py,sha256=Xx4WaprO5PXhVPbYi1L6tBmwmJMkYS-lMyG4ieN6QP0,717
2
- mcp_ticketer/__version__.py,sha256=gJUzlDdgl1Llr0GmKo1nWN84jviu8fvgk3jadt7EbaU,1118
2
+ mcp_ticketer/__version__.py,sha256=w-yViL73x_vy42OtylKLgKgQWyIAAbOKsrNKa-cIlJg,1118
3
3
  mcp_ticketer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  mcp_ticketer/adapters/__init__.py,sha256=B5DFllWn23hkhmrLykNO5uMMSdcFuuPHXyLw_jyFzuE,358
5
- mcp_ticketer/adapters/aitrackdown.py,sha256=24h3UqMj5CltCl271kmqnDFOicCVp9w7yMTKK8s_dTA,16283
5
+ mcp_ticketer/adapters/aitrackdown.py,sha256=stlbge8K6w-EyQkw_vEQNSXQgCOWN5tOlQUgGWZQNMQ,17936
6
6
  mcp_ticketer/adapters/github.py,sha256=X0lEWBCfy-vztX2vauuVSYsOCa9_ezt9hGa5BsCQTu8,46663
7
7
  mcp_ticketer/adapters/hybrid.py,sha256=UADYZLc_UNw0xHPSbgguBNzvUCnuYn12Qi9ea-zdlMk,19086
8
8
  mcp_ticketer/adapters/jira.py,sha256=W2pU-YxrSqgjm1gVt2eGc8We-G0MbRMSggQ2gWkThME,30602
9
- mcp_ticketer/adapters/linear.py,sha256=C6rHIxRaWvOBjX6ue2Nt-IPTcwFAwBkksstb7zV3YJw,71484
9
+ mcp_ticketer/adapters/linear.py,sha256=0eI8x8pv0isb7RTNmYczefUtaBFKPbOhGnnA4lrUjs8,73369
10
10
  mcp_ticketer/cache/__init__.py,sha256=Xcd-cKnt-Cx7jBzvfzUUUPaGkmyXFi5XUFWw3Z4b7d4,138
11
11
  mcp_ticketer/cache/memory.py,sha256=2yBqGi9i0SanlUhJoOC7nijWjoMa3_ntPe-V-AV-LfU,5042
12
12
  mcp_ticketer/cli/__init__.py,sha256=l9Q8iKmfGkTu0cssHBVqNZTsL4eAtFzOB25AED_0G6g,89
@@ -22,7 +22,7 @@ mcp_ticketer/cli/queue_commands.py,sha256=mm-3H6jmkUGJDyU_E46o9iRpek8tvFCm77F19O
22
22
  mcp_ticketer/cli/utils.py,sha256=2ptUrp2ELZsox0kSxAI5DFrHonOU999qh4MxbLv6VBQ,21155
23
23
  mcp_ticketer/core/__init__.py,sha256=eXovsaJymQRP2AwOBuOy6mFtI3I68D7gGenZ5V-IMqo,349
24
24
  mcp_ticketer/core/adapter.py,sha256=q64LxOInIno7EIbmuxItf8KEsd-g9grCs__Z4uwZHto,10273
25
- mcp_ticketer/core/config.py,sha256=QlWMJmxz4HsoZ4e2DZQdgKy0YHlL6UebbDVxw1CD3jI,15117
25
+ mcp_ticketer/core/config.py,sha256=aC1MAV0nghmkB6BnAEP3aa4DwLob9q6U04eP5xmQx0Y,15181
26
26
  mcp_ticketer/core/env_discovery.py,sha256=wKp2Pi5vQMGOTrM1690IBv_eoABly-pD8ah7n1zSWDc,17710
27
27
  mcp_ticketer/core/http_client.py,sha256=s5ikMiwEJ8TJjNn73wu3gv3OdAtyBEpAqPnSroRMW2k,13971
28
28
  mcp_ticketer/core/mappers.py,sha256=1aG1jFsHTCwmGRVgOlXW-VOSTGzc86gv7qjDfiR1ups,17462
@@ -39,9 +39,9 @@ mcp_ticketer/queue/queue.py,sha256=jSAkYNEIbNH1cbYuF8s6eFuZmXqn8WHXx3mbfMU2Ud8,1
39
39
  mcp_ticketer/queue/run_worker.py,sha256=_IBezjvhbJJ7gn0evTBIMbSPjvfFZwxEdT-1DLo_bRk,799
40
40
  mcp_ticketer/queue/ticket_registry.py,sha256=k8FYg2cFYsI4POb94-o-fTrIVr-ttfi60r0O5YhJYck,15321
41
41
  mcp_ticketer/queue/worker.py,sha256=TLXXXTAQT1k9Oiw2WjSd8bzT3rr8TQ8NLt9JBovGQEA,18679
42
- mcp_ticketer-0.1.27.dist-info/licenses/LICENSE,sha256=KOVrunjtILSzY-2N8Lqa3-Q8dMaZIG4LrlLTr9UqL08,1073
43
- mcp_ticketer-0.1.27.dist-info/METADATA,sha256=XPG1iLoD_XDRGzMfufeIwycZk3b_vvJ4aaHRhE_2nws,13191
44
- mcp_ticketer-0.1.27.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
- mcp_ticketer-0.1.27.dist-info/entry_points.txt,sha256=o1IxVhnHnBNG7FZzbFq-Whcs1Djbofs0qMjiUYBLx2s,60
46
- mcp_ticketer-0.1.27.dist-info/top_level.txt,sha256=WnAG4SOT1Vm9tIwl70AbGG_nA217YyV3aWFhxLH2rxw,13
47
- mcp_ticketer-0.1.27.dist-info/RECORD,,
42
+ mcp_ticketer-0.1.28.dist-info/licenses/LICENSE,sha256=KOVrunjtILSzY-2N8Lqa3-Q8dMaZIG4LrlLTr9UqL08,1073
43
+ mcp_ticketer-0.1.28.dist-info/METADATA,sha256=fJ7LnYE7qITkq4JVxoYUmNZavf9K48EhBPVshcAUOQs,13191
44
+ mcp_ticketer-0.1.28.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
+ mcp_ticketer-0.1.28.dist-info/entry_points.txt,sha256=o1IxVhnHnBNG7FZzbFq-Whcs1Djbofs0qMjiUYBLx2s,60
46
+ mcp_ticketer-0.1.28.dist-info/top_level.txt,sha256=WnAG4SOT1Vm9tIwl70AbGG_nA217YyV3aWFhxLH2rxw,13
47
+ mcp_ticketer-0.1.28.dist-info/RECORD,,