@pecot/tools-mcp 0.0.0-stage → 1.0.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.
Files changed (71) hide show
  1. package/.claude-plugin/plugin.json +8 -0
  2. package/LICENSE +21 -0
  3. package/README.md +113 -2
  4. package/bin/pecot-tools-mcp.mjs +10 -0
  5. package/cli/dist/cli.d.ts +9 -0
  6. package/cli/dist/cli.js +65 -0
  7. package/cli/dist/domain/allowlist.d.ts +228 -0
  8. package/cli/dist/domain/allowlist.js +657 -0
  9. package/cli/dist/domain/arguments.d.ts +37 -0
  10. package/cli/dist/domain/arguments.js +453 -0
  11. package/cli/dist/domain/athena-query.d.ts +22 -0
  12. package/cli/dist/domain/athena-query.js +191 -0
  13. package/cli/dist/domain/failure.d.ts +22 -0
  14. package/cli/dist/domain/failure.js +99 -0
  15. package/cli/dist/domain/redact.d.ts +5 -0
  16. package/cli/dist/domain/redact.js +38 -0
  17. package/cli/dist/domain/s3-input.d.ts +20 -0
  18. package/cli/dist/domain/s3-input.js +50 -0
  19. package/cli/dist/domain/sso-output.d.ts +23 -0
  20. package/cli/dist/domain/sso-output.js +70 -0
  21. package/cli/dist/infra/awscli.d.ts +104 -0
  22. package/cli/dist/infra/awscli.js +245 -0
  23. package/cli/dist/infra/ignore-rejection.d.ts +6 -0
  24. package/cli/dist/infra/ignore-rejection.js +13 -0
  25. package/cli/dist/infra/local-file.d.ts +9 -0
  26. package/cli/dist/infra/local-file.js +21 -0
  27. package/cli/dist/infra/sso/login-registry.d.ts +99 -0
  28. package/cli/dist/infra/sso/login-registry.js +314 -0
  29. package/cli/dist/mcp/executor.d.ts +14 -0
  30. package/cli/dist/mcp/executor.js +44 -0
  31. package/cli/dist/mcp/result.d.ts +57 -0
  32. package/cli/dist/mcp/result.js +53 -0
  33. package/cli/dist/mcp/serve.d.ts +70 -0
  34. package/cli/dist/mcp/serve.js +185 -0
  35. package/cli/dist/mcp/server.d.ts +69 -0
  36. package/cli/dist/mcp/server.js +115 -0
  37. package/cli/dist/mcp/tools/_shared.d.ts +141 -0
  38. package/cli/dist/mcp/tools/_shared.js +290 -0
  39. package/cli/dist/mcp/tools/athena.d.ts +4 -0
  40. package/cli/dist/mcp/tools/athena.js +82 -0
  41. package/cli/dist/mcp/tools/cloudwatch.d.ts +4 -0
  42. package/cli/dist/mcp/tools/cloudwatch.js +46 -0
  43. package/cli/dist/mcp/tools/ec2.d.ts +4 -0
  44. package/cli/dist/mcp/tools/ec2.js +31 -0
  45. package/cli/dist/mcp/tools/ecr.d.ts +4 -0
  46. package/cli/dist/mcp/tools/ecr.js +37 -0
  47. package/cli/dist/mcp/tools/index.d.ts +7 -0
  48. package/cli/dist/mcp/tools/index.js +37 -0
  49. package/cli/dist/mcp/tools/lambda.d.ts +4 -0
  50. package/cli/dist/mcp/tools/lambda.js +36 -0
  51. package/cli/dist/mcp/tools/logs.d.ts +4 -0
  52. package/cli/dist/mcp/tools/logs.js +74 -0
  53. package/cli/dist/mcp/tools/rds.d.ts +4 -0
  54. package/cli/dist/mcp/tools/rds.js +60 -0
  55. package/cli/dist/mcp/tools/s3.d.ts +4 -0
  56. package/cli/dist/mcp/tools/s3.js +96 -0
  57. package/cli/dist/mcp/tools/scheduler.d.ts +4 -0
  58. package/cli/dist/mcp/tools/scheduler.js +44 -0
  59. package/cli/dist/mcp/tools/sqs.d.ts +4 -0
  60. package/cli/dist/mcp/tools/sqs.js +33 -0
  61. package/cli/dist/mcp/tools/sso.d.ts +11 -0
  62. package/cli/dist/mcp/tools/sso.js +240 -0
  63. package/cli/dist/mcp/tools/sts.d.ts +4 -0
  64. package/cli/dist/mcp/tools/sts.js +15 -0
  65. package/cli/dist/node-runtime.d.ts +20 -0
  66. package/cli/dist/node-runtime.js +84 -0
  67. package/cli/dist/package.json +1 -0
  68. package/cli/dist/version.d.ts +19 -0
  69. package/cli/dist/version.js +44 -0
  70. package/npm-shrinkwrap.json +67 -0
  71. package/package.json +21 -4
