shipmail-mcp 0.6.5 → 0.7.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/dist/index.js +144 -123
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/server.json +2 -2
- package/smithery.yaml +1 -1
package/dist/index.js
CHANGED
|
@@ -4,6 +4,106 @@
|
|
|
4
4
|
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
5
5
|
import { ShipMailClient as ShipMailClient2 } from "shipmail";
|
|
6
6
|
|
|
7
|
+
// src/config.ts
|
|
8
|
+
import { readFileSync } from "fs";
|
|
9
|
+
import { env } from "process";
|
|
10
|
+
var DEFAULT_BASE_URL = "https://shipmail.to/api/v1";
|
|
11
|
+
var HELP_TEXT = `shipmail-mcp
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
shipmail-mcp
|
|
15
|
+
|
|
16
|
+
Environment:
|
|
17
|
+
SHIPMAIL_API_KEY Required ShipMail API key (or use SHIPMAIL_API_KEY_FILE).
|
|
18
|
+
SHIPMAIL_API_KEY_FILE Optional path to a file containing the API key. Takes precedence over
|
|
19
|
+
SHIPMAIL_API_KEY when set; reduces env-trace leak surface for hosts that
|
|
20
|
+
log environment variables.
|
|
21
|
+
SHIPMAIL_BASE_URL Optional API base URL. Must be https. Defaults to ${DEFAULT_BASE_URL}.
|
|
22
|
+
SHIPMAIL_ORGANIZATION_ID
|
|
23
|
+
Optional delegated child organization ID for infrastructure tools.
|
|
24
|
+
SHIPMAIL_ALLOW_INSECURE_BASE_URL=1
|
|
25
|
+
Permit non-https or non-shipmail.to base URL (development only).
|
|
26
|
+
|
|
27
|
+
ShipMail discovers tools from the API key's live permissions at startup. Change scopes, resources,
|
|
28
|
+
recipient rules, and send budgets in ShipMail Settings.`;
|
|
29
|
+
var API_KEY_HELP = "SHIPMAIL_API_KEY (or SHIPMAIL_API_KEY_FILE) is required. Create an API key in ShipMail, then run `SHIPMAIL_API_KEY=sm_live_... shipmail-mcp`.";
|
|
30
|
+
function readApiKey() {
|
|
31
|
+
const filePath = env["SHIPMAIL_API_KEY_FILE"];
|
|
32
|
+
if (filePath !== void 0 && filePath.length > 0) {
|
|
33
|
+
let raw;
|
|
34
|
+
try {
|
|
35
|
+
raw = readFileSync(filePath, "utf8");
|
|
36
|
+
} catch (error) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`Failed to read SHIPMAIL_API_KEY_FILE at ${filePath}: ${error instanceof Error ? error.message : String(error)}`,
|
|
39
|
+
{ cause: error }
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
const trimmed = raw.trim();
|
|
43
|
+
if (trimmed.length === 0) {
|
|
44
|
+
throw new Error(`SHIPMAIL_API_KEY_FILE at ${filePath} is empty.`);
|
|
45
|
+
}
|
|
46
|
+
return trimmed;
|
|
47
|
+
}
|
|
48
|
+
const direct = env["SHIPMAIL_API_KEY"];
|
|
49
|
+
if (!direct) throw new Error(API_KEY_HELP);
|
|
50
|
+
return direct;
|
|
51
|
+
}
|
|
52
|
+
var ALLOWED_BASE_URL_HOSTS = ["shipmail.to", "api.shipmail.to"];
|
|
53
|
+
function validateBaseUrl(rawValue, allowInsecure) {
|
|
54
|
+
let parsed;
|
|
55
|
+
try {
|
|
56
|
+
parsed = new URL(rawValue);
|
|
57
|
+
} catch {
|
|
58
|
+
throw new Error(`SHIPMAIL_BASE_URL is not a valid URL: ${rawValue}`);
|
|
59
|
+
}
|
|
60
|
+
if (allowInsecure) return parsed.toString().replace(/\/+$/, "");
|
|
61
|
+
if (parsed.protocol !== "https:") {
|
|
62
|
+
throw new Error(
|
|
63
|
+
"SHIPMAIL_BASE_URL must use https. Set SHIPMAIL_ALLOW_INSECURE_BASE_URL=1 for development."
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
const host = parsed.hostname.toLowerCase();
|
|
67
|
+
const isAllowedHost = ALLOWED_BASE_URL_HOSTS.some(
|
|
68
|
+
(allowed) => host === allowed || host.endsWith(`.${allowed}`)
|
|
69
|
+
);
|
|
70
|
+
if (!isAllowedHost) {
|
|
71
|
+
throw new Error(
|
|
72
|
+
`SHIPMAIL_BASE_URL host "${host}" is not allowed. Set SHIPMAIL_ALLOW_INSECURE_BASE_URL=1 for development.`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
return parsed.toString().replace(/\/+$/, "");
|
|
76
|
+
}
|
|
77
|
+
function readConfig(argv = process.argv.slice(2)) {
|
|
78
|
+
if (argv.includes("--tools")) {
|
|
79
|
+
throw new Error(
|
|
80
|
+
"--tools was removed. ShipMail MCP tools now follow the API key permissions configured in ShipMail Settings."
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
const unknownArgs = argv.filter((arg) => arg !== "--help" && arg !== "-h");
|
|
84
|
+
if (unknownArgs.length > 0) {
|
|
85
|
+
throw new Error(`Unknown argument: ${unknownArgs[0]}`);
|
|
86
|
+
}
|
|
87
|
+
const rawBaseUrl = env["SHIPMAIL_BASE_URL"];
|
|
88
|
+
const allowInsecure = env["SHIPMAIL_ALLOW_INSECURE_BASE_URL"] === "1";
|
|
89
|
+
const baseUrl = rawBaseUrl !== void 0 && rawBaseUrl.length > 0 ? validateBaseUrl(rawBaseUrl, allowInsecure) : void 0;
|
|
90
|
+
return {
|
|
91
|
+
apiKey: readApiKey(),
|
|
92
|
+
baseUrl,
|
|
93
|
+
organizationId: env["SHIPMAIL_ORGANIZATION_ID"] || void 0
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// src/server.ts
|
|
98
|
+
import { McpServer as McpServer5 } from "@modelcontextprotocol/server";
|
|
99
|
+
import { ShipMailClient } from "shipmail";
|
|
100
|
+
|
|
101
|
+
// src/cross-organization-tools.ts
|
|
102
|
+
import { performance } from "perf_hooks";
|
|
103
|
+
import "@modelcontextprotocol/server";
|
|
104
|
+
import { ShipMailError as ShipMailError2 } from "shipmail";
|
|
105
|
+
import { z as z2 } from "zod/v4";
|
|
106
|
+
|
|
7
107
|
// src/capabilities.ts
|
|
8
108
|
import { API_KEY_SCOPES, apiKeyScopesGrant } from "shipmail/api-key-scopes";
|
|
9
109
|
var MCP_CAPABILITY_VERSION = "1.0.0";
|
|
@@ -499,106 +599,6 @@ function getMcpCapability(toolName) {
|
|
|
499
599
|
return MCP_CAPABILITIES.find((capability) => capability.toolName === toolName);
|
|
500
600
|
}
|
|
501
601
|
|
|
502
|
-
// src/config.ts
|
|
503
|
-
import { readFileSync } from "fs";
|
|
504
|
-
import { env } from "process";
|
|
505
|
-
var DEFAULT_BASE_URL = "https://shipmail.to/api/v1";
|
|
506
|
-
var HELP_TEXT = `shipmail-mcp
|
|
507
|
-
|
|
508
|
-
Usage:
|
|
509
|
-
shipmail-mcp
|
|
510
|
-
|
|
511
|
-
Environment:
|
|
512
|
-
SHIPMAIL_API_KEY Required ShipMail API key (or use SHIPMAIL_API_KEY_FILE).
|
|
513
|
-
SHIPMAIL_API_KEY_FILE Optional path to a file containing the API key. Takes precedence over
|
|
514
|
-
SHIPMAIL_API_KEY when set; reduces env-trace leak surface for hosts that
|
|
515
|
-
log environment variables.
|
|
516
|
-
SHIPMAIL_BASE_URL Optional API base URL. Must be https. Defaults to ${DEFAULT_BASE_URL}.
|
|
517
|
-
SHIPMAIL_ORGANIZATION_ID
|
|
518
|
-
Optional delegated child organization ID for infrastructure tools.
|
|
519
|
-
SHIPMAIL_ALLOW_INSECURE_BASE_URL=1
|
|
520
|
-
Permit non-https or non-shipmail.to base URL (development only).
|
|
521
|
-
|
|
522
|
-
ShipMail discovers tools from the API key's live permissions at startup. Change scopes, resources,
|
|
523
|
-
recipient rules, and send budgets in ShipMail Settings.`;
|
|
524
|
-
var API_KEY_HELP = "SHIPMAIL_API_KEY (or SHIPMAIL_API_KEY_FILE) is required. Create an API key in ShipMail, then run `SHIPMAIL_API_KEY=sm_live_... shipmail-mcp`.";
|
|
525
|
-
function readApiKey() {
|
|
526
|
-
const filePath = env["SHIPMAIL_API_KEY_FILE"];
|
|
527
|
-
if (filePath !== void 0 && filePath.length > 0) {
|
|
528
|
-
let raw;
|
|
529
|
-
try {
|
|
530
|
-
raw = readFileSync(filePath, "utf8");
|
|
531
|
-
} catch (error) {
|
|
532
|
-
throw new Error(
|
|
533
|
-
`Failed to read SHIPMAIL_API_KEY_FILE at ${filePath}: ${error instanceof Error ? error.message : String(error)}`,
|
|
534
|
-
{ cause: error }
|
|
535
|
-
);
|
|
536
|
-
}
|
|
537
|
-
const trimmed = raw.trim();
|
|
538
|
-
if (trimmed.length === 0) {
|
|
539
|
-
throw new Error(`SHIPMAIL_API_KEY_FILE at ${filePath} is empty.`);
|
|
540
|
-
}
|
|
541
|
-
return trimmed;
|
|
542
|
-
}
|
|
543
|
-
const direct = env["SHIPMAIL_API_KEY"];
|
|
544
|
-
if (!direct) throw new Error(API_KEY_HELP);
|
|
545
|
-
return direct;
|
|
546
|
-
}
|
|
547
|
-
var ALLOWED_BASE_URL_HOSTS = ["shipmail.to", "api.shipmail.to"];
|
|
548
|
-
function validateBaseUrl(rawValue, allowInsecure) {
|
|
549
|
-
let parsed;
|
|
550
|
-
try {
|
|
551
|
-
parsed = new URL(rawValue);
|
|
552
|
-
} catch {
|
|
553
|
-
throw new Error(`SHIPMAIL_BASE_URL is not a valid URL: ${rawValue}`);
|
|
554
|
-
}
|
|
555
|
-
if (allowInsecure) return parsed.toString().replace(/\/+$/, "");
|
|
556
|
-
if (parsed.protocol !== "https:") {
|
|
557
|
-
throw new Error(
|
|
558
|
-
"SHIPMAIL_BASE_URL must use https. Set SHIPMAIL_ALLOW_INSECURE_BASE_URL=1 for development."
|
|
559
|
-
);
|
|
560
|
-
}
|
|
561
|
-
const host = parsed.hostname.toLowerCase();
|
|
562
|
-
const isAllowedHost = ALLOWED_BASE_URL_HOSTS.some(
|
|
563
|
-
(allowed) => host === allowed || host.endsWith(`.${allowed}`)
|
|
564
|
-
);
|
|
565
|
-
if (!isAllowedHost) {
|
|
566
|
-
throw new Error(
|
|
567
|
-
`SHIPMAIL_BASE_URL host "${host}" is not allowed. Set SHIPMAIL_ALLOW_INSECURE_BASE_URL=1 for development.`
|
|
568
|
-
);
|
|
569
|
-
}
|
|
570
|
-
return parsed.toString().replace(/\/+$/, "");
|
|
571
|
-
}
|
|
572
|
-
function readConfig(argv = process.argv.slice(2)) {
|
|
573
|
-
if (argv.includes("--tools")) {
|
|
574
|
-
throw new Error(
|
|
575
|
-
"--tools was removed. ShipMail MCP tools now follow the API key permissions configured in ShipMail Settings."
|
|
576
|
-
);
|
|
577
|
-
}
|
|
578
|
-
const unknownArgs = argv.filter((arg) => arg !== "--help" && arg !== "-h");
|
|
579
|
-
if (unknownArgs.length > 0) {
|
|
580
|
-
throw new Error(`Unknown argument: ${unknownArgs[0]}`);
|
|
581
|
-
}
|
|
582
|
-
const rawBaseUrl = env["SHIPMAIL_BASE_URL"];
|
|
583
|
-
const allowInsecure = env["SHIPMAIL_ALLOW_INSECURE_BASE_URL"] === "1";
|
|
584
|
-
const baseUrl = rawBaseUrl !== void 0 && rawBaseUrl.length > 0 ? validateBaseUrl(rawBaseUrl, allowInsecure) : void 0;
|
|
585
|
-
return {
|
|
586
|
-
apiKey: readApiKey(),
|
|
587
|
-
baseUrl,
|
|
588
|
-
organizationId: env["SHIPMAIL_ORGANIZATION_ID"] || void 0
|
|
589
|
-
};
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
// src/server.ts
|
|
593
|
-
import { McpServer as McpServer5 } from "@modelcontextprotocol/server";
|
|
594
|
-
import { ShipMailClient } from "shipmail";
|
|
595
|
-
|
|
596
|
-
// src/cross-organization-tools.ts
|
|
597
|
-
import { performance } from "perf_hooks";
|
|
598
|
-
import "@modelcontextprotocol/server";
|
|
599
|
-
import { ShipMailError as ShipMailError2 } from "shipmail";
|
|
600
|
-
import { z as z2 } from "zod/v4";
|
|
601
|
-
|
|
602
602
|
// src/result.ts
|
|
603
603
|
import { ShipMailError, ValidationError } from "shipmail";
|
|
604
604
|
|
|
@@ -7168,7 +7168,7 @@ function registerTools(rawServer, client, allowedTools, grantedOrganizations = [
|
|
|
7168
7168
|
}
|
|
7169
7169
|
|
|
7170
7170
|
// src/version.ts
|
|
7171
|
-
var VERSION = "0.
|
|
7171
|
+
var VERSION = "0.7.0";
|
|
7172
7172
|
|
|
7173
7173
|
// src/server.ts
|
|
7174
7174
|
var INSTRUCTIONS = `ShipMail MCP exposes the business email and calendar tools authorized by the connection's current ShipMail permissions.
|
|
@@ -7235,6 +7235,47 @@ function createShipMailMcpServer(config, allowedTools, organizationGrants = [])
|
|
|
7235
7235
|
return server;
|
|
7236
7236
|
}
|
|
7237
7237
|
|
|
7238
|
+
// src/startup.ts
|
|
7239
|
+
function writeStderrWarning(message) {
|
|
7240
|
+
process.stderr.write(`${message}
|
|
7241
|
+
`);
|
|
7242
|
+
}
|
|
7243
|
+
function errorMessage(error) {
|
|
7244
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7245
|
+
return message.replace(/\s+/g, " ").trim() || "Unknown error";
|
|
7246
|
+
}
|
|
7247
|
+
async function resolveAllowedTools(client, writeWarning = writeStderrWarning) {
|
|
7248
|
+
let capabilities;
|
|
7249
|
+
try {
|
|
7250
|
+
capabilities = await client.capabilities.get();
|
|
7251
|
+
} catch (error) {
|
|
7252
|
+
writeWarning(
|
|
7253
|
+
`Could not fetch ShipMail capabilities (${errorMessage(error)}). The tool list is unverified and calls may fail.`
|
|
7254
|
+
);
|
|
7255
|
+
return new Set(MCP_TOOL_NAMES);
|
|
7256
|
+
}
|
|
7257
|
+
const serverMajor = capabilities.capability_version.split(".")[0];
|
|
7258
|
+
const supportedMajor = MCP_CAPABILITY_VERSION.split(".")[0];
|
|
7259
|
+
if (!serverMajor || serverMajor !== supportedMajor) {
|
|
7260
|
+
throw new Error(
|
|
7261
|
+
`ShipMail capability version ${capabilities.capability_version} is incompatible with this shipmail-mcp version. Upgrade shipmail-mcp before reconnecting.`
|
|
7262
|
+
);
|
|
7263
|
+
}
|
|
7264
|
+
const localTools = new Set(MCP_TOOL_NAMES);
|
|
7265
|
+
const allowedTools = new Set(
|
|
7266
|
+
capabilities.allowed_mcp_tools.filter((toolName) => localTools.has(toolName))
|
|
7267
|
+
);
|
|
7268
|
+
const missingTools = capabilities.allowed_mcp_tools.filter(
|
|
7269
|
+
(toolName) => !localTools.has(toolName)
|
|
7270
|
+
);
|
|
7271
|
+
if (missingTools.length > 0) {
|
|
7272
|
+
writeWarning(
|
|
7273
|
+
`ShipMail allows tools not implemented by this shipmail-mcp version: ${missingTools.join(", ")}. Upgrade to use them.`
|
|
7274
|
+
);
|
|
7275
|
+
}
|
|
7276
|
+
return allowedTools;
|
|
7277
|
+
}
|
|
7278
|
+
|
|
7238
7279
|
// src/index.ts
|
|
7239
7280
|
function installShutdownHandlers(server) {
|
|
7240
7281
|
let shuttingDown = false;
|
|
@@ -7266,29 +7307,9 @@ async function main() {
|
|
|
7266
7307
|
"X-ShipMail-Client-Version": VERSION
|
|
7267
7308
|
}
|
|
7268
7309
|
});
|
|
7269
|
-
const
|
|
7270
|
-
const serverMajor = capabilities.capability_version.split(".")[0];
|
|
7271
|
-
const supportedMajor = MCP_CAPABILITY_VERSION.split(".")[0];
|
|
7272
|
-
if (!serverMajor || serverMajor !== supportedMajor) {
|
|
7273
|
-
throw new Error(
|
|
7274
|
-
`ShipMail capability version ${capabilities.capability_version} is incompatible with this shipmail-mcp version. Upgrade shipmail-mcp before reconnecting.`
|
|
7275
|
-
);
|
|
7276
|
-
}
|
|
7277
|
-
const localTools = new Set(MCP_TOOL_NAMES);
|
|
7278
|
-
const allowedTools = new Set(
|
|
7279
|
-
capabilities.allowed_mcp_tools.filter((toolName) => localTools.has(toolName))
|
|
7280
|
-
);
|
|
7281
|
-
const missingTools = capabilities.allowed_mcp_tools.filter(
|
|
7282
|
-
(toolName) => !localTools.has(toolName)
|
|
7283
|
-
);
|
|
7284
|
-
if (missingTools.length > 0) {
|
|
7285
|
-
process.stderr.write(
|
|
7286
|
-
`ShipMail allows tools not implemented by this shipmail-mcp version: ${missingTools.join(", ")}. Upgrade to use them.
|
|
7287
|
-
`
|
|
7288
|
-
);
|
|
7289
|
-
}
|
|
7310
|
+
const allowedTools = await resolveAllowedTools(client);
|
|
7290
7311
|
const server = serveStdio(() => createShipMailMcpServer(config, allowedTools), {
|
|
7291
|
-
legacy: "
|
|
7312
|
+
legacy: "serve"
|
|
7292
7313
|
});
|
|
7293
7314
|
installShutdownHandlers(server);
|
|
7294
7315
|
}
|
package/dist/server.js
CHANGED
|
@@ -7071,7 +7071,7 @@ function registerTools(rawServer, client, allowedTools, grantedOrganizations = [
|
|
|
7071
7071
|
}
|
|
7072
7072
|
|
|
7073
7073
|
// src/version.ts
|
|
7074
|
-
var VERSION = "0.
|
|
7074
|
+
var VERSION = "0.7.0";
|
|
7075
7075
|
|
|
7076
7076
|
// src/server.ts
|
|
7077
7077
|
var INSTRUCTIONS = `ShipMail MCP exposes the business email and calendar tools authorized by the connection's current ShipMail permissions.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shipmail-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"mcpName": "io.github.shipmail-to/shipmail-mcp",
|
|
5
5
|
"description": "Official Model Context Protocol (MCP) server for Shipmail, a business email provider with REST API, webhooks, and custom-domain inboxes for AI agents.",
|
|
6
6
|
"type": "module",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@modelcontextprotocol/server": "2.0.0",
|
|
62
|
-
"shipmail": "0.4.
|
|
62
|
+
"shipmail": "0.4.12",
|
|
63
63
|
"zod": "4.4.3"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
package/server.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"url": "https://github.com/shipmail-to/shipmail-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.7.0",
|
|
10
10
|
"websiteUrl": "https://shipmail.to/docs/mcp",
|
|
11
11
|
"remotes": [
|
|
12
12
|
{
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"registryType": "npm",
|
|
28
28
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
29
29
|
"identifier": "shipmail-mcp",
|
|
30
|
-
"version": "0.
|
|
30
|
+
"version": "0.7.0",
|
|
31
31
|
"transport": {
|
|
32
32
|
"type": "stdio"
|
|
33
33
|
},
|
package/smithery.yaml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Smithery configuration file: https://smithery.ai/docs/build/project-config/smithery-yaml
|
|
2
2
|
name: shipmail-mcp
|
|
3
|
-
version: 0.
|
|
3
|
+
version: 0.7.0
|
|
4
4
|
description: Official Shipmail MCP server for AI-agent custom-domain business email inboxes with REST API and webhooks.
|
|
5
5
|
author: ShipMail
|
|
6
6
|
repository: https://github.com/shipmail-to/shipmail-mcp
|