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

mcp_ticketer/__init__.py CHANGED
@@ -1,16 +1,16 @@
1
1
  """MCP Ticketer - Universal ticket management interface."""
2
2
 
3
3
  from .__version__ import (
4
- __author__,
5
- __author_email__,
6
- __copyright__,
7
- __description__,
8
- __license__,
9
- __title__,
10
- __version__,
11
- __version_info__,
12
- get_user_agent,
13
- get_version,
4
+ __author__,
5
+ __author_email__,
6
+ __copyright__,
7
+ __description__,
8
+ __license__,
9
+ __title__,
10
+ __version__,
11
+ __version_info__,
12
+ get_user_agent,
13
+ get_version,
14
14
  )
15
15
 
16
16
  __all__ = [
@@ -1,6 +1,6 @@
1
1
  """Version information for mcp-ticketer package."""
2
2
 
3
- __version__ = "0.1.23"
3
+ __version__ = "0.1.26"
4
4
  __version_info__ = tuple(int(part) for part in __version__.split("."))
5
5
 
6
6
  # Package metadata
@@ -806,7 +806,9 @@ class JiraAdapter(BaseAdapter[Union[Epic, Task]]):
806
806
  "custom_fields": custom_fields,
807
807
  }
808
808
 
809
- async def execute_jql(self, jql: str, limit: int = 50) -> builtins.list[Union[Epic, Task]]:
809
+ async def execute_jql(
810
+ self, jql: str, limit: int = 50
811
+ ) -> builtins.list[Union[Epic, Task]]:
810
812
  """Execute a raw JQL query.
811
813
 
812
814
  Args:
@@ -831,7 +833,9 @@ class JiraAdapter(BaseAdapter[Union[Epic, Task]]):
831
833
  issues = data.get("issues", [])
832
834
  return [self._issue_to_ticket(issue) for issue in issues]
833
835
 
834
- async def get_sprints(self, board_id: Optional[int] = None) -> builtins.list[dict[str, Any]]:
836
+ async def get_sprints(
837
+ self, board_id: Optional[int] = None
838
+ ) -> builtins.list[dict[str, Any]]:
835
839
  """Get active sprints for a board (requires JIRA Software).
836
840
 
837
841
  Args:
@@ -1547,7 +1547,9 @@ class LinearAdapter(BaseAdapter[Task]):
1547
1547
 
1548
1548
  return result["projectCreate"]["project"]["id"]
1549
1549
 
1550
- async def get_cycles(self, active_only: bool = True) -> builtins.list[dict[str, Any]]:
1550
+ async def get_cycles(
1551
+ self, active_only: bool = True
1552
+ ) -> builtins.list[dict[str, Any]]:
1551
1553
  """Get Linear cycles (sprints) for the team."""
1552
1554
  team_id = await self._ensure_team_id()
1553
1555
 
@@ -1858,7 +1860,7 @@ class LinearAdapter(BaseAdapter[Task]):
1858
1860
  search_query, variable_values={"identifier": identifier}
1859
1861
  )
1860
1862
  return result.get("issue")
1861
- except:
1863
+ except Exception:
1862
1864
  return None
1863
1865
 
1864
1866
  # Epic/Issue/Task Hierarchy Methods (Linear: Project = Epic, Issue = Issue, Sub-issue = Task)
