@sendora/mcp 1.5.1 → 1.5.2
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.
|
@@ -13,6 +13,13 @@ export const MAX_MESSAGE_BYTES = 10 * 1024 * 1024;
|
|
|
13
13
|
/** The tool's own bound on a message's attachments together, tighter than the API's (§4.2). */
|
|
14
14
|
export const MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024;
|
|
15
15
|
const BASE64_LINE_LENGTH = 76;
|
|
16
|
+
/*
|
|
17
|
+
* The control characters, U+0000 to U+001F and U+007F to U+009F, which the
|
|
18
|
+
* domain matches as \p{Cc}. ChatGPT checks every tool's patterns with an
|
|
19
|
+
* engine that cannot read \p{…}, and then refuses every tool of the
|
|
20
|
+
* connection (docs/design/oauth.md §1.2), so the patterns spell them out.
|
|
21
|
+
*/
|
|
22
|
+
export const CONTROL = String.raw `\x00-\x1F\x7F-\x9F`;
|
|
16
23
|
export const address = z
|
|
17
24
|
.union([
|
|
18
25
|
z.email(),
|
|
@@ -30,7 +37,7 @@ export const address = z
|
|
|
30
37
|
])
|
|
31
38
|
.describe('An address as a plain string, or an object with the address and a display name.');
|
|
32
39
|
const HEADER_NAME = /^[A-Za-z0-9][A-Za-z0-9-]{0,63}$/;
|
|
33
|
-
const HEADER_VALUE =
|
|
40
|
+
const HEADER_VALUE = new RegExp(`^[^${CONTROL}]{1,998}$`, 'u');
|
|
34
41
|
const DENIED_HEADERS = new Set([
|
|
35
42
|
'from',
|
|
36
43
|
'sender',
|
|
@@ -87,7 +94,7 @@ const METADATA_KEY = /^[A-Za-z0-9_.-]{1,40}$/;
|
|
|
87
94
|
export const metadata = z
|
|
88
95
|
.record(z.string(), z
|
|
89
96
|
.string()
|
|
90
|
-
.regex(
|
|
97
|
+
.regex(new RegExp(`^[^${CONTROL}]{0,500}$`, 'u'), 'metadata values are at most 500 characters without control characters'))
|
|
91
98
|
.superRefine((values, ctx) => {
|
|
92
99
|
const keys = Object.keys(values);
|
|
93
100
|
if (keys.length > 20) {
|
|
@@ -107,7 +114,7 @@ const SUBSTITUTION_KEY = /^[A-Za-z0-9_]{1,40}$/;
|
|
|
107
114
|
export const substitutions = z
|
|
108
115
|
.record(z.string(), z
|
|
109
116
|
.string()
|
|
110
|
-
.regex(
|
|
117
|
+
.regex(new RegExp(`^[^${CONTROL}]{0,500}$`, 'u'), 'substitution values are at most 500 characters without control characters'))
|
|
111
118
|
.superRefine((values, ctx) => {
|
|
112
119
|
const keys = Object.keys(values);
|
|
113
120
|
if (keys.length > 20) {
|
|
@@ -133,13 +140,13 @@ export const substitutions = z
|
|
|
133
140
|
export const tag = z
|
|
134
141
|
.string()
|
|
135
142
|
.trim()
|
|
136
|
-
.regex(
|
|
143
|
+
.regex(new RegExp(`^[^${CONTROL}]{1,100}$`, 'u'), 'a tag is 1 to 100 characters without control characters')
|
|
137
144
|
.nullable()
|
|
138
145
|
.optional();
|
|
139
146
|
export const attachment = z.object({
|
|
140
147
|
name: z
|
|
141
148
|
.string()
|
|
142
|
-
.regex(
|
|
149
|
+
.regex(new RegExp(String.raw `^[^${CONTROL}/\\]{1,255}$`, 'u'), 'a file name without path separators, at most 255 characters')
|
|
143
150
|
.describe('The file name, without path separators.'),
|
|
144
151
|
content: z
|
|
145
152
|
.base64('base64 without line breaks')
|
|
@@ -152,7 +159,7 @@ export const attachment = z.object({
|
|
|
152
159
|
.describe('A media type such as application/pdf; application/octet-stream when left out.'),
|
|
153
160
|
contentId: z
|
|
154
161
|
.string()
|
|
155
|
-
.regex(
|
|
162
|
+
.regex(new RegExp(String.raw `^[^\s<>${CONTROL}]{1,255}$`, 'u'), 'a content id without whitespace or angle brackets')
|
|
156
163
|
.nullable()
|
|
157
164
|
.optional()
|
|
158
165
|
.describe('Lets the HTML part show the attachment as cid:<contentId>.'),
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** This package's version, held equal to its package.json by a test. */
|
|
2
|
-
export const MCP_VERSION = '1.5.
|
|
2
|
+
export const MCP_VERSION = '1.5.2';
|