amenbo 0.5.1 → 0.6.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/README.en.md +8 -6
- package/README.md +8 -6
- package/dist/cache.js +4 -0
- package/dist/cache.js.map +1 -1
- package/dist/cli.js +7 -2
- package/dist/cli.js.map +1 -1
- package/dist/core.js +171 -42
- package/dist/core.js.map +1 -1
- package/dist/extract/pdf.d.ts +7 -1
- package/dist/extract/pdf.js +24 -6
- package/dist/extract/pdf.js.map +1 -1
- package/dist/fetcher/browser.d.ts +10 -3
- package/dist/fetcher/browser.js +13 -6
- package/dist/fetcher/browser.js.map +1 -1
- package/dist/fetcher/http.d.ts +12 -14
- package/dist/fetcher/http.js +95 -24
- package/dist/fetcher/http.js.map +1 -1
- package/dist/fetcher/index.d.ts +4 -1
- package/dist/fetcher/index.js +23 -2
- package/dist/fetcher/index.js.map +1 -1
- package/dist/fetcher/ssrfProxy.d.ts +1 -1
- package/dist/fetcher/ssrfProxy.js +5 -1
- package/dist/fetcher/ssrfProxy.js.map +1 -1
- package/dist/formatting.d.ts +9 -1
- package/dist/formatting.js +28 -2
- package/dist/formatting.js.map +1 -1
- package/dist/politeness.d.ts +2 -0
- package/dist/politeness.js +11 -3
- package/dist/politeness.js.map +1 -1
- package/dist/screenshot.d.ts +2 -0
- package/dist/screenshot.js +16 -8
- package/dist/screenshot.js.map +1 -1
- package/dist/server.d.ts +10 -2
- package/dist/server.js +137 -107
- package/dist/server.js.map +1 -1
- package/dist/tokens.d.ts +20 -7
- package/dist/tokens.js +74 -23
- package/dist/tokens.js.map +1 -1
- package/package.json +4 -2
package/dist/server.js
CHANGED
|
@@ -17,133 +17,42 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { realpathSync } from "node:fs";
|
|
19
19
|
import { fileURLToPath } from "node:url";
|
|
20
|
-
import { McpServer } from "@modelcontextprotocol/
|
|
21
|
-
import {
|
|
20
|
+
import { McpServer } from "@modelcontextprotocol/server";
|
|
21
|
+
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
22
22
|
import { z } from "zod";
|
|
23
23
|
import { handleFetchTool, handleScreenshotTool, politeness, registerCoreShutdownHandlers, resolvePackageVersion, } from "./core.js";
|
|
24
24
|
import { AmenboError } from "./errors.js";
|
|
25
25
|
import { formatLinksResponse } from "./formatting.js";
|
|
26
26
|
import { discoverLinks } from "./links.js";
|
|
27
|
-
// テスト用export(既存スタイルに合わせた最小のテスト可能化。InMemoryTransport経由の
|
|
28
|
-
// MCP progress notifications統合テストでclient.connect()の相手として使う)。
|
|
29
|
-
export const server = new McpServer({ name: "amenbo", version: resolvePackageVersion() });
|
|
30
27
|
/**
|
|
31
28
|
* MCP progress notifications: リクエストにprogressToken(_meta.progressToken)が付いている
|
|
32
29
|
* クライアントに対してのみ、進捗メッセージをホストUIへ通知するコールバックを組み立てる。
|
|
33
30
|
* progressTokenが無い(=進捗通知に対応しない/希望しないクライアント)場合はundefinedを返し、
|
|
34
31
|
* core.ts側の各通知ポイントは呼び出し自体を行わない(条件分岐のみでオーバーヘッドは実質ゼロ)。
|
|
35
32
|
*
|
|
36
|
-
*
|
|
33
|
+
* notifyはtotalを送らない(処理量が事前に不定なため)。失敗はツール本処理を
|
|
37
34
|
* 壊さないようベストエフォートで握りつぶし、原因のみstderrへ記録する。
|
|
38
35
|
*/
|
|
39
|
-
function buildProgressNotifier(
|
|
40
|
-
const progressToken =
|
|
36
|
+
function buildProgressNotifier(ctx) {
|
|
37
|
+
const progressToken = ctx.mcpReq._meta?.progressToken;
|
|
41
38
|
if (progressToken === undefined)
|
|
42
39
|
return undefined;
|
|
43
40
|
let progress = 0;
|
|
44
41
|
return (message) => {
|
|
45
42
|
progress += 1;
|
|
46
|
-
void
|
|
43
|
+
void ctx.mcpReq.notify({ method: "notifications/progress", params: { progressToken, progress, message } }).catch((error) => {
|
|
47
44
|
console.error("進捗通知(notifications/progress)の送信に失敗しました:", error);
|
|
48
45
|
});
|
|
49
46
|
};
|
|
50
47
|
}
|
|
51
|
-
|
|
52
|
-
title: "Fetch a web page as Markdown",
|
|
53
|
-
description: "Fetch a web page (Japanese-web-native) as low-impact, token-efficient Markdown. Built-in robots.txt compliance, rate limiting, and caching. " +
|
|
54
|
-
"mode: auto (default; quality score picks Markdown or screenshot) / markdown / outline (heading summary) / screenshot. " +
|
|
55
|
-
"Refetching a cached URL returns cache: unchanged, or diff (changed sections only), to save tokens. PDF URLs are handled automatically.",
|
|
56
|
-
inputSchema: {
|
|
57
|
-
url: z.string().url().describe("Target URL (http/https only; PDF supported)"),
|
|
58
|
-
mode: z.enum(["auto", "markdown", "outline", "screenshot"]).optional().describe("Default: auto"),
|
|
59
|
-
selector: z.string().optional().describe("CSS selector to narrow the content"),
|
|
60
|
-
section: z.string().optional().describe("Section ID obtained from outline mode; returns only that section's Markdown"),
|
|
61
|
-
page: z.number().int().positive().optional().describe("Page number (default 1)"),
|
|
62
|
-
max_tokens: z.number().int().positive().optional().describe("Approximate token budget per page (default 8000)"),
|
|
63
|
-
force_full: z.boolean().optional().describe("Default false. If true, disables diff responses (unchanged/diff) and boilerplate-block removal, always returning the full content"),
|
|
64
|
-
},
|
|
65
|
-
annotations: {
|
|
66
|
-
readOnlyHint: true,
|
|
67
|
-
openWorldHint: true,
|
|
68
|
-
},
|
|
69
|
-
}, async ({ url, mode, selector, section, page, max_tokens: maxTokens, force_full: forceFull }, extra) => {
|
|
70
|
-
try {
|
|
71
|
-
const onProgress = buildProgressNotifier(extra);
|
|
72
|
-
const content = await handleFetchTool({ url, mode, selector, section, page, max_tokens: maxTokens, force_full: forceFull, onProgress });
|
|
73
|
-
return { content };
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
const message = error instanceof AmenboError ? error.message : `予期しないエラーが発生しました: ${String(error)}`;
|
|
77
|
-
if (!(error instanceof AmenboError)) {
|
|
78
|
-
console.error(error);
|
|
79
|
-
}
|
|
80
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
server.registerTool("links", {
|
|
84
|
-
title: "List links from a page (sitemap/RSS-first)",
|
|
85
|
-
description: "Low-impact link discovery: prefers sitemap.xml / RSS / Atom feeds when available, otherwise extracts in-page links.",
|
|
86
|
-
inputSchema: {
|
|
87
|
-
url: z.string().url().describe("Starting URL"),
|
|
88
|
-
filter: z.string().optional().describe("Substring match against URL/link text, or a glob using *"),
|
|
89
|
-
},
|
|
90
|
-
annotations: {
|
|
91
|
-
readOnlyHint: true,
|
|
92
|
-
openWorldHint: true,
|
|
93
|
-
},
|
|
94
|
-
}, async ({ url, filter }, extra) => {
|
|
95
|
-
try {
|
|
96
|
-
const onProgress = buildProgressNotifier(extra);
|
|
97
|
-
const result = await discoverLinks(url, politeness, { ...(filter ? { filter } : {}), onProgress });
|
|
98
|
-
return { content: [{ type: "text", text: formatLinksResponse(url, result) }] };
|
|
99
|
-
}
|
|
100
|
-
catch (error) {
|
|
101
|
-
const message = error instanceof AmenboError ? error.message : `予期しないエラーが発生しました: ${String(error)}`;
|
|
102
|
-
if (!(error instanceof AmenboError)) {
|
|
103
|
-
console.error(error);
|
|
104
|
-
}
|
|
105
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
server.registerTool("screenshot", {
|
|
109
|
-
title: "Capture a tiled screenshot of a web page",
|
|
110
|
-
description: "For explicit visual inspection. Renders the page with a headless browser and returns tiled PNG screenshots. Built-in robots.txt compliance, rate limiting, and caching.",
|
|
111
|
-
inputSchema: {
|
|
112
|
-
url: z.string().url().describe("Target URL (http/https only)"),
|
|
113
|
-
fullPage: z.boolean().optional().describe("Default true. If false, captures only the first viewport (1 tile)"),
|
|
114
|
-
width: z.number().int().positive().optional().describe("Tile width in px (default 1280)"),
|
|
115
|
-
scale: z.number().min(0.5).max(1.0).optional().describe("Resolution scale (0.5-1.0, default 1.0); lower reduces image tokens"),
|
|
116
|
-
},
|
|
117
|
-
annotations: {
|
|
118
|
-
readOnlyHint: true,
|
|
119
|
-
openWorldHint: true,
|
|
120
|
-
},
|
|
121
|
-
}, async ({ url, fullPage, width, scale }, extra) => {
|
|
122
|
-
try {
|
|
123
|
-
const onProgress = buildProgressNotifier(extra);
|
|
124
|
-
const content = await handleScreenshotTool({ url, fullPage, width, scale, onProgress });
|
|
125
|
-
return { content };
|
|
126
|
-
}
|
|
127
|
-
catch (error) {
|
|
128
|
-
const message = error instanceof AmenboError ? error.message : `予期しないエラーが発生しました: ${String(error)}`;
|
|
129
|
-
if (!(error instanceof AmenboError)) {
|
|
130
|
-
console.error(error);
|
|
131
|
-
}
|
|
132
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
// MCPプロトコル面は既存ツールのtitle/description同様に英語固定のため、この定数は
|
|
136
|
-
// README.en.md の「推奨プロンプト」ブロックと一言一句同期を保つこと(完全一致を
|
|
137
|
-
// tests/serverUsagePrompt.test.ts が検証する)。README.md の日本語ブロックは対応する訳文で、
|
|
138
|
-
// 内容の連動は人が保つ。README側は導入者がコピペで使う独立したドキュメントとして
|
|
139
|
-
// 存在する必要があるため、単一ソース化(README側からこの定数を読み込む等)はしていない。
|
|
48
|
+
/** MCPプロトコル面は英語固定のため、ツールのtitle/description同様この定数も英語で書く。 */
|
|
140
49
|
const USAGE_PROMPT_TEXT = `## Use amenbo for web fetching
|
|
141
50
|
|
|
142
51
|
- Fetch pages with \`fetch\` (default mode \`auto\`). For pages that look long or where only part
|
|
143
52
|
is needed, first check headings and per-section token counts with \`mode: "outline"\`,
|
|
144
53
|
then fetch only the needed sections via \`section\`
|
|
145
54
|
- Getting \`unchanged\` / \`diff\` when refetching the same URL is normal (no change / changed
|
|
146
|
-
sections only). Use \`force_full: true\` only when the
|
|
55
|
+
sections only). Use \`force_full: true\` only when you need the whole content again instead of a diff
|
|
147
56
|
- When looking for pages within a site, don't guess URLs — enumerate them with \`links\`
|
|
148
57
|
(narrow down with \`filter\`)
|
|
149
58
|
- In environments with a shell, for long pages you only want to keyword-search or for bulk
|
|
@@ -157,19 +66,140 @@ const USAGE_PROMPT_TEXT = `## Use amenbo for web fetching
|
|
|
157
66
|
\`scale: 0.5\` or so reduces image tokens
|
|
158
67
|
- Fetch failures due to robots.txt denial or anti-bot measures are by design (no circumvention).
|
|
159
68
|
Report failures to the user as-is`;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
69
|
+
// USAGE_PROMPT_TEXTは README.en.md の「推奨プロンプト」ブロックと一言一句同期を保つこと(完全一致を
|
|
70
|
+
// tests/serverUsagePrompt.test.ts が検証する)。README.md の日本語ブロックは対応する訳文で、
|
|
71
|
+
// 内容の連動は人が保つ。README側は導入者がコピペで使う独立したドキュメントとして
|
|
72
|
+
// 存在する必要があるため、単一ソース化(README側からこの定数を読み込む等)はしていない。
|
|
73
|
+
/**
|
|
74
|
+
* ツール3個とプロンプト1個を登録したMCPサーバーインスタンスを1つ組み立てる。
|
|
75
|
+
*
|
|
76
|
+
* モジュールトップレベルのシングルトンにしていないのは、serveStdioがプロトコル世代
|
|
77
|
+
* (2025系 / 2026-07-28)を接続の1通目で判定してから世代ごとのインスタンスをpinする都合上、
|
|
78
|
+
* 1プロセス内でこのファクトリを複数回呼びうるため(同一インスタンスを二度connectすると失敗する)。
|
|
79
|
+
* テストからはこの関数を直接呼んでInMemoryTransportへ繋ぐ。
|
|
80
|
+
*/
|
|
81
|
+
export function createServer() {
|
|
82
|
+
const server = new McpServer({ name: "amenbo", version: resolvePackageVersion() });
|
|
83
|
+
server.registerTool("fetch", {
|
|
84
|
+
title: "Fetch a web page as Markdown",
|
|
85
|
+
description: "Fetch a web page (Japanese-web-native) as low-impact, token-efficient Markdown. Built-in robots.txt compliance, rate limiting, and caching. " +
|
|
86
|
+
"mode: auto (default; quality score picks Markdown or screenshot) / markdown / outline (heading summary) / screenshot. " +
|
|
87
|
+
"Refetching a cached URL returns cache: unchanged, or diff (changed sections only), to save tokens. PDF URLs are handled automatically.",
|
|
88
|
+
inputSchema: z.object({
|
|
89
|
+
url: z.string().url().describe("Target URL (http/https only; PDF supported)"),
|
|
90
|
+
mode: z.enum(["auto", "markdown", "outline", "screenshot"]).optional().describe("Default: auto"),
|
|
91
|
+
selector: z.string().optional().describe("CSS selector to narrow the content"),
|
|
92
|
+
section: z.string().optional().describe("Section ID obtained from outline mode; returns only that section's Markdown"),
|
|
93
|
+
page: z.number().int().positive().optional().describe("Page number (default 1)"),
|
|
94
|
+
max_tokens: z.number().int().positive().optional().describe("Approximate token budget per page (default 8000)"),
|
|
95
|
+
force_full: z.boolean().optional().describe("Default false. If true, disables diff responses (unchanged/diff) and boilerplate-block removal (pagination by max_tokens still applies)"),
|
|
96
|
+
}),
|
|
97
|
+
annotations: {
|
|
98
|
+
readOnlyHint: true,
|
|
99
|
+
openWorldHint: true,
|
|
100
|
+
},
|
|
101
|
+
}, async ({ url, mode, selector, section, page, max_tokens: maxTokens, force_full: forceFull }, ctx) => {
|
|
102
|
+
try {
|
|
103
|
+
const onProgress = buildProgressNotifier(ctx);
|
|
104
|
+
const content = await handleFetchTool({ url, mode, selector, section, page, max_tokens: maxTokens, force_full: forceFull, onProgress });
|
|
105
|
+
return { content };
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
const message = error instanceof AmenboError ? error.message : `予期しないエラーが発生しました: ${String(error)}`;
|
|
109
|
+
if (!(error instanceof AmenboError)) {
|
|
110
|
+
console.error(error);
|
|
111
|
+
}
|
|
112
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
server.registerTool("links", {
|
|
116
|
+
title: "List links from a page (sitemap/RSS-first)",
|
|
117
|
+
description: "Low-impact link discovery: prefers sitemap.xml / RSS / Atom feeds when available, otherwise extracts in-page links.",
|
|
118
|
+
inputSchema: z.object({
|
|
119
|
+
url: z.string().url().describe("Starting URL"),
|
|
120
|
+
filter: z.string().optional().describe("Substring match against URL/link text, or a glob using *"),
|
|
121
|
+
}),
|
|
122
|
+
annotations: {
|
|
123
|
+
readOnlyHint: true,
|
|
124
|
+
openWorldHint: true,
|
|
125
|
+
},
|
|
126
|
+
}, async ({ url, filter }, ctx) => {
|
|
127
|
+
try {
|
|
128
|
+
const onProgress = buildProgressNotifier(ctx);
|
|
129
|
+
const result = await discoverLinks(url, politeness, { ...(filter ? { filter } : {}), onProgress });
|
|
130
|
+
return { content: [{ type: "text", text: formatLinksResponse(url, result) }] };
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
const message = error instanceof AmenboError ? error.message : `予期しないエラーが発生しました: ${String(error)}`;
|
|
134
|
+
if (!(error instanceof AmenboError)) {
|
|
135
|
+
console.error(error);
|
|
136
|
+
}
|
|
137
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
server.registerTool("screenshot", {
|
|
141
|
+
title: "Capture a tiled screenshot of a web page",
|
|
142
|
+
description: "For explicit visual inspection. Renders the page with a headless browser and returns tiled PNG screenshots. Built-in robots.txt compliance, rate limiting, and caching.",
|
|
143
|
+
inputSchema: z.object({
|
|
144
|
+
url: z.string().url().describe("Target URL (http/https only)"),
|
|
145
|
+
fullPage: z.boolean().optional().describe("Default true. If false, captures only the first viewport (1 tile)"),
|
|
146
|
+
width: z.number().int().positive().optional().describe("Tile width in px (default 1280)"),
|
|
147
|
+
scale: z.number().min(0.5).max(1.0).optional().describe("Resolution scale (0.5-1.0, default 1.0); lower reduces image tokens"),
|
|
148
|
+
}),
|
|
149
|
+
annotations: {
|
|
150
|
+
readOnlyHint: true,
|
|
151
|
+
openWorldHint: true,
|
|
152
|
+
},
|
|
153
|
+
}, async ({ url, fullPage, width, scale }, ctx) => {
|
|
154
|
+
try {
|
|
155
|
+
const onProgress = buildProgressNotifier(ctx);
|
|
156
|
+
const content = await handleScreenshotTool({ url, fullPage, width, scale, onProgress });
|
|
157
|
+
return { content };
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
const message = error instanceof AmenboError ? error.message : `予期しないエラーが発生しました: ${String(error)}`;
|
|
161
|
+
if (!(error instanceof AmenboError)) {
|
|
162
|
+
console.error(error);
|
|
163
|
+
}
|
|
164
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
server.registerPrompt("usage", {
|
|
168
|
+
title: "How to use amenbo efficiently",
|
|
169
|
+
description: "Usage conventions for token-efficient, low-impact fetching (progressive disclosure, diff refetch, links).",
|
|
170
|
+
}, () => ({
|
|
171
|
+
messages: [{ role: "user", content: { type: "text", text: USAGE_PROMPT_TEXT } }],
|
|
172
|
+
}));
|
|
173
|
+
return server;
|
|
174
|
+
}
|
|
166
175
|
/** MCP stdioサーバーを起動する。CLI(cli.ts)が引数なし/`serve`サブコマンド時に呼ぶ後方互換経路でもある。 */
|
|
167
176
|
export async function runServer() {
|
|
168
177
|
// レビュー指摘対応: exit/SIGINT/SIGTERMハンドラ(core.ts)はサーバー常駐プロセスでのみ
|
|
169
178
|
// 必要なため、importするだけで走るモジュールトップレベルではなくここで明示的に登録する。
|
|
170
179
|
registerCoreShutdownHandlers();
|
|
171
|
-
|
|
172
|
-
|
|
180
|
+
serveStdio(() => {
|
|
181
|
+
// ファクトリの失敗をここで致命扱いにしているのは、serveStdioが同期関数で
|
|
182
|
+
// 例外をonerrorへ流すだけのため、放置すると「全リクエストが内部エラーを返し続けるのに
|
|
183
|
+
// 終了コード0で生き続けるプロセス」になるから。組み立てに失敗したサーバーは何も返せない。
|
|
184
|
+
try {
|
|
185
|
+
return createServer();
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
console.error("amenboサーバーの初期化に失敗しました:", error);
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
}, {
|
|
192
|
+
// 既定値と同じだが明示する: 'reject'にすると initialize で口を開ける2025系クライアント
|
|
193
|
+
// (現行のClaude Desktop/Cline等)が繋がらなくなるため、後方互換を捨てない判断をコードに残す。
|
|
194
|
+
legacy: "serve",
|
|
195
|
+
// ここでプロセスを落とさないのは、onerrorが単発の送信失敗と接続レベルの障害を
|
|
196
|
+
// 区別せず同じ口へ流すため(落とすと送信失敗ごときで常駐サーバーを巻き添えにする)。
|
|
197
|
+
// 起動不能の検出は上のファクトリ側が担う。トランスポート自体のstart失敗だけは
|
|
198
|
+
// SDKのAPI上ここへしか現れず切り分けられないため、記録に留める。
|
|
199
|
+
onerror: (error) => {
|
|
200
|
+
console.error("MCP stdio接続でエラーが発生しました:", error);
|
|
201
|
+
},
|
|
202
|
+
});
|
|
173
203
|
}
|
|
174
204
|
/**
|
|
175
205
|
* このモジュールが直接実行された(node dist/server.js / tsx src/server.ts / binエントリ経由)場合のみ
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/tokens.d.ts
CHANGED
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* J5:
|
|
2
|
+
* J5: 文字クラス別のトークン見積り。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
4
|
+
* 文字クラス別係数:
|
|
5
|
+
* - ラテン文字(英数字・ラテン拡張の文字): 1トークン ≒ 3.8文字
|
|
6
|
+
* - ASCII記号(約物・記法): 1文字 ≒ 0.5トークン
|
|
7
|
+
* - 非ラテン文字(キリル/ギリシャ/ヘブライ/アラビア/デーヴァナーガリー/タイ等): 1文字 ≒ 0.5トークン
|
|
8
|
+
* - CJK・ハングル(かな/カナ/漢字/全角記号/ハングル): 1文字 ≒ 0.9トークン
|
|
9
|
+
* - 記号・絵文字(約物/矢印/数学記号/ピクトグラム): 1文字 ≒ 1.5トークン
|
|
7
10
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
11
|
+
* 係数はo200k_base(GPT-4o)での実測に、既存係数と同程度(約1.15倍)の安全側マージンを乗せた値。
|
|
12
|
+
* 実測(1文字あたりトークン数): 英4.78文字/token、日0.79、韓0.75、中0.80、露0.29、
|
|
13
|
+
* 亜0.35、希0.38、印0.40、泰0.44、ヘブライ0.47、一般約物1.00、矢印/数学1.40、絵文字1.30〜1.80。
|
|
14
|
+
*
|
|
15
|
+
* 当初はASCII/CJKの二区分のみで、ハングルを含む非ラテン文字も記号・絵文字もASCII係数で
|
|
16
|
+
* 近似していたが、韓国語では実トークン量の約1/3、絵文字では約1/7にしか見積もれず、
|
|
17
|
+
* max_tokens予算が大きく超過していた(言語による不公平は本ツールでは不具合として扱う)。
|
|
18
|
+
* ASCII記号を文字と分けているのは、`| --- |`のようなMarkdown表の記法が
|
|
19
|
+
* 文字と同じ密度では圧縮されないため(このツールの主力出力なので実測で最も外れていた)。
|
|
20
|
+
*
|
|
21
|
+
* 全クラス適用後の見積り/実測比は、散文で1.14〜2.00倍(安全側)、
|
|
22
|
+
* 記法が密なMarkdown表で0.71倍(過小側の最悪ケース)。
|
|
10
23
|
*/
|
|
11
|
-
/** テキストの概算トークン数を返す(
|
|
24
|
+
/** テキストの概算トークン数を返す(文字クラス別係数)。 */
|
|
12
25
|
export declare function estimateTokens(text: string): number;
|
|
13
26
|
/** Markdownの1ブロック(見出し/段落/リスト項目/表/コードフェンス等)。 */
|
|
14
27
|
export interface Block {
|
package/dist/tokens.js
CHANGED
|
@@ -1,19 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* J5:
|
|
2
|
+
* J5: 文字クラス別のトークン見積り。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
4
|
+
* 文字クラス別係数:
|
|
5
|
+
* - ラテン文字(英数字・ラテン拡張の文字): 1トークン ≒ 3.8文字
|
|
6
|
+
* - ASCII記号(約物・記法): 1文字 ≒ 0.5トークン
|
|
7
|
+
* - 非ラテン文字(キリル/ギリシャ/ヘブライ/アラビア/デーヴァナーガリー/タイ等): 1文字 ≒ 0.5トークン
|
|
8
|
+
* - CJK・ハングル(かな/カナ/漢字/全角記号/ハングル): 1文字 ≒ 0.9トークン
|
|
9
|
+
* - 記号・絵文字(約物/矢印/数学記号/ピクトグラム): 1文字 ≒ 1.5トークン
|
|
7
10
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
11
|
+
* 係数はo200k_base(GPT-4o)での実測に、既存係数と同程度(約1.15倍)の安全側マージンを乗せた値。
|
|
12
|
+
* 実測(1文字あたりトークン数): 英4.78文字/token、日0.79、韓0.75、中0.80、露0.29、
|
|
13
|
+
* 亜0.35、希0.38、印0.40、泰0.44、ヘブライ0.47、一般約物1.00、矢印/数学1.40、絵文字1.30〜1.80。
|
|
14
|
+
*
|
|
15
|
+
* 当初はASCII/CJKの二区分のみで、ハングルを含む非ラテン文字も記号・絵文字もASCII係数で
|
|
16
|
+
* 近似していたが、韓国語では実トークン量の約1/3、絵文字では約1/7にしか見積もれず、
|
|
17
|
+
* max_tokens予算が大きく超過していた(言語による不公平は本ツールでは不具合として扱う)。
|
|
18
|
+
* ASCII記号を文字と分けているのは、`| --- |`のようなMarkdown表の記法が
|
|
19
|
+
* 文字と同じ密度では圧縮されないため(このツールの主力出力なので実測で最も外れていた)。
|
|
20
|
+
*
|
|
21
|
+
* 全クラス適用後の見積り/実測比は、散文で1.14〜2.00倍(安全側)、
|
|
22
|
+
* 記法が密なMarkdown表で0.71倍(過小側の最悪ケース)。
|
|
10
23
|
*/
|
|
11
|
-
const
|
|
24
|
+
const LATIN_CHARS_PER_TOKEN = 3.8;
|
|
12
25
|
const CJK_TOKENS_PER_CHAR = 0.9;
|
|
26
|
+
const NON_LATIN_TOKENS_PER_CHAR = 0.5;
|
|
27
|
+
const SYMBOL_TOKENS_PER_CHAR = 1.5;
|
|
28
|
+
const ASCII_PUNCT_TOKENS_PER_CHAR = 0.5;
|
|
29
|
+
/** ラテン文字・ASCII記号の範囲(基本ラテン〜ラテン文字拡張B)。 */
|
|
30
|
+
const LATIN_MAX_CODE_POINT = 0x024f;
|
|
31
|
+
/** 英数字、またはラテン文字(アクセント付きを含む)か判定する。 */
|
|
32
|
+
function isLatinWordCodePoint(cp) {
|
|
33
|
+
return ((cp >= 0x30 && cp <= 0x39) || // 0-9
|
|
34
|
+
(cp >= 0x41 && cp <= 0x5a) || // A-Z
|
|
35
|
+
(cp >= 0x61 && cp <= 0x7a) || // a-z
|
|
36
|
+
(cp >= 0x00c0 && cp <= LATIN_MAX_CODE_POINT) // ラテン1補助〜ラテン文字拡張B
|
|
37
|
+
);
|
|
38
|
+
}
|
|
13
39
|
/**
|
|
14
|
-
*
|
|
15
|
-
* ひらがな・カタカナ・漢字(統合漢字+拡張A)・CJK記号(全角スペースを除く)・
|
|
16
|
-
*
|
|
40
|
+
* 1文字あたりのトークン消費が大きい表記のコードポイントか判定する。
|
|
41
|
+
* ひらがな・カタカナ・漢字(統合漢字+拡張A/B+互換)・CJK記号(全角スペースを除く)・
|
|
42
|
+
* 全角英数/記号・半角カタカナ・ハングル(音節+字母)を対象とする。
|
|
17
43
|
*/
|
|
18
44
|
function isCjkCodePoint(cp) {
|
|
19
45
|
return ((cp >= 0x3040 && cp <= 0x309f) || // ひらがな
|
|
@@ -21,34 +47,59 @@ function isCjkCodePoint(cp) {
|
|
|
21
47
|
(cp >= 0x3400 && cp <= 0x4dbf) || // CJK統合漢字拡張A
|
|
22
48
|
(cp >= 0x4e00 && cp <= 0x9fff) || // CJK統合漢字
|
|
23
49
|
(cp >= 0xf900 && cp <= 0xfaff) || // CJK互換漢字
|
|
50
|
+
(cp >= 0x20000 && cp <= 0x2fa1f) || // CJK統合漢字拡張B以降
|
|
24
51
|
(cp >= 0x3001 && cp <= 0x303f) || // CJK記号(0x3000の全角スペースは除く)
|
|
25
|
-
(cp >= 0xff01 && cp <= 0xffef) // 全角英数/記号・半角カタカナ(0xFF00の全角スペースは除く)
|
|
52
|
+
(cp >= 0xff01 && cp <= 0xffef) || // 全角英数/記号・半角カタカナ(0xFF00の全角スペースは除く)
|
|
53
|
+
(cp >= 0xac00 && cp <= 0xd7a3) || // ハングル音節
|
|
54
|
+
(cp >= 0x1100 && cp <= 0x11ff) || // ハングル字母
|
|
55
|
+
(cp >= 0x3130 && cp <= 0x318f) // ハングル互換字母
|
|
26
56
|
);
|
|
27
57
|
}
|
|
28
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* 約物・矢印・数学記号・ピクトグラムのコードポイントか判定する。
|
|
60
|
+
* CJK記号(全角約物)は先にCJK側で判定されるため、ここへは来ない。
|
|
61
|
+
*/
|
|
62
|
+
function isSymbolCodePoint(cp) {
|
|
63
|
+
return ((cp >= 0x2000 && cp <= 0x2bff) || // 一般約物・矢印・数学記号・各種記号・装飾記号
|
|
64
|
+
(cp >= 0x2e00 && cp <= 0x2e7f) || // 補助句読点
|
|
65
|
+
cp >= 0x1f000 // 絵文字・ピクトグラム(拡張漢字はCJK側で判定済み)
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
/** テキストを文字クラス別に数える(空白はトークンをほぼ消費しないため数えない)。 */
|
|
29
69
|
function countByClass(text) {
|
|
30
|
-
|
|
31
|
-
let other = 0;
|
|
70
|
+
const counts = { cjk: 0, nonLatin: 0, symbol: 0, latinWord: 0, asciiPunct: 0 };
|
|
32
71
|
for (const ch of text) {
|
|
33
72
|
const cp = ch.codePointAt(0);
|
|
34
|
-
if (cp === undefined)
|
|
73
|
+
if (cp === undefined || /\s/u.test(ch))
|
|
35
74
|
continue;
|
|
36
75
|
if (isCjkCodePoint(cp)) {
|
|
37
|
-
cjk++;
|
|
76
|
+
counts.cjk++;
|
|
77
|
+
}
|
|
78
|
+
else if (isSymbolCodePoint(cp)) {
|
|
79
|
+
counts.symbol++;
|
|
80
|
+
}
|
|
81
|
+
else if (isLatinWordCodePoint(cp)) {
|
|
82
|
+
counts.latinWord++;
|
|
83
|
+
}
|
|
84
|
+
else if (cp > LATIN_MAX_CODE_POINT) {
|
|
85
|
+
counts.nonLatin++;
|
|
38
86
|
}
|
|
39
|
-
else
|
|
40
|
-
|
|
41
|
-
other++;
|
|
87
|
+
else {
|
|
88
|
+
counts.asciiPunct++;
|
|
42
89
|
}
|
|
43
90
|
}
|
|
44
|
-
return
|
|
91
|
+
return counts;
|
|
45
92
|
}
|
|
46
|
-
/** テキストの概算トークン数を返す(
|
|
93
|
+
/** テキストの概算トークン数を返す(文字クラス別係数)。 */
|
|
47
94
|
export function estimateTokens(text) {
|
|
48
95
|
if (text.length === 0)
|
|
49
96
|
return 0;
|
|
50
|
-
const { cjk,
|
|
51
|
-
const tokens = cjk * CJK_TOKENS_PER_CHAR +
|
|
97
|
+
const { cjk, nonLatin, symbol, latinWord, asciiPunct } = countByClass(text);
|
|
98
|
+
const tokens = cjk * CJK_TOKENS_PER_CHAR +
|
|
99
|
+
nonLatin * NON_LATIN_TOKENS_PER_CHAR +
|
|
100
|
+
symbol * SYMBOL_TOKENS_PER_CHAR +
|
|
101
|
+
asciiPunct * ASCII_PUNCT_TOKENS_PER_CHAR +
|
|
102
|
+
latinWord / LATIN_CHARS_PER_TOKEN;
|
|
52
103
|
return Math.ceil(tokens);
|
|
53
104
|
}
|
|
54
105
|
/**
|
package/dist/tokens.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amenbo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"mcpName": "io.github.Rererr/amenbo",
|
|
5
5
|
"description": "Skims the web without making waves — a Japanese-web-native MCP server for low-impact, token-efficient web collection: outline→section progressive disclosure and diff-only refetches keep context small",
|
|
6
6
|
"type": "module",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
},
|
|
30
30
|
"scripts": {
|
|
31
31
|
"build": "tsc",
|
|
32
|
+
"prepack": "npm run build",
|
|
32
33
|
"dev": "tsx src/server.ts",
|
|
33
34
|
"dev:cli": "tsx src/cli.ts",
|
|
34
35
|
"test": "vitest run",
|
|
@@ -36,7 +37,7 @@
|
|
|
36
37
|
},
|
|
37
38
|
"dependencies": {
|
|
38
39
|
"@joplin/turndown-plugin-gfm": "^1.0.67",
|
|
39
|
-
"@modelcontextprotocol/
|
|
40
|
+
"@modelcontextprotocol/server": "^2.0.0",
|
|
40
41
|
"@mozilla/readability": "^0.6.0",
|
|
41
42
|
"@napi-rs/canvas": "^1.0.2",
|
|
42
43
|
"encoding-japanese": "^2.2.0",
|
|
@@ -49,6 +50,7 @@
|
|
|
49
50
|
"zod": "^4.4.3"
|
|
50
51
|
},
|
|
51
52
|
"devDependencies": {
|
|
53
|
+
"@modelcontextprotocol/client": "^2.0.0",
|
|
52
54
|
"@types/encoding-japanese": "^2.2.1",
|
|
53
55
|
"@types/node": "^26.1.1",
|
|
54
56
|
"@types/turndown": "^5.0.6",
|