Skip to main content

Common utilities for Stinger Python services.

Project description

stinger-python-utils

Shared utilities for Stinger Python services, providing convenient message creation for MQTT communication.

Installation

uv add stinger-python-utils

MessageCreator

MessageCreator is a utility class for creating MQTT messages with standardized properties and payloads.

Basic Usage

from pydantic import BaseModel
from stinger_python_utils.message_creator import MessageCreator

class MyPayload(BaseModel):
    name: str
    value: int

payload = MyPayload(name="test", value=42)
message = MessageCreator.signal_message("my/topic", payload)

Methods

Method Purpose Return Code
signal_message(topic, payload) Send a signal with one-time delivery QoS 1, no retain
status_message(topic, payload, expiry_seconds) Send status that expires QoS 1, retained, with expiry
error_response_message(topic, return_code, correlation_id, debug_info) Error response to a request QoS 1, user properties: ReturnCode
response_message(topic, payload, return_code, correlation_id) Successful response to a request QoS 1, user properties: ReturnCode
property_state_message(topic, payload, state_version) Publish property state QoS 1, retained, JSON content type
property_update_request_message(topic, payload, version, response_topic, correlation_id) Request property update QoS 1, user property: PropertyVersion
property_response_message(topic, payload, version, return_code, correlation_id, debug_info) Respond to property update QoS 1, user properties: ReturnCode, PropertyVersion
request_message(topic, payload, response_topic, correlation_id) Send a request (auto-generates UUID if no correlation_id) QoS 1, auto correlation ID

Example: Request/Response Pattern

from pydantic import BaseModel
from stinger_python_utils.message_creator import MessageCreator

class Request(BaseModel):
    action: str

request = Request(action="start")
msg = MessageCreator.request_message(
    "devices/cmd",
    request,
    response_topic="devices/response"
)
# Returns a Message with auto-generated correlation ID

Example: Error Response

msg = MessageCreator.error_response_message(
    "devices/response",
    return_code=500,
    correlation_id="req-123",
    debug_info="Device not found"
)
# User properties include: ReturnCode=500, DebugInfo=Device not found

MCP Server

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.

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.

Installation

Install with the mcp extra to pull in the MCP SDK, stevedore, and uvicorn:

pip install 'stinger-python-utils[mcp]'
# or with uv:
uv add 'stinger-python-utils[mcp]'

MQTT Connection Configuration

The server connects to an MQTT broker using environment variables:

Variable Default Description
MQTT_HOST localhost Broker hostname or IP
MQTT_PORT 1883 Broker port
MQTT_TRANSPORT tcp tcp, websocket, or unix
MQTT_CLIENT_ID (random) MQTT client identifier

Running the Server

stdio transport (recommended for VS Code / Copilot):

stinger-mcp-server --transport stdio

SSE transport (for browser-based or remote clients):

stinger-mcp-server --transport sse --host 0.0.0.0 --port 8000

Adding to VS Code (GitHub Copilot)

Add the server to your VS Code user or workspace MCP configuration.

Option 1 — User settings (~/.vscode/mcp.json or via Settings → MCP):

{
  "servers": {
    "stinger": {
      "type": "stdio",
      "command": "stinger-mcp-server",
      "args": ["--transport", "stdio"],
      "env": {
        "MQTT_HOST": "localhost",
        "MQTT_PORT": "1883"
      }
    }
  }
}

Option 2 — Workspace settings (.vscode/mcp.json in your repo, checked into source control so the whole team shares the same configuration):

{
  "servers": {
    "stinger": {
      "type": "stdio",
      "command": "stinger-mcp-server",
      "args": ["--transport", "stdio"],
      "env": {
        "MQTT_HOST": "localhost",
        "MQTT_PORT": "1883"
      }
    }
  }
}

Once saved, open the Copilot Chat panel, switch to Agent mode, and the stinger service tools and resources will be available.

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".

Option 3 — SSE transport (connect to a server already running elsewhere, e.g. on a remote device or in a container):

First start the server with the SSE transport:

MQTT_HOST=192.168.1.100 stinger-mcp-server --transport sse --host 0.0.0.0 --port 8000

