mello-sdk 1.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mello_sdk-1.1.0/LICENSE +21 -0
- mello_sdk-1.1.0/MANIFEST.in +6 -0
- mello_sdk-1.1.0/PKG-INFO +405 -0
- mello_sdk-1.1.0/README.md +368 -0
- mello_sdk-1.1.0/docs/mello.v1.yaml +1794 -0
- mello_sdk-1.1.0/mello/__init__.py +71 -0
- mello_sdk-1.1.0/mello/cli.py +776 -0
- mello_sdk-1.1.0/mello/client.py +846 -0
- mello_sdk-1.1.0/mello/exceptions.py +85 -0
- mello_sdk-1.1.0/mello/mcp_server.py +440 -0
- mello_sdk-1.1.0/mello/models.py +698 -0
- mello_sdk-1.1.0/mello/py.typed +1 -0
- mello_sdk-1.1.0/mello/serialize.py +25 -0
- mello_sdk-1.1.0/mello_sdk.egg-info/PKG-INFO +405 -0
- mello_sdk-1.1.0/mello_sdk.egg-info/SOURCES.txt +23 -0
- mello_sdk-1.1.0/mello_sdk.egg-info/dependency_links.txt +1 -0
- mello_sdk-1.1.0/mello_sdk.egg-info/entry_points.txt +3 -0
- mello_sdk-1.1.0/mello_sdk.egg-info/requires.txt +14 -0
- mello_sdk-1.1.0/mello_sdk.egg-info/top_level.txt +1 -0
- mello_sdk-1.1.0/pyproject.toml +78 -0
- mello_sdk-1.1.0/setup.cfg +4 -0
- mello_sdk-1.1.0/tests/test_cli.py +254 -0
- mello_sdk-1.1.0/tests/test_client.py +1173 -0
- mello_sdk-1.1.0/tests/test_integration.py +134 -0
- mello_sdk-1.1.0/tests/test_mcp_server.py +404 -0
mello_sdk-1.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mello Integration Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
mello_sdk-1.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mello-sdk
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: Typed Python SDK for the Mello Public REST API
|
|
5
|
+
Author: Mello Integration Team
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://mello.mezon.vn
|
|
8
|
+
Project-URL: Documentation, https://mello.mezon.vn/api/v1
|
|
9
|
+
Keywords: mello,sdk,api,kanban,tickets
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: requests>=2.25.0
|
|
25
|
+
Provides-Extra: mcp
|
|
26
|
+
Requires-Dist: mcp>=1.0.0; extra == "mcp"
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=6.0.0; extra == "dev"
|
|
29
|
+
Requires-Dist: responses>=0.13.0; extra == "dev"
|
|
30
|
+
Requires-Dist: black>=22.0.0; extra == "dev"
|
|
31
|
+
Requires-Dist: flake8>=3.9.0; extra == "dev"
|
|
32
|
+
Requires-Dist: mypy>=0.900; extra == "dev"
|
|
33
|
+
Requires-Dist: types-requests; extra == "dev"
|
|
34
|
+
Requires-Dist: build>=1.2.0; extra == "dev"
|
|
35
|
+
Requires-Dist: twine>=5.0.0; extra == "dev"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# Mello Python SDK
|
|
39
|
+
|
|
40
|
+
Typed Python client for the [Mello Public REST API](https://mello.mezon.vn/api/v1).
|
|
41
|
+
|
|
42
|
+
The SDK wraps Mello workspaces, boards, columns, tickets, comments, history, and
|
|
43
|
+
search endpoints with dataclass models and typed exceptions.
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
uv add mello-sdk
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Install from source during development:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git clone <repository-url>
|
|
55
|
+
cd mello-python-sdk
|
|
56
|
+
uv sync --extra dev
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If you are not using `uv`, install with `pip install mello-sdk`.
|
|
60
|
+
|
|
61
|
+
## Quick Start
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from mello import MelloClient
|
|
65
|
+
|
|
66
|
+
client = MelloClient(token="YOUR_PERSONAL_API_TOKEN")
|
|
67
|
+
|
|
68
|
+
user = client.get_current_user()
|
|
69
|
+
print(f"Logged in as {user.name} ({user.email})")
|
|
70
|
+
|
|
71
|
+
for workspace in client.list_workspaces():
|
|
72
|
+
print(f"Workspace: {workspace.name}")
|
|
73
|
+
|
|
74
|
+
for board in client.list_workspace_boards(workspace.id):
|
|
75
|
+
print(f" Board: {board.name} ({board.code})")
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## CLI
|
|
79
|
+
|
|
80
|
+
`mello-cli` is a JSON-first command-line interface for scripts and AI agents. It
|
|
81
|
+
uses `MELLO_API_KEY` by default and emits exactly one JSON object on stdout.
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
export MELLO_API_KEY="mello_pat_..."
|
|
85
|
+
|
|
86
|
+
mello-cli me get
|
|
87
|
+
mello-cli workspace list
|
|
88
|
+
mello-cli ticket search --workspace-id "workspace-uuid" --query "login crash"
|
|
89
|
+
mello-cli ticket update --ticket-id "ticket-uuid" --set title="Fix login on iOS"
|
|
90
|
+
mello-cli ticket update --ticket-id "ticket-uuid" --clear pic_user_id
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Omitted update fields stay unchanged. `--clear field` (or `--set field=null`)
|
|
94
|
+
clears nullable fields such as `pic_user_id`, `supervisor_id`, and dates.
|
|
95
|
+
|
|
96
|
+
Destructive and high-impact operations require explicit confirmation. After
|
|
97
|
+
confirming the target with the user, pass `--yes`:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
mello-cli --yes ticket delete --ticket-id "ticket-uuid"
|
|
101
|
+
mello-cli --yes github replace-board-repos \
|
|
102
|
+
--workspace-id "workspace-uuid" --board-id "board-uuid" \
|
|
103
|
+
--repositories '[{"installation_id": 1, "github_repo_id": 2}]'
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Use `--token`, `--base-url`, and `--timeout` to override `MELLO_API_KEY`,
|
|
107
|
+
`MELLO_BASE_URL`, and `MELLO_TIMEOUT`. Run `mello-cli --help` for the complete
|
|
108
|
+
resource command surface.
|
|
109
|
+
|
|
110
|
+
### Install the CLI globally
|
|
111
|
+
|
|
112
|
+
Install `mello-cli` (and `mello-mcp-server`) globally as an isolated tool with
|
|
113
|
+
[uv](https://docs.astral.sh/uv/):
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# From PyPI
|
|
117
|
+
uv tool install mello-sdk
|
|
118
|
+
|
|
119
|
+
# Or directly from this repository (local development)
|
|
120
|
+
uv tool install --from . mello-sdk
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The executables land in `~/.local/bin` (make sure it is on your `PATH`).
|
|
124
|
+
|
|
125
|
+
**Important:** when installed from a local source directory, the global tool
|
|
126
|
+
does **not** track your changes. After updating the CLI code in this repo,
|
|
127
|
+
reinstall to refresh the global executables:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
uv tool install --from . mello-sdk --force
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Claude Code Skill
|
|
134
|
+
|
|
135
|
+
The repository ships a [Claude Code](https://claude.com/claude-code) skill at
|
|
136
|
+
[`skills/mello/`](skills/mello/) that teaches agents to operate Mello through
|
|
137
|
+
`mello-cli` (JSON output, safe confirmation rules, update semantics).
|
|
138
|
+
|
|
139
|
+
To use it, install the skill into your Claude Code configuration:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Personal (available in every project)
|
|
143
|
+
cp -r skills/mello ~/.claude/skills/mello
|
|
144
|
+
|
|
145
|
+
# Or project-local (only inside a specific project)
|
|
146
|
+
cp -r skills/mello /path/to/your-project/.claude/skills/mello
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Then make sure `mello-cli` is installed globally (see above) and
|
|
150
|
+
`MELLO_API_KEY` is set in your shell environment. Claude Code will trigger the
|
|
151
|
+
`mello` skill automatically for Mello-related requests.
|
|
152
|
+
|
|
153
|
+
## MCP Server
|
|
154
|
+
|
|
155
|
+
The package can also run as a Model Context Protocol server for AI assistants
|
|
156
|
+
that support MCP tools.
|
|
157
|
+
|
|
158
|
+
Install the MCP extra:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
uv add "mello-sdk[mcp]"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
For local development from this repository:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
uv sync --extra mcp --extra dev
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Configure the server with environment variables:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
export MELLO_API_KEY="mello_pat_..."
|
|
174
|
+
export MELLO_BASE_URL="https://mello.mezon.vn/api/v1" # optional
|
|
175
|
+
export MELLO_TIMEOUT="30" # optional seconds
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Run it with the console script:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
uv run mello-mcp-server
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Or run the module directly:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
uv run python -m mello.mcp_server
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
The MCP server exposes the SDK's full read/write surface: workspaces, boards,
|
|
191
|
+
columns, tickets, comments, history, and search. Update tools accept an
|
|
192
|
+
`updates` object so omitted fields are left unchanged while explicit `null`
|
|
193
|
+
values are sent to Mello for nullable fields.
|
|
194
|
+
|
|
195
|
+
### Transport
|
|
196
|
+
|
|
197
|
+
`main()` selects the transport from the `MCP_TRANSPORT` environment variable.
|
|
198
|
+
The default is `stdio` for local assistant integrations. Set it to
|
|
199
|
+
`streamable-http` (or `sse`) to expose the server over HTTP. In HTTP mode the
|
|
200
|
+
bind address is controlled by `MCP_HOST` (default `0.0.0.0`) and `MCP_PORT`
|
|
201
|
+
(default `8000`).
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
MCP_TRANSPORT=streamable-http MCP_PORT=8000 uv run mello-mcp-server
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Docker
|
|
208
|
+
|
|
209
|
+
The repository ships a `Dockerfile` and `docker-compose.yml` that run the
|
|
210
|
+
server with the `streamable-http` transport on port `8000`.
|
|
211
|
+
|
|
212
|
+
Build and run with Docker:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
docker build -t mello-mcp-server .
|
|
216
|
+
docker run --rm -p 8000:8000 -e MELLO_API_KEY="mello_pat_..." mello-mcp-server
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Or use Docker Compose (reads `MELLO_API_KEY` from your environment or `.env`):
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
export MELLO_API_KEY="mello_pat_..."
|
|
223
|
+
docker compose up --build
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
The HTTP endpoint is served at `http://localhost:8000/mcp`. Point an MCP client
|
|
227
|
+
that supports the streamable-http transport at that URL.
|
|
228
|
+
|
|
229
|
+
## Usage
|
|
230
|
+
|
|
231
|
+
### Boards
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
board = client.create_board(
|
|
235
|
+
workspace_id="workspace-uuid",
|
|
236
|
+
name="Q3 Planning",
|
|
237
|
+
code="Q3PL",
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
board_detail = client.get_board(board.id)
|
|
241
|
+
|
|
242
|
+
client.update_board(
|
|
243
|
+
board.id,
|
|
244
|
+
name="Q3 Project Planning",
|
|
245
|
+
background_color="#3b5998",
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
client.delete_board(board.id)
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Columns
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
column = client.create_column(
|
|
255
|
+
board_id="board-uuid",
|
|
256
|
+
name="In Review",
|
|
257
|
+
position=2,
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
client.update_column(column.id, name="Code Review", color="#ffcc00")
|
|
261
|
+
|
|
262
|
+
client.reorder_columns(
|
|
263
|
+
board_id="board-uuid",
|
|
264
|
+
column_ids=["column-uuid-1", "column-uuid-2", "column-uuid-3"],
|
|
265
|
+
)
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Tickets
|
|
269
|
+
|
|
270
|
+
```python
|
|
271
|
+
ticket = client.create_ticket(
|
|
272
|
+
column_id="column-uuid",
|
|
273
|
+
title="Fix login crash",
|
|
274
|
+
description="Steps to reproduce...",
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
ticket_detail = client.get_ticket(ticket.id)
|
|
278
|
+
print(len(ticket_detail.comments))
|
|
279
|
+
|
|
280
|
+
client.update_ticket(
|
|
281
|
+
ticket.id,
|
|
282
|
+
title="Fix login crash on iOS",
|
|
283
|
+
pic_user_id="user-uuid",
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
# Nullable fields can be cleared explicitly with None.
|
|
287
|
+
client.update_ticket(
|
|
288
|
+
ticket.id,
|
|
289
|
+
pic_user_id=None,
|
|
290
|
+
supervisor_id=None,
|
|
291
|
+
start_date=None,
|
|
292
|
+
end_date=None,
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
client.move_ticket(ticket.id, column_id="other-column-uuid", position=0)
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Comments, History, And Search
|
|
299
|
+
|
|
300
|
+
```python
|
|
301
|
+
comment = client.create_comment(
|
|
302
|
+
ticket_id="ticket-uuid",
|
|
303
|
+
body="Investigating this issue now.",
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
comments = client.list_comments(ticket_id="ticket-uuid")
|
|
307
|
+
history = client.list_history(ticket_id="ticket-uuid")
|
|
308
|
+
results = client.search_tickets(workspace_id="workspace-uuid", q="login crash")
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Error Handling
|
|
312
|
+
|
|
313
|
+
The SDK raises typed exceptions derived from `MelloAPIException` for API errors:
|
|
314
|
+
|
|
315
|
+
```python
|
|
316
|
+
from mello import (
|
|
317
|
+
MelloAPIException,
|
|
318
|
+
MelloClient,
|
|
319
|
+
ForbiddenException,
|
|
320
|
+
NotFoundException,
|
|
321
|
+
RateLimitedException,
|
|
322
|
+
UnauthorizedException,
|
|
323
|
+
ValidationErrorException,
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
client = MelloClient(token="YOUR_PERSONAL_API_TOKEN")
|
|
327
|
+
|
|
328
|
+
try:
|
|
329
|
+
client.get_current_user()
|
|
330
|
+
except UnauthorizedException:
|
|
331
|
+
print("Invalid or expired API token.")
|
|
332
|
+
except ForbiddenException:
|
|
333
|
+
print("The token cannot access this resource.")
|
|
334
|
+
except NotFoundException:
|
|
335
|
+
print("Resource not found.")
|
|
336
|
+
except ValidationErrorException as exc:
|
|
337
|
+
print(f"Validation failed: {exc.fields}")
|
|
338
|
+
except RateLimitedException:
|
|
339
|
+
print("Rate limit exceeded. Try again later.")
|
|
340
|
+
except MelloAPIException as exc:
|
|
341
|
+
print(f"Mello API error {exc.status_code}: {exc.error_code}")
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
## Development
|
|
345
|
+
|
|
346
|
+
Install development dependencies:
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
python3 -m venv .venv
|
|
350
|
+
source .venv/bin/activate
|
|
351
|
+
pip install -e ".[dev]"
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Run unit tests:
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
pytest
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Run live integration tests. These tests create and delete data in your Mello
|
|
361
|
+
workspace, so use a dedicated test token when possible:
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
export MELLO_API_KEY="mello_pat_..."
|
|
365
|
+
pytest -m integration
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
Run quality checks:
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
black --check mello tests
|
|
372
|
+
flake8 mello tests
|
|
373
|
+
mypy mello tests
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## Build And Publish
|
|
377
|
+
|
|
378
|
+
The package uses `pyproject.toml` with `setuptools`. Build artifacts locally:
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
python -m build
|
|
382
|
+
python -m twine check dist/*
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Recommended release flow:
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
rm -rf dist/ build/ *.egg-info
|
|
389
|
+
python -m build
|
|
390
|
+
python -m twine check dist/*
|
|
391
|
+
python -m twine upload --repository testpypi dist/*
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
After validating installation from TestPyPI, publish to PyPI:
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
python -m twine upload dist/*
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Use PyPI API tokens instead of passwords, and avoid committing `.env`,
|
|
401
|
+
`.pypirc`, `dist/`, or build artifacts.
|
|
402
|
+
|
|
403
|
+
## License
|
|
404
|
+
|
|
405
|
+
MIT. See [LICENSE](LICENSE).
|