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.9.tar.gz (129.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.9-py3-none-any.whl (17.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: stinger_python_utils-0.1.9.tar.gz
  • Upload date:
  • Size: 129.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.9.tar.gz
Algorithm Hash digest
SHA256 322114c2b77923f4600bee43eb8b081adfd8bc335aa6bcaa2e90b0bd353d862a
MD5 8ddf5bb551ba5610c2ef74fcb2471c63
BLAKE2b-256 d2f38b4c7b09f14958c29b9038eff3508755552a7dd106e8e6e8052bddea7601

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stinger_python_utils-0.1.9-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.9-py3-none-any.whl
Algorithm Hash digest
SHA256 1547faf73ce920cf15a7a7c9d2f56d63aba560aea7b378090402395e67d4cff0
MD5 9bad269c23a26009d7f5f337ccc8fb68
BLAKE2b-256 f94e822ce111da8b9d95bf9250682a68ab6c6ece0c6bac44a089b63daefafc5d

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