Claude Code for xmlrpc.server: Python XML-RPC Server — Claude Skills 360 Blog
Blog / AI / Claude Code for xmlrpc.server: Python XML-RPC Server
AI

Claude Code for xmlrpc.server: Python XML-RPC Server

Published: November 17, 2028
Read time: 5 min read
By: Claude Skills 360

Python’s xmlrpc.server module creates HTTP servers that expose callable functions and methods as XML-RPC endpoints, enabling language-neutral RPC. from xmlrpc.server import SimpleXMLRPCServer, MultiPathXMLRPCServer. Create: server = SimpleXMLRPCServer(("localhost", 8000), allow_none=True, logRequests=False). Register function: server.register_function(fn, name="math.add")fn becomes callable as math.add via RPC; omit name to use fn.__name__. Register instance: server.register_instance(obj) — all public (non-_ prefixed) methods of obj become RPC methods; set allow_dotted_names=False (the default) to prevent attribute traversal. Enable introspection: server.register_introspection_functions() → adds system.listMethods, system.methodSignature, system.methodHelp. Enable multicall: server.register_multicall_functions() → adds system.multicall for batching. Serve: server.serve_forever() / server.handle_request(). Multi-path: MultiPathXMLRPCServer(addr) with server.add_dispatcher("/rpc/math", math_dispatcher). CGI: CGIXMLRPCRequestHandler().handle_request() for Apache/nginx CGI deployments. Thread safety: subclass socketserver.ThreadingMixIn + SimpleXMLRPCServer for concurrent requests. Claude Code generates REST-free RPC services, calculator APIs, test harnesses, and multi-service XML-RPC routers.

CLAUDE.md for xmlrpc.server

## xmlrpc.server Stack
- Stdlib: from xmlrpc.server import SimpleXMLRPCServer
- Create: server = SimpleXMLRPCServer(("0.0.0.0", 8000), allow_none=True)
- Reg fn: server.register_function(fn)             # uses fn.__name__
-         server.register_function(fn, "ns.method")
- Reg obj: server.register_instance(MyService())   # all public methods
- Intro:  server.register_introspection_functions()
- Serve:  server.serve_forever()   (blocking)
-         server.handle_request()  (one shot, for testing)

xmlrpc.server XML-RPC Server Pipeline

# app/xmlrpcutil.py — service class, threading, dispatch, client test, auth
from __future__ import annotations

import hashlib
import hmac
import socketserver
import threading
import time
import xmlrpc.client
from http.server import BaseHTTPRequestHandler
from typing import Any
from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler


# ─────────────────────────────────────────────────────────────────────────────
# 1. Service classes
# ─────────────────────────────────────────────────────────────────────────────

class MathService:
    """
    Simple arithmetic service exposed over XML-RPC.

    RPC methods: add, subtract, multiply, divide, power, factorial
    """

    def add(self, a: float, b: float) -> float:
        """Add two numbers. >>> add(2, 3) → 5"""
        return a + b

    def subtract(self, a: float, b: float) -> float:
        """Subtract b from a."""
        return a - b

    def multiply(self, a: float, b: float) -> float:
        """Multiply two numbers."""
        return a * b

    def divide(self, a: float, b: float) -> float:
        """Divide a by b. Raises xmlrpc.client.Fault if b == 0."""
        if b == 0:
            raise xmlrpc.client.Fault(1, "Division by zero")
        return a / b

    def power(self, base: float, exp: float) -> float:
        """Return base ** exp."""
        return base ** exp

    def factorial(self, n: int) -> int:
        """Return n! for non-negative integer n."""
        if not isinstance(n, int) or n < 0:
            raise xmlrpc.client.Fault(2, "n must be a non-negative integer")
        result = 1
        for i in range(2, n + 1):
            result *= i
        return result


class EchoService:
    """
    Utility service: echo, ping, info, type_of.
    """

    def __init__(self, server_name: str = "xmlrpc-demo"):
        self._name = server_name
        self._start = time.time()

    def ping(self) -> str:
        """Return 'pong'."""
        return "pong"

    def echo(self, value: Any) -> Any:
        """Return the value as-is."""
        return value

    def info(self) -> dict:
        """Return server metadata."""
        return {
            "name": self._name,
            "uptime_seconds": round(time.time() - self._start, 2),
            "python_xmlrpc": "xmlrpc.server",
        }

    def type_of(self, value: Any) -> str:
        """Return the type name of the given value."""
        return type(value).__name__


# ─────────────────────────────────────────────────────────────────────────────
# 2. Server factory
# ─────────────────────────────────────────────────────────────────────────────

class ThreadedXMLRPCServer(socketserver.ThreadingMixIn, SimpleXMLRPCServer):
    """Thread-per-request XML-RPC server."""
    daemon_threads = True
    allow_reuse_address = True


def make_server(
    host: str = "127.0.0.1",
    port: int = 8000,
    allow_none: bool = True,
    log_requests: bool = False,
    threaded: bool = True,
) -> SimpleXMLRPCServer:
    """
    Create a (optionally threaded) SimpleXMLRPCServer with introspection + multicall.

    Example:
        server = make_server(port=9000)
        server.register_instance(MathService())
        server.handle_request()   # one shot for testing
    """
    cls = ThreadedXMLRPCServer if threaded else SimpleXMLRPCServer
    server = cls(
        (host, port),
        allow_none=allow_none,
        logRequests=log_requests,
    )
    server.register_introspection_functions()
    server.register_multicall_functions()
    return server


