Argparse generator from dataclass
Project description
Inspired by Simple Parsing, simplified and extended to build extensive, extendable command line interface without much code.
pip install argklass
Features
Automatic cli discovery and command plugin
# Folder structure project/cli/ ├── __init__.py <= empty ├── editor/ │ ├── __init__.py <= ParentCommand(editor) │ ├── cook.py <= Command(cook) │ ├── client.py <= Command(client) │ ├── game.py <= Command(game) │ └── open.py <= Command(open) └── uat/ ├── __init__.py <= ParentCommand(uat) ├── localize.py <= Command(localize) └── test.py <= Command(test) # editor/__init__.py from argklass.command import ParentCommand class Editor(ParentCommand): name = "editor" COMMANDS = Editor # cook.py from argklass.command import Command class Cook(Command): name = "cook" @staticmethod def execute(args) -> int: print("cook") COMMANDS = Cook # cli = CommandLineInterface(project.cli) cli.run() # or cli.run(["editor", "cook", "--help"]) # cli editor cook --help cli uat localize --help- New Argument format
able to show the entire command line interface with all its subparsers
new format mirror dataclass syntax
editor Set of commands to launch the editors in different modes server Parameters added to the Map URL game docstring ... client docstring ... resavepackages docstring ... cook docstring ... ml Launch unreal engine with mladapter setup editor Other arguments open docstring ... localize docstring ... worldpartition Convert a UE4 map using world partition -h, --help Show help engine Set of commands to manage engine installation/source add docstring ... update Update the engine source code format docstring ... --profile: str docstring ... --file: str docstring ... --fail_on_error: bool = False docstring ... --col: int = 24 docstring ...
Compact argparse definition
def workdir(): d = os.getcwd() if os.access(d, os.W_OK): return d return None @dataclass class MyArguments: a : str # Positional b : int = 20 # My argument c : bool = False # My argument d : int = choice(0, 1, 2, 3, 4, default=1) # choices e : List[int] = argument(default=[0]) # list f : Optional[int] = None # Optional p : Tuple[int, int] = (1, 1) # help p g : Color = Color.RED # help g s : SubArgs = SubArgs # helps group cmd: Union[cmd1, cmd2] = subparsers(cmd1=cmd1, cmd2=cmd2) # Command subparser de : str = deduceable(workdir) parser = ArgumentParser() parser.add_arguments(MyArguments) args = parser.parse_args()Save and load arguments from configuration files
parser = build_parser(commands) # load/save defaults before parsing save_defaults(parser, "config.hjson") apply_defaults(parser, "config.hjson") args = parser.parse_args(["editor", "editor"]) # load save arguments after parsing save_as_config(parser, args, "dump.hjson") apply_config(parser, args, "dump.hjson")Lower level interface, that gives you back all of argparse power
@dataclass class SubArgs: aa: str = argument(default="123") @dataclass class cmd1: args: str = "str1" @dataclass class cmd2: args: str = "str2" @dataclass class MyArguments: a: str = argument(help="Positional") b: int = argument(default=20, help="My argument") c: bool = argument(action="store_true", help="My argument") d: int = argument(default=1, choices=[0, 1, 2, 3, 4], help="choices") e: List[int] = argument(default=[0], help="list") f: Optional[int] = argument(default=None, help="Optional") p: Tuple[int, int] = argument(default=(1, 1), help="help p") g: Color = argument(default=Color.RED, help="help g") s: SubArgs = group(default=SubArgs, help="helps group") cmd: Union[cmd1, cmd2] = subparsers(cmd1=cmd1, cmd2=cmd2) parser = ArgumentParser() parser.add_arguments(MyArguments) args = parser.parse_args()
MCP Server
argklass can expose your CLI commands as MCP tools, letting AI agents call them directly.
pip install "argklass[mcp]"
Quick start
The fastest way to run an MCP server is the built-in entry point — just point it at your CLI module:
# stdio (default) — for MCP clients that spawn the process
python -m argklass.mcp mypackage.cli
# SSE — for testing or web-based clients
python -m argklass.mcp mypackage.cli --transport sse
# Streamable HTTP — the newest MCP transport
python -m argklass.mcp mypackage.cli --transport streamable-http
# Custom host/port/name
python -m argklass.mcp mypackage.cli --transport sse --host 0.0.0.0 --port 9000 --name my-tools
Programmatic usage
For more control, use create_mcp_server directly:
import mycommands
from argklass.mcp import create_mcp_server
server = create_mcp_server(mycommands, name="my-tools")
# inspect discovered tools
for tool in server.tools:
print(tool.name, tool.schema)
# run as a stdio MCP server
server.run()
# or run with SSE
server.run(transport="sse", host="0.0.0.0", port=9000)
The server walks the parser tree, discovers every leaf command, converts its arguments to JSON Schema, and registers them as MCP tools. When a tool is invoked, the arguments are converted back to argv and the command runs normally — stdout, stderr and exit code are returned to the caller.
You can also call tools directly for testing:
output = server.call("editor_cook", {"--dry-run": True})
Configuration (sysconfig)
argklass.sysconfig lets you define configuration as dataclasses, with values resolved from environment variables, a config dict, or defaults (in that priority order).
from dataclasses import dataclass, field
from argklass.sysconfig import ConfigContext
ctx = ConfigContext(prefix="MYAPP")
@dataclass
class DatabaseConfig:
host: str = ctx.configfield("db.host", str, "localhost") # MYAPP_DB_HOST
port: int = ctx.configfield("db.port", int, 5432) # MYAPP_DB_PORT
@dataclass
class AppConfig:
debug: bool = ctx.configfield("app.debug", bool, False) # MYAPP_APP_DEBUG
db: DatabaseConfig = field(default_factory=DatabaseConfig)
Each field is resolved at instantiation time. Override via environment:
export MYAPP_DB_HOST=db.prod.internal
export MYAPP_DB_PORT=5433
Or programmatically with a config dict:
ctx.set_config({"db": {"host": "db.staging.internal"}})
cfg = AppConfig() # cfg.db.host == "db.staging.internal"
File I/O supports YAML, JSON and HJSON:
# save / load
ctx.save_config(cfg, "config.yaml")
cfg = ctx.load_config(AppConfig, "config.yaml")
# load and apply as the context's config dict
ctx.load_and_apply("overrides.yaml")
When several libraries use argklass in the same process, each one creates its own ConfigContext with a unique prefix, keeping environment variables and config dicts fully isolated.
Architecture
argklass works by building the argument parser as a tree, adding metadata to each nodes when necessary.
One of the core component is ArgumentParserIterator which traverse the parsing tree. Each features, such as argument grouping into dataclasses or saving/loading configuration, are implemented as a simple traversal.
This enable us to implement each feature independently from each other and make them optional.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file argklass-2.0.0.tar.gz.
File metadata
- Download URL: argklass-2.0.0.tar.gz
- Upload date:
- Size: 37.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab9884b883dfad19206c6483fbaaabe7b34f099091fa35f9c2224414975106cf
|
|
| MD5 |
b93c8a55b53193cb029feef90d714402
|
|
| BLAKE2b-256 |
bd2328602349fc351dfac42aa1f0ce7c6deba3ca13db9ae2c15c9cccb1b93dbf
|
File details
Details for the file argklass-2.0.0-py3-none-any.whl.
File metadata
- Download URL: argklass-2.0.0-py3-none-any.whl
- Upload date:
- Size: 37.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
56f6211a7ea9f9fc58c1f1ec03f46ac5288cd26be272e7cf356f1d81285df970
|
|
| MD5 |
81e46f7d5240faeb73d885697f6cf228
|
|
| BLAKE2b-256 |
86ccee3384c546c34ef7f850c268ecf2ed11803ee71bb1aa57d51b145a30e797
|