glaip-sdk 0.0.3__py3-none-any.whl → 0.0.5__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.
- glaip_sdk/__init__.py +5 -5
- glaip_sdk/branding.py +146 -0
- glaip_sdk/cli/__init__.py +1 -1
- glaip_sdk/cli/agent_config.py +82 -0
- glaip_sdk/cli/commands/__init__.py +3 -3
- glaip_sdk/cli/commands/agents.py +786 -271
- glaip_sdk/cli/commands/configure.py +19 -19
- glaip_sdk/cli/commands/mcps.py +151 -141
- glaip_sdk/cli/commands/models.py +1 -1
- glaip_sdk/cli/commands/tools.py +252 -178
- glaip_sdk/cli/display.py +244 -0
- glaip_sdk/cli/io.py +106 -0
- glaip_sdk/cli/main.py +27 -20
- glaip_sdk/cli/resolution.py +59 -0
- glaip_sdk/cli/utils.py +372 -213
- glaip_sdk/cli/validators.py +235 -0
- glaip_sdk/client/__init__.py +3 -224
- glaip_sdk/client/agents.py +632 -171
- glaip_sdk/client/base.py +66 -4
- glaip_sdk/client/main.py +226 -0
- glaip_sdk/client/mcps.py +143 -18
- glaip_sdk/client/tools.py +327 -104
- glaip_sdk/config/constants.py +10 -1
- glaip_sdk/models.py +43 -3
- glaip_sdk/rich_components.py +29 -0
- glaip_sdk/utils/__init__.py +18 -171
- glaip_sdk/utils/agent_config.py +181 -0
- glaip_sdk/utils/client_utils.py +159 -79
- glaip_sdk/utils/display.py +100 -0
- glaip_sdk/utils/general.py +94 -0
- glaip_sdk/utils/import_export.py +140 -0
- glaip_sdk/utils/rendering/formatting.py +6 -1
- glaip_sdk/utils/rendering/renderer/__init__.py +67 -8
- glaip_sdk/utils/rendering/renderer/base.py +340 -247
- glaip_sdk/utils/rendering/renderer/debug.py +3 -2
- glaip_sdk/utils/rendering/renderer/panels.py +11 -10
- glaip_sdk/utils/rendering/steps.py +1 -1
- glaip_sdk/utils/resource_refs.py +192 -0
- glaip_sdk/utils/rich_utils.py +29 -0
- glaip_sdk/utils/serialization.py +285 -0
- glaip_sdk/utils/validation.py +273 -0
- {glaip_sdk-0.0.3.dist-info → glaip_sdk-0.0.5.dist-info}/METADATA +6 -5
- glaip_sdk-0.0.5.dist-info/RECORD +55 -0
- glaip_sdk/cli/commands/init.py +0 -177
- glaip_sdk-0.0.3.dist-info/RECORD +0 -40
- {glaip_sdk-0.0.3.dist-info → glaip_sdk-0.0.5.dist-info}/WHEEL +0 -0
- {glaip_sdk-0.0.3.dist-info → glaip_sdk-0.0.5.dist-info}/entry_points.txt +0 -0
|
@@ -11,10 +11,12 @@ from pathlib import Path
|
|
|
11
11
|
import click
|
|
12
12
|
import yaml
|
|
13
13
|
from rich.console import Console
|
|
14
|
-
from rich.
|
|
15
|
-
from rich.table import Table
|
|
14
|
+
from rich.text import Text
|
|
16
15
|
|
|
17
16
|
from glaip_sdk import Client
|
|
17
|
+
from glaip_sdk._version import __version__ as _SDK_VERSION
|
|
18
|
+
from glaip_sdk.branding import AIPBranding
|
|
19
|
+
from glaip_sdk.rich_components import AIPTable
|
|
18
20
|
|
|
19
21
|
console = Console()
|
|
20
22
|
|
|
@@ -66,7 +68,7 @@ def list_config():
|
|
|
66
68
|
)
|
|
67
69
|
return
|
|
68
70
|
|
|
69
|
-
table =
|
|
71
|
+
table = AIPTable(title="🔧 AIP Configuration")
|
|
70
72
|
table.add_column("Setting", style="cyan", width=20)
|
|
71
73
|
table.add_column("Value", style="green")
|
|
72
74
|
|
|
@@ -79,7 +81,7 @@ def list_config():
|
|
|
79
81
|
table.add_row(key, str(value))
|
|
80
82
|
|
|
81
83
|
console.print(table)
|
|
82
|
-
console.print(f"\n📁 Config file: {CONFIG_FILE}")
|
|
84
|
+
console.print(Text(f"\n📁 Config file: {CONFIG_FILE}"))
|
|
83
85
|
|
|
84
86
|
|
|
85
87
|
@config_group.command("set")
|
|
@@ -102,9 +104,9 @@ def set_config(key, value):
|
|
|
102
104
|
|
|
103
105
|
if key == "api_key":
|
|
104
106
|
masked_value = "***" + value[-4:] if len(value) > 4 else "***"
|
|
105
|
-
console.print(f"✅ Set {key} = {masked_value}")
|
|
107
|
+
console.print(Text(f"✅ Set {key} = {masked_value}"))
|
|
106
108
|
else:
|
|
107
|
-
console.print(f"✅ Set {key} = {value}")
|
|
109
|
+
console.print(Text(f"✅ Set {key} = {value}"))
|
|
108
110
|
|
|
109
111
|
|
|
110
112
|
@config_group.command("get")
|
|
@@ -115,7 +117,7 @@ def get_config(key):
|
|
|
115
117
|
config = load_config()
|
|
116
118
|
|
|
117
119
|
if key not in config:
|
|
118
|
-
console.print(f"[yellow]Configuration key '{key}' not found.[/yellow]")
|
|
120
|
+
console.print(Text(f"[yellow]Configuration key '{key}' not found.[/yellow]"))
|
|
119
121
|
raise click.ClickException(f"Configuration key not found: {key}")
|
|
120
122
|
|
|
121
123
|
value = config[key]
|
|
@@ -136,13 +138,13 @@ def unset_config(key):
|
|
|
136
138
|
config = load_config()
|
|
137
139
|
|
|
138
140
|
if key not in config:
|
|
139
|
-
console.print(f"[yellow]Configuration key '{key}' not found.[/yellow]")
|
|
141
|
+
console.print(Text(f"[yellow]Configuration key '{key}' not found.[/yellow]"))
|
|
140
142
|
return
|
|
141
143
|
|
|
142
144
|
del config[key]
|
|
143
145
|
save_config(config)
|
|
144
146
|
|
|
145
|
-
console.print(f"✅ Removed {key} from configuration")
|
|
147
|
+
console.print(Text(f"✅ Removed {key} from configuration"))
|
|
146
148
|
|
|
147
149
|
|
|
148
150
|
@config_group.command("reset")
|
|
@@ -168,13 +170,11 @@ def reset_config(force):
|
|
|
168
170
|
|
|
169
171
|
def _configure_interactive():
|
|
170
172
|
"""Shared configuration logic for both configure commands."""
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
title="🔧 Configuration Setup",
|
|
175
|
-
border_style="cyan",
|
|
176
|
-
)
|
|
173
|
+
# Display AIP welcome banner
|
|
174
|
+
branding = AIPBranding.create_from_sdk(
|
|
175
|
+
sdk_version=_SDK_VERSION, package_name="glaip-sdk"
|
|
177
176
|
)
|
|
177
|
+
branding.display_welcome_panel(title="🔧 AIP Configuration")
|
|
178
178
|
|
|
179
179
|
# Load existing config
|
|
180
180
|
config = load_config()
|
|
@@ -208,7 +208,7 @@ def _configure_interactive():
|
|
|
208
208
|
# Save configuration
|
|
209
209
|
save_config(config)
|
|
210
210
|
|
|
211
|
-
console.print(f"\n✅ Configuration saved to: {CONFIG_FILE}")
|
|
211
|
+
console.print(Text(f"\n✅ Configuration saved to: {CONFIG_FILE}"))
|
|
212
212
|
|
|
213
213
|
# Test the new configuration
|
|
214
214
|
console.print("\n🔌 Testing connection...")
|
|
@@ -219,9 +219,9 @@ def _configure_interactive():
|
|
|
219
219
|
# Try to list resources to test connection
|
|
220
220
|
try:
|
|
221
221
|
agents = client.list_agents()
|
|
222
|
-
console.print(f"✅ Connection successful! Found {len(agents)} agents")
|
|
222
|
+
console.print(Text(f"✅ Connection successful! Found {len(agents)} agents"))
|
|
223
223
|
except Exception as e:
|
|
224
|
-
console.print(f"⚠️ Connection established but API call failed: {e}")
|
|
224
|
+
console.print(Text(f"⚠️ Connection established but API call failed: {e}"))
|
|
225
225
|
console.print(
|
|
226
226
|
" You may need to check your API permissions or network access"
|
|
227
227
|
)
|
|
@@ -229,7 +229,7 @@ def _configure_interactive():
|
|
|
229
229
|
client.close()
|
|
230
230
|
|
|
231
231
|
except Exception as e:
|
|
232
|
-
console.print(f"❌ Connection failed: {e}")
|
|
232
|
+
console.print(Text(f"❌ Connection failed: {e}"))
|
|
233
233
|
console.print(" Please check your API URL and key")
|
|
234
234
|
console.print(" You can run 'aip status' later to test again")
|
|
235
235
|
|
glaip_sdk/cli/commands/mcps.py
CHANGED
|
@@ -5,20 +5,37 @@ Authors:
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import json
|
|
8
|
+
from pathlib import Path
|
|
8
9
|
|
|
9
10
|
import click
|
|
10
11
|
from rich.console import Console
|
|
11
|
-
from rich.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
from rich.text import Text
|
|
13
|
+
|
|
14
|
+
from glaip_sdk.cli.display import (
|
|
15
|
+
display_api_error,
|
|
16
|
+
display_confirmation_prompt,
|
|
17
|
+
display_creation_success,
|
|
18
|
+
display_deletion_success,
|
|
19
|
+
display_update_success,
|
|
20
|
+
handle_json_output,
|
|
21
|
+
handle_rich_output,
|
|
22
|
+
)
|
|
23
|
+
from glaip_sdk.cli.io import (
|
|
24
|
+
export_resource_to_file_with_validation as export_resource_to_file,
|
|
25
|
+
)
|
|
26
|
+
from glaip_sdk.cli.io import (
|
|
27
|
+
fetch_raw_resource_details,
|
|
28
|
+
)
|
|
29
|
+
from glaip_sdk.cli.resolution import resolve_resource_reference
|
|
30
|
+
from glaip_sdk.cli.utils import (
|
|
15
31
|
coerce_to_row,
|
|
16
32
|
get_client,
|
|
17
33
|
output_flags,
|
|
18
34
|
output_list,
|
|
19
35
|
output_result,
|
|
20
|
-
resolve_resource,
|
|
21
36
|
)
|
|
37
|
+
from glaip_sdk.rich_components import AIPPanel
|
|
38
|
+
from glaip_sdk.utils import format_datetime
|
|
22
39
|
|
|
23
40
|
console = Console()
|
|
24
41
|
|
|
@@ -31,12 +48,14 @@ def mcps_group():
|
|
|
31
48
|
|
|
32
49
|
def _resolve_mcp(ctx, client, ref, select=None):
|
|
33
50
|
"""Resolve MCP reference (ID or name) with ambiguity handling."""
|
|
34
|
-
return
|
|
51
|
+
return resolve_resource_reference(
|
|
35
52
|
ctx,
|
|
53
|
+
client,
|
|
36
54
|
ref,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
55
|
+
"mcp",
|
|
56
|
+
client.mcps.get_mcp_by_id,
|
|
57
|
+
client.mcps.find_mcps,
|
|
58
|
+
"MCP",
|
|
40
59
|
select=select,
|
|
41
60
|
)
|
|
42
61
|
|
|
@@ -105,55 +124,117 @@ def create(ctx, name, transport, description, config):
|
|
|
105
124
|
config=mcp_config,
|
|
106
125
|
)
|
|
107
126
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
console.print(panel)
|
|
127
|
+
# Handle JSON output
|
|
128
|
+
handle_json_output(ctx, mcp.model_dump())
|
|
129
|
+
|
|
130
|
+
# Handle Rich output
|
|
131
|
+
rich_panel = display_creation_success(
|
|
132
|
+
"MCP",
|
|
133
|
+
mcp.name,
|
|
134
|
+
mcp.id,
|
|
135
|
+
Type="server",
|
|
136
|
+
Transport=getattr(mcp, "transport", transport),
|
|
137
|
+
Description=description or "No description",
|
|
138
|
+
)
|
|
139
|
+
handle_rich_output(ctx, rich_panel)
|
|
122
140
|
|
|
123
141
|
except Exception as e:
|
|
124
|
-
|
|
125
|
-
if view
|
|
126
|
-
|
|
127
|
-
else:
|
|
128
|
-
console.print(f"[red]Error creating MCP: {e}[/red]")
|
|
142
|
+
handle_json_output(ctx, error=e)
|
|
143
|
+
if ctx.obj.get("view") != "json":
|
|
144
|
+
display_api_error(e, "MCP creation")
|
|
129
145
|
raise click.ClickException(str(e))
|
|
130
146
|
|
|
131
147
|
|
|
132
148
|
@mcps_group.command()
|
|
133
149
|
@click.argument("mcp_ref")
|
|
150
|
+
@click.option(
|
|
151
|
+
"--export",
|
|
152
|
+
type=click.Path(dir_okay=False, writable=True),
|
|
153
|
+
help="Export complete MCP configuration to file (format auto-detected from .json/.yaml extension)",
|
|
154
|
+
)
|
|
134
155
|
@output_flags()
|
|
135
156
|
@click.pass_context
|
|
136
|
-
def get(ctx, mcp_ref):
|
|
137
|
-
"""Get MCP details.
|
|
157
|
+
def get(ctx, mcp_ref, export):
|
|
158
|
+
"""Get MCP details.
|
|
159
|
+
|
|
160
|
+
Examples:
|
|
161
|
+
aip mcps get my-mcp
|
|
162
|
+
aip mcps get my-mcp --export mcp.json # Exports complete configuration as JSON
|
|
163
|
+
aip mcps get my-mcp --export mcp.yaml # Exports complete configuration as YAML
|
|
164
|
+
"""
|
|
138
165
|
try:
|
|
139
166
|
client = get_client(ctx)
|
|
140
167
|
|
|
141
168
|
# Resolve MCP using helper function
|
|
142
169
|
mcp = _resolve_mcp(ctx, client, mcp_ref)
|
|
143
170
|
|
|
144
|
-
#
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
171
|
+
# Handle export option
|
|
172
|
+
if export:
|
|
173
|
+
export_path = Path(export)
|
|
174
|
+
# Auto-detect format from file extension
|
|
175
|
+
if export_path.suffix.lower() in [".yaml", ".yml"]:
|
|
176
|
+
detected_format = "yaml"
|
|
177
|
+
else:
|
|
178
|
+
detected_format = "json"
|
|
179
|
+
|
|
180
|
+
# Always export comprehensive data - re-fetch MCP with full details if needed
|
|
181
|
+
try:
|
|
182
|
+
mcp = client.mcps.get_mcp_by_id(mcp.id)
|
|
183
|
+
except Exception as e:
|
|
184
|
+
console.print(
|
|
185
|
+
Text(f"[yellow]⚠️ Could not fetch full MCP details: {e}[/yellow]")
|
|
186
|
+
)
|
|
187
|
+
console.print(
|
|
188
|
+
Text("[yellow]⚠️ Proceeding with available data[/yellow]")
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
export_resource_to_file(mcp, export_path, detected_format)
|
|
192
|
+
console.print(
|
|
193
|
+
Text(
|
|
194
|
+
f"[green]✅ Complete MCP configuration exported to: {export_path} (format: {detected_format})[/green]"
|
|
195
|
+
)
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
# Try to fetch raw API data first to preserve ALL fields
|
|
199
|
+
raw_mcp_data = fetch_raw_resource_details(client, mcp, "mcps")
|
|
200
|
+
|
|
201
|
+
if raw_mcp_data:
|
|
202
|
+
# Use raw API data - this preserves ALL fields
|
|
203
|
+
# Format dates for better display (minimal postprocessing)
|
|
204
|
+
formatted_data = raw_mcp_data.copy()
|
|
205
|
+
if "created_at" in formatted_data:
|
|
206
|
+
formatted_data["created_at"] = format_datetime(
|
|
207
|
+
formatted_data["created_at"]
|
|
208
|
+
)
|
|
209
|
+
if "updated_at" in formatted_data:
|
|
210
|
+
formatted_data["updated_at"] = format_datetime(
|
|
211
|
+
formatted_data["updated_at"]
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
# Display using output_result with raw data
|
|
215
|
+
output_result(
|
|
216
|
+
ctx,
|
|
217
|
+
formatted_data,
|
|
218
|
+
title="MCP Details",
|
|
219
|
+
panel_title=f"🔌 {raw_mcp_data.get('name', 'Unknown')}",
|
|
220
|
+
)
|
|
221
|
+
else:
|
|
222
|
+
# Fall back to original method if raw fetch fails
|
|
223
|
+
console.print("[yellow]Falling back to Pydantic model data[/yellow]")
|
|
224
|
+
|
|
225
|
+
# Create result data with actual available fields
|
|
226
|
+
result_data = {
|
|
227
|
+
"id": str(getattr(mcp, "id", "N/A")),
|
|
228
|
+
"name": getattr(mcp, "name", "N/A"),
|
|
229
|
+
"type": getattr(mcp, "type", "N/A"),
|
|
230
|
+
"config": getattr(mcp, "config", "N/A"),
|
|
231
|
+
"status": getattr(mcp, "status", "N/A"),
|
|
232
|
+
"connection_status": getattr(mcp, "connection_status", "N/A"),
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
output_result(
|
|
236
|
+
ctx, result_data, title="MCP Details", panel_title=f"🔌 {mcp.name}"
|
|
237
|
+
)
|
|
157
238
|
|
|
158
239
|
except Exception as e:
|
|
159
240
|
raise click.ClickException(str(e))
|
|
@@ -199,18 +280,17 @@ def list_tools(ctx, mcp_ref):
|
|
|
199
280
|
raise click.ClickException(str(e))
|
|
200
281
|
|
|
201
282
|
|
|
202
|
-
@mcps_group.command("
|
|
283
|
+
@mcps_group.command("connect")
|
|
203
284
|
@click.option(
|
|
204
285
|
"--from-file",
|
|
205
286
|
"config_file",
|
|
206
|
-
type=click.Path(exists=True),
|
|
207
287
|
required=True,
|
|
208
288
|
help="MCP config JSON file",
|
|
209
289
|
)
|
|
210
290
|
@output_flags()
|
|
211
291
|
@click.pass_context
|
|
212
|
-
def
|
|
213
|
-
"""
|
|
292
|
+
def connect(ctx, config_file):
|
|
293
|
+
"""Connect to MCP using config file."""
|
|
214
294
|
try:
|
|
215
295
|
client = get_client(ctx)
|
|
216
296
|
|
|
@@ -221,64 +301,9 @@ def tools_from_config(ctx, config_file):
|
|
|
221
301
|
view = (ctx.obj or {}).get("view", "rich")
|
|
222
302
|
if view != "json":
|
|
223
303
|
console.print(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
# Get tools from MCP config
|
|
228
|
-
tools = client.mcps.get_mcp_tools_from_config(config)
|
|
229
|
-
|
|
230
|
-
view = (ctx.obj or {}).get("view", "rich")
|
|
231
|
-
if view == "json":
|
|
232
|
-
click.echo(json.dumps(tools, indent=2))
|
|
233
|
-
else: # rich output
|
|
234
|
-
if tools:
|
|
235
|
-
table = Table(
|
|
236
|
-
title="🔧 Tools from MCP Config",
|
|
237
|
-
show_header=True,
|
|
238
|
-
header_style="bold magenta",
|
|
304
|
+
Text(
|
|
305
|
+
f"[yellow]Connecting to MCP with config from {config_file}...[/yellow]"
|
|
239
306
|
)
|
|
240
|
-
table.add_column("Name", style="cyan", no_wrap=True)
|
|
241
|
-
table.add_column("Description", style="green")
|
|
242
|
-
table.add_column("Type", style="yellow")
|
|
243
|
-
|
|
244
|
-
for tool in tools:
|
|
245
|
-
table.add_row(
|
|
246
|
-
tool.get("name", "N/A"),
|
|
247
|
-
tool.get("description", "N/A")[:50] + "..."
|
|
248
|
-
if len(tool.get("description", "")) > 50
|
|
249
|
-
else tool.get("description", "N/A"),
|
|
250
|
-
tool.get("type", "N/A"),
|
|
251
|
-
)
|
|
252
|
-
console.print(table)
|
|
253
|
-
else:
|
|
254
|
-
console.print("[yellow]No tools found in MCP config[/yellow]")
|
|
255
|
-
|
|
256
|
-
except Exception as e:
|
|
257
|
-
raise click.ClickException(str(e))
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
@mcps_group.command("test-connection")
|
|
261
|
-
@click.option(
|
|
262
|
-
"--from-file",
|
|
263
|
-
"config_file",
|
|
264
|
-
required=True,
|
|
265
|
-
help="MCP config JSON file",
|
|
266
|
-
)
|
|
267
|
-
@output_flags()
|
|
268
|
-
@click.pass_context
|
|
269
|
-
def test_connection(ctx, config_file):
|
|
270
|
-
"""Test MCP connection using config file."""
|
|
271
|
-
try:
|
|
272
|
-
client = get_client(ctx)
|
|
273
|
-
|
|
274
|
-
# Load MCP config from file
|
|
275
|
-
with open(config_file) as f:
|
|
276
|
-
config = json.load(f)
|
|
277
|
-
|
|
278
|
-
view = (ctx.obj or {}).get("view", "rich")
|
|
279
|
-
if view != "json":
|
|
280
|
-
console.print(
|
|
281
|
-
f"[yellow]Testing MCP connection with config from {config_file}...[/yellow]"
|
|
282
307
|
)
|
|
283
308
|
|
|
284
309
|
# Test connection using config
|
|
@@ -286,12 +311,12 @@ def test_connection(ctx, config_file):
|
|
|
286
311
|
|
|
287
312
|
view = (ctx.obj or {}).get("view", "rich")
|
|
288
313
|
if view == "json":
|
|
289
|
-
|
|
314
|
+
handle_json_output(ctx, result)
|
|
290
315
|
else:
|
|
291
|
-
success_panel =
|
|
292
|
-
f"[green]✓[/green] MCP connection
|
|
316
|
+
success_panel = AIPPanel(
|
|
317
|
+
f"[green]✓[/green] MCP connection successful!\n\n"
|
|
293
318
|
f"[bold]Result:[/bold] {result}",
|
|
294
|
-
title="🔌 Connection
|
|
319
|
+
title="🔌 Connection",
|
|
295
320
|
border_style="green",
|
|
296
321
|
)
|
|
297
322
|
console.print(success_panel)
|
|
@@ -330,23 +355,16 @@ def update(ctx, mcp_ref, name, description, config):
|
|
|
330
355
|
if not update_data:
|
|
331
356
|
raise click.ClickException("No update fields specified")
|
|
332
357
|
|
|
333
|
-
# Update MCP
|
|
358
|
+
# Update MCP (automatically chooses PUT or PATCH based on provided fields)
|
|
334
359
|
updated_mcp = client.mcps.update_mcp(mcp.id, **update_data)
|
|
335
360
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
click.echo(json.dumps(updated_mcp.model_dump(), indent=2))
|
|
339
|
-
else:
|
|
340
|
-
console.print(
|
|
341
|
-
f"[green]✅ MCP '{updated_mcp.name}' updated successfully[/green]"
|
|
342
|
-
)
|
|
361
|
+
handle_json_output(ctx, updated_mcp.model_dump())
|
|
362
|
+
handle_rich_output(ctx, display_update_success("MCP", updated_mcp.name))
|
|
343
363
|
|
|
344
364
|
except Exception as e:
|
|
345
|
-
|
|
346
|
-
if view
|
|
347
|
-
|
|
348
|
-
else:
|
|
349
|
-
console.print(f"[red]Error updating MCP: {e}[/red]")
|
|
365
|
+
handle_json_output(ctx, error=e)
|
|
366
|
+
if (ctx.obj or {}).get("view") != "json":
|
|
367
|
+
display_api_error(e, "MCP update")
|
|
350
368
|
raise click.ClickException(str(e))
|
|
351
369
|
|
|
352
370
|
|
|
@@ -364,30 +382,22 @@ def delete(ctx, mcp_ref, yes):
|
|
|
364
382
|
mcp = _resolve_mcp(ctx, client, mcp_ref)
|
|
365
383
|
|
|
366
384
|
# Confirm deletion
|
|
367
|
-
if not yes and not
|
|
368
|
-
f"Are you sure you want to delete MCP '{mcp.name}'?"
|
|
369
|
-
):
|
|
370
|
-
view = (ctx.obj or {}).get("view", "rich")
|
|
371
|
-
if view != "json":
|
|
372
|
-
console.print("Deletion cancelled.")
|
|
385
|
+
if not yes and not display_confirmation_prompt("MCP", mcp.name):
|
|
373
386
|
return
|
|
374
387
|
|
|
375
388
|
client.mcps.delete_mcp(mcp.id)
|
|
376
389
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
console.print(f"[green]✅ MCP '{mcp.name}' deleted successfully[/green]")
|
|
390
|
+
handle_json_output(
|
|
391
|
+
ctx,
|
|
392
|
+
{
|
|
393
|
+
"success": True,
|
|
394
|
+
"message": f"MCP '{mcp.name}' deleted",
|
|
395
|
+
},
|
|
396
|
+
)
|
|
397
|
+
handle_rich_output(ctx, display_deletion_success("MCP", mcp.name))
|
|
386
398
|
|
|
387
399
|
except Exception as e:
|
|
388
|
-
|
|
389
|
-
if view
|
|
390
|
-
|
|
391
|
-
else:
|
|
392
|
-
console.print(f"[red]Error deleting MCP: {e}[/red]")
|
|
400
|
+
handle_json_output(ctx, error=e)
|
|
401
|
+
if (ctx.obj or {}).get("view") != "json":
|
|
402
|
+
display_api_error(e, "MCP deletion")
|
|
393
403
|
raise click.ClickException(str(e))
|