stinger-python-utils 0.1.7__tar.gz → 0.1.8__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.
Files changed (22) hide show
  1. stinger_python_utils-0.1.8/PKG-INFO +276 -0
  2. stinger_python_utils-0.1.8/README.md +261 -0
  3. {stinger_python_utils-0.1.7 → stinger_python_utils-0.1.8}/pyproject.toml +11 -1
  4. stinger_python_utils-0.1.8/src/stinger_python_utils/mcp/__init__.py +20 -0
  5. stinger_python_utils-0.1.8/src/stinger_python_utils/mcp/__main__.py +58 -0
  6. stinger_python_utils-0.1.8/src/stinger_python_utils/mcp/plugin.py +220 -0
  7. stinger_python_utils-0.1.8/src/stinger_python_utils/mcp/server.py +633 -0
  8. {stinger_python_utils-0.1.7 → stinger_python_utils-0.1.8}/src/stinger_python_utils/message_creator.py +17 -0
  9. stinger_python_utils-0.1.8/uv.lock +868 -0
  10. stinger_python_utils-0.1.7/PKG-INFO +0 -84
  11. stinger_python_utils-0.1.7/README.md +0 -73
  12. stinger_python_utils-0.1.7/uv.lock +0 -1476
  13. {stinger_python_utils-0.1.7 → stinger_python_utils-0.1.8}/.github/workflows/python-tests.yml +0 -0
  14. {stinger_python_utils-0.1.7 → stinger_python_utils-0.1.8}/.github/workflows/python37.yml +0 -0
  15. {stinger_python_utils-0.1.7 → stinger_python_utils-0.1.8}/.gitignore +0 -0
  16. {stinger_python_utils-0.1.7 → stinger_python_utils-0.1.8}/.python-version +0 -0
  17. {stinger_python_utils-0.1.7 → stinger_python_utils-0.1.8}/.vscode/settings.json +0 -0
  18. {stinger_python_utils-0.1.7 → stinger_python_utils-0.1.8}/LICENSE +0 -0
  19. {stinger_python_utils-0.1.7 → stinger_python_utils-0.1.8}/src/stinger_python_utils/__init__.py +0 -0
  20. {stinger_python_utils-0.1.7 → stinger_python_utils-0.1.8}/src/stinger_python_utils/return_codes.py +0 -0
  21. {stinger_python_utils-0.1.7 → stinger_python_utils-0.1.8}/test/__init__.py +0 -0
  22. {stinger_python_utils-0.1.7 → stinger_python_utils-0.1.8}/test/test_message_creator.py +0 -0
