mailflat-mcp 0.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.
- mailflat_mcp-0.1.0/.gitignore +6 -0
- mailflat_mcp-0.1.0/LICENSE +21 -0
- mailflat_mcp-0.1.0/PKG-INFO +78 -0
- mailflat_mcp-0.1.0/README.md +55 -0
- mailflat_mcp-0.1.0/pyproject.toml +41 -0
- mailflat_mcp-0.1.0/src/mailflat_mcp/__init__.py +18 -0
- mailflat_mcp-0.1.0/src/mailflat_mcp/__main__.py +9 -0
- mailflat_mcp-0.1.0/src/mailflat_mcp/py.typed +0 -0
- mailflat_mcp-0.1.0/src/mailflat_mcp/server.py +118 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MailFlat
|
|
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.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mailflat-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MailFlat MCP server — disposable inbox tools (create, wait_for_otp, send, ...) for Claude Desktop, Cursor, and any MCP client.
|
|
5
|
+
Project-URL: Homepage, https://mailflat.net
|
|
6
|
+
Project-URL: Documentation, https://mailflat.net/docs
|
|
7
|
+
Project-URL: Source, https://github.com/onderyentar/mailflat
|
|
8
|
+
Author-email: MailFlat <support@mailflat.net>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ai-agents,claude,cursor,disposable-email,email,mcp,model-context-protocol,otp
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: Communications :: Email
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Requires-Dist: mailflat>=0.1.0
|
|
19
|
+
Requires-Dist: mcp>=1.2
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# MailFlat — MCP server
|
|
25
|
+
|
|
26
|
+
Native [Model Context Protocol](https://modelcontextprotocol.io) server for
|
|
27
|
+
[MailFlat](https://mailflat.net). Gives Claude Desktop, Cursor, or any MCP client
|
|
28
|
+
**disposable inbox tooling** — create inboxes, wait for OTP codes, send DKIM-signed mail,
|
|
29
|
+
and clean up. Built on the [`mailflat`](https://pypi.org/project/mailflat/) Python SDK.
|
|
30
|
+
|
|
31
|
+
## Run
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# zero-install, isolated (recommended)
|
|
35
|
+
MAILFLAT_API_KEY=mf_live_… uvx mailflat-mcp
|
|
36
|
+
|
|
37
|
+
# or install it
|
|
38
|
+
pipx install mailflat-mcp
|
|
39
|
+
MAILFLAT_API_KEY=mf_live_… mailflat-mcp
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Claude Desktop / Cursor config
|
|
43
|
+
|
|
44
|
+
Add to `claude_desktop_config.json` (or your client's MCP config):
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"mcpServers": {
|
|
49
|
+
"mailflat": {
|
|
50
|
+
"command": "uvx",
|
|
51
|
+
"args": ["mailflat-mcp"],
|
|
52
|
+
"env": { "MAILFLAT_API_KEY": "mf_live_..." }
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Get your API key from the [MailFlat dashboard](https://mailflat.net) → Agents.
|
|
59
|
+
|
|
60
|
+
## Tools (6)
|
|
61
|
+
|
|
62
|
+
| Tool | What it does |
|
|
63
|
+
|---|---|
|
|
64
|
+
| `create_inbox(prefix?, label?, retention_hours?)` | Open a disposable inbox; `retention_hours` capped by your plan |
|
|
65
|
+
| `list_inboxes()` | All inboxes this key can see |
|
|
66
|
+
| `read_messages(address)` | Read every message in an inbox |
|
|
67
|
+
| `wait_for_otp(address, timeout=30)` | Poll until an OTP arrives, then return it |
|
|
68
|
+
| `send_email(address, to, subject?, body?, html?)` | Send a DKIM-signed mail from the inbox |
|
|
69
|
+
| `delete_inbox(address)` | Delete the inbox and its messages |
|
|
70
|
+
|
|
71
|
+
## Configuration
|
|
72
|
+
|
|
73
|
+
- `MAILFLAT_API_KEY` — your account API key (required).
|
|
74
|
+
- `MAILFLAT_API_URL` — override the API base (default `https://mailflat.net`; for self-hosted / BYOD).
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
|
|
78
|
+
MIT
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# MailFlat — MCP server
|
|
2
|
+
|
|
3
|
+
Native [Model Context Protocol](https://modelcontextprotocol.io) server for
|
|
4
|
+
[MailFlat](https://mailflat.net). Gives Claude Desktop, Cursor, or any MCP client
|
|
5
|
+
**disposable inbox tooling** — create inboxes, wait for OTP codes, send DKIM-signed mail,
|
|
6
|
+
and clean up. Built on the [`mailflat`](https://pypi.org/project/mailflat/) Python SDK.
|
|
7
|
+
|
|
8
|
+
## Run
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
# zero-install, isolated (recommended)
|
|
12
|
+
MAILFLAT_API_KEY=mf_live_… uvx mailflat-mcp
|
|
13
|
+
|
|
14
|
+
# or install it
|
|
15
|
+
pipx install mailflat-mcp
|
|
16
|
+
MAILFLAT_API_KEY=mf_live_… mailflat-mcp
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Claude Desktop / Cursor config
|
|
20
|
+
|
|
21
|
+
Add to `claude_desktop_config.json` (or your client's MCP config):
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"mcpServers": {
|
|
26
|
+
"mailflat": {
|
|
27
|
+
"command": "uvx",
|
|
28
|
+
"args": ["mailflat-mcp"],
|
|
29
|
+
"env": { "MAILFLAT_API_KEY": "mf_live_..." }
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Get your API key from the [MailFlat dashboard](https://mailflat.net) → Agents.
|
|
36
|
+
|
|
37
|
+
## Tools (6)
|
|
38
|
+
|
|
39
|
+
| Tool | What it does |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `create_inbox(prefix?, label?, retention_hours?)` | Open a disposable inbox; `retention_hours` capped by your plan |
|
|
42
|
+
| `list_inboxes()` | All inboxes this key can see |
|
|
43
|
+
| `read_messages(address)` | Read every message in an inbox |
|
|
44
|
+
| `wait_for_otp(address, timeout=30)` | Poll until an OTP arrives, then return it |
|
|
45
|
+
| `send_email(address, to, subject?, body?, html?)` | Send a DKIM-signed mail from the inbox |
|
|
46
|
+
| `delete_inbox(address)` | Delete the inbox and its messages |
|
|
47
|
+
|
|
48
|
+
## Configuration
|
|
49
|
+
|
|
50
|
+
- `MAILFLAT_API_KEY` — your account API key (required).
|
|
51
|
+
- `MAILFLAT_API_URL` — override the API base (default `https://mailflat.net`; for self-hosted / BYOD).
|
|
52
|
+
|
|
53
|
+
## License
|
|
54
|
+
|
|
55
|
+
MIT
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "mailflat-mcp"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "MailFlat MCP server — disposable inbox tools (create, wait_for_otp, send, ...) for Claude Desktop, Cursor, and any MCP client."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "MailFlat", email = "support@mailflat.net" }]
|
|
13
|
+
keywords = ["mcp", "model-context-protocol", "email", "disposable-email", "otp", "ai-agents", "claude", "cursor"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Topic :: Communications :: Email",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"mailflat>=0.1.0",
|
|
23
|
+
"mcp>=1.2",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.scripts]
|
|
27
|
+
mailflat-mcp = "mailflat_mcp.server:main"
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Homepage = "https://mailflat.net"
|
|
31
|
+
Documentation = "https://mailflat.net/docs"
|
|
32
|
+
Source = "https://github.com/onderyentar/mailflat"
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
dev = ["pytest>=7"]
|
|
36
|
+
|
|
37
|
+
[tool.hatch.build.targets.wheel]
|
|
38
|
+
packages = ["src/mailflat_mcp"]
|
|
39
|
+
|
|
40
|
+
[tool.hatch.build.targets.sdist]
|
|
41
|
+
include = ["src/mailflat_mcp", "README.md", "LICENSE"]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""MailFlat MCP server paketi — `mailflat` SDK üstünde MCP tool seti.
|
|
2
|
+
|
|
3
|
+
`uvx mailflat-mcp` ile çalışır; Claude Desktop / Cursor / agent framework'lerine
|
|
4
|
+
disposable inbox araçları açar.
|
|
5
|
+
|
|
6
|
+
Connected to:
|
|
7
|
+
- imports from: mailflat_mcp.server
|
|
8
|
+
- imported by: console script `mailflat-mcp`, MCP client'lar
|
|
9
|
+
|
|
10
|
+
Key exports:
|
|
11
|
+
- `mcp` — FastMCP instance
|
|
12
|
+
- `main()` — stdio server giriş noktası
|
|
13
|
+
"""
|
|
14
|
+
from .server import main, mcp
|
|
15
|
+
|
|
16
|
+
__version__ = "0.1.0"
|
|
17
|
+
|
|
18
|
+
__all__ = ["mcp", "main", "__version__"]
|
|
File without changes
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""MailFlat MCP server — GPT/Claude/Cursor/LangChain için 6 araçlık tool seti.
|
|
2
|
+
|
|
3
|
+
`mailflat` Python SDK'sının üstüne ince bir MCP kabuğu; HTTP/iş mantığı SDK'da (DRY).
|
|
4
|
+
Auth: `MAILFLAT_API_KEY` env (dashboard'dan alınan `mf_live_...`).
|
|
5
|
+
|
|
6
|
+
Çalıştırma:
|
|
7
|
+
uvx mailflat-mcp # PyPI'den, izolasyonlu
|
|
8
|
+
MAILFLAT_API_KEY=mf_live_... uvx mailflat-mcp
|
|
9
|
+
|
|
10
|
+
Connected to:
|
|
11
|
+
- depends on: mailflat (SDK), mcp (FastMCP)
|
|
12
|
+
- used by: Claude Desktop / Cursor / herhangi bir MCP client
|
|
13
|
+
|
|
14
|
+
Key exports (MCP tools):
|
|
15
|
+
- create_inbox(prefix?, label?, retention_hours?)
|
|
16
|
+
- list_inboxes()
|
|
17
|
+
- read_messages(address)
|
|
18
|
+
- wait_for_otp(address, timeout=30)
|
|
19
|
+
- send_email(address, to, subject?, body?, html?)
|
|
20
|
+
- delete_inbox(address)
|
|
21
|
+
"""
|
|
22
|
+
import os
|
|
23
|
+
|
|
24
|
+
from mcp.server.fastmcp import FastMCP
|
|
25
|
+
|
|
26
|
+
from mailflat import EncryptedInboxError, MailFlat, MailFlatError, OTPTimeoutError
|
|
27
|
+
|
|
28
|
+
mcp = FastMCP("mailflat")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _client() -> MailFlat:
|
|
32
|
+
"""SDK client (MAILFLAT_API_KEY ile). Testlerde monkeypatch edilir."""
|
|
33
|
+
return MailFlat(
|
|
34
|
+
api_key=os.environ.get("MAILFLAT_API_KEY") or "",
|
|
35
|
+
base_url=os.environ.get("MAILFLAT_API_URL", "https://mailflat.net"),
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@mcp.tool()
|
|
40
|
+
def create_inbox(prefix: str = "", label: str = "", retention_hours: int = 0) -> dict:
|
|
41
|
+
"""Create a real disposable email inbox. Returns the inbox address.
|
|
42
|
+
`retention_hours` is optional (0 = your plan's max); requests above your plan are capped."""
|
|
43
|
+
try:
|
|
44
|
+
with _client() as c:
|
|
45
|
+
inbox = c.create(
|
|
46
|
+
prefix=prefix or None,
|
|
47
|
+
label=label or None,
|
|
48
|
+
retention_hours=retention_hours if retention_hours and retention_hours > 0 else None,
|
|
49
|
+
)
|
|
50
|
+
return inbox.raw
|
|
51
|
+
except MailFlatError as e:
|
|
52
|
+
return {"error": str(e)}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@mcp.tool()
|
|
56
|
+
def list_inboxes() -> dict:
|
|
57
|
+
"""List all inboxes available to this API key."""
|
|
58
|
+
try:
|
|
59
|
+
with _client() as c:
|
|
60
|
+
return {"ok": True, "inboxes": [i.raw for i in c.list()]}
|
|
61
|
+
except MailFlatError as e:
|
|
62
|
+
return {"error": str(e)}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@mcp.tool()
|
|
66
|
+
def read_messages(address: str) -> dict:
|
|
67
|
+
"""Read all messages in the given inbox address."""
|
|
68
|
+
try:
|
|
69
|
+
with _client() as c:
|
|
70
|
+
return {"ok": True, "emails": [m.raw for m in c.inbox(address).messages()]}
|
|
71
|
+
except MailFlatError as e:
|
|
72
|
+
return {"error": str(e)}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@mcp.tool()
|
|
76
|
+
def wait_for_otp(address: str, timeout: int = 30) -> dict:
|
|
77
|
+
"""Poll the inbox until an OTP code arrives (or timeout). Returns {otp_code, email}."""
|
|
78
|
+
try:
|
|
79
|
+
with _client() as c:
|
|
80
|
+
inbox = c.inbox(address)
|
|
81
|
+
otp = inbox.wait_for_otp(timeout=timeout)
|
|
82
|
+
latest = inbox.latest()
|
|
83
|
+
return {"otp_code": otp, "email": latest.raw if latest else None}
|
|
84
|
+
except OTPTimeoutError:
|
|
85
|
+
return {"otp_code": None, "error": "timeout"}
|
|
86
|
+
except EncryptedInboxError as e:
|
|
87
|
+
return {"otp_code": None, "encrypted": True, "error": str(e)}
|
|
88
|
+
except MailFlatError as e:
|
|
89
|
+
return {"otp_code": None, "error": str(e)}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@mcp.tool()
|
|
93
|
+
def send_email(address: str, to: str, subject: str = "", body: str = "", html: str = "") -> dict:
|
|
94
|
+
"""Send an email FROM the given inbox address (DKIM-signed via MailFlat's MTA).
|
|
95
|
+
Use for replies or outbound automation. `html` is optional."""
|
|
96
|
+
try:
|
|
97
|
+
with _client() as c:
|
|
98
|
+
return c.inbox(address).send(to, subject=subject, body=body, html=html or None)
|
|
99
|
+
except MailFlatError as e:
|
|
100
|
+
return {"error": str(e)}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@mcp.tool()
|
|
104
|
+
def delete_inbox(address: str) -> dict:
|
|
105
|
+
"""Delete an inbox and all its messages by address. Irreversible."""
|
|
106
|
+
try:
|
|
107
|
+
with _client() as c:
|
|
108
|
+
return c.inbox(address).delete()
|
|
109
|
+
except MailFlatError as e:
|
|
110
|
+
return {"error": str(e)}
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def main():
|
|
114
|
+
mcp.run() # stdio transport (MCP client'lar buna bağlanır)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
if __name__ == "__main__":
|
|
118
|
+
main()
|