@yunori/mcp 0.1.0 → 0.1.1
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/api.js +1 -1
- package/dist/mail-text.js +19 -9
- package/package.json +1 -1
package/dist/api.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* personal API token, so the server's scope check decides what happens; this
|
|
4
4
|
* only makes sure the token goes to one place and that failures read clearly.
|
|
5
5
|
*/
|
|
6
|
-
export const VERSION = "0.1.
|
|
6
|
+
export const VERSION = "0.1.1";
|
|
7
7
|
export const DEFAULT_BASE_URL = "https://yunori.email";
|
|
8
8
|
const TOKEN_SHAPE = /^tori_pat_[A-Za-z0-9]{32}$/;
|
|
9
9
|
const TIMEOUT_MS = 30_000;
|
package/dist/mail-text.js
CHANGED
|
@@ -229,20 +229,30 @@ export function draftBody(parts) {
|
|
|
229
229
|
}
|
|
230
230
|
// ── Handing mail to a model ─────────────────────────────────────────────────
|
|
231
231
|
/**
|
|
232
|
-
* Characters a person never sees and a model reads anyway
|
|
233
|
-
* (
|
|
234
|
-
*
|
|
232
|
+
* Characters a person never sees and a model reads anyway, which a sender can
|
|
233
|
+
* hide instructions in or split a tag with: the Tags block (invisible ASCII),
|
|
234
|
+
* zero-width characters, direction overrides, soft hyphens, variation selectors
|
|
235
|
+
* and the rest of what Unicode calls default-ignorable, and every control
|
|
236
|
+
* character but tab and newline. `sdk/mcp` carries the same patterns, and the
|
|
237
|
+
* test holds them equal.
|
|
235
238
|
*/
|
|
236
|
-
const INVISIBLE = /[\
|
|
237
|
-
/**
|
|
238
|
-
|
|
239
|
+
const INVISIBLE = /(?![\t\n\r])[\p{Default_Ignorable_Code_Point}\p{Cc}]/gu;
|
|
240
|
+
/**
|
|
241
|
+
* A sender can write the closing tag too, so nothing that reads as one survives
|
|
242
|
+
* inside: any case, spaced out, backslashed, in wide characters. Matching only as
|
|
243
|
+
* far as "untrusted" takes in `<untrusted_email>` from `@yunori/agent-mail-mcp`
|
|
244
|
+
* too, which may be feeding the same model.
|
|
245
|
+
*/
|
|
246
|
+
const FENCE_LOOKALIKE = /[<<﹤][\s\\//]*(untrusted)/giu;
|
|
247
|
+
const defuse = (text) => text.replace(INVISIBLE, "").replace(FENCE_LOOKALIKE, "[$1");
|
|
239
248
|
/**
|
|
240
249
|
* Anything strangers had a hand in, wrapped so a model can tell it from what it
|
|
241
250
|
* was asked. This is a signal to the model, not a wall: the wall is the token's
|
|
242
251
|
* scopes, which is why the docs tell people to leave Send unticked.
|
|
243
252
|
*/
|
|
244
253
|
export function fenceMail(value) {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
254
|
+
// String by string, because once this is JSON a newline in a tag is the two
|
|
255
|
+
// characters \n and the pattern can't see through it. Then the whole, for keys.
|
|
256
|
+
const json = JSON.stringify(value, (_key, v) => (typeof v === "string" ? defuse(v) : v), 2) ?? "null";
|
|
257
|
+
return `<untrusted_mail>\n${defuse(json)}\n</untrusted_mail>`;
|
|
248
258
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yunori/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "MCP server for your Yunori mail: let an AI assistant read your mailboxes, organise them and write drafts, with a token you control.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "FutureForge Studios",
|