Then point VS Code at it in .vscode/mcp.json:

{
  "servers": {
    "stinger": {
      "type": "sse",
      "url": "http://localhost:8000/sse"
    }
  }
}

Replace localhost with the hostname or IP of the machine running the server.

Writing a Plugin

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:

my_service/mcp_plugin.py:

from stinger_python_utils.mcp import (
    StingerMCPPlugin,
    SignalDefinition,
    PropertyDefinition,
    MethodDefinition,
)
from .client import MyServiceClient
from .discoverer import MyServiceDiscoverer

class MyServicePlugin(StingerMCPPlugin):

    def get_plugin_name(self) -> str:
        return "my_service"  # used as URI scheme: my_service://instance/...

    def get_discovery_class(self) -> type:
        return MyServiceDiscoverer

    def get_client_class(self) -> type:
        return MyServiceClient

    def get_signals(self) -> list[SignalDefinition]:
        return [
            SignalDefinition(name="status_changed", description="Emitted when device status changes"),
        ]

    def get_properties(self) -> list[PropertyDefinition]:
        return [
            PropertyDefinition(
                name="brightness",
                schema={
                    "type": "object",
                    "properties": {"value": {"type": "integer", "minimum": 0, "maximum": 100}},
                    "required": ["value"],
                },
                readonly=False,
                description="Brightness level (0–100)",
            ),
        ]

    def get_methods(self) -> list[MethodDefinition]:
        return [
            MethodDefinition(
                name="restart",
                arguments_schema={"type": "object", "properties": {}},
                description="Restart the device",
            ),
        ]

pyproject.toml of the plugin package:

[project.entry-points."stinger_python_utils.mcp_plugins"]
my_service = "my_service.mcp_plugin:MyServicePlugin"

Install the plugin package into the same environment as stinger-python-utils[mcp] and the server will discover it automatically on next start.

MCP Resource and Tool Naming

For each discovered service instance the server exposes:

MCP primitive Name / URI pattern Description
Resource {plugin}://{instance_id}/property/{name} Current property value (JSON)
Resource {plugin}://{instance_id}/signal/{name} Mailbox of the last 10 signals (JSON array with timestamps)
Tool {plugin}_{instance_id}_{method_name} Calls a method on the instance
Tool {plugin}_{instance_id}_set_{property_name} Sets a writable property

As instances come and go the tool and resource lists update automatically.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

stinger_python_utils-0.1.8.tar.gz (58.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

stinger_python_utils-0.1.8-py3-none-any.whl (17.0 kB view details)

Uploaded Python 3

File details

Details for the file stinger_python_utils-0.1.8.tar.gz.

File metadata

  • Download URL: stinger_python_utils-0.1.8.tar.gz
  • Upload date:
  • Size: 58.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.12 {"installer":{"name":"uv","version":"0.9.12"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"25.10","id":"questing","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for stinger_python_utils-0.1.8.tar.gz
Algorithm Hash digest
SHA256 1dbf27c8b5ef16867b85eaa5beba93b38f85fa8e80f3f728bd763d506da3efca
MD5 643bf6e5ef16b4e5b2a77cae1e1a8ae7
BLAKE2b-256 28ca33efcf6e6f06a86803e9aa769bc40162cfac8697a7e0a9a6c4cf4b005022

See more details on using hashes here.

File details

Details for the file stinger_python_utils-0.1.8-py3-none-any.whl.

File metadata

  • Download URL: stinger_python_utils-0.1.8-py3-none-any.whl
  • Upload date:
  • Size: 17.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.12 {"installer":{"name":"uv","version":"0.9.12"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"25.10","id":"questing","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for stinger_python_utils-0.1.8-py3-none-any.whl
Algorithm Hash digest
SHA256 5dfeb2f66b23fa6f3a3093eaae955f58512abdd8c1eb5854ef30cbd011ed0289
MD5 d379ab8b55e1d1a54f0f774b737ad6df
BLAKE2b-256 45dd448055485fcc273bae614a83333ab11a25bcd3d2a6b9f0146ce688901f07

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page