fix: expose portable Mastodon hashtag schemas for MCP clients

This commit is contained in:
2026-10-07 21:59:30 +09:00
parent 794859e4a4
commit a538628670
3 changed files with 46 additions and 2 deletions
+5
View File
@@ -37,6 +37,11 @@ External tools are stateless and do not share the internal research turn's
12-request budget. No tool writes to an SNS account. Tool failures return 12-request budget. No tool writes to an SNS account. Tool failures return
`isError: true` and a structured error in text content. `isError: true` and a structured error in text content.
Tool input schemas must also work with non-JavaScript JSON Schema validators.
Mastodon hashtag character restrictions remain enforced by the server and are
described in the schema, without exporting JavaScript Unicode property escapes
as a `pattern` that Python JSON Schema validators reject.
Activity publication uses the same service as Home and Messages. Exact retries Activity publication uses the same service as Home and Messages. Exact retries
return the original receipt before revision checks; conflicting publications return the original receipt before revision checks; conflicting publications
make no changes. Browser clients refresh on committed changes through the make no changes. Browser clients refresh on committed changes through the
@@ -0,0 +1,34 @@
import { expect, it } from "vitest";
import { z } from "zod";
import { mastodonSourceSchema } from "./mastodon-source";
it.each(["日本語_123", "café", "AB12", " hello_world "])(
"accepts Unicode hashtag %s",
(target) => {
expect(mastodonSourceSchema.parse({ platform: "mastodon", kind: "hashtag", target })).toEqual({
platform: "mastodon",
kind: "hashtag",
target: target.trim(),
});
},
);
it.each(["", " ", "#tag", "two words", "tag-name", "😀", "a".repeat(129)])(
"rejects invalid hashtag %s",
(target) => {
expect(
mastodonSourceSchema.safeParse({ platform: "mastodon", kind: "hashtag", target }).success,
).toBe(false);
},
);
it("describes hashtag constraints without requiring Unicode regex support in MCP clients", () => {
const schema = z.toJSONSchema(mastodonSourceSchema.options[2].shape.target, { io: "input" });
expect(schema).toEqual({
$schema: "https://json-schema.org/draft/2020-12/schema",
type: "string",
minLength: 1,
maxLength: 128,
description: "Hashtag without #, containing only Unicode letters, numbers, and underscores.",
});
});
+7 -2
View File
@@ -22,8 +22,13 @@ export const mastodonSourceSchema = z.discriminatedUnion("kind", [
target: z target: z
.string() .string()
.trim() .trim()
.regex(/^[\p{L}\p{N}_]+$/u) .min(1)
.max(128), .max(128)
// JSON Schema consumers do not all support Unicode property escapes.
.refine((value) => /^[\p{L}\p{N}_]+$/u.test(value), {
message: "Use only letters, numbers, and underscores in a hashtag.",
})
.describe("Hashtag without #, containing only Unicode letters, numbers, and underscores."),
}) })
.strict(), .strict(),
z z