journal-gateway-client 0.7.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.
- journal_gateway_client-0.7.0/.gitignore +5 -0
- journal_gateway_client-0.7.0/PKG-INFO +130 -0
- journal_gateway_client-0.7.0/README.md +105 -0
- journal_gateway_client-0.7.0/journal_gateway_client/__init__.py +26 -0
- journal_gateway_client-0.7.0/journal_gateway_client/server.py +575 -0
- journal_gateway_client-0.7.0/journal_gateway_client/types.py +65 -0
- journal_gateway_client-0.7.0/pyproject.toml +35 -0
- journal_gateway_client-0.7.0/tests/__init__.py +0 -0
- journal_gateway_client-0.7.0/tests/test_server.py +530 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: journal-gateway-client
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: Python client library for the Journal Gateway protocol
|
|
5
|
+
Project-URL: Homepage, https://journal.one
|
|
6
|
+
Project-URL: Repository, https://github.com/EnduranceLabs/journal-edge
|
|
7
|
+
Project-URL: Documentation, https://github.com/EnduranceLabs/journal-edge#readme
|
|
8
|
+
Author-email: Journal <support@journal.one>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
Keywords: gateway,journal,mcp,model-context-protocol,websocket
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: websockets>=13.0
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# journal-gateway-client
|
|
27
|
+
|
|
28
|
+
Python client library for the Journal Gateway protocol. Runs a WebSocket server that gateways connect to, authenticates them, auto-pulls their tools and skills, and lets you call tools.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install journal-gateway-client
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
import asyncio
|
|
40
|
+
from journal_gateway_client import GatewayServer, TokenValidationResult
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
async def validate_token(token: str) -> TokenValidationResult | None:
|
|
44
|
+
# Return a TokenValidationResult on success, None on failure
|
|
45
|
+
if token == "gw_valid":
|
|
46
|
+
return TokenValidationResult(organization_id="org_123")
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
async def main() -> None:
|
|
51
|
+
server = GatewayServer(validate_token=validate_token, port=8080)
|
|
52
|
+
|
|
53
|
+
server.on_gateway_connected = lambda gw: print("connected:", gw.id, gw.integrations)
|
|
54
|
+
server.on_gateway_updated = lambda gw: print("tools/skills changed:", gw.id)
|
|
55
|
+
server.on_gateway_disconnected = lambda gw: print("disconnected:", gw.id)
|
|
56
|
+
|
|
57
|
+
await server.start()
|
|
58
|
+
|
|
59
|
+
# Call a tool on a connected gateway
|
|
60
|
+
result = await server.call_tool("postgresql", "query", {"sql": "SELECT 1"})
|
|
61
|
+
print(result.content)
|
|
62
|
+
|
|
63
|
+
await server.stop()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
asyncio.run(main())
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Key APIs
|
|
70
|
+
|
|
71
|
+
- **`start()` / `stop()`** — lifecycle
|
|
72
|
+
- **`call_tool(integration_id, tool_name, arguments, timeout=60.0)`** — execute a tool call on any gateway that provides the integration
|
|
73
|
+
- **`call_tool_for_org(organization_id, integration_id, tool_name, arguments, timeout=90.0)`** — same, scoped to an organization with automatic load balancing and retry on a different gateway
|
|
74
|
+
- **`get_tools_for_org(organization_id)`** — list deduplicated tools across all gateways for an org
|
|
75
|
+
- **`get_versions(gateway_id)` / `get_tools(gateway_id)` / `get_skills(gateway_id)`** — explicit pulls from a specific gateway
|
|
76
|
+
- **`connected_gateways`** — all currently connected gateways
|
|
77
|
+
|
|
78
|
+
## Callbacks
|
|
79
|
+
|
|
80
|
+
Set these attributes on the server instance:
|
|
81
|
+
|
|
82
|
+
- **`on_gateway_connected(gateway)`** — fired after a gateway authenticates and its initial tools/skills are pulled
|
|
83
|
+
- **`on_gateway_updated(gateway)`** — fired when a gateway's tools or skills change at runtime
|
|
84
|
+
- **`on_gateway_disconnected(gateway)`** — fired when a gateway disconnects
|
|
85
|
+
|
|
86
|
+
## Telemetry
|
|
87
|
+
|
|
88
|
+
The library has no telemetry dependency of its own. Two constructor arguments let you
|
|
89
|
+
wire it into your logging/tracing stack:
|
|
90
|
+
|
|
91
|
+
- **`get_trace_context`** — called on every `call_tool`. Return the active W3C trace
|
|
92
|
+
context as `{"traceparent": ..., "tracestate": ...}` and it is propagated on the
|
|
93
|
+
`tool_call` message; the gateway parents its `gateway.tool_call` span onto it, so the
|
|
94
|
+
remote tool execution appears in your distributed trace. Return `None` when there is
|
|
95
|
+
no active span.
|
|
96
|
+
- **`on_socket_error(error, gateway)`** — called when a gateway socket drops abnormally
|
|
97
|
+
(e.g. a connection reset). `gateway` is `None` if the socket errored before completing
|
|
98
|
+
the handshake. If the gateway had connected, `on_gateway_disconnected` fires as usual.
|
|
99
|
+
When not provided, unexpected connection errors fall back to the `journal_gateway_client`
|
|
100
|
+
logger — bind this callback if you want to route them into your own error tracking.
|
|
101
|
+
|
|
102
|
+
Example wiring with OpenTelemetry and a logger:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from opentelemetry import propagate
|
|
106
|
+
|
|
107
|
+
def trace_context():
|
|
108
|
+
carrier: dict[str, str] = {}
|
|
109
|
+
propagate.inject(carrier)
|
|
110
|
+
if "traceparent" not in carrier:
|
|
111
|
+
return None
|
|
112
|
+
return {"traceparent": carrier["traceparent"], "tracestate": carrier.get("tracestate")}
|
|
113
|
+
|
|
114
|
+
server = GatewayServer(
|
|
115
|
+
validate_token=validate_token,
|
|
116
|
+
port=8080,
|
|
117
|
+
get_trace_context=trace_context,
|
|
118
|
+
on_socket_error=lambda err, gw: logger.error(
|
|
119
|
+
"gateway socket error", exc_info=err, extra={"gateway_id": gw.id if gw else None}
|
|
120
|
+
),
|
|
121
|
+
)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Full documentation
|
|
125
|
+
|
|
126
|
+
See the [root README](https://github.com/EnduranceLabs/journal-edge#readme) for protocol details, gateway configuration, and architecture.
|
|
127
|
+
|
|
128
|
+
## License
|
|
129
|
+
|
|
130
|
+
MIT
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# journal-gateway-client
|
|
2
|
+
|
|
3
|
+
Python client library for the Journal Gateway protocol. Runs a WebSocket server that gateways connect to, authenticates them, auto-pulls their tools and skills, and lets you call tools.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install journal-gateway-client
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
import asyncio
|
|
15
|
+
from journal_gateway_client import GatewayServer, TokenValidationResult
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
async def validate_token(token: str) -> TokenValidationResult | None:
|
|
19
|
+
# Return a TokenValidationResult on success, None on failure
|
|
20
|
+
if token == "gw_valid":
|
|
21
|
+
return TokenValidationResult(organization_id="org_123")
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
async def main() -> None:
|
|
26
|
+
server = GatewayServer(validate_token=validate_token, port=8080)
|
|
27
|
+
|
|
28
|
+
server.on_gateway_connected = lambda gw: print("connected:", gw.id, gw.integrations)
|
|
29
|
+
server.on_gateway_updated = lambda gw: print("tools/skills changed:", gw.id)
|
|
30
|
+
server.on_gateway_disconnected = lambda gw: print("disconnected:", gw.id)
|
|
31
|
+
|
|
32
|
+
await server.start()
|
|
33
|
+
|
|
34
|
+
# Call a tool on a connected gateway
|
|
35
|
+
result = await server.call_tool("postgresql", "query", {"sql": "SELECT 1"})
|
|
36
|
+
print(result.content)
|
|
37
|
+
|
|
38
|
+
await server.stop()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
asyncio.run(main())
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Key APIs
|
|
45
|
+
|
|
46
|
+
- **`start()` / `stop()`** — lifecycle
|
|
47
|
+
- **`call_tool(integration_id, tool_name, arguments, timeout=60.0)`** — execute a tool call on any gateway that provides the integration
|
|
48
|
+
- **`call_tool_for_org(organization_id, integration_id, tool_name, arguments, timeout=90.0)`** — same, scoped to an organization with automatic load balancing and retry on a different gateway
|
|
49
|
+
- **`get_tools_for_org(organization_id)`** — list deduplicated tools across all gateways for an org
|
|
50
|
+
- **`get_versions(gateway_id)` / `get_tools(gateway_id)` / `get_skills(gateway_id)`** — explicit pulls from a specific gateway
|
|
51
|
+
- **`connected_gateways`** — all currently connected gateways
|
|
52
|
+
|
|
53
|
+
## Callbacks
|
|
54
|
+
|
|
55
|
+
Set these attributes on the server instance:
|
|
56
|
+
|
|
57
|
+
- **`on_gateway_connected(gateway)`** — fired after a gateway authenticates and its initial tools/skills are pulled
|
|
58
|
+
- **`on_gateway_updated(gateway)`** — fired when a gateway's tools or skills change at runtime
|
|
59
|
+
- **`on_gateway_disconnected(gateway)`** — fired when a gateway disconnects
|
|
60
|
+
|
|
61
|
+
## Telemetry
|
|
62
|
+
|
|
63
|
+
The library has no telemetry dependency of its own. Two constructor arguments let you
|
|
64
|
+
wire it into your logging/tracing stack:
|
|
65
|
+
|
|
66
|
+
- **`get_trace_context`** — called on every `call_tool`. Return the active W3C trace
|
|
67
|
+
context as `{"traceparent": ..., "tracestate": ...}` and it is propagated on the
|
|
68
|
+
`tool_call` message; the gateway parents its `gateway.tool_call` span onto it, so the
|
|
69
|
+
remote tool execution appears in your distributed trace. Return `None` when there is
|
|
70
|
+
no active span.
|
|
71
|
+
- **`on_socket_error(error, gateway)`** — called when a gateway socket drops abnormally
|
|
72
|
+
(e.g. a connection reset). `gateway` is `None` if the socket errored before completing
|
|
73
|
+
the handshake. If the gateway had connected, `on_gateway_disconnected` fires as usual.
|
|
74
|
+
When not provided, unexpected connection errors fall back to the `journal_gateway_client`
|
|
75
|
+
logger — bind this callback if you want to route them into your own error tracking.
|
|
76
|
+
|
|
77
|
+
Example wiring with OpenTelemetry and a logger:
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from opentelemetry import propagate
|
|
81
|
+
|
|
82
|
+
def trace_context():
|
|
83
|
+
carrier: dict[str, str] = {}
|
|
84
|
+
propagate.inject(carrier)
|
|
85
|
+
if "traceparent" not in carrier:
|
|
86
|
+
return None
|
|
87
|
+
return {"traceparent": carrier["traceparent"], "tracestate": carrier.get("tracestate")}
|
|
88
|
+
|
|
89
|
+
server = GatewayServer(
|
|
90
|
+
validate_token=validate_token,
|
|
91
|
+
port=8080,
|
|
92
|
+
get_trace_context=trace_context,
|
|
93
|
+
on_socket_error=lambda err, gw: logger.error(
|
|
94
|
+
"gateway socket error", exc_info=err, extra={"gateway_id": gw.id if gw else None}
|
|
95
|
+
),
|
|
96
|
+
)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Full documentation
|
|
100
|
+
|
|
101
|
+
See the [root README](https://github.com/EnduranceLabs/journal-edge#readme) for protocol details, gateway configuration, and architecture.
|
|
102
|
+
|
|
103
|
+
## License
|
|
104
|
+
|
|
105
|
+
MIT
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from .server import GatewayServer, TokenValidationResult
|
|
2
|
+
from .types import (
|
|
3
|
+
Integration,
|
|
4
|
+
ToolDefinition,
|
|
5
|
+
Skill,
|
|
6
|
+
ToolResult,
|
|
7
|
+
GatewayError,
|
|
8
|
+
TextContent,
|
|
9
|
+
ImageContent,
|
|
10
|
+
ContentBlock,
|
|
11
|
+
ConnectedGateway,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"GatewayServer",
|
|
16
|
+
"TokenValidationResult",
|
|
17
|
+
"Integration",
|
|
18
|
+
"ToolDefinition",
|
|
19
|
+
"Skill",
|
|
20
|
+
"ToolResult",
|
|
21
|
+
"GatewayError",
|
|
22
|
+
"TextContent",
|
|
23
|
+
"ImageContent",
|
|
24
|
+
"ContentBlock",
|
|
25
|
+
"ConnectedGateway",
|
|
26
|
+
]
|