@@ -0,0 +1,276 @@
1
+ Metadata-Version: 2.4
2
+ Name: stinger-python-utils
3
+ Version: 0.1.8
4
+ Summary: Common utilities for Stinger Python services.
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.7
8
+ Requires-Dist: pydantic>=2.5.3
9
+ Requires-Dist: pyqttier>=0.2.0
10
+ Provides-Extra: mcp
11
+ Requires-Dist: mcp>=1.0.0; extra == 'mcp'
12
+ Requires-Dist: stevedore>=5.0; extra == 'mcp'
13
+ Requires-Dist: uvicorn>=0.20.0; extra == 'mcp'
14
+ Description-Content-Type: text/markdown
15
+
16
+ # stinger-python-utils
17
+
18
+ Shared utilities for Stinger Python services, providing convenient message creation for MQTT communication.
19
+
20
+
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ uv add stinger-python-utils
26
+ ```
27
+
28
+ ## MessageCreator
29
+
30
+ `MessageCreator` is a utility class for creating MQTT messages with standardized properties and payloads.
31
+
32
+ ### Basic Usage
33
+
34
+ ```python
35
+ from pydantic import BaseModel
36
+ from stinger_python_utils.message_creator import MessageCreator
37
+
38
+ class MyPayload(BaseModel):
39
+ name: str
40
+ value: int
41
+
42
+ payload = MyPayload(name="test", value=42)
43
+ message = MessageCreator.signal_message("my/topic", payload)
44
+ ```
45
+
46
+ ### Methods
47
+
48
+ | Method | Purpose | Return Code |
49
+ |--------|---------|-------------|
50
+ | `signal_message(topic, payload)` | Send a signal with one-time delivery | QoS 1, no retain |
51
+ | `status_message(topic, payload, expiry_seconds)` | Send status that expires | QoS 1, retained, with expiry |
52
+ | `error_response_message(topic, return_code, correlation_id, debug_info)` | Error response to a request | QoS 1, user properties: `ReturnCode` |
53
+ | `response_message(topic, payload, return_code, correlation_id)` | Successful response to a request | QoS 1, user properties: `ReturnCode` |
54
+ | `property_state_message(topic, payload, state_version)` | Publish property state | QoS 1, retained, JSON content type |
55
+ | `property_update_request_message(topic, payload, version, response_topic, correlation_id)` | Request property update | QoS 1, user property: `PropertyVersion` |
56
+ | `property_response_message(topic, payload, version, return_code, correlation_id, debug_info)` | Respond to property update | QoS 1, user properties: `ReturnCode`, `PropertyVersion` |
57
+ | `request_message(topic, payload, response_topic, correlation_id)` | Send a request (auto-generates UUID if no correlation_id) | QoS 1, auto correlation ID |
58
+
59
+ ### Example: Request/Response Pattern
60
+
61
+ ```python
62
+ from pydantic import BaseModel
63
+ from stinger_python_utils.message_creator import MessageCreator
64
+
65
+ class Request(BaseModel):
66
+ action: str
67
+
68
+ request = Request(action="start")
69
+ msg = MessageCreator.request_message(
70
+ "devices/cmd",
71
+ request,
72
+ response_topic="devices/response"
73
+ )
74
+ # Returns a Message with auto-generated correlation ID
75
+ ```
76
+
77
+ ### Example: Error Response
78
+
79
+ ```python
80
+ msg = MessageCreator.error_response_message(
81
+ "devices/response",
82
+ return_code=500,
83
+ correlation_id="req-123",
84
+ debug_info="Device not found"
85
+ )
86
+ # User properties include: ReturnCode=500, DebugInfo=Device not found
87
+ ```
88
+
89
+ ---
90
+
91
+ ## MCP Server
92
+
93
+ `stinger-python-utils` includes an optional **Model Context Protocol (MCP) server** that exposes stinger-ipc services to AI coding assistants such as GitHub Copilot in VS Code.
94
+
95
+ The server discovers live stinger-ipc service instances over MQTT and dynamically registers them as MCP **resources** (properties and signal mailboxes) and **tools** (methods and writable property setters). Functionality is provided by plugins — third-party packages that register against the `stinger_python_utils.mcp_plugins` stevedore entry-point namespace.
96
+
97
+ ### Installation
98
+
99
+ Install with the `mcp` extra to pull in the MCP SDK, stevedore, and uvicorn:
100
+
101
+ ```bash
102
+ pip install 'stinger-python-utils[mcp]'
103
+ # or with uv:
104
+ uv add 'stinger-python-utils[mcp]'
105
+ ```
106
+
107
+ ### MQTT Connection Configuration
108
+
109
+ The server connects to an MQTT broker using environment variables:
110
+
111
+ | Variable | Default | Description |
112
+ |----------|---------|-------------|
113
+ | `MQTT_HOST` | `localhost` | Broker hostname or IP |
114
+ | `MQTT_PORT` | `1883` | Broker port |
115
+ | `MQTT_TRANSPORT` | `tcp` | `tcp`, `websocket`, or `unix` |
116
+ | `MQTT_CLIENT_ID` | *(random)* | MQTT client identifier |
117
+
118
+ ### Running the Server
119
+
120
+ **stdio transport** (recommended for VS Code / Copilot):
121
+
122
+ ```bash
123
+ stinger-mcp-server --transport stdio
124
+ ```
125
+
126
+ **SSE transport** (for browser-based or remote clients):
127
+
128
+ ```bash
129
+ stinger-mcp-server --transport sse --host 0.0.0.0 --port 8000
130
+ ```
131
+
132
+ ### Adding to VS Code (GitHub Copilot)
133
+
134
+ Add the server to your VS Code user or workspace MCP configuration.
135
+
136
+ **Option 1 — User settings** (`~/.vscode/mcp.json` or via *Settings → MCP*):
137
+
138
+ ```json
139
+ {
140
+ "servers": {
141
+ "stinger": {
142
+ "type": "stdio",
143
+ "command": "stinger-mcp-server",
144
+ "args": ["--transport", "stdio"],
145
+ "env": {
146
+ "MQTT_HOST": "localhost",
147
+ "MQTT_PORT": "1883"
148
+ }
149
+ }
150
+ }
151
+ }
152
+ ```
153
+
154
+ **Option 2 — Workspace settings** (`.vscode/mcp.json` in your repo, checked into source control so the whole team shares the same configuration):
155
+
156
+ ```json
157
+ {
158
+ "servers": {
159
+ "stinger": {
160
+ "type": "stdio",
161
+ "command": "stinger-mcp-server",
162
+ "args": ["--transport", "stdio"],
163
+ "env": {
164
+ "MQTT_HOST": "localhost",
165
+ "MQTT_PORT": "1883"
166
+ }
167
+ }
168
+ }
169
+ }
170
+ ```
171
+
172
+ Once saved, open the Copilot Chat panel, switch to **Agent** mode, and the stinger service tools and resources will be available.
173
+
174
+ > **Tip:** If `stinger-mcp-server` is installed inside a virtual environment rather than globally, use the full path to the executable, e.g. `"/path/to/.venv/bin/stinger-mcp-server"`.
175
+
176
+ **Option 3 — SSE transport** (connect to a server already running elsewhere, e.g. on a remote device or in a container):
177
+
178
+ First start the server with the SSE transport:
179
+
180
+ ```bash
181
+ MQTT_HOST=192.168.1.100 stinger-mcp-server --transport sse --host 0.0.0.0 --port 8000
182
+ ```
183
+
184
+ Then point VS Code at it in `.vscode/mcp.json`:
185
+
186
+ ```json
187
+ {
188
+ "servers": {
189
+ "stinger": {
190
+ "type": "sse",
191
+ "url": "http://localhost:8000/sse"
192
+ }
193
+ }
194
+ }
195
+ ```
196
+
197
+ Replace `localhost` with the hostname or IP of the machine running the server.
198
+
199
+ ### Writing a Plugin
200
+
201
+ Plugins provide the actual service-type knowledge to the MCP server. Create a class that extends `StingerMCPPlugin` and register it as a stevedore entry-point:
202
+
203
+ **`my_service/mcp_plugin.py`**:
204
+
205
+ ```python
206
+ from stinger_python_utils.mcp import (
207
+ StingerMCPPlugin,
208
+ SignalDefinition,
209
+ PropertyDefinition,
210
+ MethodDefinition,
211
+ )
212
+ from .client import MyServiceClient
213
+ from .discoverer import MyServiceDiscoverer
214
+
215
+ class MyServicePlugin(StingerMCPPlugin):
216
+
217
+ def get_plugin_name(self) -> str:
218
+ return "my_service" # used as URI scheme: my_service://instance/...
219
+
220
+ def get_discovery_class(self) -> type:
221
+ return MyServiceDiscoverer
222
+
223
+ def get_client_class(self) -> type:
224
+ return MyServiceClient
225
+
226
+ def get_signals(self) -> list[SignalDefinition]:
227
+ return [
228
+ SignalDefinition(name="status_changed", description="Emitted when device status changes"),
229
+ ]
230
+
231
+ def get_properties(self) -> list[PropertyDefinition]:
232
+ return [
233
+ PropertyDefinition(
234
+ name="brightness",
235
+ schema={
236
+ "type": "object",
237
+ "properties": {"value": {"type": "integer", "minimum": 0, "maximum": 100}},
238
+ "required": ["value"],
239
+ },
240
+ readonly=False,
241
+ description="Brightness level (0–100)",
242
+ ),
243
+ ]
244
+
245
+ def get_methods(self) -> list[MethodDefinition]:
246
+ return [
247
+ MethodDefinition(
248
+ name="restart",
249
+ arguments_schema={"type": "object", "properties": {}},
250
+ description="Restart the device",
251
+ ),
252
+ ]
253
+ ```
254
+
255
+ **`pyproject.toml`** of the plugin package:
256
+
257
+ ```toml
258
+ [project.entry-points."stinger_python_utils.mcp_plugins"]
259
+ my_service = "my_service.mcp_plugin:MyServicePlugin"
260
+ ```
261
+
262
+ Install the plugin package into the same environment as `stinger-python-utils[mcp]` and the server will discover it automatically on next start.
263
+
264
+ ### MCP Resource and Tool Naming
265
+
266
+ For each discovered service instance the server exposes:
267
+
268
+ | MCP primitive | Name / URI pattern | Description |
269
+ |---------------|--------------------|-------------|
270
+ | Resource | `{plugin}://{instance_id}/property/{name}` | Current property value (JSON) |
271
+ | Resource | `{plugin}://{instance_id}/signal/{name}` | Mailbox of the last 10 signals (JSON array with timestamps) |
272
+ | Tool | `{plugin}_{instance_id}_{method_name}` | Calls a method on the instance |
273
+ | Tool | `{plugin}_{instance_id}_set_{property_name}` | Sets a writable property |
274
+
275
+ As instances come and go the tool and resource lists update automatically.
276
+
@@ -0,0 +1,261 @@
1
+ # stinger-python-utils
2
+
3
+ Shared utilities for Stinger Python services, providing convenient message creation for MQTT communication.
4
+
5
+
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ uv add stinger-python-utils
11
+ ```
12
+
13
+ ## MessageCreator
14
+
15
+ `MessageCreator` is a utility class for creating MQTT messages with standardized properties and payloads.
16
+
17
+ ### Basic Usage
18
+
19
+ ```python
20
+ from pydantic import BaseModel
21
+ from stinger_python_utils.message_creator import MessageCreator
22
+
23
+ class MyPayload(BaseModel):
24
+ name: str
25
+ value: int
26
+
27
+ payload = MyPayload(name="test", value=42)
28
+ message = MessageCreator.signal_message("my/topic", payload)
29
+ ```
30
+
31
+ ### Methods
32
+
33
+ | Method | Purpose | Return Code |
34
+ |--------|---------|-------------|
35
+ | `signal_message(topic, payload)` | Send a signal with one-time delivery | QoS 1, no retain |
36
+ | `status_message(topic, payload, expiry_seconds)` | Send status that expires | QoS 1, retained, with expiry |
37
+ | `error_response_message(topic, return_code, correlation_id, debug_info)` | Error response to a request | QoS 1, user properties: `ReturnCode` |
38
+ | `response_message(topic, payload, return_code, correlation_id)` | Successful response to a request | QoS 1, user properties: `ReturnCode` |
39
+ | `property_state_message(topic, payload, state_version)` | Publish property state | QoS 1, retained, JSON content type |
40
+ | `property_update_request_message(topic, payload, version, response_topic, correlation_id)` | Request property update | QoS 1, user property: `PropertyVersion` |
41
+ | `property_response_message(topic, payload, version, return_code, correlation_id, debug_info)` | Respond to property update | QoS 1, user properties: `ReturnCode`, `PropertyVersion` |
42
+ | `request_message(topic, payload, response_topic, correlation_id)` | Send a request (auto-generates UUID if no correlation_id) | QoS 1, auto correlation ID |
43
+
44
+ ### Example: Request/Response Pattern
45
+
46
+ ```python
47
+ from pydantic import BaseModel
48
+ from stinger_python_utils.message_creator import MessageCreator
49
+
50
+ class Request(BaseModel):
51
+ action: str
52
+
53
+ request = Request(action="start")
54
+ msg = MessageCreator.request_message(
55
+ "devices/cmd",
56
+ request,
57
+ response_topic="devices/response"
58
+ )
59
+ # Returns a Message with auto-generated correlation ID
60
+ ```
61
+
62
+ ### Example: Error Response
63
+
64
+ ```python
65
+ msg = MessageCreator.error_response_message(
66
+ "devices/response",
67
+ return_code=500,
68
+ correlation_id="req-123",
69
+ debug_info="Device not found"
70
+ )
71
+ # User properties include: ReturnCode=500, DebugInfo=Device not found
72
+ ```
73
+
74
+ ---
75
+
76
+ ## MCP Server
77
+
78
+ `stinger-python-utils` includes an optional **Model Context Protocol (MCP) server** that exposes stinger-ipc services to AI coding assistants such as GitHub Copilot in VS Code.
79
+
80
+ The server discovers live stinger-ipc service instances over MQTT and dynamically registers them as MCP **resources** (properties and signal mailboxes) and **tools** (methods and writable property setters). Functionality is provided by plugins — third-party packages that register against the `stinger_python_utils.mcp_plugins` stevedore entry-point namespace.
81
+
82
+ ### Installation
83
+
84
+ Install with the `mcp` extra to pull in the MCP SDK, stevedore, and uvicorn:
85
+
86
+ ```bash
87
+ pip install 'stinger-python-utils[mcp]'
88
+ # or with uv:
89
+ uv add 'stinger-python-utils[mcp]'
90
+ ```
91
+
92
+ ### MQTT Connection Configuration
93
+
94
+ The server connects to an MQTT broker using environment variables:
95
+
96
+ | Variable | Default | Description |
97
+ |----------|---------|-------------|
98
+ | `MQTT_HOST` | `localhost` | Broker hostname or IP |
99
+ | `MQTT_PORT` | `1883` | Broker port |
100
+ | `MQTT_TRANSPORT` | `tcp` | `tcp`, `websocket`, or `unix` |
101
+ | `MQTT_CLIENT_ID` | *(random)* | MQTT client identifier |
102
+
103
+ ### Running the Server
104
+
105
+ **stdio transport** (recommended for VS Code / Copilot):
106
+
107
+ ```bash
108
+ stinger-mcp-server --transport stdio
109
+ ```
110
+
111
+ **SSE transport** (for browser-based or remote clients):
112
+
113
+ ```bash
114
+ stinger-mcp-server --transport sse --host 0.0.0.0 --port 8000
115
+ ```
116
+
117
+ ### Adding to VS Code (GitHub Copilot)
118
+
119
+ Add the server to your VS Code user or workspace MCP configuration.
120
+
121
+ **Option 1 — User settings** (`~/.vscode/mcp.json` or via *Settings → MCP*):
122
+
123
+ ```json
124
+ {
125
+ "servers": {
126
+ "stinger": {
127
+ "type": "stdio",
128
+ "command": "stinger-mcp-server",
129
+ "args": ["--transport", "stdio"],
130
+ "env": {
131
+ "MQTT_HOST": "localhost",
132
+ "MQTT_PORT": "1883"
133
+ }
134
+ }
135
+ }
136
+ }
137
+ ```
138
+
139
+ **Option 2 — Workspace settings** (`.vscode/mcp.json` in your repo, checked into source control so the whole team shares the same configuration):
140
+
141
+ ```json
142
+ {
143
+ "servers": {
144
+ "stinger": {
145
+ "type": "stdio",
146
+ "command": "stinger-mcp-server",
147
+ "args": ["--transport", "stdio"],
148
+ "env": {
149
+ "MQTT_HOST": "localhost",
150
+ "MQTT_PORT": "1883"
151
+ }
152
+ }
153
+ }
154
+ }
155
+ ```
156
+
157
+ Once saved, open the Copilot Chat panel, switch to **Agent** mode, and the stinger service tools and resources will be available.
158
+
159
+ > **Tip:** If `stinger-mcp-server` is installed inside a virtual environment rather than globally, use the full path to the executable, e.g. `"/path/to/.venv/bin/stinger-mcp-server"`.
160
+
161
+ **Option 3 — SSE transport** (connect to a server already running elsewhere, e.g. on a remote device or in a container):
162
+
163
+ First start the server with the SSE transport:
164
+
165
+ ```bash
166
+ MQTT_HOST=192.168.1.100 stinger-mcp-server --transport sse --host 0.0.0.0 --port 8000
167
+ ```
168
+
169
+ Then point VS Code at it in `.vscode/mcp.json`:
170
+
171
+ ```json
172
+ {
173
+ "servers": {
174
+ "stinger": {
175
+ "type": "sse",
176
+ "url": "http://localhost:8000/sse"
177
+ }
178
+ }
179
+ }
180
+ ```
181
+
182
+ Replace `localhost` with the hostname or IP of the machine running the server.
183
+
184
+ ### Writing a Plugin
185
+
186
+ Plugins provide the actual service-type knowledge to the MCP server. Create a class that extends `StingerMCPPlugin` and register it as a stevedore entry-point:
187
+
188
+ **`my_service/mcp_plugin.py`**:
189
+
190
+ ```python
191
+ from stinger_python_utils.mcp import (
192
+ StingerMCPPlugin,
193
+ SignalDefinition,
194
+ PropertyDefinition,
195
+ MethodDefinition,
196
+ )
197
+ from .client import MyServiceClient
198
+ from .discoverer import MyServiceDiscoverer
199
+
200
+ class MyServicePlugin(StingerMCPPlugin):
201
+
202
+ def get_plugin_name(self) -> str:
203
+ return "my_service" # used as URI scheme: my_service://instance/...
204
+
205
+ def get_discovery_class(self) -> type:
206
+ return MyServiceDiscoverer
207
+
208
+ def get_client_class(self) -> type:
209
+ return MyServiceClient
210
+
211
+ def get_signals(self) -> list[SignalDefinition]:
212
+ return [
213
+ SignalDefinition(name="status_changed", description="Emitted when device status changes"),
214
+ ]
215
+
216
+ def get_properties(self) -> list[PropertyDefinition]:
217
+ return [
218
+ PropertyDefinition(
219
+ name="brightness",
220
+ schema={
221
+ "type": "object",
222
+ "properties": {"value": {"type": "integer", "minimum": 0, "maximum": 100}},
223
+ "required": ["value"],
224
+ },
225
+ readonly=False,
226
+ description="Brightness level (0–100)",
227
+ ),
228
+ ]
229
+
230
+ def get_methods(self) -> list[MethodDefinition]:
231
+ return [
232
+ MethodDefinition(
233
+ name="restart",
234
+ arguments_schema={"type": "object", "properties": {}},
235
+ description="Restart the device",
236
+ ),
237
+ ]
238
+ ```
239
+
240
+ **`pyproject.toml`** of the plugin package:
241
+
242
+ ```toml
243
+ [project.entry-points."stinger_python_utils.mcp_plugins"]
244
+ my_service = "my_service.mcp_plugin:MyServicePlugin"
245
+ ```
246
+
247
+ Install the plugin package into the same environment as `stinger-python-utils[mcp]` and the server will discover it automatically on next start.
248
+
249
+ ### MCP Resource and Tool Naming
250
+
251
+ For each discovered service instance the server exposes:
252
+
253
+ | MCP primitive | Name / URI pattern | Description |
254
+ |---------------|--------------------|-------------|
255
+ | Resource | `{plugin}://{instance_id}/property/{name}` | Current property value (JSON) |
256
+ | Resource | `{plugin}://{instance_id}/signal/{name}` | Mailbox of the last 10 signals (JSON array with timestamps) |
257
+ | Tool | `{plugin}_{instance_id}_{method_name}` | Calls a method on the instance |
258
+ | Tool | `{plugin}_{instance_id}_set_{property_name}` | Sets a writable property |
259
+
260
+ As instances come and go the tool and resource lists update automatically.
261
+
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "stinger-python-utils"
7
- version = "0.1.7"
7
+ version = "0.1.8"
8
8
  description = "Common utilities for Stinger Python services."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -14,6 +14,16 @@ dependencies = [
14
14
  "pyqttier>=0.2.0",
15
15
  ]
