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.
@@ -0,0 +1,5 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.egg-info/
4
+ .venv/
5
+ dist/
@@ -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
+ ]