@mailkite/mcp 0.5.0 → 0.6.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mailkite/mcp",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Model Context Protocol server for MailKite — exposes the MailKite API to LLM agents as tools. A thin layer over the MailKite Node SDK and the shared sdks/spec contract.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -41,6 +41,6 @@
41
41
  "dependencies": {
42
42
  "@modelcontextprotocol/sdk": "^1.0.0",
43
43
  "ajv": "^8.17.1",
44
- "mailkite": "^0.5.0"
44
+ "mailkite": "^0.6.0"
45
45
  }
46
46
  }
package/server.mjs CHANGED
@@ -202,6 +202,25 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
202
202
  };
203
203
  }
204
204
 
205
+ // uploadAttachment is the one method whose input isn't a plain JSON body: `path` is read
206
+ // off the local disk and streamed as a raw binary upload. The generic resolveCall →
207
+ // mk.request() path only does JSON, so delegate to the SDK method, which picks the
208
+ // transport (path/bytes → binary, url/content → JSON). Validate against the same schema.
209
+ if (tool._method.name === "uploadAttachment") {
210
+ try {
211
+ const input = req.params.arguments || {};
212
+ const validate = validators["upload-attachment-request"];
213
+ if (validate && !validate(input)) {
214
+ return { isError: true, content: [{ type: "text", text: `Invalid input for upload-attachment-request: ${ajv.errorsText(validate.errors)}` }] };
215
+ }
216
+ const result = await mk.uploadAttachment(input);
217
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
218
+ } catch (err) {
219
+ const text = err instanceof MailKiteError ? `MailKite API error ${err.status}: ${err.message}` : `Error: ${err.message}`;
220
+ return { isError: true, content: [{ type: "text", text }] };
221
+ }
222
+ }
223
+
205
224
  try {
206
225
  const { method, urlPath, body } = resolveCall(tool._method, req.params.arguments);
207
226
  const result = await mk.request(method, urlPath, body);
package/spec/api.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mailkite",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Canonical interface contract for every MailKite SDK. One low-level request() plus one function per endpoint. All languages expose the same shape; only naming adapts to each language's convention (e.g. Go exports PascalCase).",
5
5
  "baseUrl": "https://api.mailkite.dev",
6
6
  "auth": {
@@ -27,7 +27,7 @@
27
27
  },
28
28
  {
29
29
  "name": "uploadAttachment",
30
- "summary": "Upload a file to MailKite storage and get back a secure, time-limited URL. Reference the returned `url` as an attachment in send() (`{ filename, url }`) or link it inline in your HTML — instead of base64-inlining large files on every send. `content` is the file bytes, base64-encoded; `retentionDays` (7/30/90/365, default 7) sets how long the file and URL live.",
30
+ "summary": "Upload a file to MailKite storage and get back a secure, time-limited URL. Reference the returned `url` as an attachment in send() (`{ filename, url }`) or link it inline in your HTML — instead of base64-inlining large files on every send. Give the file ONE of four ways: a local `path` (read and streamed as raw bytes by the CLI/SDK/local MCP), a remote `url` (MailKite fetches and re-hosts it), base64 `content`, or — over raw HTTP — the file bytes as the POST body with `?filename=`. `retentionDays` (7/30/90/365, default 7) sets how long the file and URL live.",
31
31
  "http": {
32
32
  "method": "POST",
33
33
  "path": "/v1/attachments"
package/spec/cases.json CHANGED
@@ -72,6 +72,44 @@
72
72
  "expiresAt": "2026-07-02T00:00:00.000Z"
73
73
  }
74
74
  },
75
+ {
76
+ "name": "upload_attachment_url",
77
+ "method": "uploadAttachment",
78
+ "args": {
79
+ "url": "https://files.example.com/po.pdf",
80
+ "filename": "po.pdf",
81
+ "contentType": "application/pdf"
82
+ },
83
+ "request": {
84
+ "method": "POST",
85
+ "path": "/v1/attachments",
86
+ "bodySchema": "upload-attachment-request",
87
+ "body": {
88
+ "url": "https://files.example.com/po.pdf",
89
+ "filename": "po.pdf",
90
+ "contentType": "application/pdf"
91
+ }
92
+ },
93
+ "response": {
94
+ "status": 201,
95
+ "body": {
96
+ "id": "7d/usr_demo/0a1b2c3d/po.pdf",
97
+ "url": "https://api.mailkite.dev/up/7d/usr_demo/0a1b2c3d/po.pdf?exp=1799999999&sig=deadbeef",
98
+ "filename": "po.pdf",
99
+ "contentType": "application/pdf",
100
+ "size": 9,
101
+ "expiresAt": "2026-07-02T00:00:00.000Z"
102
+ }
103
+ },
104
+ "result": {
105
+ "id": "7d/usr_demo/0a1b2c3d/po.pdf",
106
+ "url": "https://api.mailkite.dev/up/7d/usr_demo/0a1b2c3d/po.pdf?exp=1799999999&sig=deadbeef",
107
+ "filename": "po.pdf",
108
+ "contentType": "application/pdf",
109
+ "size": 9,
110
+ "expiresAt": "2026-07-02T00:00:00.000Z"
111
+ }
112
+ },
75
113
  {
76
114
  "name": "send_full",
77
115
  "method": "send",
@@ -2,13 +2,15 @@
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "upload-attachment-request",
4
4
  "title": "Upload attachment request body",
5
+ "description": "Provide the file ONE of four ways: `path` (a local file the SDK/CLI/MCP reads and streams as raw bytes), `url` (a remote file MailKite fetches and re-hosts), `content` (base64-encoded bytes), or — at the HTTP layer — the raw file bytes as the POST body with `?filename=`. `path`/raw-bytes go up as a real binary upload (like an S3/R2 PUT); `url`/`content` go up as JSON.",
5
6
  "type": "object",
6
- "required": ["filename", "content"],
7
7
  "additionalProperties": false,
8
8
  "properties": {
9
- "filename": { "type": "string", "description": "The file's name, e.g. \"invoice.pdf\". Shown to recipients on download." },
10
- "content": { "type": "string", "description": "The file bytes, base64-encoded." },
11
- "contentType": { "type": "string", "description": "MIME type, e.g. \"application/pdf\". Defaults to application/octet-stream." },
9
+ "filename": { "type": "string", "description": "The file's name, e.g. \"invoice.pdf\". Shown to recipients on download. Optional when it can be derived from `path` or `url`." },
10
+ "path": { "type": "string", "description": "Local filesystem path to the file. Read client-side by the CLI, SDKs, and the local MCP server, then uploaded as raw bytes. Not available on the hosted MCP (no filesystem)." },
11
+ "url": { "type": "string", "description": "A remote http(s) URL. MailKite fetches it and re-hosts the bytes under your account. Max 25 MB." },
12
+ "content": { "type": "string", "description": "The file bytes, base64-encoded. The lowest-common-denominator fallback when you can't send a path, URL, or raw bytes." },
13
+ "contentType": { "type": "string", "description": "MIME type, e.g. \"application/pdf\". Defaults to application/octet-stream (or is inferred from the file extension / fetched response)." },
12
14
  "retentionDays": {
13
15
  "type": "integer",
14
16
  "enum": [7, 30, 90, 365],