@@ -0,0 +1,237 @@
1
+ """Auggie CLI configuration for mcp-ticketer integration.
2
+
3
+ IMPORTANT: Auggie CLI ONLY supports global configuration at ~/.augment/settings.json.
4
+ There is no project-level configuration support.
5
+ """
6
+
7
+ import json
8
+ from pathlib import Path
9
+ from typing import Any
10
+
11
+ from rich.console import Console
12
+
13
+ from .mcp_configure import find_mcp_ticketer_binary, load_project_config
14
+
15
+ console = Console()
16
+
17
+
18
+ def find_auggie_config() -> Path:
19
+ """Find or create Auggie CLI configuration file.
20
+
21
+ Auggie CLI only supports global user-level configuration.
22
+
23
+ Returns:
24
+ Path to Auggie settings file at ~/.augment/settings.json
25
+
26
+ """
27
+ # Global user-level configuration (ONLY option for Auggie)
28
+ config_path = Path.home() / ".augment" / "settings.json"
29
+ return config_path
30
+
31
+
32
+ def load_auggie_config(config_path: Path) -> dict[str, Any]:
33
+ """Load existing Auggie configuration or return empty structure.
34
+
35
+ Args:
36
+ config_path: Path to Auggie settings file
37
+
38
+ Returns:
39
+ Auggie configuration dict
40
+
41
+ """
42
+ if config_path.exists():
43
+ try:
44
+ with open(config_path) as f:
45
+ config: dict[str, Any] = json.load(f)
46
+ return config
47
+ except json.JSONDecodeError as e:
48
+ console.print(
49
+ f"[yellow]⚠ Warning: Could not parse existing config: {e}[/yellow]"
50
+ )
51
+ console.print("[yellow]Creating new configuration...[/yellow]")
52
+
53
+ # Return empty structure with mcpServers section
54
+ return {"mcpServers": {}}
55
+
56
+
57
+ def save_auggie_config(config_path: Path, config: dict[str, Any]) -> None:
58
+ """Save Auggie configuration to file.
59
+
60
+ Args:
61
+ config_path: Path to Auggie settings file
62
+ config: Configuration to save
63
+
64
+ """
65
+ # Ensure directory exists
66
+ config_path.parent.mkdir(parents=True, exist_ok=True)
67
+
68
+ # Write with 2-space indentation (JSON standard)
69
+ with open(config_path, "w") as f:
70
+ json.dump(config, f, indent=2)
71
+
72
+
73
+ def create_auggie_server_config(
74
+ binary_path: str, project_config: dict[str, Any]
75
+ ) -> dict[str, Any]:
76
+ """Create Auggie MCP server configuration for mcp-ticketer.
77
+
78
+ Args:
79
+ binary_path: Path to mcp-ticketer binary
80
+ project_config: Project configuration from .mcp-ticketer/config.json
81
+
82
+ Returns:
83
+ Auggie MCP server configuration dict
84
+
85
+ """
86
+ # Get adapter configuration
87
+ adapter = project_config.get("default_adapter", "aitrackdown")
88
+ adapters_config = project_config.get("adapters", {})
89
+ adapter_config = adapters_config.get(adapter, {})
90
+
91
+ # Build environment variables
92
+ env_vars = {}
93
+
94
+ # Add adapter type
95
+ env_vars["MCP_TICKETER_ADAPTER"] = adapter
96
+
97
+ # Add adapter-specific environment variables
98
+ if adapter == "aitrackdown":
99
+ # Set base path for local adapter
100
+ base_path = adapter_config.get("base_path", ".aitrackdown")
101
+ # Use absolute path to home directory for global config
102
+ # Since Auggie is global, we can't rely on project-specific paths
103
+ env_vars["MCP_TICKETER_BASE_PATH"] = str(
104
+ Path.home() / ".mcp-ticketer" / base_path
105
+ )
106
+
107
+ elif adapter == "linear":
108
+ if "api_key" in adapter_config:
109
+ env_vars["LINEAR_API_KEY"] = adapter_config["api_key"]
110
+ if "team_id" in adapter_config:
111
+ env_vars["LINEAR_TEAM_ID"] = adapter_config["team_id"]
112
+
113
+ elif adapter == "github":
114
+ if "token" in adapter_config:
115
+ env_vars["GITHUB_TOKEN"] = adapter_config["token"]
116
+ if "owner" in adapter_config:
117
+ env_vars["GITHUB_OWNER"] = adapter_config["owner"]
118
+ if "repo" in adapter_config:
119
+ env_vars["GITHUB_REPO"] = adapter_config["repo"]
120
+
121
+ elif adapter == "jira":
122
+ if "api_token" in adapter_config:
123
+ env_vars["JIRA_API_TOKEN"] = adapter_config["api_token"]
124
+ if "email" in adapter_config:
125
+ env_vars["JIRA_EMAIL"] = adapter_config["email"]
126
+ if "server" in adapter_config:
127
+ env_vars["JIRA_SERVER"] = adapter_config["server"]
128
+ if "project_key" in adapter_config:
129
+ env_vars["JIRA_PROJECT_KEY"] = adapter_config["project_key"]
130
+
131
+ # Create server configuration (simpler than Gemini - no timeout/trust)
132
+ config = {
133
+ "command": binary_path,
134
+ "args": ["serve"],
135
+ "env": env_vars,
136
+ }
137
+
138
+ return config
139
+
140
+
141
+ def configure_auggie_mcp(force: bool = False) -> None:
142
+ """Configure Auggie CLI to use mcp-ticketer.
143
+
144
+ IMPORTANT: Auggie CLI ONLY supports global configuration.
145
+ This will configure ~/.augment/settings.json for all projects.
146
+
147
+ Args:
148
+ force: Overwrite existing configuration
149
+
150
+ Raises:
151
+ FileNotFoundError: If binary or project config not found
152
+ ValueError: If configuration is invalid
153
+
154
+ """
155
+ # Step 1: Find mcp-ticketer binary
156
+ console.print("[cyan]🔍 Finding mcp-ticketer binary...[/cyan]")
157
+ try:
158
+ binary_path = find_mcp_ticketer_binary()
159
+ console.print(f"[green]✓[/green] Found: {binary_path}")
160
+ except FileNotFoundError as e:
161
+ console.print(f"[red]✗[/red] {e}")
162
+ raise
163
+
164
+ # Step 2: Load project configuration
165
+ console.print("\n[cyan]📖 Reading project configuration...[/cyan]")
166
+ try:
167
+ project_config = load_project_config()
168
+ adapter = project_config.get("default_adapter", "aitrackdown")
169
+ console.print(f"[green]✓[/green] Adapter: {adapter}")
170
+ except (FileNotFoundError, ValueError) as e:
171
+ console.print(f"[red]✗[/red] {e}")
172
+ raise
173
+
174
+ # Step 3: Find Auggie config location
175
+ console.print("\n[cyan]🔧 Configuring global Auggie CLI...[/cyan]")
176
+ console.print(
177
+ "[yellow]⚠ NOTE: Auggie only supports global configuration (affects all projects)[/yellow]"
178
+ )
179
+
180
+ auggie_config_path = find_auggie_config()
181
+ console.print(f"[dim]Config location: {auggie_config_path}[/dim]")
182
+
183
+ # Step 4: Load existing Auggie configuration
184
+ auggie_config = load_auggie_config(auggie_config_path)
185
+
186
+ # Step 5: Check if mcp-ticketer already configured
187
+ if "mcp-ticketer" in auggie_config.get("mcpServers", {}):
188
+ if not force:
189
+ console.print("[yellow]⚠ mcp-ticketer is already configured[/yellow]")
190
+ console.print("[dim]Use --force to overwrite existing configuration[/dim]")
191
+ return
192
+ else:
193
+ console.print("[yellow]⚠ Overwriting existing configuration[/yellow]")
194
+
195
+ # Step 6: Create mcp-ticketer server config
196
+ server_config = create_auggie_server_config(
197
+ binary_path=binary_path, project_config=project_config
198
+ )
199
+
200
+ # Step 7: Update Auggie configuration
201
+ if "mcpServers" not in auggie_config:
202
+ auggie_config["mcpServers"] = {}
203
+
204
+ auggie_config["mcpServers"]["mcp-ticketer"] = server_config
205
+
206
+ # Step 8: Save configuration
207
+ try:
208
+ save_auggie_config(auggie_config_path, auggie_config)
209
+ console.print("\n[green]✓ Successfully configured mcp-ticketer[/green]")
210
+ console.print(f"[dim]Configuration saved to: {auggie_config_path}[/dim]")
211
+
212
+ # Print configuration details
213
+ console.print("\n[bold]Configuration Details:[/bold]")
214
+ console.print(" Server name: mcp-ticketer")
215
+ console.print(f" Adapter: {adapter}")
216
+ console.print(f" Binary: {binary_path}")
217
+ console.print(" Scope: Global (affects all projects)")
218
+ if "env" in server_config:
219
+ console.print(
220
+ f" Environment variables: {list(server_config['env'].keys())}"
221
+ )
222
+
223
+ # Next steps
224
+ console.print("\n[bold cyan]Next Steps:[/bold cyan]")
225
+ console.print("1. Restart Auggie CLI for changes to take effect")
226
+ console.print("2. Run 'auggie' command in any directory")
227
+ console.print("3. mcp-ticketer tools will be available via MCP")
228
+ console.print(
229
+ "\n[yellow]⚠ Warning: This is a global configuration affecting all projects[/yellow]"
230
+ )
231
+ console.print(
232
+ "[dim]If you need project-specific configuration, use Claude or Gemini instead[/dim]"
233
+ )
234
+
235
+ except Exception as e:
236
+ console.print(f"\n[red]✗ Failed to save configuration:[/red] {e}")
237
+ raise
@@ -0,0 +1,257 @@
1
+ """Codex CLI configuration for mcp-ticketer integration.
2
+
3
+ Codex CLI only supports global configuration at ~/.codex/config.toml.
4
+ Unlike Claude Code and Gemini CLI, there is no project-level configuration support.
5
+ """
6
+
7
+ import sys
8
+ from pathlib import Path
9
+ from typing import Any, Dict, Optional
10
+
11
+ if sys.version_info >= (3, 11):
12
+ import tomllib
13
+ else:
14
+ import tomli as tomllib
15
+
16
+ import tomli_w
17
+ from rich.console import Console
18
+
19
+ from .mcp_configure import find_mcp_ticketer_binary, load_project_config
20
+
21
+ console = Console()
22
+
23
+
24
+ def find_codex_config() -> Path:
25
+ """Find Codex CLI configuration file location.
26
+
27
+ Codex CLI ONLY supports global configuration at ~/.codex/config.toml.
28
+ No project-level or user-scoped configuration is available.
29
+
30
+ Returns:
31
+ Path to Codex global config file at ~/.codex/config.toml
32
+
33
+ """
34
+ # Codex only supports global config (no project-level support)
35
+ config_path = Path.home() / ".codex" / "config.toml"
36
+ return config_path
37
+
38
+
39
+ def load_codex_config(config_path: Path) -> Dict[str, Any]:
40
+ """Load existing Codex configuration or return empty structure.
41
+
42
+ Args:
43
+ config_path: Path to Codex config.toml file
44
+
45
+ Returns:
46
+ Codex configuration dict with mcp_servers section
47
+
48
+ """
49
+ if config_path.exists():
50
+ try:
51
+ with open(config_path, "rb") as f:
52
+ return tomllib.load(f)
53
+ except Exception as e:
54
+ console.print(
55
+ f"[yellow]⚠ Warning: Could not parse existing config: {e}[/yellow]"
56
+ )
57
+ console.print("[yellow]Creating new configuration...[/yellow]")
58
+
59
+ # Return empty structure with mcp_servers section
60
+ # NOTE: Use underscore mcp_servers, not camelCase mcpServers
61
+ return {"mcp_servers": {}}
62
+
63
+
64
+ def save_codex_config(config_path: Path, config: Dict[str, Any]) -> None:
65
+ """Save Codex configuration to TOML file.
66
+
67
+ Args:
68
+ config_path: Path to Codex config.toml file
69
+ config: Configuration to save
70
+
71
+ """
72
+ # Ensure directory exists
73
+ config_path.parent.mkdir(parents=True, exist_ok=True)
74
+
75
+ # Write TOML with proper formatting
76
+ with open(config_path, "wb") as f:
77
+ tomli_w.dump(config, f)
78
+
79
+
80
+ def create_codex_server_config(
81
+ binary_path: str, project_config: dict, cwd: Optional[str] = None
82
+ ) -> Dict[str, Any]:
83
+ """Create Codex MCP server configuration for mcp-ticketer.
84
+
85
+ Args:
86
+ binary_path: Path to mcp-ticketer binary
87
+ project_config: Project configuration from .mcp-ticketer/config.json
88
+ cwd: Working directory for server (optional, not used for global config)
89
+
90
+ Returns:
91
+ Codex MCP server configuration dict
92
+
93
+ """
94
+ # Get adapter configuration
95
+ adapter = project_config.get("default_adapter", "aitrackdown")
96
+ adapters_config = project_config.get("adapters", {})
97
+ adapter_config = adapters_config.get(adapter, {})
98
+
99
+ # Build environment variables
100
+ env_vars: Dict[str, str] = {}
101
+
102
+ # Add PYTHONPATH if running from development environment
103
+ if cwd:
104
+ env_vars["PYTHONPATH"] = str(Path(cwd) / "src")
105
+
106
+ # Add adapter type
107
+ env_vars["MCP_TICKETER_ADAPTER"] = adapter
108
+
109
+ # Add adapter-specific environment variables
110
+ if adapter == "aitrackdown":
111
+ # Set base path for local adapter
112
+ base_path = adapter_config.get("base_path", ".aitrackdown")
113
+ if cwd:
114
+ # Use absolute path if cwd is provided
115
+ env_vars["MCP_TICKETER_BASE_PATH"] = str(Path(cwd) / base_path)
116
+ else:
117
+ env_vars["MCP_TICKETER_BASE_PATH"] = base_path
118
+
119
+ elif adapter == "linear":
120
+ if "api_key" in adapter_config:
121
+ env_vars["LINEAR_API_KEY"] = adapter_config["api_key"]
122
+ if "team_id" in adapter_config:
123
+ env_vars["LINEAR_TEAM_ID"] = adapter_config["team_id"]
124
+
125
+ elif adapter == "github":
126
+ if "token" in adapter_config:
127
+ env_vars["GITHUB_TOKEN"] = adapter_config["token"]
128
+ if "owner" in adapter_config:
129
+ env_vars["GITHUB_OWNER"] = adapter_config["owner"]
130
+ if "repo" in adapter_config:
131
+ env_vars["GITHUB_REPO"] = adapter_config["repo"]
132
+
133
+ elif adapter == "jira":
134
+ if "api_token" in adapter_config:
135
+ env_vars["JIRA_API_TOKEN"] = adapter_config["api_token"]
136
+ if "email" in adapter_config:
137
+ env_vars["JIRA_EMAIL"] = adapter_config["email"]
138
+ if "server" in adapter_config:
139
+ env_vars["JIRA_SERVER"] = adapter_config["server"]
140
+ if "project_key" in adapter_config:
141
+ env_vars["JIRA_PROJECT_KEY"] = adapter_config["project_key"]
142
+
143
+ # Create server configuration with Codex-specific structure
144
+ # NOTE: Codex uses nested dict structure for env vars
145
+ config: Dict[str, Any] = {
146
+ "command": binary_path,
147
+ "args": ["serve"],
148
+ "env": env_vars,
149
+ }
150
+
151
+ return config
152
+
153
+
154
+ def configure_codex_mcp(force: bool = False) -> None:
155
+ """Configure Codex CLI to use mcp-ticketer.
156
+
157
+ IMPORTANT: Codex CLI ONLY supports global configuration at ~/.codex/config.toml.
158
+ There is no project-level or user-scoped configuration available.
159
+
160
+ After configuration, you must restart Codex CLI for changes to take effect.
161
+
162
+ Args:
163
+ force: Overwrite existing configuration
164
+
165
+ Raises:
166
+ FileNotFoundError: If binary or project config not found
167
+ ValueError: If configuration is invalid
168
+
169
+ """
170
+ # Step 1: Find mcp-ticketer binary
171
+ console.print("[cyan]🔍 Finding mcp-ticketer binary...[/cyan]")
172
+ try:
173
+ binary_path = find_mcp_ticketer_binary()
174
+ console.print(f"[green]✓[/green] Found: {binary_path}")
175
+ except FileNotFoundError as e:
176
+ console.print(f"[red]✗[/red] {e}")
177
+ raise
178
+
179
+ # Step 2: Load project configuration
180
+ console.print("\n[cyan]📖 Reading project configuration...[/cyan]")
181
+ try:
182
+ project_config = load_project_config()
183
+ adapter = project_config.get("default_adapter", "aitrackdown")
184
+ console.print(f"[green]✓[/green] Adapter: {adapter}")
185
+ except (FileNotFoundError, ValueError) as e:
186
+ console.print(f"[red]✗[/red] {e}")
187
+ raise
188
+
189
+ # Step 3: Find Codex config location (always global)
190
+ console.print("\n[cyan]🔧 Configuring Codex CLI (global-only)...[/cyan]")
191
+ console.print(
192
+ "[yellow]⚠ Note: Codex CLI only supports global configuration[/yellow]"
193
+ )
194
+
195
+ codex_config_path = find_codex_config()
196
+ console.print(f"[dim]Config location: {codex_config_path}[/dim]")
197
+
198
+ # Step 4: Load existing Codex configuration
199
+ codex_config = load_codex_config(codex_config_path)
200
+
201
+ # Step 5: Check if mcp-ticketer already configured
202
+ # NOTE: Use underscore mcp_servers, not camelCase
203
+ mcp_servers = codex_config.get("mcp_servers", {})
204
+ if "mcp-ticketer" in mcp_servers:
205
+ if not force:
206
+ console.print("[yellow]⚠ mcp-ticketer is already configured[/yellow]")
207
+ console.print("[dim]Use --force to overwrite existing configuration[/dim]")
208
+ return
209
+ else:
210
+ console.print("[yellow]⚠ Overwriting existing configuration[/yellow]")
211
+
212
+ # Step 6: Create mcp-ticketer server config
213
+ # For global config, include current working directory for context
214
+ cwd = str(Path.cwd())
215
+ server_config = create_codex_server_config(
216
+ binary_path=binary_path, project_config=project_config, cwd=cwd
217
+ )
218
+
219
+ # Step 7: Update Codex configuration
220
+ if "mcp_servers" not in codex_config:
221
+ codex_config["mcp_servers"] = {}
222
+
223
+ codex_config["mcp_servers"]["mcp-ticketer"] = server_config
224
+
225
+ # Step 8: Save configuration
226
+ try:
227
+ save_codex_config(codex_config_path, codex_config)
228
+ console.print("\n[green]✓ Successfully configured mcp-ticketer[/green]")
229
+ console.print(f"[dim]Configuration saved to: {codex_config_path}[/dim]")
230
+
231
+ # Print configuration details
232
+ console.print("\n[bold]Configuration Details:[/bold]")
233
+ console.print(" Server name: mcp-ticketer")
234
+ console.print(f" Adapter: {adapter}")
235
+ console.print(f" Binary: {binary_path}")
236
+ console.print(" Scope: global (Codex only supports global config)")
237
+ console.print(f" Working directory: {cwd}")
238
+ if "env" in server_config:
239
+ console.print(
240
+ f" Environment variables: {list(server_config['env'].keys())}"
241
+ )
242
+
243
+ # Next steps
244
+ console.print("\n[bold cyan]Next Steps:[/bold cyan]")
245
+ console.print("1. [bold]Restart Codex CLI[/bold] (required for changes)")
246
+ console.print("2. Run 'codex' command from any directory")
247
+ console.print("3. mcp-ticketer tools will be available via MCP")
248
+ console.print(
249
+ "\n[yellow]⚠ Warning: This is a global configuration that affects all Codex sessions[/yellow]"
250
+ )
251
+ console.print(
252
+ "[yellow] The configuration includes paths from your current project directory[/yellow]"
253
+ )
254
+
255
+ except Exception as e:
256
+ console.print(f"\n[red]✗ Failed to save configuration:[/red] {e}")
257
+ raise
@@ -0,0 +1,261 @@
1
+ """Gemini CLI configuration for mcp-ticketer integration."""
2
+
3
+ import json
4
+ from pathlib import Path
5
+ from typing import Literal, Optional
6
+
7
+ from rich.console import Console
8
+
9
+ from .mcp_configure import find_mcp_ticketer_binary, load_project_config
10
+
11
+ console = Console()
12
+
13
+
14
+ def find_gemini_config(scope: Literal["project", "user"] = "project") -> Path:
15
+ """Find or create Gemini CLI configuration file.
16
+
17
+ Args:
18
+ scope: Configuration scope - "project" for .gemini/settings.json
19
+ or "user" for ~/.gemini/settings.json
20
+
21
+ Returns:
22
+ Path to Gemini settings file
23
+
24
+ """
25
+ if scope == "user":
26
+ # User-level configuration
27
+ config_path = Path.home() / ".gemini" / "settings.json"
28
+ else:
29
+ # Project-level configuration
30
+ config_path = Path.cwd() / ".gemini" / "settings.json"
31
+
32
+ return config_path
33
+
34
+
35
+ def load_gemini_config(config_path: Path) -> dict:
36
+ """Load existing Gemini configuration or return empty structure.
37
+
38
+ Args:
39
+ config_path: Path to Gemini settings file
40
+
41
+ Returns:
42
+ Gemini configuration dict
43
+
44
+ """
45
+ if config_path.exists():
46
+ try:
47
+ with open(config_path) as f:
48
+ return json.load(f)
49
+ except json.JSONDecodeError as e:
50
+ console.print(
51
+ f"[yellow]⚠ Warning: Could not parse existing config: {e}[/yellow]"
52
+ )
53
+ console.print("[yellow]Creating new configuration...[/yellow]")
54
+
55
+ # Return empty structure with mcpServers section
56
+ return {"mcpServers": {}}
57
+
58
+
59
+ def save_gemini_config(config_path: Path, config: dict) -> None:
60
+ """Save Gemini configuration to file.
61
+
62
+ Args:
63
+ config_path: Path to Gemini settings file
64
+ config: Configuration to save
65
+
66
+ """
67
+ # Ensure directory exists
68
+ config_path.parent.mkdir(parents=True, exist_ok=True)
69
+
70
+ # Write with 2-space indentation (Gemini CLI standard)
71
+ with open(config_path, "w") as f:
72
+ json.dump(config, f, indent=2)
73
+
74
+
75
+ def create_gemini_server_config(
76
+ binary_path: str, project_config: dict, cwd: Optional[str] = None
77
+ ) -> dict:
78
+ """Create Gemini MCP server configuration for mcp-ticketer.
79
+
80
+ Args:
81
+ binary_path: Path to mcp-ticketer binary
82
+ project_config: Project configuration from .mcp-ticketer/config.json
83
+ cwd: Working directory for server (optional)
84
+
85
+ Returns:
86
+ Gemini MCP server configuration dict
87
+
88
+ """
89
+ # Get adapter configuration
90
+ adapter = project_config.get("default_adapter", "aitrackdown")
91
+ adapters_config = project_config.get("adapters", {})
92
+ adapter_config = adapters_config.get(adapter, {})
93
+
94
+ # Build environment variables
95
+ env_vars = {}
96
+
97
+ # Add PYTHONPATH if running from development environment
98
+ if cwd:
99
+ env_vars["PYTHONPATH"] = str(Path(cwd) / "src")
100
+
101
+ # Add adapter type
102
+ env_vars["MCP_TICKETER_ADAPTER"] = adapter
103
+
104
+ # Add adapter-specific environment variables
105
+ if adapter == "aitrackdown":
106
+ # Set base path for local adapter
107
+ base_path = adapter_config.get("base_path", ".aitrackdown")
108
+ if cwd:
109
+ # Use absolute path if cwd is provided
110
+ env_vars["MCP_TICKETER_BASE_PATH"] = str(Path(cwd) / base_path)
111
+ else:
112
+ env_vars["MCP_TICKETER_BASE_PATH"] = base_path
113
+
114
+ elif adapter == "linear":
115
+ if "api_key" in adapter_config:
116
+ env_vars["LINEAR_API_KEY"] = adapter_config["api_key"]
117
+ if "team_id" in adapter_config:
118
+ env_vars["LINEAR_TEAM_ID"] = adapter_config["team_id"]
119
+
120
+ elif adapter == "github":
121
+ if "token" in adapter_config:
122
+ env_vars["GITHUB_TOKEN"] = adapter_config["token"]
123
+ if "owner" in adapter_config:
124
+ env_vars["GITHUB_OWNER"] = adapter_config["owner"]
125
+ if "repo" in adapter_config:
126
+ env_vars["GITHUB_REPO"] = adapter_config["repo"]
127
+
128
+ elif adapter == "jira":
129
+ if "api_token" in adapter_config:
130
+ env_vars["JIRA_API_TOKEN"] = adapter_config["api_token"]
131
+ if "email" in adapter_config:
132
+ env_vars["JIRA_EMAIL"] = adapter_config["email"]
133
+ if "server" in adapter_config:
134
+ env_vars["JIRA_SERVER"] = adapter_config["server"]
135
+ if "project_key" in adapter_config:
136
+ env_vars["JIRA_PROJECT_KEY"] = adapter_config["project_key"]
137
+
138
+ # Create server configuration with Gemini-specific options
139
+ config = {
140
+ "command": binary_path,
141
+ "args": ["serve"],
142
+ "env": env_vars,
143
+ "timeout": 15000, # 15 seconds timeout
144
+ "trust": False, # Don't trust by default (security)
145
+ }
146
+
147
+ return config
148
+
149
+
150
+ def configure_gemini_mcp(
151
+ scope: Literal["project", "user"] = "project", force: bool = False
152
+ ) -> None:
153
+ """Configure Gemini CLI to use mcp-ticketer.
154
+
155
+ Args:
156
+ scope: Configuration scope - "project" or "user"
157
+ force: Overwrite existing configuration
158
+
159
+ Raises:
160
+ FileNotFoundError: If binary or project config not found
161
+ ValueError: If configuration is invalid
162
+
163
+ """
164
+ # Step 1: Find mcp-ticketer binary
165
+ console.print("[cyan]🔍 Finding mcp-ticketer binary...[/cyan]")
166
+ try:
167
+ binary_path = find_mcp_ticketer_binary()
168
+ console.print(f"[green]✓[/green] Found: {binary_path}")
169
+ except FileNotFoundError as e:
170
+ console.print(f"[red]✗[/red] {e}")
171
+ raise
172
+
173
+ # Step 2: Load project configuration
174
+ console.print("\n[cyan]📖 Reading project configuration...[/cyan]")
175
+ try:
176
+ project_config = load_project_config()
177
+ adapter = project_config.get("default_adapter", "aitrackdown")
178
+ console.print(f"[green]✓[/green] Adapter: {adapter}")
179
+ except (FileNotFoundError, ValueError) as e:
180
+ console.print(f"[red]✗[/red] {e}")
181
+ raise
182
+
183
+ # Step 3: Find Gemini config location
184
+ config_type = "user-level" if scope == "user" else "project-level"
185
+ console.print(f"\n[cyan]🔧 Configuring {config_type} Gemini CLI...[/cyan]")
186
+
187
+ gemini_config_path = find_gemini_config(scope)
188
+ console.print(f"[dim]Config location: {gemini_config_path}[/dim]")
189
+
190
+ # Step 4: Load existing Gemini configuration
191
+ gemini_config = load_gemini_config(gemini_config_path)
192
+
193
+ # Step 5: Check if mcp-ticketer already configured
194
+ if "mcp-ticketer" in gemini_config.get("mcpServers", {}):
195
+ if not force:
196
+ console.print("[yellow]⚠ mcp-ticketer is already configured[/yellow]")
197
+ console.print("[dim]Use --force to overwrite existing configuration[/dim]")
198
+ return
199
+ else:
200
+ console.print("[yellow]⚠ Overwriting existing configuration[/yellow]")
201
+
202
+ # Step 6: Create mcp-ticketer server config
203
+ cwd = str(Path.cwd()) if scope == "project" else None
204
+ server_config = create_gemini_server_config(
205
+ binary_path=binary_path, project_config=project_config, cwd=cwd
206
+ )
207
+
208
+ # Step 7: Update Gemini configuration
209
+ if "mcpServers" not in gemini_config:
210
+ gemini_config["mcpServers"] = {}
211
+
212
+ gemini_config["mcpServers"]["mcp-ticketer"] = server_config
213
+
214
+ # Step 8: Save configuration
215
+ try:
216
+ save_gemini_config(gemini_config_path, gemini_config)
217
+ console.print("\n[green]✓ Successfully configured mcp-ticketer[/green]")
218
+ console.print(f"[dim]Configuration saved to: {gemini_config_path}[/dim]")
219
+
220
+ # Print configuration details
221
+ console.print("\n[bold]Configuration Details:[/bold]")
222
+ console.print(" Server name: mcp-ticketer")
223
+ console.print(f" Adapter: {adapter}")
224
+ console.print(f" Binary: {binary_path}")
225
+ console.print(f" Timeout: {server_config['timeout']}ms")
226
+ console.print(f" Trust: {server_config['trust']}")
227
+ if cwd:
228
+ console.print(f" Working directory: {cwd}")
229
+ if "env" in server_config:
230
+ console.print(
231
+ f" Environment variables: {list(server_config['env'].keys())}"
232
+ )
233
+
234
+ # Next steps
235
+ console.print("\n[bold cyan]Next Steps:[/bold cyan]")
236
+ if scope == "user":
237
+ console.print("1. Gemini CLI will use this configuration globally")
238
+ console.print("2. Run 'gemini' command in any directory")
239
+ else:
240
+ console.print("1. Run 'gemini' command in this project directory")
241
+ console.print("2. Gemini CLI will detect project-level configuration")
242
+ console.print("3. mcp-ticketer tools will be available via MCP")
243
+
244
+ # Add .gemini to .gitignore for project-level config
245
+ if scope == "project":
246
+ gitignore_path = Path.cwd() / ".gitignore"
247
+ if gitignore_path.exists():
248
+ gitignore_content = gitignore_path.read_text()
249
+ if ".gemini" not in gitignore_content:
250
+ with open(gitignore_path, "a") as f:
251
+ f.write("\n# Gemini CLI\n.gemini/\n")
252
+ console.print("\n[dim]✓ Added .gemini/ to .gitignore[/dim]")
253
+ else:
254
+ # Create .gitignore if it doesn't exist
255
+ with open(gitignore_path, "w") as f:
256
+ f.write("# Gemini CLI\n.gemini/\n")
257
+ console.print("\n[dim]✓ Created .gitignore with .gemini/[/dim]")
258
+
259
+ except Exception as e:
260
+ console.print(f"\n[red]✗ Failed to save configuration:[/red] {e}")
261
+ raise
mcp_ticketer/cli/main.py CHANGED
@@ -1118,6 +1118,13 @@ app.add_typer(queue_app, name="queue")
1118
1118
  # Add discover command to main app