16
16
 
17
+ [project.optional-dependencies]
18
+ mcp = [
19
+ "mcp>=1.0.0",
20
+ "stevedore>=5.0",
21
+ "uvicorn>=0.20.0",
22
+ ]
23
+
24
+ [project.scripts]
25
+ stinger-mcp-server = "stinger_python_utils.mcp.__main__:main"
26
+
17
27
  [tool.uv]
18
28
  managed = true
19
29
 
@@ -0,0 +1,20 @@
1
+ """Stinger MCP server – plugin-based MCP interface to stinger-ipc services.
2
+
3
+ Public API re-exported here for convenience::
4
+
5
+ from stinger_python_utils.mcp import StingerMCPPlugin, SignalDefinition, ...
6
+ """
7
+
8
+ from .plugin import (
9
+ MethodDefinition,
10
+ PropertyDefinition,
11
+ SignalDefinition,
12
+ StingerMCPPlugin,
13
+ )
14
+
15
+ __all__ = [
16
+ "MethodDefinition",
17
+ "PropertyDefinition",
18
+ "SignalDefinition",
19
+ "StingerMCPPlugin",
20
+ ]
@@ -0,0 +1,58 @@
1
+ """Entry-point for ``python -m stinger_python_utils.mcp``."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import asyncio
7
+ import logging
8
+
9
+
10
+ def main() -> None:
11
+ parser = argparse.ArgumentParser(
12
+ prog="stinger-mcp-server",
13
+ description="Stinger MCP Server – expose stinger-ipc services over MCP",
14
+ )
15
+ parser.add_argument(
16
+ "--transport",
17
+ choices=["stdio", "sse", "streamable-http"],
18
+ default="stdio",
19
+ help="MCP transport to use (default: stdio)",
20
+ )
21
+ parser.add_argument(
22
+ "--host",
23
+ default="0.0.0.0",
24
+ help="Bind address for SSE/streamable-http transport (default: 0.0.0.0)",
25
+ )
26
+ parser.add_argument(
27
+ "--port",
28
+ type=int,
29
+ default=8000,
30
+ help="Port for SSE/streamable-http transport (default: 8000)",
31
+ )
32
+ parser.add_argument(
33
+ "--log-level",
34
+ default="INFO",
35
+ choices=["DEBUG", "INFO", "WARNING", "ERROR"],
36
+ help="Logging level (default: INFO)",
37
+ )
38
+ args = parser.parse_args()
39
+
40
+ logging.basicConfig(
41
+ level=getattr(logging, args.log_level),
42
+ format="%(asctime)s %(levelname)-8s %(name)s %(message)s",
43
+ )
44
+
45
+ from .server import StingerMCPServer
46
+
47
+ server = StingerMCPServer()
48
+
49
+ if args.transport == "stdio":
50
+ asyncio.run(server.run_stdio())
51
+ elif args.transport == "sse":
52
+ asyncio.run(server.run_sse(host=args.host, port=args.port))
53
+ elif args.transport == "streamable-http":
54
+ asyncio.run(server.run_streamable_http(host=args.host, port=args.port))
55
+
56
+
57
+ if __name__ == "__main__":
58
+ main()