cade-cli 0.4.0__tar.gz → 0.5.0__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.
- cade_cli-0.5.0/LICENSE +21 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/PKG-INFO +25 -4
- {cade_cli-0.4.0 → cade_cli-0.5.0}/pyproject.toml +4 -4
- cade_cli-0.5.0/src/cadecoder/__init__.py +1 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/cli/auth.py +0 -30
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/cli/commands/context.py +11 -1
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/cli/commands/mcp.py +11 -2
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/cli/commands/thread.py +9 -1
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/tools/manager/mcp.py +38 -5
- cade_cli-0.4.0/src/cadecoder/__init__.py +0 -1
- {cade_cli-0.4.0 → cade_cli-0.5.0}/.gitignore +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/README.md +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/ai/__init__.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/ai/prompts.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/cli/__init__.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/cli/app.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/cli/commands/__init__.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/cli/commands/auth.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/cli/commands/chat.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/cli/commands/model.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/cli/commands/tools.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/core/__init__.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/core/config.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/core/constants.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/core/errors.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/core/logging.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/core/names.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/core/types.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/execution/__init__.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/execution/context_window.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/execution/orchestrator.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/execution/parallel.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/providers/__init__.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/providers/anthropic.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/providers/base.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/providers/ollama.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/providers/openai.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/storage/__init__.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/storage/threads.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/templates/login_failed.html +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/templates/login_success.html +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/templates/styles.css +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/tools/__init__.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/tools/local/__init__.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/tools/local/filesystem.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/tools/local/git.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/tools/local/search.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/tools/local/shell.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/tools/manager/__init__.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/tools/manager/base.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/tools/manager/composite.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/tools/manager/config.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/ui/__init__.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/ui/display.py +0 -0
- {cade_cli-0.4.0 → cade_cli-0.5.0}/src/cadecoder/ui/session.py +0 -0
cade_cli-0.5.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Arcade AI Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cade-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Cade - The CLI Agent from Arcade.dev
|
|
5
5
|
Project-URL: Homepage, https://arcade.dev
|
|
6
6
|
Project-URL: Documentation, https://docs.arcade.dev
|
|
@@ -8,7 +8,28 @@ Project-URL: Repository, https://github.com/arcadeai-labs/cade
|
|
|
8
8
|
Project-URL: Issues, https://github.com/arcadeai-labs/cade/issues
|
|
9
9
|
Project-URL: Changelog, https://github.com/arcadeai-labs/cade/releases
|
|
10
10
|
Author-email: "Arcade AI Inc." <dev@arcade.dev>
|
|
11
|
-
License: MIT
|
|
11
|
+
License: MIT License
|
|
12
|
+
|
|
13
|
+
Copyright (c) 2024 Arcade AI Inc.
|
|
14
|
+
|
|
15
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
16
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
17
|
+
in the Software without restriction, including without limitation the rights
|
|
18
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
19
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
20
|
+
furnished to do so, subject to the following conditions:
|
|
21
|
+
|
|
22
|
+
The above copyright notice and this permission notice shall be included in all
|
|
23
|
+
copies or substantial portions of the Software.
|
|
24
|
+
|
|
25
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
26
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
27
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
28
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
29
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
30
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
31
|
+
SOFTWARE.
|
|
32
|
+
License-File: LICENSE
|
|
12
33
|
Keywords: agent,ai,arcade,cli,coding-assistant,llm,mcp
|
|
13
34
|
Classifier: Development Status :: 4 - Beta
|
|
14
35
|
Classifier: Environment :: Console
|
|
@@ -29,12 +50,12 @@ Requires-Dist: arcade-tdk>=2.0.0
|
|
|
29
50
|
Requires-Dist: authlib<2.0.0,>=1.6.0
|
|
30
51
|
Requires-Dist: httpx<1.0.0,>=0.27.0
|
|
31
52
|
Requires-Dist: openai<2.0.0,>=1.0.0
|
|
32
|
-
Requires-Dist: prompt-toolkit
|
|
53
|
+
Requires-Dist: prompt-toolkit<4.0.0,>=3.0.52
|
|
33
54
|
Requires-Dist: pydantic[email]<3.0.0,>=2.0.0
|
|
34
55
|
Requires-Dist: pyperclip<2.0.0,>=1.8.0
|
|
35
56
|
Requires-Dist: pyyaml<7.0.0,>=6.0
|
|
36
57
|
Requires-Dist: rich<14.0.0,>=13.0.0
|
|
37
|
-
Requires-Dist: tiktoken
|
|
58
|
+
Requires-Dist: tiktoken<1.0.0,>=0.11.0
|
|
38
59
|
Requires-Dist: toml<1.0.0,>=0.10.0
|
|
39
60
|
Requires-Dist: typer>0.10.0
|
|
40
61
|
Requires-Dist: ulid==1.1
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "cade-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.5.0"
|
|
4
4
|
description = "Cade - The CLI Agent from Arcade.dev"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
7
|
-
license = {
|
|
7
|
+
license = {file = "LICENSE"}
|
|
8
8
|
authors = [
|
|
9
9
|
{ name = "Arcade AI Inc.", email = "dev@arcade.dev" },
|
|
10
10
|
]
|
|
@@ -36,8 +36,8 @@ dependencies = [
|
|
|
36
36
|
"arcade-core>=4.1.0,<5.0.0",
|
|
37
37
|
"authlib>=1.6.0,<2.0.0",
|
|
38
38
|
"pyperclip>=1.8.0,<2.0.0",
|
|
39
|
-
"prompt-toolkit>=3.0.52",
|
|
40
|
-
"tiktoken>=0.11.0",
|
|
39
|
+
"prompt-toolkit>=3.0.52,<4.0.0",
|
|
40
|
+
"tiktoken>=0.11.0,<1.0.0",
|
|
41
41
|
"httpx>=0.27.0,<1.0.0",
|
|
42
42
|
]
|
|
43
43
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.5.0"
|
|
@@ -10,7 +10,6 @@ import threading
|
|
|
10
10
|
import uuid
|
|
11
11
|
import webbrowser
|
|
12
12
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
13
|
-
from pathlib import Path
|
|
14
13
|
from typing import Any
|
|
15
14
|
from urllib.parse import parse_qs
|
|
16
15
|
|
|
@@ -452,32 +451,3 @@ def get_access_token(coordinator_url: str | None = None) -> str:
|
|
|
452
451
|
ValueError: If not logged in or token refresh fails
|
|
453
452
|
"""
|
|
454
453
|
return get_valid_access_token(coordinator_url)
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
# For backward compatibility with legacy API key format
|
|
458
|
-
def _check_legacy_credentials() -> tuple[str, str] | None:
|
|
459
|
-
"""Check for legacy API key credentials.
|
|
460
|
-
|
|
461
|
-
Returns:
|
|
462
|
-
Tuple of (api_key, email) if found, None otherwise.
|
|
463
|
-
"""
|
|
464
|
-
import yaml
|
|
465
|
-
|
|
466
|
-
creds_path = Path.home() / ".arcade" / "credentials.yaml"
|
|
467
|
-
if not creds_path.exists():
|
|
468
|
-
return None
|
|
469
|
-
|
|
470
|
-
try:
|
|
471
|
-
with creds_path.open() as f:
|
|
472
|
-
data = yaml.safe_load(f) or {}
|
|
473
|
-
|
|
474
|
-
cloud = data.get("cloud", {})
|
|
475
|
-
if isinstance(cloud, dict) and "api" in cloud:
|
|
476
|
-
api_key = cloud.get("api", {}).get("key")
|
|
477
|
-
email = cloud.get("user", {}).get("email")
|
|
478
|
-
if api_key and email:
|
|
479
|
-
return api_key, email
|
|
480
|
-
except Exception:
|
|
481
|
-
pass
|
|
482
|
-
|
|
483
|
-
return None
|
|
@@ -14,7 +14,17 @@ from rich.table import Table
|
|
|
14
14
|
from cadecoder.core.logging import log
|
|
15
15
|
|
|
16
16
|
console = Console(stderr=True)
|
|
17
|
-
context_app = typer.Typer(
|
|
17
|
+
context_app = typer.Typer(
|
|
18
|
+
help="Manage organization and project context", invoke_without_command=True
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@context_app.callback()
|
|
23
|
+
def context_callback(ctx: typer.Context) -> None:
|
|
24
|
+
"""Manage organization and project context"""
|
|
25
|
+
if ctx.invoked_subcommand is None:
|
|
26
|
+
console.print(ctx.get_help())
|
|
27
|
+
raise typer.Exit(0)
|
|
18
28
|
|
|
19
29
|
|
|
20
30
|
@context_app.command(name="show")
|
|
@@ -17,17 +17,26 @@ from cadecoder.tools.manager import (
|
|
|
17
17
|
MCPServerStore,
|
|
18
18
|
MCPToolManager,
|
|
19
19
|
)
|
|
20
|
+
from cadecoder.tools.manager.mcp import MCP_PROTOCOL_VERSION
|
|
20
21
|
|
|
21
22
|
# Create MCP command group
|
|
22
23
|
mcp_app = typer.Typer(
|
|
23
24
|
name="mcp",
|
|
24
25
|
help="Manage MCP (Model Context Protocol) servers",
|
|
25
|
-
|
|
26
|
+
invoke_without_command=True,
|
|
26
27
|
)
|
|
27
28
|
|
|
28
29
|
console = Console()
|
|
29
30
|
|
|
30
31
|
|
|
32
|
+
@mcp_app.callback()
|
|
33
|
+
def mcp_callback(ctx: typer.Context) -> None:
|
|
34
|
+
"""Manage MCP (Model Context Protocol) servers"""
|
|
35
|
+
if ctx.invoked_subcommand is None:
|
|
36
|
+
console.print(ctx.get_help())
|
|
37
|
+
raise typer.Exit(0)
|
|
38
|
+
|
|
39
|
+
|
|
31
40
|
@mcp_app.command("list")
|
|
32
41
|
def list_servers() -> None:
|
|
33
42
|
"""List all configured MCP servers."""
|
|
@@ -379,7 +388,7 @@ def authorize_server(
|
|
|
379
388
|
await manager._send_request(
|
|
380
389
|
"initialize",
|
|
381
390
|
{
|
|
382
|
-
"protocolVersion":
|
|
391
|
+
"protocolVersion": MCP_PROTOCOL_VERSION,
|
|
383
392
|
"capabilities": {},
|
|
384
393
|
"clientInfo": {"name": "cade", "version": "1.0.0"},
|
|
385
394
|
},
|
|
@@ -11,12 +11,20 @@ from cadecoder.storage.threads import get_thread_history
|
|
|
11
11
|
thread_app = typer.Typer(
|
|
12
12
|
name="thread",
|
|
13
13
|
help="Manage chat threads",
|
|
14
|
-
|
|
14
|
+
invoke_without_command=True,
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
console = Console()
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
@thread_app.callback()
|
|
21
|
+
def thread_callback(ctx: typer.Context) -> None:
|
|
22
|
+
"""Manage chat threads"""
|
|
23
|
+
if ctx.invoked_subcommand is None:
|
|
24
|
+
console.print(ctx.get_help())
|
|
25
|
+
raise typer.Exit(0)
|
|
26
|
+
|
|
27
|
+
|
|
20
28
|
@thread_app.command("list")
|
|
21
29
|
def list_threads(
|
|
22
30
|
limit: Annotated[
|
|
@@ -21,6 +21,9 @@ from cadecoder.tools.manager.config import (
|
|
|
21
21
|
MCPTransportType,
|
|
22
22
|
)
|
|
23
23
|
|
|
24
|
+
# MCP protocol version - client's preferred version for negotiation
|
|
25
|
+
MCP_PROTOCOL_VERSION = "2025-11-25"
|
|
26
|
+
|
|
24
27
|
|
|
25
28
|
class StdioMCPConnection:
|
|
26
29
|
"""Manages stdio subprocess for MCP server."""
|
|
@@ -110,7 +113,10 @@ class MCPOAuthHandler:
|
|
|
110
113
|
async def _ensure_client(self) -> httpx.AsyncClient:
|
|
111
114
|
"""Ensure HTTP client exists."""
|
|
112
115
|
if self._client is None:
|
|
113
|
-
self._client = httpx.AsyncClient(
|
|
116
|
+
self._client = httpx.AsyncClient(
|
|
117
|
+
timeout=httpx.Timeout(30.0),
|
|
118
|
+
follow_redirects=True,
|
|
119
|
+
)
|
|
114
120
|
return self._client
|
|
115
121
|
|
|
116
122
|
def parse_www_authenticate(self, header: str) -> dict[str, str]:
|
|
@@ -428,6 +434,7 @@ class MCPToolManager(ToolManager):
|
|
|
428
434
|
self._client: httpx.AsyncClient | None = None
|
|
429
435
|
|
|
430
436
|
self._session_id: str | None = None
|
|
437
|
+
self._negotiated_protocol_version: str | None = None
|
|
431
438
|
self._oauth_handler = MCPOAuthHandler(server_config)
|
|
432
439
|
self._auth_server_metadata: dict[str, Any] | None = None
|
|
433
440
|
|
|
@@ -441,6 +448,9 @@ class MCPToolManager(ToolManager):
|
|
|
441
448
|
if self._session_id:
|
|
442
449
|
headers["Mcp-Session-Id"] = self._session_id
|
|
443
450
|
|
|
451
|
+
if self._negotiated_protocol_version:
|
|
452
|
+
headers["MCP-Protocol-Version"] = self._negotiated_protocol_version
|
|
453
|
+
|
|
444
454
|
if self.config.auth_type == MCPAuthType.BEARER and self.config.auth_value:
|
|
445
455
|
headers["Authorization"] = f"Bearer {self.config.auth_value}"
|
|
446
456
|
elif self.config.auth_type == MCPAuthType.API_KEY and self.config.auth_value:
|
|
@@ -456,6 +466,7 @@ class MCPToolManager(ToolManager):
|
|
|
456
466
|
if self._client is None:
|
|
457
467
|
self._client = httpx.AsyncClient(
|
|
458
468
|
timeout=httpx.Timeout(60.0, connect=10.0),
|
|
469
|
+
follow_redirects=True,
|
|
459
470
|
)
|
|
460
471
|
return self._client
|
|
461
472
|
|
|
@@ -609,7 +620,9 @@ class MCPToolManager(ToolManager):
|
|
|
609
620
|
log.error(f"MCP stdio request failed for {self.config.name}: {e}")
|
|
610
621
|
raise
|
|
611
622
|
|
|
612
|
-
async def _send_http_request(
|
|
623
|
+
async def _send_http_request(
|
|
624
|
+
self, method: str, params: dict[str, Any] | None = None, _retry: bool = False
|
|
625
|
+
) -> Any:
|
|
613
626
|
"""Send a JSON-RPC request via HTTP transport."""
|
|
614
627
|
await self._maybe_refresh_oauth_token()
|
|
615
628
|
|
|
@@ -634,6 +647,19 @@ class MCPToolManager(ToolManager):
|
|
|
634
647
|
f"Captured MCP session ID for '{self.config.name}': {self._session_id[:8]}..."
|
|
635
648
|
)
|
|
636
649
|
|
|
650
|
+
# Per MCP spec: 404 with active session means session expired, reinitialize
|
|
651
|
+
if response.status_code == 404 and self._session_id and not _retry:
|
|
652
|
+
log.warning(f"MCP server '{self.config.name}' session expired, reinitializing")
|
|
653
|
+
self._session_id = None
|
|
654
|
+
self._negotiated_protocol_version = None
|
|
655
|
+
self._initialized = False
|
|
656
|
+
self._tools_cache = None
|
|
657
|
+
if await self.initialize():
|
|
658
|
+
return await self._send_http_request(method, params, _retry=True)
|
|
659
|
+
raise Exception(
|
|
660
|
+
f"MCP server '{self.config.name}' session expired and reinitialization failed"
|
|
661
|
+
)
|
|
662
|
+
|
|
637
663
|
if response.status_code == 401:
|
|
638
664
|
auth_url = await self._handle_401_response(response)
|
|
639
665
|
raise ToolAuthorizationRequired(
|
|
@@ -696,16 +722,22 @@ class MCPToolManager(ToolManager):
|
|
|
696
722
|
result = await self._send_request(
|
|
697
723
|
"initialize",
|
|
698
724
|
{
|
|
699
|
-
"protocolVersion":
|
|
725
|
+
"protocolVersion": MCP_PROTOCOL_VERSION,
|
|
700
726
|
"capabilities": {"tools": {}},
|
|
701
727
|
"clientInfo": {"name": "cade", "version": "1.0.0"},
|
|
702
728
|
},
|
|
703
729
|
)
|
|
704
730
|
|
|
705
731
|
if result:
|
|
732
|
+
self._negotiated_protocol_version = result.get(
|
|
733
|
+
"protocolVersion", MCP_PROTOCOL_VERSION
|
|
734
|
+
)
|
|
706
735
|
self._initialized = True
|
|
707
736
|
await self._send_notification("notifications/initialized")
|
|
708
|
-
log.info(
|
|
737
|
+
log.info(
|
|
738
|
+
f"MCP server '{self.config.name}' initialized "
|
|
739
|
+
f"(protocol: {self._negotiated_protocol_version})"
|
|
740
|
+
)
|
|
709
741
|
return True
|
|
710
742
|
|
|
711
743
|
return False
|
|
@@ -789,7 +821,6 @@ class MCPToolManager(ToolManager):
|
|
|
789
821
|
|
|
790
822
|
def _parse_arcade_error(self, error_text: str) -> str:
|
|
791
823
|
"""Parse arcade-mcp-server error object string to extract clean error message."""
|
|
792
|
-
import re
|
|
793
824
|
|
|
794
825
|
# Try to extract message field: message="..."
|
|
795
826
|
message_match = re.search(r'message="([^"]*)"', error_text)
|
|
@@ -861,6 +892,7 @@ class MCPToolManager(ToolManager):
|
|
|
861
892
|
try:
|
|
862
893
|
self._initialized = False
|
|
863
894
|
self._session_id = None
|
|
895
|
+
self._negotiated_protocol_version = None
|
|
864
896
|
|
|
865
897
|
success = await self.initialize()
|
|
866
898
|
if success:
|
|
@@ -923,5 +955,6 @@ class MCPToolManager(ToolManager):
|
|
|
923
955
|
await self._client.aclose()
|
|
924
956
|
self._client = None
|
|
925
957
|
self._session_id = None
|
|
958
|
+
self._negotiated_protocol_version = None
|
|
926
959
|
self._initialized = False
|
|
927
960
|
await self._oauth_handler.close()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.4.0"
|
|
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
|
|
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
|
|
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
|
|
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
|