nlalpha-capability 0.2.0__tar.gz → 0.3.1__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.
- {nlalpha_capability-0.2.0 → nlalpha_capability-0.3.1}/PKG-INFO +2 -2
- {nlalpha_capability-0.2.0 → nlalpha_capability-0.3.1}/pyproject.toml +2 -2
- {nlalpha_capability-0.2.0 → nlalpha_capability-0.3.1}/src/nlalpha_capability/server.py +46 -13
- {nlalpha_capability-0.2.0 → nlalpha_capability-0.3.1}/.gitignore +0 -0
- {nlalpha_capability-0.2.0 → nlalpha_capability-0.3.1}/Dockerfile +0 -0
- {nlalpha_capability-0.2.0 → nlalpha_capability-0.3.1}/LICENSE +0 -0
- {nlalpha_capability-0.2.0 → nlalpha_capability-0.3.1}/README.md +0 -0
- {nlalpha_capability-0.2.0 → nlalpha_capability-0.3.1}/README.zh.md +0 -0
- {nlalpha_capability-0.2.0 → nlalpha_capability-0.3.1}/src/nlalpha_capability/__init__.py +0 -0
- {nlalpha_capability-0.2.0 → nlalpha_capability-0.3.1}/tests/test_family_helper_discovery.py +0 -0
- {nlalpha_capability-0.2.0 → nlalpha_capability-0.3.1}/tests/test_provider_discovery.py +0 -0
- {nlalpha_capability-0.2.0 → nlalpha_capability-0.3.1}/tests/test_self_description.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: nlalpha-capability
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: NLAlpha capability discovery MCP server.
|
|
5
5
|
Project-URL: Homepage, https://github.com/ruimarj/nlalpha-capability
|
|
6
6
|
Project-URL: Repository, https://github.com/ruimarj/nlalpha-capability
|
|
@@ -9,7 +9,7 @@ License-Expression: AGPL-3.0-or-later
|
|
|
9
9
|
License-File: LICENSE
|
|
10
10
|
Requires-Python: <3.13,>=3.12
|
|
11
11
|
Requires-Dist: mcp<2.0,>=1.6.0
|
|
12
|
-
Requires-Dist: nlalpha-core[json-log,telemetry]>=0.7.
|
|
12
|
+
Requires-Dist: nlalpha-core[json-log,telemetry]>=0.7.1
|
|
13
13
|
Requires-Dist: starlette>=0.37
|
|
14
14
|
Requires-Dist: uvicorn>=0.30
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
@@ -4,14 +4,14 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "nlalpha-capability"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.1"
|
|
8
8
|
description = "NLAlpha capability discovery MCP server."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "AGPL-3.0-or-later"
|
|
11
11
|
license-files = ["LICENSE"]
|
|
12
12
|
requires-python = ">=3.12,<3.13"
|
|
13
13
|
dependencies = [
|
|
14
|
-
"nlalpha-core[telemetry,json-log]>=0.7.
|
|
14
|
+
"nlalpha-core[telemetry,json-log]>=0.7.1",
|
|
15
15
|
"mcp>=1.6.0,<2.0",
|
|
16
16
|
"uvicorn>=0.30",
|
|
17
17
|
"starlette>=0.37",
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import asyncio
|
|
5
6
|
from contextlib import asynccontextmanager
|
|
6
7
|
from dataclasses import asdict
|
|
7
8
|
from importlib.metadata import version
|
|
@@ -26,24 +27,46 @@ from nlalpha.core.telemetry import configure_telemetry, shutdown, get_meter, set
|
|
|
26
27
|
|
|
27
28
|
logger = logging.getLogger("nlalpha-capability")
|
|
28
29
|
|
|
30
|
+
|
|
31
|
+
@asynccontextmanager
|
|
32
|
+
async def _session_manager_lifespan(mcp):
|
|
33
|
+
stop = asyncio.Event()
|
|
34
|
+
started = asyncio.Event()
|
|
35
|
+
|
|
36
|
+
async def run():
|
|
37
|
+
async with mcp.session_manager.run():
|
|
38
|
+
started.set()
|
|
39
|
+
await stop.wait()
|
|
40
|
+
|
|
41
|
+
task = asyncio.create_task(run())
|
|
42
|
+
task.add_done_callback(lambda _: started.set())
|
|
43
|
+
await started.wait()
|
|
44
|
+
if task.done():
|
|
45
|
+
task.result()
|
|
46
|
+
try:
|
|
47
|
+
yield
|
|
48
|
+
finally:
|
|
49
|
+
stop.set()
|
|
50
|
+
await task
|
|
51
|
+
|
|
29
52
|
_meter = get_meter()
|
|
30
53
|
_domains_counter = _meter.create_counter("nlalpha.capability.domains.listed")
|
|
31
54
|
_helpers_histogram = _meter.create_histogram("nlalpha.capability.helpers.count")
|
|
32
55
|
|
|
33
56
|
|
|
34
57
|
def about(sections: list[str] | None = None) -> dict[str, Any]:
|
|
35
|
-
"""
|
|
58
|
+
"""Start here: describe installed providers, helper domains, families, and diagnostics; task workflows use the strategy service's list_skills and load_skill."""
|
|
36
59
|
with start_span("mcp.about"):
|
|
37
60
|
try:
|
|
38
61
|
return describe_document("service", "nlalpha-capability", "nlalpha-capability", version("nlalpha-capability"), {
|
|
39
62
|
"principles": common_description(),
|
|
40
63
|
"navigation": {
|
|
41
|
-
"about": "
|
|
64
|
+
"about": "Start here: read shared principles, installed capability providers, and helper domains.",
|
|
42
65
|
"list_capability_providers": "Discover selectable capability providers and their installed identities.",
|
|
43
66
|
"list_capability_domains": "Discover domains from actual available helper declarations.",
|
|
44
67
|
"list_capabilities_by_domain": "Read available helpers in a selected helper domain.",
|
|
45
68
|
"list_family_helpers": "Read helpers from the same cached family contract used by strategy validation.",
|
|
46
|
-
"confess": "Read a provider's manifest, methods, helpers, and
|
|
69
|
+
"confess": "Read a provider's manifest, methods, helpers, and guidance before using its capabilities.",
|
|
47
70
|
"diagnose_providers": "Inspect installed providers or families that failed discovery or are unavailable.",
|
|
48
71
|
},
|
|
49
72
|
"providers": CapabilityPluginRegistry.list_provider_records(),
|
|
@@ -56,7 +79,7 @@ def about(sections: list[str] | None = None) -> dict[str, Any]:
|
|
|
56
79
|
|
|
57
80
|
|
|
58
81
|
def confess(provider_id: str, sections: list[str] | None = None) -> dict[str, Any]:
|
|
59
|
-
"""
|
|
82
|
+
"""Read a cached provider's manifest, helpers, and guidance before using its capabilities."""
|
|
60
83
|
with start_span("mcp.confess", attributes={"provider_id": provider_id}):
|
|
61
84
|
try:
|
|
62
85
|
record = CapabilityPluginRegistry.get_record(provider_id)
|
|
@@ -182,24 +205,34 @@ async def _health(request):
|
|
|
182
205
|
def create_app(*, allowed_hosts: list[str] | tuple[str, ...] | None = None,
|
|
183
206
|
on_shutdown: Callable[[], None] | None = None) -> Starlette:
|
|
184
207
|
"""Create an independent MCP transport with an explicit host allowlist."""
|
|
185
|
-
mcp = FastMCP(
|
|
208
|
+
mcp = FastMCP(
|
|
209
|
+
"nlalpha-capability",
|
|
210
|
+
instructions=(
|
|
211
|
+
"NLAlpha capability MCP service. Start with `about` for navigation and `confess(provider_id)` "
|
|
212
|
+
"for provider semantics before using helpers. Task workflows are packaged as NLAlpha skills "
|
|
213
|
+
"in the strategy service: call `list_skills` then `load_skill` there when a workflow is "
|
|
214
|
+
"needed, one language per call."
|
|
215
|
+
),
|
|
216
|
+
)
|
|
186
217
|
mcp.settings.transport_security = TransportSecuritySettings(
|
|
187
218
|
enable_dns_rebinding_protection=True, allowed_hosts=resolve_allowed_hosts(allowed_hosts),
|
|
188
219
|
)
|
|
189
220
|
for tool in (list_capability_domains, list_capabilities_by_domain, list_family_helpers,
|
|
190
221
|
list_capability_providers, diagnose_providers, about, confess):
|
|
191
222
|
mcp.add_tool(tool)
|
|
223
|
+
http_app = mcp.streamable_http_app()
|
|
224
|
+
|
|
192
225
|
@asynccontextmanager
|
|
193
226
|
async def lifespan(app):
|
|
194
227
|
"""Invoke only the explicitly injected process cleanup on application shutdown."""
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
on_shutdown
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
app = Starlette(routes=[Route("/health", _health), *
|
|
228
|
+
async with _session_manager_lifespan(mcp):
|
|
229
|
+
try:
|
|
230
|
+
yield
|
|
231
|
+
finally:
|
|
232
|
+
if on_shutdown is not None:
|
|
233
|
+
on_shutdown()
|
|
234
|
+
|
|
235
|
+
app = Starlette(routes=[Route("/health", _health), *http_app.routes], lifespan=lifespan)
|
|
203
236
|
app.state.mcp = mcp
|
|
204
237
|
return app
|
|
205
238
|
|
|
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
|