def serve_in_thread(
    server: SimpleXMLRPCServer,
) -> threading.Thread:
    """
    Run server.serve_forever() in a daemon thread.
    Returns the thread object; call server.shutdown() to stop.

    Example:
        server = make_server(port=9001)
        server.register_instance(EchoService())
        t = serve_in_thread(server)
        # ... do work ...
        server.shutdown()
    """
    t = threading.Thread(target=server.serve_forever, daemon=True)
    t.start()
    return t


# ─────────────────────────────────────────────────────────────────────────────
# 3. Client helper
# ─────────────────────────────────────────────────────────────────────────────

def make_client(
    host: str = "127.0.0.1",
    port: int = 8000,
    path: str = "/RPC2",
    allow_none: bool = True,
    timeout: int = 10,
) -> xmlrpc.client.ServerProxy:
    """
    Create an xmlrpc.client.ServerProxy connected to the given server.

    Example:
        client = make_client(port=9000)
        result = client.add(3, 4)
        methods = client.system.listMethods()
    """
    uri = f"http://{host}:{port}{path}"
    return xmlrpc.client.ServerProxy(
        uri, allow_none=allow_none, use_datetime=True
    )


def multicall(
    client: xmlrpc.client.ServerProxy,
    calls: list[tuple[str, list]],
) -> list[Any]:
    """
    Execute multiple RPC calls in one HTTP request using system.multicall.

    Example:
        results = multicall(client, [
            ("add",      [1, 2]),
            ("multiply", [3, 4]),
            ("ping",     []),
        ])
    """
    mc = xmlrpc.client.MultiCall(client)
    for method_name, args in calls:
        getattr(mc, method_name)(*args)
    return list(mc())


# ─────────────────────────────────────────────────────────────────────────────
# 4. Multi-service dispatcher
# ─────────────────────────────────────────────────────────────────────────────

def register_services(
    server: SimpleXMLRPCServer,
    services: dict[str, object],
    prefix_separator: str = ".",
) -> None:
    """
    Register multiple service instances under dotted-prefix namespaces.
    Each public method of obj is registered as "prefix.method_name".

    Example:
        register_services(server, {
            "math": MathService(),
            "echo": EchoService(),
        })
        # client.math.add(1, 2), client.echo.ping()
    """
    for prefix, obj in services.items():
        for name in dir(obj):
            if name.startswith("_"):
                continue
            fn = getattr(obj, name)
            if callable(fn):
                rpc_name = f"{prefix}{prefix_separator}{name}"
                server.register_function(fn, rpc_name)


# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    import socket
    print("=== xmlrpc.server demo ===")

    # ── Find a free port ──────────────────────────────────────────────────────
    with socket.socket() as s:
        s.bind(("127.0.0.1", 0))
        port = s.getsockname()[1]

    # ── Start server ──────────────────────────────────────────────────────────
    server = make_server(port=port, log_requests=False)
    register_services(server, {
        "math": MathService(),
        "echo": EchoService("demo-server"),
    })
    t = serve_in_thread(server)
    time.sleep(0.1)    # let thread start

    print(f"\n  Server listening on 127.0.0.1:{port}")

    # ── Client calls ──────────────────────────────────────────────────────────
    client = make_client(port=port)

    print("\n--- individual calls ---")
    print(f"  math.add(3, 4)        = {client.math.add(3, 4)}")
    print(f"  math.multiply(6, 7)   = {client.math.multiply(6, 7)}")
    print(f"  math.factorial(10)    = {client.math.factorial(10)}")
    print(f"  echo.ping()           = {client.echo.ping()!r}")
    print(f"  echo.type_of([1,2,3]) = {client.echo.type_of([1, 2, 3])!r}")

    try:
        client.math.divide(1, 0)
    except xmlrpc.client.Fault as e:
        print(f"  divide(1,0) fault: {e.faultCode} {e.faultString!r}")

    # ── Introspection ─────────────────────────────────────────────────────────
    print("\n--- system.listMethods() ---")
    methods = client.system.listMethods()
    for m in sorted(methods):
        print(f"  {m}")

    # ── Multicall ─────────────────────────────────────────────────────────────
    print("\n--- multicall ---")
    results = multicall(client, [
        ("math.add",      [10, 20]),
        ("math.power",    [2, 8]),
        ("echo.ping",     []),
    ])
    for (name, _), result in zip(
        [("math.add", []), ("math.power", []), ("echo.ping", [])], results
    ):
        print(f"  {name}: {result}")

    # ── Shutdown ──────────────────────────────────────────────────────────────
    server.shutdown()
    t.join(timeout=2)
    print("\n=== done ===")

For the Flask / FastAPI (PyPI) alternatives — modern REST or JSON-RPC APIs built with Flask @app.route or FastAPI @app.post("/rpc") provide typed schemas, automatic OpenAPI docs, middleware, authentication decorators, and async support — use Flask or FastAPI for any new service; use xmlrpc.server for legacy integrations, compatibility with existing XML-RPC clients (WordPress, Confluence, Bugzilla, many monitoring tools), zero-dependency service exposure in constrained environments, and CLI tooling that already uses xmlrpc.client. For the rpyc (PyPI) alternative — rpyc.connect(host, port) provides Python-native object-level RPC including streaming, callbacks, and transparent remote attribute access — use rpyc when both client and server are Python and you want richer calling semantics; use xmlrpc.server when clients may be PHP, Ruby, Java, or any language with an XML-RPC library, since the protocol is a widely-supported cross-language standard. The Claude Skills 360 bundle includes xmlrpc.server skill sets covering MathService/EchoService service classes, ThreadedXMLRPCServer with make_server()/serve_in_thread() factories, make_client()/multicall() client helpers, and register_services() multi-namespace dispatcher. Start with the free tier to try XML-RPC server patterns and xmlrpc.server pipeline code generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free