1119
1119
  app.add_typer(discover_app, name="discover")
1120
1120
 
1121
+ # Create MCP configuration command group
1122
+ mcp_app = typer.Typer(
1123
+ name="mcp",
1124
+ help="Configure MCP integration for AI clients (Claude, Gemini, Codex, Auggie)",
1125
+ add_completion=False,
1126
+ )
1127
+
1121
1128
 
1122
1129
  @app.command()
1123
1130
  def check(queue_id: str = typer.Argument(..., help="Queue ID to check")):
@@ -1233,8 +1240,8 @@ def serve(
1233
1240
  sys.exit(1)
1234
1241
 
1235
1242
 
1236
- @app.command()
1237
- def mcp(
1243
+ @mcp_app.command(name="claude")
1244
+ def mcp_claude(
1238
1245
  global_config: bool = typer.Option(
1239
1246
  False,
1240
1247
  "--global",
@@ -1252,6 +1259,17 @@ def mcp(
1252
1259
 
1253
1260
  By default, configures project-level (.mcp/config.json).
1254
1261
  Use --global to configure Claude Desktop instead.
1262
+
1263
+ Examples:
1264
+ # Configure for current project (default)
1265
+ mcp-ticketer mcp claude
1266
+
1267
+ # Configure Claude Desktop globally
1268
+ mcp-ticketer mcp claude --global
1269
+
1270
+ # Force overwrite existing configuration
1271
+ mcp-ticketer mcp claude --force
1272
+
1255
1273
  """
1256
1274
  from ..cli.mcp_configure import configure_claude_mcp
1257
1275
 
@@ -1262,6 +1280,121 @@ def mcp(
1262
1280
  raise typer.Exit(1)
1263
1281
 
1264
1282
 
1283
+ @mcp_app.command(name="gemini")
1284
+ def mcp_gemini(
1285
+ scope: str = typer.Option(
1286
+ "project",
1287
+ "--scope",
1288
+ "-s",
1289
+ help="Configuration scope: 'project' (default) or 'user'",
1290
+ ),
1291
+ force: bool = typer.Option(
1292
+ False, "--force", "-f", help="Overwrite existing configuration"
1293
+ ),
1294
+ ):
1295
+ """Configure Gemini CLI to use mcp-ticketer MCP server.
1296
+
1297
+ Reads configuration from .mcp-ticketer/config.json and creates
1298
+ Gemini CLI settings file with mcp-ticketer configuration.
1299
+
1300
+ By default, configures project-level (.gemini/settings.json).
1301
+ Use --scope user to configure user-level (~/.gemini/settings.json).
1302
+
1303
+ Examples:
1304
+ # Configure for current project (default)
1305
+ mcp-ticketer mcp gemini
1306
+
1307
+ # Configure at user level
1308
+ mcp-ticketer mcp gemini --scope user
1309
+
1310
+ # Force overwrite existing configuration
1311
+ mcp-ticketer mcp gemini --force
1312
+
1313
+ """
1314
+ from ..cli.gemini_configure import configure_gemini_mcp
1315
+
1316
+ # Validate scope parameter
1317
+ if scope not in ["project", "user"]:
1318
+ console.print(
1319
+ f"[red]✗ Invalid scope:[/red] '{scope}'. Must be 'project' or 'user'"
1320
+ )
1321
+ raise typer.Exit(1)
1322
+
1323
+ try:
1324
+ configure_gemini_mcp(scope=scope, force=force) # type: ignore
1325
+ except Exception as e:
1326
+ console.print(f"[red]✗ Configuration failed:[/red] {e}")
1327
+ raise typer.Exit(1)
1328
+
1329
+
1330
+ @mcp_app.command(name="codex")
1331
+ def mcp_codex(
1332
+ force: bool = typer.Option(
1333
+ False, "--force", "-f", help="Overwrite existing configuration"
1334
+ ),
1335
+ ):
1336
+ """Configure Codex CLI to use mcp-ticketer MCP server.
1337
+
1338
+ Reads configuration from .mcp-ticketer/config.json and creates
1339
+ Codex CLI config.toml with mcp-ticketer configuration.
1340
+
1341
+ IMPORTANT: Codex CLI ONLY supports global configuration at ~/.codex/config.toml.
1342
+ There is no project-level configuration support. After configuration,
1343
+ you must restart Codex CLI for changes to take effect.
1344
+
1345
+ Examples:
1346
+ # Configure Codex CLI globally
1347
+ mcp-ticketer mcp codex
1348
+
1349
+ # Force overwrite existing configuration
1350
+ mcp-ticketer mcp codex --force
1351
+
1352
+ """
1353
+ from ..cli.codex_configure import configure_codex_mcp
1354
+
1355
+ try:
1356
+ configure_codex_mcp(force=force)
1357
+ except Exception as e:
1358
+ console.print(f"[red]✗ Configuration failed:[/red] {e}")
1359
+ raise typer.Exit(1)
1360
+
1361
+
1362
+ @mcp_app.command(name="auggie")
1363
+ def mcp_auggie(
1364
+ force: bool = typer.Option(
1365
+ False, "--force", "-f", help="Overwrite existing configuration"
1366
+ ),
1367
+ ):
1368
+ """Configure Auggie CLI to use mcp-ticketer MCP server.
1369
+
1370
+ Reads configuration from .mcp-ticketer/config.json and creates
1371
+ Auggie CLI settings.json with mcp-ticketer configuration.
1372
+
1373
+ IMPORTANT: Auggie CLI ONLY supports global configuration at ~/.augment/settings.json.
1374
+ There is no project-level configuration support. After configuration,
1375
+ you must restart Auggie CLI for changes to take effect.
1376
+
1377
+ Examples:
1378
+ # Configure Auggie CLI globally
1379
+ mcp-ticketer mcp auggie
1380
+
1381
+ # Force overwrite existing configuration
1382
+ mcp-ticketer mcp auggie --force
1383
+
1384
+ """
1385
+ from ..cli.auggie_configure import configure_auggie_mcp
1386
+
1387
+ try:
1388
+ configure_auggie_mcp(force=force)
1389
+ except Exception as e:
1390
+ console.print(f"[red]✗ Configuration failed:[/red] {e}")
1391
+ raise typer.Exit(1)
1392
+
1393
+
1394
+ # Add MCP command group to main app (must be after all subcommands are defined)
1395
+ app.add_typer(mcp_app, name="mcp")
1396
+
1397
+
1265
1398
  def main():
1266
1399
  """Main entry point."""
1267
1400
  app()
@@ -8,11 +8,7 @@ from typing import Any
8
8
  from rich.console import Console
9
9
  from rich.prompt import Confirm
10
10
 
11
- from ..core.project_config import (
12
- AdapterConfig,
13
- ConfigResolver,
14
- TicketerConfig,
15
- )
11
+ from ..core.project_config import AdapterConfig, ConfigResolver, TicketerConfig
16
12
 
17
13
  console = Console()
18
14
 
@@ -14,7 +14,10 @@ import os
14
14
  from dataclasses import asdict, dataclass, field
15
15
  from enum import Enum
16
16
  from pathlib import Path
17
- from typing import Any, Optional
17
+ from typing import Any, Optional, TYPE_CHECKING
18
+
19
+ if TYPE_CHECKING:
20
+ from .env_discovery import DiscoveryResult
18
21
 
19
22
  logger = logging.getLogger(__name__)
20
23
 
@@ -12,6 +12,9 @@ from ..core import AdapterRegistry
12
12
  from ..core.models import SearchQuery
13
13
  from ..queue import Queue, QueueStatus, WorkerManager
14
14
 
15
+ # Import adapters module to trigger registration
16
+ import mcp_ticketer.adapters # noqa: F401
17
+
15
18
  # Load environment variables early (prioritize .env.local)
16
19
  # Check for .env.local first (takes precedence)
17
20
  env_local_file = Path.cwd() / ".env.local"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-ticketer
3
- Version: 0.1.23
3
+ Version: 0.1.26
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>
@@ -39,6 +39,8 @@ Requires-Dist: psutil>=5.9.0
39
39
  Requires-Dist: pydantic>=2.0
40
40
  Requires-Dist: python-dotenv>=1.0.0
41
41
  Requires-Dist: rich>=13.0.0
42
+ Requires-Dist: tomli>=2.0.0; python_version < "3.11"
43
+ Requires-Dist: tomli-w>=1.0.0
42
44
  Requires-Dist: typer>=0.9.0
43
45
  Requires-Dist: typing-extensions>=4.8.0
44
46
  Provides-Extra: all
@@ -129,6 +131,39 @@ pip install -e .
129
131
  - Python 3.9+
130
132
  - Virtual environment (recommended)
131
133
 
134
+ ## 🤖 Supported AI Clients
135
+
136
+ MCP Ticketer integrates with multiple AI clients via the Model Context Protocol (MCP):
137
+
138
+ | AI Client | Support | Config Type | Project-Level | Setup Command |
139
+ |-----------|---------|-------------|---------------|---------------|
140
+ | **Claude Code** | ✅ Native | JSON | ✅ Yes | `mcp-ticketer mcp claude` |
141
+ | **Gemini CLI** | ✅ Full | JSON | ✅ Yes | `mcp-ticketer mcp gemini` |
142
+ | **Codex CLI** | ✅ Full | TOML | ❌ Global only | `mcp-ticketer mcp codex` |
143
+ | **Auggie** | ✅ Full | JSON | ❌ Global only | `mcp-ticketer mcp auggie` |
144
+
145
+ ### Quick MCP Setup
146
+
147
+ ```bash
148
+ # Claude Code (recommended for project-specific workflows)
149
+ mcp-ticketer init --adapter aitrackdown # First, initialize an adapter
150
+ mcp-ticketer mcp claude # Then configure MCP
151
+
152
+ # Gemini CLI (Google's AI client)
153
+ mcp-ticketer init --adapter aitrackdown
154
+ mcp-ticketer mcp gemini --scope project
155
+
156
+ # Codex CLI (global configuration, requires restart)
157
+ mcp-ticketer init --adapter aitrackdown
158
+ mcp-ticketer mcp codex
159
+
160
+ # Auggie (simple global setup)
161
+ mcp-ticketer init --adapter aitrackdown
162
+ mcp-ticketer mcp auggie
163
+ ```
164
+
165
+ **See [AI Client Integration Guide](docs/AI_CLIENT_INTEGRATION.md) for detailed setup instructions.**
166
+
132
167
  ## 🚀 Quick Start
133
168
 
134
169
  ### 1. Initialize Configuration
@@ -179,28 +214,43 @@ mcp-ticketer search "login bug" --state open
179
214
 
180
215
  ## 🤖 MCP Server Integration
181
216
 
182
- Run the MCP server for AI tool integration:
217
+ MCP Ticketer provides seamless integration with AI clients through automatic configuration:
183
218
 
184
219
  ```bash
185
- mcp-ticketer-server
220
+ # Run MCP server manually (for testing)
221
+ mcp-ticketer serve
222
+
223
+ # Or configure your AI client automatically (recommended)
224
+ mcp-ticketer mcp claude # For Claude Code
225
+ mcp-ticketer mcp gemini # For Gemini CLI
226
+ mcp-ticketer mcp codex # For Codex CLI
227
+ mcp-ticketer mcp auggie # For Auggie
186
228
  ```
187
229
 
188
- Configure your AI tool to use the MCP server:
230
+ **Configuration is automatic** - the commands above will:
231
+ 1. Detect your mcp-ticketer installation
232
+ 2. Read your adapter configuration
233
+ 3. Generate the appropriate MCP server config
234
+ 4. Save it to the correct location for your AI client
235
+
236
+ **Manual Configuration Example** (Claude Code):
189
237
 
190
238
  ```json
191
239
  {
192
240
  "mcpServers": {
193
- "ticketer": {
194
- "command": "mcp-ticketer-server",
195
- "args": [],
241
+ "mcp-ticketer": {
242
+ "command": "/path/to/mcp-ticketer",
243
+ "args": ["serve"],
196
244
  "env": {
197
- "MCP_TICKETER_ADAPTER": "jira"
245
+ "MCP_TICKETER_ADAPTER": "aitrackdown"
198
246
  }
199
247
  }
200
248
  }
201
249
  }
202
250
  ```
203
251
 
252
+ **See [AI Client Integration Guide](docs/AI_CLIENT_INTEGRATION.md) for client-specific details.**
253
+
204
254
  ## 📚 Documentation
205
255
 
206
256
  Full documentation is available at [https://mcp-ticketerer.readthedocs.io](https://mcp-ticketerer.readthedocs.io)
@@ -1,20 +1,23 @@
1
- mcp_ticketer/__init__.py,sha256=701DkKv4mtXRwbG6GjYhryb-aV8FVmq3RMF-qD_V3I8,497
2
- mcp_ticketer/__version__.py,sha256=L30Ek80zyhmFK6JeBpHlO8fe-4ZFzdJMtpN64wq35I4,1118
1
+ mcp_ticketer/__init__.py,sha256=Xx4WaprO5PXhVPbYi1L6tBmwmJMkYS-lMyG4ieN6QP0,717
2
+ mcp_ticketer/__version__.py,sha256=Blu_YTtqV4xVWOGVEqjOak3E8m3Fe2X2xVHzhlPhTTA,1118
3
3
  mcp_ticketer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  mcp_ticketer/adapters/__init__.py,sha256=B5DFllWn23hkhmrLykNO5uMMSdcFuuPHXyLw_jyFzuE,358
5
5
  mcp_ticketer/adapters/aitrackdown.py,sha256=24h3UqMj5CltCl271kmqnDFOicCVp9w7yMTKK8s_dTA,16283
6
6
  mcp_ticketer/adapters/github.py,sha256=X0lEWBCfy-vztX2vauuVSYsOCa9_ezt9hGa5BsCQTu8,46663
7
7
  mcp_ticketer/adapters/hybrid.py,sha256=XFqHtWTLguE61ZGuZ156gxoz-wMr21AxLSADI1QVxcU,19025
8
- mcp_ticketer/adapters/jira.py,sha256=WcuqHtix2iHz0nMy2QhtQfHYhq4byb_ETfsusiCwocE,30574
9
- mcp_ticketer/adapters/linear.py,sha256=z39jQt74AVGmrV5HrJQdoRT-j58FoY21hbfAysrsdTc,71460
8
+ mcp_ticketer/adapters/jira.py,sha256=W2pU-YxrSqgjm1gVt2eGc8We-G0MbRMSggQ2gWkThME,30602
9
+ mcp_ticketer/adapters/linear.py,sha256=C6rHIxRaWvOBjX6ue2Nt-IPTcwFAwBkksstb7zV3YJw,71484
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
13
+ mcp_ticketer/cli/auggie_configure.py,sha256=MXKzLtqe3K_UTQ2GacHAWbvf_B0779KL325smiAKE0Q,8212
14
+ mcp_ticketer/cli/codex_configure.py,sha256=xDppHouT6_-cYXswyAggoPX5bSlRXMvCoM_x9PQ-42A,9086
13
15
  mcp_ticketer/cli/configure.py,sha256=BsA_pSHQMQS0t1bJO_wMM8LWsd5sWJDASjEPRHvwC18,16198
14
16
  mcp_ticketer/cli/discover.py,sha256=AF_qlQc1Oo0UkWayoF5pmRChS5J3fJjH6f2YZzd_k8w,13188
15
- mcp_ticketer/cli/main.py,sha256=njw45cl8FBtPpaQfmk4jn3D9Dc6UQo0qWxYfPPcmwZg,43115
17
+ mcp_ticketer/cli/gemini_configure.py,sha256=ZNSA1lBW-itVToza-JxW95Po7daVXKiZAh7lp6pmXMU,9343
18
+ mcp_ticketer/cli/main.py,sha256=AvWLtlKrAtgWv6cfXNRzESqJE7CRhHdKeDuNWOxj5GM,47111
16
19
  mcp_ticketer/cli/mcp_configure.py,sha256=RzV50UjXgOmvMp-9S0zS39psuvjffVByaMrqrUaAGAM,9594
17
- mcp_ticketer/cli/migrate_config.py,sha256=E-uD9_GTWQzfdiBweFYtCKyXOYtIaRHv7QuyVjV-rbI,5973
20
+ mcp_ticketer/cli/migrate_config.py,sha256=MYsr_C5ZxsGg0P13etWTWNrJ_lc6ElRCkzfQADYr3DM,5956
18
21
  mcp_ticketer/cli/queue_commands.py,sha256=mm-3H6jmkUGJDyU_E46o9iRpek8tvFCm77F19OtHiZI,7884
19
22
  mcp_ticketer/cli/utils.py,sha256=2ptUrp2ELZsox0kSxAI5DFrHonOU999qh4MxbLv6VBQ,21155
20
23
  mcp_ticketer/core/__init__.py,sha256=eXovsaJymQRP2AwOBuOy6mFtI3I68D7gGenZ5V-IMqo,349
@@ -24,19 +27,19 @@ mcp_ticketer/core/env_discovery.py,sha256=wKp2Pi5vQMGOTrM1690IBv_eoABly-pD8ah7n1
24
27
  mcp_ticketer/core/http_client.py,sha256=s5ikMiwEJ8TJjNn73wu3gv3OdAtyBEpAqPnSroRMW2k,13971
25
28
  mcp_ticketer/core/mappers.py,sha256=1aG1jFsHTCwmGRVgOlXW-VOSTGzc86gv7qjDfiR1ups,17462
26
29
  mcp_ticketer/core/models.py,sha256=DRuJoYbjp9fcPV9GwQfhVcNUB0XmwQB3vuqW8hQWZ_k,6491
27
- mcp_ticketer/core/project_config.py,sha256=BeBkeCaQC0kZmpIhkdsqOL1zHBeDmkaRbcVUwAk8B0s,23265
30
+ mcp_ticketer/core/project_config.py,sha256=yYxlgxjcEPeOwx-b-SXFpe0k9pW9xzBRAK72PsItG-o,23346
28
31
  mcp_ticketer/core/registry.py,sha256=ShYLDPE62KFJpB0kj_zFyQzRxSH3LkQEEuo1jaakb1k,3483
29
32
  mcp_ticketer/mcp/__init__.py,sha256=Y05eTzsPk0wH8yKNIM-ekpGjgSDO0bQr0EME-vOP4GE,123
30
- mcp_ticketer/mcp/server.py,sha256=U0bkHYe_DGa7wNPtuawsA8i_llHmpADgtq-OkYMjoBo,37041
33
+ mcp_ticketer/mcp/server.py,sha256=YXhKqxz5b4k7_38yj0dCHOmNBFbXppQbctbL8zUOLVQ,37134
31
34
  mcp_ticketer/queue/__init__.py,sha256=1YIaCpZpFqPcqvDEQXiEvDLiw94DXRdCJkBaVIFQrms,231
32
35
  mcp_ticketer/queue/__main__.py,sha256=gc_tE9NUdK07OJfTZuD4t6KeBD_vxFQIhknGTQUG_jk,109
33
36
  mcp_ticketer/queue/manager.py,sha256=qqUqq_JtH8jfg-MDfc-UIgFaa7gYsA1eBaR2KsCw48c,7513
34
37
  mcp_ticketer/queue/queue.py,sha256=zD7SRDP7zfGm4gokqzgL0CLuPUPxbBNmddsOqLMCbjQ,13162
35
38
  mcp_ticketer/queue/run_worker.py,sha256=_IBezjvhbJJ7gn0evTBIMbSPjvfFZwxEdT-1DLo_bRk,799
36
39
  mcp_ticketer/queue/worker.py,sha256=2wusez3Wxmun6qAmup3WsGjBD-vNgtLwxygYviXdECQ,14634
37
- mcp_ticketer-0.1.23.dist-info/licenses/LICENSE,sha256=KOVrunjtILSzY-2N8Lqa3-Q8dMaZIG4LrlLTr9UqL08,1073
38
- mcp_ticketer-0.1.23.dist-info/METADATA,sha256=YrPCs8xszAbjFsMBB2CO_7vU6gVAMDUimqDiumqV3uk,11211
39
- mcp_ticketer-0.1.23.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
40
- mcp_ticketer-0.1.23.dist-info/entry_points.txt,sha256=o1IxVhnHnBNG7FZzbFq-Whcs1Djbofs0qMjiUYBLx2s,60
41
- mcp_ticketer-0.1.23.dist-info/top_level.txt,sha256=WnAG4SOT1Vm9tIwl70AbGG_nA217YyV3aWFhxLH2rxw,13
42
- mcp_ticketer-0.1.23.dist-info/RECORD,,
40
+ mcp_ticketer-0.1.26.dist-info/licenses/LICENSE,sha256=KOVrunjtILSzY-2N8Lqa3-Q8dMaZIG4LrlLTr9UqL08,1073
41
+ mcp_ticketer-0.1.26.dist-info/METADATA,sha256=U39e27Ve_r8quq7j089RGcFHPuTN6QL1UbVI6o6ZwrA,13191
42
+ mcp_ticketer-0.1.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
43
+ mcp_ticketer-0.1.26.dist-info/entry_points.txt,sha256=o1IxVhnHnBNG7FZzbFq-Whcs1Djbofs0qMjiUYBLx2s,60
44
+ mcp_ticketer-0.1.26.dist-info/top_level.txt,sha256=WnAG4SOT1Vm9tIwl70AbGG_nA217YyV3aWFhxLH2rxw,13
45
+ mcp_ticketer-0.1.26.dist-info/RECORD,,