@sendora/mcp 1.5.2 → 1.8.6

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/LICENSE CHANGED
@@ -19,3 +19,5 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
22
+
23
+ The MIT terms above do not cover the Sendora name or the Sendora symbol.
package/README.md CHANGED
@@ -2,9 +2,11 @@
2
2
 
3
3
  The official [Model Context Protocol](https://modelcontextprotocol.io) server for
4
4
  [Sendora](https://sendora.se), transactional email delivery. It helps a coding
5
- agent such as Claude Code, Cursor or VS Code build against the API,
6
- `@sendora/sdk` for TypeScript or `sendora` for Python: it reads Sendora's documentation, sends a test mail and reads what
7
- happened to it, and sets up streams, webhooks and sending domains.
5
+ agent such as Claude Code, Cursor or VS Code build against the API and its
6
+ SDKs: `@sendora/sdk` for TypeScript, `sendora` for Python, and
7
+ `sendora/sendora-php` for PHP with `sendora/sendora-laravel` for Laravel. It
8
+ reads Sendora's documentation, sends a test mail and reads what happened to
9
+ it, and sets up streams, webhooks and sending domains.
8
10
 
9
11
  The documentation is built into it: the guides, every operation of the API
10
12
  reference, the error codes and each SDK's README and rules for agents, from the
@@ -74,11 +76,19 @@ message's timeline, and `add_domain` and `check_domain` the domain's DNS
74
76
  records with a button that checks them again. Every other client gets the
75
77
  same answer as text.
76
78
 
77
- The documents are resources under `sendora://docs/…`, `sendora://reference/…`,
78
- `sendora://errors`, `sendora://sdk/readme`, `sendora://sdk/skill`,
79
- `sendora://sdk/python/readme` and `sendora://sdk/python/skill`, listed by
80
- `sendora://index`. Three prompts: `set_up_sendora`, `why_not_delivered` and
81
- `verify_webhooks`.
79
+ The documents are resources, and `sendora://index` lists them:
80
+
81
+ - the guides, under `sendora://docs/…`, and the API reference, under
82
+ `sendora://reference/…`;
83
+ - the error codes, `sendora://errors`;
84
+ - the TypeScript SDK's README and rules for agents, `sendora://sdk/readme`
85
+ and `sendora://sdk/skill`;
86
+ - the Python SDK's, `sendora://sdk/python/readme` and
87
+ `sendora://sdk/python/skill`;
88
+ - the PHP SDK's, `sendora://sdk/php/readme` and `sendora://sdk/php/skill`;
89
+ - the Laravel package's README, `sendora://sdk/laravel/readme`.
90
+
91
+ Three prompts: `set_up_sendora`, `why_not_delivered` and `verify_webhooks`.
82
92
 
83
93
  ## The official server
84
94
 
package/dist/docs.js CHANGED
@@ -23,7 +23,11 @@ function indexOf(documents) {
23
23
  ].join('\n'),
24
24
  };
25
25
  }
26
- const SKILLS = new Set(['sendora://sdk/skill', 'sendora://sdk/python/skill']);
26
+ const SKILLS = new Set([
27
+ 'sendora://sdk/skill',
28
+ 'sendora://sdk/python/skill',
29
+ 'sendora://sdk/php/skill',
30
+ ]);
27
31
  /** The bundle as `scripts/build-docs.ts` writes it, checked, with the index in front. */
28
32
  export function docsFrom(bundle) {
29
33
  const built = bundleSchema.parse(bundle).documents;
package/dist/errors.js CHANGED
@@ -5,6 +5,16 @@ const retryAfter = (error) => error.retryAfter === null
5
5
  ? 'Wait a moment and try again.'
6
6
  : `Wait ${String(error.retryAfter)} seconds and try again.`;
7
7
  const unconfirmed = () => 'Nothing was confirmed, so a send may or may not have been accepted: look for it with search_messages before sending again.';
8
+ /** The limit on unpaid emails (docs/design/billing.md §3.5): a wait while a charge makes room, a send too large to ever fit, or a charge to pay first. */
9
+ const unpaidLimit = (error) => {
10
+ if (error.retryAfter !== null) {
11
+ return `A charge for the emails so far is under way and makes room once it is paid. Wait ${String(error.retryAfter)} seconds and try again.`;
12
+ }
13
+ if (error.priceOre !== null && error.limitOre !== null && error.priceOre > error.limitOre) {
14
+ return "This send alone costs more than the account's limit for unpaid emails, so it never fits as one. Send it in smaller parts, or write to support@sendora.se to have the limit raised.";
15
+ }
16
+ return `No charge under way makes room yet. An administrator sees what the account owes under Account › Billing (Konto › Fakturering) in the dashboard, ${DASHBOARD}/account/billing.`;
17
+ };
8
18
  const capOwner = {
9
19
  account: `An administrator raises the account's ceiling under Account › Usage (Konto › Användning) in the dashboard, ${DASHBOARD}/account/usage.`,
10
20
  server: "The server's own cap is Sendora's to set; write to support to change it.",
@@ -25,6 +35,7 @@ const hints = {
25
35
  read_only_connection: () => 'The person approved this connection without changes on live servers, and the account is read only through a connection. They can connect again and tick "Tillåt ändringar på liveservrar" on the approval page, or the change can be made on a test server.',
26
36
  test_server_only: () => 'Through a connected app, keys, webhooks and what cannot be undone happen on test servers only. Make the change on a test server, or in the dashboard.',
27
37
  payment_required: null,
38
+ unpaid_limit_reached: unpaidLimit,
28
39
  account_paused: null,
29
40
  account_not_active: null,
30
41
  spam_complaint_locked: null,