libentry 1.24.6__py3-none-any.whl → 1.24.8__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.
- libentry/mcp/api.py +44 -3
- libentry/mcp/client.py +19 -14
- {libentry-1.24.6.dist-info → libentry-1.24.8.dist-info}/METADATA +1 -1
- {libentry-1.24.6.dist-info → libentry-1.24.8.dist-info}/RECORD +9 -9
- {libentry-1.24.6.dist-info → libentry-1.24.8.dist-info}/LICENSE +0 -0
- {libentry-1.24.6.dist-info → libentry-1.24.8.dist-info}/WHEEL +0 -0
- {libentry-1.24.6.dist-info → libentry-1.24.8.dist-info}/entry_points.txt +0 -0
- {libentry-1.24.6.dist-info → libentry-1.24.8.dist-info}/top_level.txt +0 -0
- {libentry-1.24.6.dist-info → libentry-1.24.8.dist-info}/zip-safe +0 -0
libentry/mcp/api.py
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
__author__ = "xi"
|
4
4
|
__all__ = [
|
5
|
+
"HasRequestPath",
|
5
6
|
"APIInfo",
|
6
7
|
"api",
|
7
8
|
"route",
|
@@ -12,8 +13,9 @@ __all__ = [
|
|
12
13
|
"list_api_info",
|
13
14
|
]
|
14
15
|
|
16
|
+
import re
|
15
17
|
from functools import partial
|
16
|
-
from typing import Callable, List, Literal, Optional, Tuple
|
18
|
+
from typing import Any, Callable, List, Literal, Optional, Tuple, Type, Union
|
17
19
|
|
18
20
|
from pydantic import BaseModel, ConfigDict
|
19
21
|
|
@@ -26,6 +28,34 @@ TAG_TOOL = "tool"
|
|
26
28
|
TAG_RESOURCE = "resource"
|
27
29
|
|
28
30
|
|
31
|
+
class HasRequestPath:
|
32
|
+
"""The object has a request path.
|
33
|
+
A request path is a snake named string starts with "/".
|
34
|
+
"""
|
35
|
+
|
36
|
+
__request_name__ = None
|
37
|
+
|
38
|
+
@classmethod
|
39
|
+
def get_request_path(cls) -> str:
|
40
|
+
name = cls.__request_name__
|
41
|
+
if name:
|
42
|
+
if name.startswith("/"):
|
43
|
+
return name
|
44
|
+
else:
|
45
|
+
return "/" + name
|
46
|
+
else:
|
47
|
+
name = cls.__name__
|
48
|
+
if name.endswith("Request"):
|
49
|
+
name = name[:-7]
|
50
|
+
return "/" + cls._camel_to_snake(name)
|
51
|
+
|
52
|
+
@staticmethod
|
53
|
+
def _camel_to_snake(name: str) -> str:
|
54
|
+
s1 = re.sub(r"(.)([A-Z][a-z]+)", r"\1_\2", name)
|
55
|
+
s2 = re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", s1)
|
56
|
+
return s2.lower()
|
57
|
+
|
58
|
+
|
29
59
|
class APIInfo(BaseModel):
|
30
60
|
path: str
|
31
61
|
methods: List[Literal["GET", "POST"]]
|
@@ -37,7 +67,7 @@ class APIInfo(BaseModel):
|
|
37
67
|
|
38
68
|
|
39
69
|
def api(
|
40
|
-
path: Optional[str] = None,
|
70
|
+
path: Optional[Union[str, Type[HasRequestPath], HasRequestPath, Any]] = None,
|
41
71
|
methods: List[Literal["GET", "POST"]] = ("GET", "POST"),
|
42
72
|
name: Optional[str] = None,
|
43
73
|
description: Optional[str] = None,
|
@@ -50,8 +80,19 @@ def api(
|
|
50
80
|
fn_name = getattr(fn, "__name__")
|
51
81
|
fn_doc = getattr(fn, "__doc__")
|
52
82
|
|
83
|
+
if path:
|
84
|
+
if hasattr(path, "get_request_path"):
|
85
|
+
_path = path.get_request_path()
|
86
|
+
else:
|
87
|
+
_path = path
|
88
|
+
else:
|
89
|
+
_path = f"/{fn_name}"
|
90
|
+
|
91
|
+
if not isinstance(_path, str):
|
92
|
+
raise TypeError(f"\"path\" should be instance of str or HasRequestPath.")
|
93
|
+
|
53
94
|
api_info = APIInfo(
|
54
|
-
path=
|
95
|
+
path=_path,
|
55
96
|
methods=methods,
|
56
97
|
name=name or fn_name,
|
57
98
|
description=description or fn_doc,
|
libentry/mcp/client.py
CHANGED
@@ -8,19 +8,18 @@ from queue import Queue
|
|
8
8
|
from threading import Semaphore, Thread
|
9
9
|
from time import sleep
|
10
10
|
from types import GeneratorType
|
11
|
-
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
|
11
|
+
from typing import Any, Dict, Iterable, List, Optional, Tuple, Type, Union
|
12
12
|
from urllib.parse import urlencode, urljoin
|
13
13
|
|
14
14
|
import httpx
|
15
15
|
from pydantic import BaseModel, TypeAdapter
|
16
16
|
|
17
17
|
from libentry import json
|
18
|
+
from libentry.mcp.api import HasRequestPath
|
18
19
|
from libentry.mcp.types import CallToolRequestParams, CallToolResult, ClientCapabilities, HTTPOptions, HTTPRequest, \
|
19
20
|
HTTPResponse, Implementation, InitializeRequestParams, InitializeResult, JSONObject, JSONRPCError, \
|
20
|
-
JSONRPCNotification, \
|
21
|
-
|
22
|
-
JSONRPCResponse, JSONType, ListResourcesResult, ListToolsResult, MIME, ReadResourceRequestParams, \
|
23
|
-
ReadResourceResult, SSE, SubroutineError, SubroutineResponse
|
21
|
+
JSONRPCNotification, JSONRPCRequest, JSONRPCResponse, JSONType, ListResourcesResult, ListToolsResult, MIME, \
|
22
|
+
ReadResourceRequestParams, ReadResourceResult, SSE, SubroutineError, SubroutineResponse
|
24
23
|
|
25
24
|
|
26
25
|
class ServiceError(RuntimeError):
|
@@ -122,16 +121,16 @@ class SubroutineMixIn(abc.ABC):
|
|
122
121
|
@abc.abstractmethod
|
123
122
|
def subroutine_request(
|
124
123
|
self,
|
125
|
-
path: str,
|
126
|
-
params:
|
124
|
+
path: Union[str, Type[HasRequestPath], HasRequestPath, Any],
|
125
|
+
params: Optional[Union[JSONObject, BaseModel]] = None,
|
127
126
|
options: Optional[HTTPOptions] = None
|
128
127
|
) -> Union[SubroutineResponse, Iterable[SubroutineResponse]]:
|
129
128
|
raise NotImplementedError()
|
130
129
|
|
131
130
|
def request(
|
132
131
|
self,
|
133
|
-
path: str,
|
134
|
-
params: Optional[JSONObject] = None,
|
132
|
+
path: Union[str, Type[HasRequestPath], HasRequestPath, Any],
|
133
|
+
params: Optional[Union[JSONObject, BaseModel]] = None,
|
135
134
|
options: Optional[HTTPOptions] = None
|
136
135
|
) -> Union[JSONType, Iterable[JSONType]]:
|
137
136
|
response = self.subroutine_request(path, params, options)
|
@@ -153,7 +152,7 @@ class SubroutineMixIn(abc.ABC):
|
|
153
152
|
|
154
153
|
def get(
|
155
154
|
self,
|
156
|
-
path: str,
|
155
|
+
path: Union[str, Type[HasRequestPath], HasRequestPath, Any],
|
157
156
|
options: Optional[HTTPOptions] = None
|
158
157
|
) -> Union[JSONType, Iterable[JSONType]]:
|
159
158
|
if options is None:
|
@@ -164,8 +163,8 @@ class SubroutineMixIn(abc.ABC):
|
|
164
163
|
|
165
164
|
def post(
|
166
165
|
self,
|
167
|
-
path: str,
|
168
|
-
params: Optional[JSONObject] = None,
|
166
|
+
path: Union[str, Type[HasRequestPath], HasRequestPath, Any],
|
167
|
+
params: Optional[Union[JSONObject, BaseModel]] = None,
|
169
168
|
options: Optional[HTTPOptions] = None
|
170
169
|
) -> Union[JSONType, Iterable[JSONType]]:
|
171
170
|
if options is None:
|
@@ -462,13 +461,19 @@ class APIClient(SubroutineMixIn, MCPMixIn):
|
|
462
461
|
|
463
462
|
def subroutine_request(
|
464
463
|
self,
|
465
|
-
path: str,
|
466
|
-
params:
|
464
|
+
path: Union[str, Type[HasRequestPath], HasRequestPath, Any],
|
465
|
+
params: Optional[Union[JSONObject, BaseModel]] = None,
|
467
466
|
options: Optional[HTTPOptions] = None
|
468
467
|
) -> Union[SubroutineResponse, Iterable[SubroutineResponse]]:
|
468
|
+
if isinstance(path, BaseModel):
|
469
|
+
if params is None:
|
470
|
+
params = path
|
469
471
|
if isinstance(params, BaseModel):
|
470
472
|
params = params.model_dump(exclude_none=True)
|
471
473
|
|
474
|
+
if hasattr(path, "get_request_path"):
|
475
|
+
path = path.get_request_path()
|
476
|
+
|
472
477
|
json_request = HTTPRequest(
|
473
478
|
path=path,
|
474
479
|
json_obj=params,
|
@@ -11,8 +11,8 @@ libentry/schema.py,sha256=40SOhCF_eytWOF47MWKCRHKHl_lCaQVetx1Af62PkiI,10439
|
|
11
11
|
libentry/test_api.py,sha256=Xw7B7sH6g1iCTV5sFzyBF3JAJzeOr9xg0AyezTNsnIk,4452
|
12
12
|
libentry/utils.py,sha256=O7P6GadtUIjq0N2IZH7PhHZDUM3NebzcqyDqytet7CM,683
|
13
13
|
libentry/mcp/__init__.py,sha256=1oLL20yLB1GL9IbFiZD8OReDqiCpFr-yetIR6x1cNkI,23
|
14
|
-
libentry/mcp/api.py,sha256=
|
15
|
-
libentry/mcp/client.py,sha256=
|
14
|
+
libentry/mcp/api.py,sha256=GDErVCz_hh_ZeMxLS8bTPyBUhCTHw3Mm-nGFMV2W2yo,3669
|
15
|
+
libentry/mcp/client.py,sha256=3HmKAsFenPlDk1lfSdXL9GJwfCSU92uQS04zvZGeJfQ,23065
|
16
16
|
libentry/mcp/service.py,sha256=qA6I9Mi-eudRYwVGhff1_aAImK424bhASlsWaHP8XNI,34971
|
17
17
|
libentry/mcp/types.py,sha256=aAoVO4jjqEvDzNneuZapmRYonLLnGsbcLoypVyRNNYg,12389
|
18
18
|
libentry/service/__init__.py,sha256=1oLL20yLB1GL9IbFiZD8OReDqiCpFr-yetIR6x1cNkI,23
|
@@ -22,10 +22,10 @@ libentry/service/list.py,sha256=ElHWhTgShGOhaxMUEwVbMXos0NQKjHsODboiQ-3AMwE,1397
|
|
22
22
|
libentry/service/running.py,sha256=FrPJoJX6wYxcHIysoatAxhW3LajCCm0Gx6l7__6sULQ,5105
|
23
23
|
libentry/service/start.py,sha256=mZT7b9rVULvzy9GTZwxWnciCHgv9dbGN2JbxM60OMn4,1270
|
24
24
|
libentry/service/stop.py,sha256=wOpwZgrEJ7QirntfvibGq-XsTC6b3ELhzRW2zezh-0s,1187
|
25
|
-
libentry-1.24.
|
26
|
-
libentry-1.24.
|
27
|
-
libentry-1.24.
|
28
|
-
libentry-1.24.
|
29
|
-
libentry-1.24.
|
30
|
-
libentry-1.24.
|
31
|
-
libentry-1.24.
|
25
|
+
libentry-1.24.8.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
26
|
+
libentry-1.24.8.dist-info/METADATA,sha256=xTdFiobksHW7BiQG0DgyOd3d46as22zSv3q2uxz5jKM,1135
|
27
|
+
libentry-1.24.8.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
28
|
+
libentry-1.24.8.dist-info/entry_points.txt,sha256=1v_nLVDsjvVJp9SWhl4ef2zZrsLTBtFWgrYFgqvQBgc,61
|
29
|
+
libentry-1.24.8.dist-info/top_level.txt,sha256=u2uF6-X5fn2Erf9PYXOg_6tntPqTpyT-yzUZrltEd6I,9
|
30
|
+
libentry-1.24.8.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
31
|
+
libentry-1.24.8.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|