Metadata-Version: 2.4
Name: laurento-plugin-kit
Version: 1.0.0
Summary: Memorable Python decorators for building Agent Plugin packages
License-Expression: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: mcp
Requires-Dist: mcp<2,>=1.12; extra == "mcp"
Dynamic: license-file

# EasyPlugins 1.0.0

Memorable Python syntax for building portable ChatGPT/Codex Agent Plugin files.
This is a third-party authoring helper, not an OpenAI SDK. It generates packages;
it does not publish, install, host, authenticate, or grant account access.

## Install (Python 3.10 or newer)

Extract this ZIP, open a terminal in the extracted folder containing pyproject.toml:

```bash
python -m pip install .
```

There is no published PyPI release from this project. Install the provided folder
or included wheel. For local Python MCP tools, additionally install:

```bash
python -m pip install "mcp>=1.12,<2"
```

## Your first plugin

Save this as my_plugin.py:

```python
from easyplugins import Plugin_info, Plugin_Adon, Plugin_create_file

@Plugin_info(
    title="Writing Helper",
    description="Help people write clear messages.",
    author="Your name",
)
class MyPlugin:
    pass

@Plugin_Adon(MyPlugin)
def improve_writing():
    """Use when someone asks to improve a draft."""
    return "Ask who the audience is. Improve clarity while preserving the meaning."

if __name__ == "__main__":
    Plugin_create_file(MyPlugin)
```

Run `python my_plugin.py`. You get:

- dist/writing-helper/plugin.json (title, author, version and listing metadata)
- dist/writing-helper/skills/improve-writing/SKILL.md
- dist/writing-helper.zip

`Plugin_create_file` is an ordinary function because building is an action.
Use your decorated class (MyPlugin) as its argument, not the Plugin_info function.
The directory is a lowercase slug; the display title keeps your capitalization.

## No class required

```python
plugin = Plugin_info("Writing Helper", "Help people write clear messages.")
Plugin_Adon(plugin, name="writing", description="Use for writing tasks.",
            instructions="Ask about audience and write a clear draft.")
Plugin_create_file(plugin, output="my-output")
```

## Real Python tools

```python
from easyplugins import Plugin_tool

@Plugin_tool(MyPlugin)
def add(a: int, b: int) -> int:
    """Add two integers."""
    return a + b
```

Add tools before the main build call. The full examples/my_plugin.py demonstrates
this. All tools and metadata must live in one saved Python file. Type annotations
are required for parameters. Async functions are supported by FastMCP.

The build copies that entire source file as plugin_source.py and generates
server.py, requirements.txt and a stdio MCP entry in mcp.json. Keep file creation,
prints, and other execution under `if __name__ == "__main__":` because the server
loads the source module. Tool helpers in the same file work. External local
modules/assets are not automatically bundled; install third-party dependencies
in the server environment. Never put secrets in the source file: it is copied.

Install this package and MCP in the Python environment used by the host's
`python` command. Generated requirements.txt identifies dependencies, but this
unpublished package must first be installed from the provided wheel or source.
A local stdio server requires a host that can launch local processes; a ZIP alone
does not make Python tools run in ChatGPT web/mobile. Host connection, trust,
and installation are separate steps.

## Connect an existing remote MCP server

```python
Plugin_Adon(MyPlugin, name="my-service", url="https://your-real-service.example/mcp")
```

Replace the example with a real endpoint you operate or are authorized to use.
This writes streamable-http configuration; it does not verify the endpoint or
configure its authentication. Skill-only plugins need no running Python server.

## API reference

| Helper | Purpose |
| --- | --- |
| Plugin_info(title, description, author, version, name=..., short_description=...) | Metadata object or class/function decorator |
| Plugin_Adon(plugin, name=..., description=...) | Decorate a zero-argument function returning skill instructions |
| Plugin_Adon(plugin, instructions=...) | Add instructions directly |
| Plugin_Adon(plugin, url=...) | Add a remote HTTPS MCP connection |
| Plugin_Addon | Correctly spelled alias for Plugin_Adon |
| Plugin_tool(plugin, name=..., description=...) | Register a typed function as a tool |
| Plugin_create_file(plugin, output="dist", archive=True) | Build a new folder and ZIP; return folder Path |
| Plugin_build | Alias for Plugin_create_file |

Existing output folders/archives are refused. Choose another output directory
or remove an old build yourself. Names, metadata, duplicate registrations,
URLs, tool parameters and empty plugins are validated. This is not a full
JSON Schema or host compatibility validator. Python decorators execute real
Python, so only run authoring files you trust.

## Verification

```bash
python -m unittest discover -s tests -v
python examples/my_plugin.py
```

Package install, metadata/skill output, archive contents, duplicate-output
protection and validation are tested. Generated MCP source is checked with a
protocol smoke test using a stub if MCP is not available. Live MCP/ChatGPT host
integration is not certified by these tests.

Format reference: https://developers.openai.com/plugins/build/plugins

## License

MIT. See LICENSE.