@@ -0,0 +1,290 @@
1
+ // 全ツール共通の入出力スキーマと、許可リストのエントリを 1 本の実行手順へ通す処理。
2
+ //
3
+ // 系統別のツール定義(`mcp/tools/{sts,lambda,logs,sqs,athena,s3}.ts`)が宣言するのは、使うエントリと入力スキーマだけ。
4
+ // 検証 → 実行前拒否 → 引数組み立て → awscli 起動 → 失敗種別判定 → 秘匿化 → 切り詰め、という手順はここに 1 本だけ置く。
5
+ // 手順をツール側へ複製すると、秘匿化や上限の適用を忘れるおそれがある。
6
+ /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types -- call.signal は mutable なメンバを持つ。
7
+ readonly 化すると、SDK 側の型と適合しなくなる。 */
8
+ import { z } from 'zod';
9
+ import { PROFILE_PATTERN, REGION_PATTERN, } from '../../domain/allowlist.js';
10
+ import { buildArguments, validateInput } from '../../domain/arguments.js';
11
+ import { classifyFailure } from '../../domain/failure.js';
12
+ import { redactSecrets } from '../../domain/redact.js';
13
+ import { ensureAwscli, OUTPUT_LIMIT_BYTES, runAwscli } from '../../infra/awscli.js';
14
+ import { limitOutput, toCallToolResult } from '../result.js';
15
+ /**
16
+ 1 回の awscli 呼び出しに与える既定の制限時間。
17
+ */
18
+ export const TOOL_TIMEOUT_MS = 120_000;
19
+ // 終了コードの規約は、許可リストの呼び出しと SSO の呼び出しで同じ値を使う。
20
+ // 応答を読む側が 1 つの表で解釈できるようにするため。SSO 側(tools/sso.ts)から参照するので export する。
21
+ /**
22
+ awscli を起動せずに拒否したときの終了コード(UsageError 相当)。
23
+ */
24
+ export const PRE_EXECUTION_EXIT_CODE = 2;
25
+ /**
26
+ 時間切れの終了コード(coreutils timeout の慣習)。
27
+ */
28
+ export const TIMEOUT_EXIT_CODE = 124;
29
+ /**
30
+ コマンドが見つからないときの終了コード(シェルの慣習)。
31
+ */
32
+ export const COMMAND_NOT_FOUND_EXIT_CODE = 127;
33
+ /**
34
+ 終了コードを持たない失敗(シグナル終了等)の既定値。
35
+ */
36
+ export const UNKNOWN_FAILURE_EXIT_CODE = 1;
37
+ /**
38
+ `profile` だけの入力。
39
+
40
+ SSO の 2 件は region を取らない(contracts/mcp-tools.md §SSO 認証)。
41
+ そのため共通入力から profile だけを切り出し、両方が同じ書式・同じ説明文を公開できるようにする。
42
+ */
43
+ export const PROFILE_INPUT_SHAPE = {
44
+ profile: z.string().regex(PROFILE_PATTERN).optional()
45
+ .describe('AWS プロファイル名。未指定なら awscli の既定解決に従う'),
46
+ };
47
+ /**
48
+ 全ツール共通の任意入力。
49
+
50
+ 書式の定義は domain/allowlist.ts の PROFILE_PATTERN / REGION_PATTERN にある。
51
+ ここはその定数をそのまま inputSchema へ載せる(契約書の共通規約を tools/list で見せるため)。
52
+ 値を書き写さないので、定義は 1 箇所のまま。書式違反はハンドラ到達前に入力検証エラーとなる。awscli は起動しない。
53
+ */
54
+ export const COMMON_INPUT_SHAPE = {
55
+ ...PROFILE_INPUT_SHAPE,
56
+ region: z.string().regex(REGION_PATTERN).optional()
57
+ .describe('AWS リージョン(ap-northeast-1 等)。未指定なら awscli の既定解決に従う'),
58
+ };
59
+ /**
60
+ クライアント側ページング(`--max-items` / `--starting-token`)を持つツールの入力。
61
+ */
62
+ export const MAX_ITEMS_PAGINATION_SHAPE = {
63
+ max_items: z.number().int().min(1).optional().describe('1 回の応答に含める最大件数'),
64
+ starting_token: z.string().optional().describe('前回応答の nextToken。続きを取得する'),
65
+ };
66
+ /**
67
+ API 固有ページング(`logs get-log-events`)を持つツールの入力。
68
+ */
69
+ export const LIMIT_NEXT_TOKEN_PAGINATION_SHAPE = {
70
+ limit: z.number().int().min(1).max(10_000).optional().describe('取得するイベント数の上限(1〜10000)'),
71
+ next_token: z.string().optional().describe('前回応答の nextForwardToken / nextBackwardToken'),
72
+ start_from_head: z.boolean().default(false).describe('true なら古いイベントから返す'),
73
+ };
74
+ /**
75
+ ExecutionResult と同形の outputSchema。全ツールで共有する。
76
+ */
77
+ export const TOOL_OUTPUT_SCHEMA = z.object({
78
+ ok: z.boolean().describe('awscli の実行が成功したか'),
79
+ exitCode: z.number().describe('終了コード (0 = success、実行前拒否 2、時間切れ 124、未導入 127)'),
80
+ category: z.string().optional().describe('失敗種別(成功時は省略)'),
81
+ data: z.record(z.string(), z.unknown()).describe('awscli の JSON 出力、または行配列'),
82
+ artifacts: z.array(z.string()).describe('書き出したローカルファイルの絶対パス'),
83
+ message: z.string().describe('呼び出し元エージェント向けの 1 行サマリ'),
84
+ stderr: z.string().optional().describe('秘匿化済みの awscli stderr(失敗時のみ)'),
85
+ });
86
+ /**
87
+ 失敗種別ごとの再試行方法。message の後半に載せる。
88
+ */
89
+ const FAILURE_HINTS = {
90
+ 'not-allowed': '許可されていない操作です。公開しているツールの範囲で実行してください',
91
+ 'invalid-input': '入力を修正して再実行してください',
92
+ 'awscli-missing': 'awscli v2 (2.22 以上) を導入して PATH を通してください',
93
+ 'auth-missing': '認証設定がありません。aws_sso_login を実行するか profile を指定してください',
94
+ 'auth-expired': '認証の有効期限が切れています。aws_sso_login で再認証してください',
95
+ 'permission-denied': '権限が不足しています。profile / role を確認してください',
96
+ 'resource-not-found': '対象が見つかりません。名前・リージョンを確認してください',
97
+ 'timeout': '時間切れです。取得範囲を狭めて再実行してください',
98
+ 'other': 'awscli が失敗しました。stderr を確認してください',
99
+ };
100
+ /**
101
+ 出力が上限を超えたときの案内。
102
+ */
103
+ const TRUNCATION_MESSAGE = `出力が上限 ${String(OUTPUT_LIMIT_BYTES)} バイトを超えたため先頭のみ返しました。`
104
+ + 'max_items を減らすか starting_token で分割して再取得してください';
105
+ /**
106
+ stderr が上限で切り詰められたときに message へ足す注記。
107
+ */
108
+ const STDERR_TRUNCATION_NOTE = '(stderr は上限を超えたため先頭のみ載せています)';
109
+ function isRecord(value) {
110
+ return value instanceof Object && !Array.isArray(value);
111
+ }
112
+ function commonOptions(arguments_) {
113
+ const profile = arguments_['profile'];
114
+ const region = arguments_['region'];
115
+ return {
116
+ ...((typeof profile === 'string') && { profile }),
117
+ ...((typeof region === 'string') && { region }),
118
+ };
119
+ }
120
+ function parseJsonOutput(text) {
121
+ try {
122
+ const parsed = JSON.parse(text);
123
+ return isRecord(parsed) ? parsed : undefined;
124
+ }
125
+ catch {
126
+ // JSON として読めない出力(空・警告のみ等)は行配列へ落とす。
127
+ return undefined;
128
+ }
129
+ }
130
+ function toLines(text) {
131
+ const body = text.endsWith('\n') ? text.slice(0, -1) : text;
132
+ return body === '' ? [] : body.split('\n');
133
+ }
134
+ /**
135
+ 失敗種別と awscli の終了コードから応答の exitCode を決める。
136
+
137
+ exitCode を持たない失敗(シグナル終了・awscli を起動していない SSO の状態遷移)は
138
+ 省略するか null で渡し、1 以上へ畳む。ok: false と exitCode 0 が同居しないようにする。
139
+ */
140
+ export function resolveExitCode(category, exitCode) {
141
+ if (category === 'timeout')
142
+ return TIMEOUT_EXIT_CODE;
143
+ if (category === 'awscli-missing')
144
+ return COMMAND_NOT_FOUND_EXIT_CODE;
145
+ return exitCode ?? UNKNOWN_FAILURE_EXIT_CODE;
146
+ }
147
+ function failureMessage(toolName, category) {
148
+ // eslint-disable-next-line security/detect-object-injection -- category は FailureCategory の列挙値
149
+ return `${toolName} が失敗しました (${category})。${FAILURE_HINTS[category]}`;
150
+ }
151
+ /**
152
+ 成功時の data。JSON 出力はそのまま、非 JSON 出力は行配列にする。
153
+ */
154
+ function successData(entry, stdout) {
155
+ const parsed = entry.jsonOutput ? parseJsonOutput(stdout) : undefined;
156
+ if (parsed === undefined)
157
+ return { lines: toLines(stdout) };
158
+ const nextToken = parsed['NextToken'];
159
+ return typeof nextToken === 'string' && entry.pagination === 'max-items' ? { ...parsed, nextToken } : parsed;
160
+ }
161
+ /**
162
+ 許可リストのエントリ 1 件を実行し、ExecutionResult を返す。
163
+
164
+ 検証で弾いた場合は awscli を起動しない(exitCode 2)。awscli の失敗は種別判定にかけ、
165
+ 応答へ載せる stdout / stderr は必ず秘匿化と上限を通す。
166
+ */
167
+ export async function executeAllowlisted(entry, arguments_, call, options = {}) {
168
+ const invalid = validateInput(entry, arguments_);
169
+ if (invalid !== undefined) {
170
+ return {
171
+ ok: false,
172
+ exitCode: PRE_EXECUTION_EXIT_CODE,
173
+ category: invalid.category,
174
+ data: {},
175
+ artifacts: [],
176
+ message: invalid.message,
177
+ };
178
+ }
179
+ const rejected = options.reject?.(arguments_);
180
+ if (rejected !== undefined) {
181
+ return {
182
+ ok: false,
183
+ exitCode: PRE_EXECUTION_EXIT_CODE,
184
+ category: rejected.category,
185
+ data: {},
186
+ artifacts: [],
187
+ message: rejected.message,
188
+ };
189
+ }
190
+ const probe = await ensureAwscli();
191
+ if (!probe.ok) {
192
+ return {
193
+ ok: false,
194
+ exitCode: COMMAND_NOT_FOUND_EXIT_CODE,
195
+ category: probe.category,
196
+ data: {},
197
+ artifacts: [],
198
+ message: probe.message,
199
+ };
200
+ }
201
+ const result = await runAwscli(buildArguments(entry, arguments_, commonOptions(arguments_)), {
202
+ timeoutMs: options.timeoutMs ?? TOOL_TIMEOUT_MS,
203
+ signal: call.signal,
204
+ });
205
+ if (result.timedOut || result.exitCode !== 0) {
206
+ const category = classifyFailure({
207
+ exitCode: result.exitCode,
208
+ stderr: result.stderr,
209
+ timedOut: result.timedOut,
210
+ ...(result.spawnErrorCode !== undefined && { spawnErrorCode: result.spawnErrorCode }),
211
+ });
212
+ // 巨大な stderr は先頭だけを載せる。通知せず欠けると読み手が全文だと誤認するため、
213
+ // 切り詰めたことを message に残す。
214
+ const limitedStderr = limitOutput(redactSecrets(result.stderr));
215
+ return {
216
+ ok: false,
217
+ exitCode: resolveExitCode(category, result.exitCode),
218
+ category,
219
+ data: {},
220
+ artifacts: [],
221
+ message: failureMessage(entry.toolName, category)
222
+ + (limitedStderr.truncated ? STDERR_TRUNCATION_NOTE : ''),
223
+ stderr: limitedStderr.text,
224
+ };
225
+ }
226
+ // artifacts は切り詰めの有無に依らず載せる。書き出しは awscli 側で完了しており、
227
+ // 応答の切り詰めは「出力が長い」ことしか意味しないため。
228
+ const artifacts = options.artifactsOf?.(arguments_) ?? [];
229
+ const limited = limitOutput(redactSecrets(result.stdout));
230
+ if (limited.truncated) {
231
+ return {
232
+ ok: true,
233
+ exitCode: 0,
234
+ data: { output: limited.text, truncated: true },
235
+ artifacts,
236
+ message: TRUNCATION_MESSAGE,
237
+ };
238
+ }
239
+ return {
240
+ ok: true,
241
+ exitCode: 0,
242
+ data: successData(entry, limited.text),
243
+ artifacts,
244
+ message: `${entry.toolName} が成功しました`,
245
+ };
246
+ }
247
+ /**
248
+ annotations を許可リストの kind から導く。
249
+
250
+ 契約表の「読取専用」列は read だけが true で、fetch(ローカルへ書き出す)と
251
+ execute(Athena のクエリ起動)は false。destructiveHint は fetch だけ true にする:
252
+ `overwrite: true` の呼び出しはローカルの既存ファイルを上書きして戻せない。
253
+ openWorldHint は AWS API へ到達するので全件 true。
254
+
255
+ 契約書の共通規約も destructiveHint を fetch 2 件だけ true と定めており、ここはそれと一致する。
256
+ */
257
+ function annotationsOf(entry) {
258
+ return {
259
+ readOnlyHint: entry.kind === 'read',
260
+ destructiveHint: entry.kind === 'fetch',
261
+ openWorldHint: true,
262
+ };
263
+ }
264
+ /**
265
+ 許可リストのエントリ 1 件を MCP ツール定義にする。
266
+
267
+ 入力の検証は 2 段になる。
268
+ inputSchema(型・列挙・書式)は SDK がハンドラ到達前に見て、入力検証エラーを返す。
269
+ 許可リスト側の規則(先頭 '-'・排他・shorthand の構成要素)は、executeAllowlisted が見て isError の応答にする。ハンドラで再度 zod parse はしない
270
+ (SDK が既に未知キーの除去と default の適用を済ませている)。
271
+ */
272
+ export function allowlistedTool(spec, options = {}) {
273
+ const executeOptions = {
274
+ ...(options.timeoutMs !== undefined && { timeoutMs: options.timeoutMs }),
275
+ ...(spec.reject !== undefined && { reject: spec.reject }),
276
+ ...(spec.artifactsOf !== undefined && { artifactsOf: spec.artifactsOf }),
277
+ };
278
+ return {
279
+ name: spec.entry.toolName,
280
+ config: {
281
+ title: spec.title,
282
+ description: spec.description,
283
+ inputSchema: spec.inputSchema,
284
+ outputSchema: TOOL_OUTPUT_SCHEMA,
285
+ annotations: annotationsOf(spec.entry),
286
+ },
287
+ handler: async (arguments_, call) => toCallToolResult(await executeAllowlisted(spec.entry, arguments_, call, executeOptions)),
288
+ };
289
+ }
290
+ //# sourceMappingURL=_shared.js.map
@@ -0,0 +1,4 @@
1
+ import type { ToolDefinition } from '../server.js';
2
+ import { type ToolOptions } from './_shared.js';
3
+ export declare function athenaTools(options?: Readonly<ToolOptions>): readonly ToolDefinition[];
4
+ //# sourceMappingURL=athena.d.ts.map
@@ -0,0 +1,82 @@
1
+ // Athena 系のツール定義。
2
+ //
3
+ // start-query-execution だけは許可リストの静的宣言でクエリ内容を縛れないため、
4
+ // 実行前拒否(reject)で参照専用クエリ以外を落とす。
5
+ import { z } from 'zod';
6
+ import { ATHENA_GET_QUERY_EXECUTION, ATHENA_GET_QUERY_RESULTS, ATHENA_START_QUERY_EXECUTION, } from '../../domain/allowlist.js';
7
+ import { classifyAthenaQuery } from '../../domain/athena-query.js';
8
+ import { allowlistedTool, COMMON_INPUT_SHAPE, MAX_ITEMS_PAGINATION_SHAPE, } from './_shared.js';
9
+ /**
10
+ 参照専用でないクエリを not-allowed で落とす。
11
+
12
+ query_string が文字列でない場合は undefined を返し、必須入力の検証(invalid-input)へ委ねる。
13
+ ここで別種別を返すと「必須入力の欠落」が「許可されていない操作」に化ける。
14
+ */
15
+ function rejectNonReadOnlyQuery(arguments_) {
16
+ const query = arguments_['query_string'];
17
+ if (typeof query !== 'string')
18
+ return undefined;
19
+ const classified = classifyAthenaQuery(query);
20
+ return classified.allowed
21
+ ? undefined
22
+ : { category: 'not-allowed', message: classified.message };
23
+ }
24
+ /**
25
+ catalog の単独指定を invalid-input で落とす。
26
+
27
+ 契約書は catalog を「database と併用」と定めている。
28
+ 組み立て自体は `--query-execution-context Catalog=…` を作れてしまう。
29
+ ただし Database を欠いた QueryExecutionContext を実 Athena API が受けるかは未確認なので、契約の範囲へ寄せる。
30
+ */
31
+ function rejectCatalogWithoutDatabase(arguments_) {
32
+ if ((typeof arguments_['catalog'] !== 'string') || (typeof arguments_['database'] === 'string'))
33
+ return undefined;
34
+ return {
35
+ category: 'invalid-input',
36
+ message: 'catalog は database と併せて指定してください',
37
+ };
38
+ }
39
+ /**
40
+ start-query-execution の実行前拒否。クエリ内容 → catalog の順に見る。
41
+ */
42
+ function rejectStartQueryExecution(arguments_) {
43
+ return rejectNonReadOnlyQuery(arguments_) ?? rejectCatalogWithoutDatabase(arguments_);
44
+ }
45
+ export function athenaTools(options = {}) {
46
+ return [
47
+ allowlistedTool({
48
+ entry: ATHENA_START_QUERY_EXECUTION,
49
+ title: 'クエリの実行開始',
50
+ description: '参照クエリ(SELECT / WITH / SHOW / DESCRIBE / EXPLAIN)の実行を開始し query_execution_id を返す。変更系と複数文は実行前に拒否する。結果は aws_athena_get_query_execution で完了を待ってから aws_athena_get_query_results で取る',
51
+ inputSchema: z.object({
52
+ query_string: z.string().describe('実行する参照クエリ。1 文だけを指定し、先頭は SELECT / WITH / SHOW / DESCRIBE / EXPLAIN のいずれかにする(括弧で囲まない)'),
53
+ work_group: z.string().optional().describe('ワークグループ名'),
54
+ database: z.string().optional().describe('既定のデータベース名'),
55
+ catalog: z.string().optional().describe('データカタログ名。database と併せて指定する(単独指定はしない)'),
56
+ output_location: z.string().optional().describe('結果の出力先(s3:// で始まる)'),
57
+ ...COMMON_INPUT_SHAPE,
58
+ }),
59
+ reject: rejectStartQueryExecution,
60
+ }, options),
61
+ allowlistedTool({
62
+ entry: ATHENA_GET_QUERY_EXECUTION,
63
+ title: 'クエリ実行状態の取得',
64
+ description: 'クエリ実行の状態(QUEUED / RUNNING / SUCCEEDED / FAILED / CANCELLED)と統計を返す',
65
+ inputSchema: z.object({
66
+ query_execution_id: z.string().describe('aws_athena_start_query_execution が返した ID'),
67
+ ...COMMON_INPUT_SHAPE,
68
+ }),
69
+ }, options),
70
+ allowlistedTool({
71
+ entry: ATHENA_GET_QUERY_RESULTS,
72
+ title: 'クエリ結果の取得',
73
+ description: '完了したクエリの結果行を返す。件数が多い場合は max_items と starting_token で分割する',
74
+ inputSchema: z.object({
75
+ query_execution_id: z.string().describe('aws_athena_start_query_execution が返した ID'),
76
+ ...MAX_ITEMS_PAGINATION_SHAPE,
77
+ ...COMMON_INPUT_SHAPE,
78
+ }),
79
+ }, options),
80
+ ];
81
+ }
82
+ //# sourceMappingURL=athena.js.map
@@ -0,0 +1,4 @@
1
+ import type { ToolDefinition } from '../server.js';
2
+ import { type ToolOptions } from './_shared.js';
3
+ export declare function cloudwatchTools(options?: Readonly<ToolOptions>): readonly ToolDefinition[];
4
+ //# sourceMappingURL=cloudwatch.d.ts.map
@@ -0,0 +1,46 @@
1
+ // CloudWatch(メトリクス)系のツール定義。
2
+ //
3
+ // ログ系は logs.ts が持つ。こちらはメトリクスの統計取得だけを公開する。
4
+ import { z } from 'zod';
5
+ import { CLOUDWATCH_GET_METRIC_STATISTICS, CLOUDWATCH_UNIT_VALUES } from '../../domain/allowlist.js';
6
+ import { allowlistedTool, COMMON_INPUT_SHAPE } from './_shared.js';
7
+ /**
8
+ ディメンション 1 件。`z.object` は宣言外のキーを通知せず削るため strictObject を使う。
9
+ JSON Schema では `items.additionalProperties: false` になり、SDK が入力検証エラーで拒否する。
10
+ */
11
+ const DIMENSION_ELEMENT = z.strictObject({
12
+ name: z.string().describe('ディメンション名(QueueName・FunctionName 等)'),
13
+ value: z.string().describe('ディメンション値'),
14
+ });
15
+ /**
16
+ 取得できる統計値。パーセンタイル(ExtendedStatistics)は公開しない。
17
+ */
18
+ const STATISTIC_ENUM = z.enum(['SampleCount', 'Average', 'Sum', 'Minimum', 'Maximum']);
19
+ /**
20
+ CloudWatch の標準単位。許可リストと同じ配列を読む(綴りの定義は allowlist.ts)。
21
+ */
22
+ const UNIT_ENUM = z.enum(CLOUDWATCH_UNIT_VALUES);
23
+ export function cloudwatchTools(options = {}) {
24
+ return [
25
+ allowlistedTool({
26
+ entry: CLOUDWATCH_GET_METRIC_STATISTICS,
27
+ title: 'メトリクス統計の取得',
28
+ description: 'メトリクス 1 本の統計値を期間指定で取得する。dimensions はメトリクス作成時と同じ組み合わせを全て指定しないと空の結果になる',
29
+ inputSchema: z.object({
30
+ namespace: z.string().describe('メトリクスの名前空間(AWS/SQS・AWS/Lambda 等)'),
31
+ metric_name: z.string().describe('メトリクス名(NumberOfMessagesSent 等)'),
32
+ dimensions: z.array(DIMENSION_ELEMENT).max(30).optional()
33
+ .describe('絞り込むディメンション。メトリクスが持つ組み合わせを過不足なく指定する'),
34
+ start_time: z.string().describe('取得開始時刻。ISO 8601 形式で、タイムゾーン(Z か +09:00 形式)必須(2026-09-01T00:00:00Z / 2026-09-01T09:00:00+09:00)'),
35
+ end_time: z.string().describe('取得終了時刻。ISO 8601 形式で、タイムゾーン(Z か +09:00 形式)必須(start_time と同じ書式)'),
36
+ period: z.number().int().min(1).describe('集計間隔(秒)。60 の倍数で指定する'),
37
+ statistics: z.array(STATISTIC_ENUM).min(1).max(5)
38
+ .describe('取得する統計値。1〜5 件を指定する'),
39
+ unit: UNIT_ENUM.optional()
40
+ .describe('絞り込む単位。データの単位と一致しないと結果が空になる'),
41
+ ...COMMON_INPUT_SHAPE,
42
+ }),
43
+ }, options),
44
+ ];
45
+ }
46
+ //# sourceMappingURL=cloudwatch.js.map
@@ -0,0 +1,4 @@
1
+ import type { ToolDefinition } from '../server.js';
2
+ import { type ToolOptions } from './_shared.js';
3
+ export declare function ec2Tools(options?: Readonly<ToolOptions>): readonly ToolDefinition[];
4
+ //# sourceMappingURL=ec2.d.ts.map
@@ -0,0 +1,31 @@
1
+ // EC2 系のツール定義。
2
+ import { z } from 'zod';
3
+ import { EC2_DESCRIBE_INSTANCES } from '../../domain/allowlist.js';
4
+ import { allowlistedTool, COMMON_INPUT_SHAPE, MAX_ITEMS_PAGINATION_SHAPE, } from './_shared.js';
5
+ /**
6
+ 絞り込み条件 1 件。`values` のいずれかに一致すれば対象になる。
7
+
8
+ `z.object` は宣言外のキーを通知せず削るため strictObject を使う。
9
+ JSON Schema では `items.additionalProperties: false` になり、SDK が入力検証エラーで拒否する。
10
+ */
11
+ const FILTER_ELEMENT = z.strictObject({
12
+ name: z.string().describe('フィルタ名(instance-state-name・tag:Name 等)'),
13
+ values: z.array(z.string()).min(1).describe('いずれかに一致すれば対象になる値'),
14
+ });
15
+ const INSTANCE_IDS_INPUT = z.array(z.string()).min(1).optional().describe('取得するインスタンス ID(i-… の形式)');
16
+ export function ec2Tools(options = {}) {
17
+ return [
18
+ allowlistedTool({
19
+ entry: EC2_DESCRIBE_INSTANCES,
20
+ title: 'EC2 インスタンスの一覧',
21
+ description: 'インスタンスの状態・タイプ・タグ・ネットワーク構成を返す。出力が大きいので max_items か filters で絞る',
22
+ inputSchema: z.object({
23
+ instance_ids: INSTANCE_IDS_INPUT,
24
+ filters: z.array(FILTER_ELEMENT).optional().describe('絞り込み条件。複数指定すると全てに一致するものが返る'),
25
+ ...MAX_ITEMS_PAGINATION_SHAPE,
26
+ ...COMMON_INPUT_SHAPE,
27
+ }),
28
+ }, options),
29
+ ];
30
+ }
31
+ //# sourceMappingURL=ec2.js.map
@@ -0,0 +1,4 @@
1
+ import type { ToolDefinition } from '../server.js';
2
+ import { type ToolOptions } from './_shared.js';
3
+ export declare function ecrTools(options?: Readonly<ToolOptions>): readonly ToolDefinition[];
4
+ //# sourceMappingURL=ecr.d.ts.map
@@ -0,0 +1,37 @@
1
+ // ECR 系のツール定義。
2
+ //
3
+ // tag_status は awscli の `--filter tagStatus=<値>` へ合成する(許可リスト側の shorthand)。
4
+ // 利用者に shorthand の文字列そのものを書かせないのは Athena と同じ理由。
5
+ import { z } from 'zod';
6
+ import { ECR_DESCRIBE_IMAGES } from '../../domain/allowlist.js';
7
+ import { allowlistedTool, COMMON_INPUT_SHAPE, MAX_ITEMS_PAGINATION_SHAPE, } from './_shared.js';
8
+ /**
9
+ 取得するイメージの指定 1 件。タグとダイジェストのどちらか一方だけでも指定できる。
10
+
11
+ `z.object` は宣言外のキーを通知せず削るため strictObject を使う。
12
+ JSON Schema では `items.additionalProperties: false` になり、SDK が入力検証エラーで拒否する。
13
+ */
14
+ const IMAGE_ID_ELEMENT = z.strictObject({
15
+ image_tag: z.string().optional().describe('イメージタグ'),
16
+ image_digest: z.string().optional().describe('イメージダイジェスト(sha256:… の形式)'),
17
+ });
18
+ export function ecrTools(options = {}) {
19
+ return [
20
+ allowlistedTool({
21
+ entry: ECR_DESCRIBE_IMAGES,
22
+ title: 'コンテナイメージの一覧',
23
+ description: 'リポジトリ内のイメージのタグ・ダイジェスト・push 時刻を返す。デプロイ時刻の確認に使う。未指定時は ACTIVE のイメージのみが返る',
24
+ inputSchema: z.object({
25
+ repository_name: z.string().describe('リポジトリ名'),
26
+ registry_id: z.string().optional().describe('レジストリの AWS アカウント ID(12 桁)。未指定なら既定のレジストリ'),
27
+ image_ids: z.array(IMAGE_ID_ELEMENT).max(100).optional()
28
+ .describe('取得するイメージの指定。要素ごとに image_tag と image_digest の少なくとも一方が必要。starting_token とは併用できない'),
29
+ tag_status: z.enum(['TAGGED', 'UNTAGGED', 'ANY']).optional()
30
+ .describe('タグの有無で絞り込む。未指定なら絞り込まない'),
31
+ ...MAX_ITEMS_PAGINATION_SHAPE,
32
+ ...COMMON_INPUT_SHAPE,
33
+ }),
34
+ }, options),
35
+ ];
36
+ }
37
+ //# sourceMappingURL=ecr.js.map
@@ -0,0 +1,7 @@
1
+ import type { ToolDefinition } from '../server.js';
2
+ import type { ToolOptions } from './_shared.js';
3
+ /**
4
+ tools/list に公開するツール。並びはそのまま tools/list の並びになる。
5
+ */
6
+ export declare function allTools(options?: Readonly<ToolOptions>): readonly ToolDefinition[];
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,37 @@
1
+ // 公開するツールの集約。serve.ts が createMcpServer() へ渡す。
2
+ //
3
+ // 並びは contracts/mcp-tools.md の表の順で、そのまま tools/list の並びになる。SSO の 2 件は
4
+ // 契約書で許可リストの表より前に置かれているため先頭に来る(許可リストには入らない)。
5
+ // 系統別の関数へ分けているのは、1 系統を足すときに触るファイルを閉じるため。
6
+ import { athenaTools } from './athena.js';
7
+ import { cloudwatchTools } from './cloudwatch.js';
8
+ import { ec2Tools } from './ec2.js';
9
+ import { ecrTools } from './ecr.js';
10
+ import { lambdaTools } from './lambda.js';
11
+ import { logsTools } from './logs.js';
12
+ import { rdsTools } from './rds.js';
13
+ import { s3Tools } from './s3.js';
14
+ import { schedulerTools } from './scheduler.js';
15
+ import { sqsTools } from './sqs.js';
16
+ import { ssoTools } from './sso.js';
17
+ import { stsTools } from './sts.js';
18
+ /**
19
+ tools/list に公開するツール。並びはそのまま tools/list の並びになる。
20
+ */
21
+ export function allTools(options = {}) {
22
+ return [
23
+ ...ssoTools(options),
24
+ ...stsTools(options),
25
+ ...lambdaTools(options),
26
+ ...logsTools(options),
27
+ ...cloudwatchTools(options),
28
+ ...sqsTools(options),
29
+ ...athenaTools(options),
30
+ ...s3Tools(options),
31
+ ...rdsTools(options),
32
+ ...schedulerTools(options),
33
+ ...ecrTools(options),
34
+ ...ec2Tools(options),
35
+ ];
36
+ }
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,4 @@
1
+ import type { ToolDefinition } from '../server.js';
2
+ import { type ToolOptions } from './_shared.js';
3
+ export declare function lambdaTools(options?: Readonly<ToolOptions>): readonly ToolDefinition[];
4
+ //# sourceMappingURL=lambda.d.ts.map
@@ -0,0 +1,36 @@
1
+ // Lambda 系のツール定義。
2
+ import { z } from 'zod';
3
+ import { LAMBDA_GET_FUNCTION_CONFIGURATION, LAMBDA_LIST_EVENT_SOURCE_MAPPINGS, LAMBDA_LIST_FUNCTIONS, } from '../../domain/allowlist.js';
4
+ import { allowlistedTool, COMMON_INPUT_SHAPE, MAX_ITEMS_PAGINATION_SHAPE, } from './_shared.js';
5
+ export function lambdaTools(options = {}) {
6
+ return [
7
+ allowlistedTool({
8
+ entry: LAMBDA_LIST_FUNCTIONS,
9
+ title: 'Lambda 関数の一覧',
10
+ description: 'リージョン内の Lambda 関数を一覧する。件数が多い場合は max_items と starting_token で分割する',
11
+ inputSchema: z.object({ ...MAX_ITEMS_PAGINATION_SHAPE, ...COMMON_INPUT_SHAPE }),
12
+ }, options),
13
+ allowlistedTool({
14
+ entry: LAMBDA_GET_FUNCTION_CONFIGURATION,
15
+ title: 'Lambda 関数の構成取得',
16
+ description: '関数 1 件の構成(ランタイム・ハンドラ・環境変数・タイムアウト等)を返す',
17
+ inputSchema: z.object({
18
+ function_name: z.string().describe('関数名・部分 ARN・完全 ARN のいずれか'),
19
+ qualifier: z.string().optional().describe('バージョン番号またはエイリアス名。未指定なら $LATEST'),
20
+ ...COMMON_INPUT_SHAPE,
21
+ }),
22
+ }, options),
23
+ allowlistedTool({
24
+ entry: LAMBDA_LIST_EVENT_SOURCE_MAPPINGS,
25
+ title: 'イベントソースマッピングの一覧',
26
+ description: '関数とイベントソース(SQS キュー・DynamoDB ストリーム等)の対応を一覧する。event_source_arn と function_name のどちらでも絞れる',
27
+ inputSchema: z.object({
28
+ event_source_arn: z.string().optional().describe('イベントソースの ARN(arn: で始まる)'),
29
+ function_name: z.string().optional().describe('関数名・部分 ARN・完全 ARN のいずれか'),
30
+ ...MAX_ITEMS_PAGINATION_SHAPE,
31
+ ...COMMON_INPUT_SHAPE,
32
+ }),
33
+ }, options),
34
+ ];
35
+ }
36
+ //# sourceMappingURL=lambda.js.map
@@ -0,0 +1,4 @@
1
+ import type { ToolDefinition } from '../server.js';
2
+ import { type ToolOptions } from './_shared.js';
3
+ export declare function logsTools(options?: Readonly<ToolOptions>): readonly ToolDefinition[];
4
+ //# sourceMappingURL=logs.d.ts.map