@pecot/tools-mcp 0.0.0-stage → 1.0.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/.claude-plugin/plugin.json +8 -0
- package/LICENSE +21 -0
- package/README.md +113 -2
- package/bin/pecot-tools-mcp.mjs +10 -0
- package/cli/dist/cli.d.ts +9 -0
- package/cli/dist/cli.js +65 -0
- package/cli/dist/domain/allowlist.d.ts +228 -0
- package/cli/dist/domain/allowlist.js +657 -0
- package/cli/dist/domain/arguments.d.ts +37 -0
- package/cli/dist/domain/arguments.js +453 -0
- package/cli/dist/domain/athena-query.d.ts +22 -0
- package/cli/dist/domain/athena-query.js +191 -0
- package/cli/dist/domain/failure.d.ts +22 -0
- package/cli/dist/domain/failure.js +99 -0
- package/cli/dist/domain/redact.d.ts +5 -0
- package/cli/dist/domain/redact.js +38 -0
- package/cli/dist/domain/s3-input.d.ts +20 -0
- package/cli/dist/domain/s3-input.js +50 -0
- package/cli/dist/domain/sso-output.d.ts +23 -0
- package/cli/dist/domain/sso-output.js +70 -0
- package/cli/dist/infra/awscli.d.ts +104 -0
- package/cli/dist/infra/awscli.js +245 -0
- package/cli/dist/infra/ignore-rejection.d.ts +6 -0
- package/cli/dist/infra/ignore-rejection.js +13 -0
- package/cli/dist/infra/local-file.d.ts +9 -0
- package/cli/dist/infra/local-file.js +21 -0
- package/cli/dist/infra/sso/login-registry.d.ts +99 -0
- package/cli/dist/infra/sso/login-registry.js +314 -0
- package/cli/dist/mcp/executor.d.ts +14 -0
- package/cli/dist/mcp/executor.js +44 -0
- package/cli/dist/mcp/result.d.ts +57 -0
- package/cli/dist/mcp/result.js +53 -0
- package/cli/dist/mcp/serve.d.ts +70 -0
- package/cli/dist/mcp/serve.js +185 -0
- package/cli/dist/mcp/server.d.ts +69 -0
- package/cli/dist/mcp/server.js +115 -0
- package/cli/dist/mcp/tools/_shared.d.ts +141 -0
- package/cli/dist/mcp/tools/_shared.js +290 -0
- package/cli/dist/mcp/tools/athena.d.ts +4 -0
- package/cli/dist/mcp/tools/athena.js +82 -0
- package/cli/dist/mcp/tools/cloudwatch.d.ts +4 -0
- package/cli/dist/mcp/tools/cloudwatch.js +46 -0
- package/cli/dist/mcp/tools/ec2.d.ts +4 -0
- package/cli/dist/mcp/tools/ec2.js +31 -0
- package/cli/dist/mcp/tools/ecr.d.ts +4 -0
- package/cli/dist/mcp/tools/ecr.js +37 -0
- package/cli/dist/mcp/tools/index.d.ts +7 -0
- package/cli/dist/mcp/tools/index.js +37 -0
- package/cli/dist/mcp/tools/lambda.d.ts +4 -0
- package/cli/dist/mcp/tools/lambda.js +36 -0
- package/cli/dist/mcp/tools/logs.d.ts +4 -0
- package/cli/dist/mcp/tools/logs.js +74 -0
- package/cli/dist/mcp/tools/rds.d.ts +4 -0
- package/cli/dist/mcp/tools/rds.js +60 -0
- package/cli/dist/mcp/tools/s3.d.ts +4 -0
- package/cli/dist/mcp/tools/s3.js +96 -0
- package/cli/dist/mcp/tools/scheduler.d.ts +4 -0
- package/cli/dist/mcp/tools/scheduler.js +44 -0
- package/cli/dist/mcp/tools/sqs.d.ts +4 -0
- package/cli/dist/mcp/tools/sqs.js +33 -0
- package/cli/dist/mcp/tools/sso.d.ts +11 -0
- package/cli/dist/mcp/tools/sso.js +240 -0
- package/cli/dist/mcp/tools/sts.d.ts +4 -0
- package/cli/dist/mcp/tools/sts.js +15 -0
- package/cli/dist/node-runtime.d.ts +20 -0
- package/cli/dist/node-runtime.js +84 -0
- package/cli/dist/package.json +1 -0
- package/cli/dist/version.d.ts +19 -0
- package/cli/dist/version.js +44 -0
- package/npm-shrinkwrap.json +67 -0
- package/package.json +21 -4
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// CloudWatch Logs 系のツール定義。
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { LOGS_DESCRIBE_LOG_GROUPS, LOGS_DESCRIBE_LOG_STREAMS, LOGS_FILTER_LOG_EVENTS, LOGS_GET_LOG_EVENTS, } from '../../domain/allowlist.js';
|
|
4
|
+
import { allowlistedTool, COMMON_INPUT_SHAPE, LIMIT_NEXT_TOKEN_PAGINATION_SHAPE, MAX_ITEMS_PAGINATION_SHAPE, } from './_shared.js';
|
|
5
|
+
/**
|
|
6
|
+
並び順の指定。既定は昇順(false)。
|
|
7
|
+
*/
|
|
8
|
+
const DESCENDING_INPUT = z.boolean().default(false).describe('true なら降順に並べる');
|
|
9
|
+
/**
|
|
10
|
+
検索対象のログストリーム名の一覧。
|
|
11
|
+
*/
|
|
12
|
+
const LOG_STREAM_NAMES_INPUT = z.array(z.string()).optional()
|
|
13
|
+
.describe('検索対象のログストリーム名。log_stream_name_prefix とは併用できない');
|
|
14
|
+
/**
|
|
15
|
+
期間の絞り込み。epoch ミリ秒で、両ツールとも同じ意味を持つ。
|
|
16
|
+
*/
|
|
17
|
+
const TIME_RANGE_SHAPE = {
|
|
18
|
+
start_time: z.number().int().optional().describe('取得開始時刻(UNIX epoch ミリ秒)'),
|
|
19
|
+
end_time: z.number().int().optional().describe('取得終了時刻(UNIX epoch ミリ秒)'),
|
|
20
|
+
};
|
|
21
|
+
export function logsTools(options = {}) {
|
|
22
|
+
return [
|
|
23
|
+
allowlistedTool({
|
|
24
|
+
entry: LOGS_DESCRIBE_LOG_GROUPS,
|
|
25
|
+
title: 'ロググループの一覧',
|
|
26
|
+
description: 'CloudWatch Logs のロググループを一覧する。log_group_name_prefix で前方一致に絞れる',
|
|
27
|
+
inputSchema: z.object({
|
|
28
|
+
log_group_name_prefix: z.string().optional().describe('ロググループ名の前方一致'),
|
|
29
|
+
...MAX_ITEMS_PAGINATION_SHAPE,
|
|
30
|
+
...COMMON_INPUT_SHAPE,
|
|
31
|
+
}),
|
|
32
|
+
}, options),
|
|
33
|
+
allowlistedTool({
|
|
34
|
+
entry: LOGS_DESCRIBE_LOG_STREAMS,
|
|
35
|
+
title: 'ログストリームの一覧',
|
|
36
|
+
description: 'ロググループ内のログストリームを一覧する。最新のストリームを探すには order_by に LastEventTime を指定して descending を true にする',
|
|
37
|
+
inputSchema: z.object({
|
|
38
|
+
log_group_name: z.string().describe('対象のロググループ名'),
|
|
39
|
+
log_stream_name_prefix: z.string().optional().describe('ログストリーム名の前方一致'),
|
|
40
|
+
order_by: z.enum(['LogStreamName', 'LastEventTime']).optional().describe('並び替えの基準'),
|
|
41
|
+
descending: DESCENDING_INPUT,
|
|
42
|
+
...MAX_ITEMS_PAGINATION_SHAPE,
|
|
43
|
+
...COMMON_INPUT_SHAPE,
|
|
44
|
+
}),
|
|
45
|
+
}, options),
|
|
46
|
+
allowlistedTool({
|
|
47
|
+
entry: LOGS_GET_LOG_EVENTS,
|
|
48
|
+
title: 'ログイベントの取得',
|
|
49
|
+
description: 'ログストリーム 1 本のイベントを取得する。続きは応答の nextForwardToken を next_token に渡す',
|
|
50
|
+
inputSchema: z.object({
|
|
51
|
+
log_group_name: z.string().describe('対象のロググループ名'),
|
|
52
|
+
log_stream_name: z.string().describe('対象のログストリーム名'),
|
|
53
|
+
...TIME_RANGE_SHAPE,
|
|
54
|
+
...LIMIT_NEXT_TOKEN_PAGINATION_SHAPE,
|
|
55
|
+
...COMMON_INPUT_SHAPE,
|
|
56
|
+
}),
|
|
57
|
+
}, options),
|
|
58
|
+
allowlistedTool({
|
|
59
|
+
entry: LOGS_FILTER_LOG_EVENTS,
|
|
60
|
+
title: 'ログイベントの検索',
|
|
61
|
+
description: 'ロググループ横断でログイベントを検索する。log_stream_names と log_stream_name_prefix は同時に指定できない',
|
|
62
|
+
inputSchema: z.object({
|
|
63
|
+
log_group_name: z.string().describe('対象のロググループ名'),
|
|
64
|
+
log_stream_names: LOG_STREAM_NAMES_INPUT,
|
|
65
|
+
log_stream_name_prefix: z.string().optional().describe('検索対象のログストリーム名の前方一致。log_stream_names とは併用できない'),
|
|
66
|
+
filter_pattern: z.string().optional().describe('CloudWatch Logs のフィルタパターン'),
|
|
67
|
+
...TIME_RANGE_SHAPE,
|
|
68
|
+
...MAX_ITEMS_PAGINATION_SHAPE,
|
|
69
|
+
...COMMON_INPUT_SHAPE,
|
|
70
|
+
}),
|
|
71
|
+
}, options),
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=logs.js.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// RDS 系のツール定義。
|
|
2
|
+
//
|
|
3
|
+
// 3 件とも `--filters` は公開しない。API が受ける属性はバージョンで変わるため、契約に固定できる
|
|
4
|
+
// 引数だけに絞っている。
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { RDS_DESCRIBE_DB_CLUSTERS, RDS_DESCRIBE_DB_INSTANCES, RDS_DESCRIBE_EVENTS, RDS_SOURCE_TYPE_VALUES, } from '../../domain/allowlist.js';
|
|
7
|
+
import { allowlistedTool, COMMON_INPUT_SHAPE, MAX_ITEMS_PAGINATION_SHAPE, } from './_shared.js';
|
|
8
|
+
/**
|
|
9
|
+
イベントを引ける発生元の種別。許可リストと同じ配列を読む(綴りの定義元は allowlist.ts)。
|
|
10
|
+
*/
|
|
11
|
+
const SOURCE_TYPE_ENUM = z.enum(RDS_SOURCE_TYPE_VALUES);
|
|
12
|
+
/**
|
|
13
|
+
絞り込むイベントカテゴリ。
|
|
14
|
+
*/
|
|
15
|
+
const EVENT_CATEGORIES_INPUT = z.array(z.string()).min(1).optional()
|
|
16
|
+
.describe('絞り込むイベントカテゴリ(availability・failover 等)');
|
|
17
|
+
export function rdsTools(options = {}) {
|
|
18
|
+
return [
|
|
19
|
+
allowlistedTool({
|
|
20
|
+
entry: RDS_DESCRIBE_EVENTS,
|
|
21
|
+
title: 'RDS イベントの取得',
|
|
22
|
+
description: 'DB インスタンス・クラスタのイベント履歴(停止・起動・フェイルオーバー等)を返す。指定しない場合は直近 1 時間ぶんで、保持期間は 14 日',
|
|
23
|
+
inputSchema: z.object({
|
|
24
|
+
source_identifier: z.string().optional()
|
|
25
|
+
.describe('イベントの発生元の識別子。指定するときは source_type も併せて指定する'),
|
|
26
|
+
source_type: SOURCE_TYPE_ENUM.optional().describe('イベントの発生元の種別'),
|
|
27
|
+
start_time: z.string().optional()
|
|
28
|
+
.describe('取得開始時刻。ISO 8601 形式で、タイムゾーン(Z か +09:00 形式)必須(2026-09-01T00:00:00Z / 2026-09-01T09:00:00+09:00)'),
|
|
29
|
+
end_time: z.string().optional()
|
|
30
|
+
.describe('取得終了時刻。ISO 8601 形式で、タイムゾーン(Z か +09:00 形式)必須(start_time と同じ書式)'),
|
|
31
|
+
duration: z.number().int().min(1).optional()
|
|
32
|
+
.describe('現在から遡る分数。start_time / end_time とは併用できない'),
|
|
33
|
+
event_categories: EVENT_CATEGORIES_INPUT,
|
|
34
|
+
...MAX_ITEMS_PAGINATION_SHAPE,
|
|
35
|
+
...COMMON_INPUT_SHAPE,
|
|
36
|
+
}),
|
|
37
|
+
}, options),
|
|
38
|
+
allowlistedTool({
|
|
39
|
+
entry: RDS_DESCRIBE_DB_CLUSTERS,
|
|
40
|
+
title: 'DB クラスタの一覧',
|
|
41
|
+
description: 'Aurora / Multi-AZ DB クラスタの構成と状態を返す。db_cluster_identifier で 1 本に絞れる',
|
|
42
|
+
inputSchema: z.object({
|
|
43
|
+
db_cluster_identifier: z.string().optional().describe('クラスタ識別子または ARN。未指定なら全件'),
|
|
44
|
+
...MAX_ITEMS_PAGINATION_SHAPE,
|
|
45
|
+
...COMMON_INPUT_SHAPE,
|
|
46
|
+
}),
|
|
47
|
+
}, options),
|
|
48
|
+
allowlistedTool({
|
|
49
|
+
entry: RDS_DESCRIBE_DB_INSTANCES,
|
|
50
|
+
title: 'DB インスタンスの一覧',
|
|
51
|
+
description: 'DB インスタンスの構成と状態(DBInstanceStatus・エンドポイント等)を返す。db_instance_identifier で 1 台に絞れる',
|
|
52
|
+
inputSchema: z.object({
|
|
53
|
+
db_instance_identifier: z.string().optional().describe('インスタンス識別子または ARN。未指定なら全件'),
|
|
54
|
+
...MAX_ITEMS_PAGINATION_SHAPE,
|
|
55
|
+
...COMMON_INPUT_SHAPE,
|
|
56
|
+
}),
|
|
57
|
+
}, options),
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=rds.js.map
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// S3 系のツール定義。
|
|
2
|
+
//
|
|
3
|
+
// 取得方向(S3 → ローカル)は入力の型で固定されており、逆方向は表現できない(research R7)。
|
|
4
|
+
// 残る上書き規則だけを実行前拒否(reject)で見て、書き出し先を artifacts に載せる。
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { S3API_GET_OBJECT, S3_CP, S3_LS } from '../../domain/allowlist.js';
|
|
7
|
+
import { doesFileExist, isDirectory } from '../../infra/local-file.js';
|
|
8
|
+
import { allowlistedTool, COMMON_INPUT_SHAPE, } from './_shared.js';
|
|
9
|
+
function targetOf(arguments_, name) {
|
|
10
|
+
// eslint-disable-next-line security/detect-object-injection -- name は本ファイルの TargetName リテラル 2 値のみ
|
|
11
|
+
const value = arguments_[name];
|
|
12
|
+
return typeof value === 'string' ? value : undefined;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
書き出し先を実行前に見る(research R7 の Edge Case)。
|
|
16
|
+
|
|
17
|
+
ディレクトリは overwrite に依らず拒否する。
|
|
18
|
+
`aws s3 cp s3://b/k /dir` は `/dir/k` を書く。
|
|
19
|
+
「上書きするなら overwrite に true を」の案内どおりに再実行しても、artifacts に載る書き出し先(`/dir`)と実体がずれたまま成功してしまう。
|
|
20
|
+
|
|
21
|
+
既存ファイルは overwrite が無ければ拒否する。書き出し先が未指定・非文字列のときは undefined を
|
|
22
|
+
返し、必須入力の検証へ委ねる。
|
|
23
|
+
*/
|
|
24
|
+
function rejectExistingTarget(name) {
|
|
25
|
+
return (arguments_) => {
|
|
26
|
+
const target = targetOf(arguments_, name);
|
|
27
|
+
if (target === undefined)
|
|
28
|
+
return;
|
|
29
|
+
if (isDirectory(target)) {
|
|
30
|
+
return {
|
|
31
|
+
category: 'invalid-input',
|
|
32
|
+
message: `${name} にディレクトリは指定できません。書き出すファイルの絶対パスを指定してください: ${target}`,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
if ((arguments_['overwrite'] === true) || !doesFileExist(target))
|
|
36
|
+
return;
|
|
37
|
+
return {
|
|
38
|
+
category: 'invalid-input',
|
|
39
|
+
message: `${name} は既に存在します。上書きするなら overwrite に true を指定してください: ${target}`,
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
成功時に artifacts へ載せる書き出し先。
|
|
45
|
+
*/
|
|
46
|
+
function artifactsOfTarget(name) {
|
|
47
|
+
return (arguments_) => {
|
|
48
|
+
const target = targetOf(arguments_, name);
|
|
49
|
+
return target === undefined ? [] : [target];
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const OVERWRITE_INPUT = z.boolean().default(false)
|
|
53
|
+
.describe('true なら書き出し先が既にあっても上書きする');
|
|
54
|
+
export function s3Tools(options = {}) {
|
|
55
|
+
return [
|
|
56
|
+
allowlistedTool({
|
|
57
|
+
entry: S3_LS,
|
|
58
|
+
title: 'S3 の一覧',
|
|
59
|
+
description: 'バケットまたは prefix の直下を一覧する。s3_uri を省略するとバケット一覧を返す。JSON 出力を持たないコマンドのため data.lines に行単位で返る',
|
|
60
|
+
inputSchema: z.object({
|
|
61
|
+
s3_uri: z.string().optional().describe('一覧する対象(s3://bucket または s3://bucket/prefix/)。省略時はバケット一覧'),
|
|
62
|
+
...COMMON_INPUT_SHAPE,
|
|
63
|
+
}),
|
|
64
|
+
}, options),
|
|
65
|
+
allowlistedTool({
|
|
66
|
+
entry: S3_CP,
|
|
67
|
+
title: 'S3 オブジェクトの取得',
|
|
68
|
+
description: 'S3 のオブジェクト 1 件をローカルの絶対パスへ取得する。アップロード方向と再帰コピーは公開していない',
|
|
69
|
+
inputSchema: z.object({
|
|
70
|
+
s3_uri: z.string().describe('取得元(s3://bucket/key の形式)'),
|
|
71
|
+
local_path: z.string().describe('書き出し先のローカル絶対パス'),
|
|
72
|
+
overwrite: OVERWRITE_INPUT,
|
|
73
|
+
...COMMON_INPUT_SHAPE,
|
|
74
|
+
}),
|
|
75
|
+
reject: rejectExistingTarget('local_path'),
|
|
76
|
+
artifactsOf: artifactsOfTarget('local_path'),
|
|
77
|
+
}, options),
|
|
78
|
+
allowlistedTool({
|
|
79
|
+
entry: S3API_GET_OBJECT,
|
|
80
|
+
title: 'S3 オブジェクトの取得(メタデータ付き)',
|
|
81
|
+
description: 'バケットとキーを指定してオブジェクトを取得し、メタデータを JSON で返す。version_id でバージョン指定、range で部分取得ができる',
|
|
82
|
+
inputSchema: z.object({
|
|
83
|
+
bucket: z.string().describe('バケット名'),
|
|
84
|
+
key: z.string().describe('オブジェクトキー'),
|
|
85
|
+
outfile: z.string().describe('書き出し先のローカル絶対パス'),
|
|
86
|
+
version_id: z.string().optional().describe('取得するバージョン ID'),
|
|
87
|
+
range: z.string().optional().describe('取得するバイト範囲(bytes=0-1023 の形式)'),
|
|
88
|
+
overwrite: OVERWRITE_INPUT,
|
|
89
|
+
...COMMON_INPUT_SHAPE,
|
|
90
|
+
}),
|
|
91
|
+
reject: rejectExistingTarget('outfile'),
|
|
92
|
+
artifactsOf: artifactsOfTarget('outfile'),
|
|
93
|
+
}, options),
|
|
94
|
+
];
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=s3.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// EventBridge Scheduler 系のツール定義。
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { SCHEDULER_GET_SCHEDULE, SCHEDULER_LIST_SCHEDULES } from '../../domain/allowlist.js';
|
|
4
|
+
import { allowlistedTool, COMMON_INPUT_SHAPE, MAX_ITEMS_PAGINATION_SHAPE, } from './_shared.js';
|
|
5
|
+
/**
|
|
6
|
+
一覧の絞り込みに使うスケジュールグループ名。
|
|
7
|
+
|
|
8
|
+
`list-schedules` の `--group-name` は未指定なら全グループが対象で、`get-schedule` の
|
|
9
|
+
既定(default グループ)とは意味が違うので定数を分ける。
|
|
10
|
+
*/
|
|
11
|
+
const LIST_GROUP_NAME_INPUT = z.string().optional()
|
|
12
|
+
.describe('絞り込むスケジュールグループ名。未指定なら全グループを一覧する');
|
|
13
|
+
/**
|
|
14
|
+
単体取得の対象になるスケジュールグループ名。
|
|
15
|
+
*/
|
|
16
|
+
const GET_GROUP_NAME_INPUT = z.string().optional()
|
|
17
|
+
.describe('スケジュールグループ名。未指定なら default グループを見る');
|
|
18
|
+
export function schedulerTools(options = {}) {
|
|
19
|
+
return [
|
|
20
|
+
allowlistedTool({
|
|
21
|
+
entry: SCHEDULER_LIST_SCHEDULES,
|
|
22
|
+
title: 'スケジュールの一覧',
|
|
23
|
+
description: 'EventBridge Scheduler のスケジュールを一覧する。詳細(実行式・ターゲット)は aws_scheduler_get_schedule で取る',
|
|
24
|
+
inputSchema: z.object({
|
|
25
|
+
group_name: LIST_GROUP_NAME_INPUT,
|
|
26
|
+
name_prefix: z.string().optional().describe('スケジュール名の前方一致'),
|
|
27
|
+
state: z.enum(['ENABLED', 'DISABLED']).optional().describe('絞り込む状態'),
|
|
28
|
+
...MAX_ITEMS_PAGINATION_SHAPE,
|
|
29
|
+
...COMMON_INPUT_SHAPE,
|
|
30
|
+
}),
|
|
31
|
+
}, options),
|
|
32
|
+
allowlistedTool({
|
|
33
|
+
entry: SCHEDULER_GET_SCHEDULE,
|
|
34
|
+
title: 'スケジュールの詳細取得',
|
|
35
|
+
description: 'スケジュール 1 件の実行式(ScheduleExpression)・タイムゾーン・ターゲット・状態を返す',
|
|
36
|
+
inputSchema: z.object({
|
|
37
|
+
name: z.string().describe('スケジュール名'),
|
|
38
|
+
group_name: GET_GROUP_NAME_INPUT,
|
|
39
|
+
...COMMON_INPUT_SHAPE,
|
|
40
|
+
}),
|
|
41
|
+
}, options),
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// SQS 系のツール定義。
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { SQS_GET_QUEUE_ATTRIBUTES, SQS_LIST_QUEUES } from '../../domain/allowlist.js';
|
|
4
|
+
import { allowlistedTool, COMMON_INPUT_SHAPE, MAX_ITEMS_PAGINATION_SHAPE, } from './_shared.js';
|
|
5
|
+
/**
|
|
6
|
+
取得する属性名。既定は全属性。
|
|
7
|
+
*/
|
|
8
|
+
const ATTRIBUTE_NAMES_INPUT = z.array(z.string()).default(['All']).describe('取得する属性名。既定は全属性');
|
|
9
|
+
export function sqsTools(options = {}) {
|
|
10
|
+
return [
|
|
11
|
+
allowlistedTool({
|
|
12
|
+
entry: SQS_LIST_QUEUES,
|
|
13
|
+
title: 'キューの一覧',
|
|
14
|
+
description: 'SQS のキュー URL を一覧する。queue_name_prefix でキュー名の前方一致に絞れる',
|
|
15
|
+
inputSchema: z.object({
|
|
16
|
+
queue_name_prefix: z.string().optional().describe('キュー名の前方一致'),
|
|
17
|
+
...MAX_ITEMS_PAGINATION_SHAPE,
|
|
18
|
+
...COMMON_INPUT_SHAPE,
|
|
19
|
+
}),
|
|
20
|
+
}, options),
|
|
21
|
+
allowlistedTool({
|
|
22
|
+
entry: SQS_GET_QUEUE_ATTRIBUTES,
|
|
23
|
+
title: 'キュー属性の取得',
|
|
24
|
+
description: 'キュー 1 本の属性(滞留件数・可視性タイムアウト・デッドレターキュー設定等)を返す',
|
|
25
|
+
inputSchema: z.object({
|
|
26
|
+
queue_url: z.string().describe('キューの URL(https:// で始まる)'),
|
|
27
|
+
attribute_names: ATTRIBUTE_NAMES_INPUT,
|
|
28
|
+
...COMMON_INPUT_SHAPE,
|
|
29
|
+
}),
|
|
30
|
+
}, options),
|
|
31
|
+
];
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=sqs.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ToolDefinition } from '../server.js';
|
|
2
|
+
import { type ToolOptions } from './_shared.js';
|
|
3
|
+
/**
|
|
4
|
+
SSO の 2 件を組み立てる。
|
|
5
|
+
|
|
6
|
+
ハンドラは ToolCallContext(signal)を使わない。tools/call のキャンセルで子を落とすと、
|
|
7
|
+
「開始だけして後で確認する」という 2 段構成の趣旨に反する。
|
|
8
|
+
クライアントの接続断は serve.ts の stdin end の処理が子を片付けるため、孤児は残らない。
|
|
9
|
+
*/
|
|
10
|
+
export declare function ssoTools(options?: Readonly<ToolOptions>): readonly ToolDefinition[];
|
|
11
|
+
//# sourceMappingURL=sso.d.ts.map
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
// SSO 認証の 2 段構成(contracts/mcp-tools.md §SSO 認証 / research R5 / FR-007)。
|
|
2
|
+
//
|
|
3
|
+
// `aws sso login` は認証が終わるまで戻らないため、開始(URL とコードを即時に返す)と
|
|
4
|
+
// 完了確認を別のツールに分ける。子プロセスの保持と状態遷移は infra/sso/login-registry.ts が持ち、
|
|
5
|
+
// ここは応答の組み立て(ヒント・上限・annotations)だけを持つ。
|
|
6
|
+
//
|
|
7
|
+
// この 2 件は許可リスト(domain/allowlist.ts)に入れない。許可リストは「awscli を 1 回起動して
|
|
8
|
+
// 出力を返す」形のコマンド表で、tests/integration/real-awscli.test.ts が全件を実 awscli へ通す。
|
|
9
|
+
// そのため、入れると実行のたびに本物のデバイス認証が発行される。
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { ensureAwscli } from '../../infra/awscli.js';
|
|
12
|
+
import { loginRegistry as sharedLoginRegistry, } from '../../infra/sso/login-registry.js';
|
|
13
|
+
import { limitOutput, toCallToolResult } from '../result.js';
|
|
14
|
+
import { PRE_EXECUTION_EXIT_CODE, PROFILE_INPUT_SHAPE, resolveExitCode, TIMEOUT_EXIT_CODE, TOOL_OUTPUT_SCHEMA, UNKNOWN_FAILURE_EXIT_CODE, } from './_shared.js';
|
|
15
|
+
/**
|
|
16
|
+
SSO 専用の失敗種別ごとの再試行方法。
|
|
17
|
+
|
|
18
|
+
共通表(_shared.ts の FAILURE_HINTS)は auth-missing / auth-expired で、
|
|
19
|
+
「aws_sso_login を実行してください」と案内する。SSO 自身の失敗に使うと、案内が循環する。
|
|
20
|
+
*/
|
|
21
|
+
const SSO_FAILURE_HINTS = {
|
|
22
|
+
'not-allowed': '許可されていない操作です。公開しているツールの範囲で実行してください',
|
|
23
|
+
'invalid-input': 'profile を修正して再実行してください',
|
|
24
|
+
'awscli-missing': 'awscli v2 (2.22 以上) を導入して PATH を通してください',
|
|
25
|
+
'auth-missing': 'profile に SSO の設定がありません。端末で aws configure sso を実行してください',
|
|
26
|
+
'auth-expired': 'トークンのキャッシュを読めませんでした。profile の SSO 設定を確認してください',
|
|
27
|
+
'permission-denied': 'SSO の許可セットに対象アカウントが含まれているか確認してください',
|
|
28
|
+
'resource-not-found': 'profile の sso_start_url / sso_region を確認してください',
|
|
29
|
+
'timeout': '制限時間内に認証が完了しませんでした。aws_sso_login を再度呼び出してください',
|
|
30
|
+
'other': 'awscli が失敗しました。stderr を確認してください',
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
出力が上限で切り詰められたときに message へ足す注記。
|
|
34
|
+
*/
|
|
35
|
+
const OUTPUT_TRUNCATION_NOTE = '(出力は上限を超えたため先頭のみ載せています)';
|
|
36
|
+
/**
|
|
37
|
+
annotations(判断の根拠は契約書の共通規約)。
|
|
38
|
+
|
|
39
|
+
`aws_sso_login` は AWS 側に新しいトークンを発行させるので readOnlyHint は false。
|
|
40
|
+
`aws_sso_login_status` はレジストリを読むだけなので true。壊す対象を持たないため
|
|
41
|
+
destructiveHint は 2 件とも false。openWorldHint は共通規約に合わせて 2 件とも true にする
|
|
42
|
+
(status は awscli を起動しないが、返す内容は外界での承認の進み具合に依存する)。
|
|
43
|
+
*/
|
|
44
|
+
const LOGIN_ANNOTATIONS = { readOnlyHint: false, destructiveHint: false, openWorldHint: true };
|
|
45
|
+
const STATUS_ANNOTATIONS = { readOnlyHint: true, destructiveHint: false, openWorldHint: true };
|
|
46
|
+
function profileOf(arguments_) {
|
|
47
|
+
const profile = arguments_['profile'];
|
|
48
|
+
return typeof profile === 'string' ? profile : undefined;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
応答 data に載せる URL / コード。確定前と、デバイスフローに入らなかった場合は載らない。
|
|
52
|
+
*/
|
|
53
|
+
function promptData(session) {
|
|
54
|
+
return {
|
|
55
|
+
...(session.verificationUrl !== undefined && { verificationUrl: session.verificationUrl }),
|
|
56
|
+
...(session.verificationUrlComplete !== undefined && { verificationUrlComplete: session.verificationUrlComplete }),
|
|
57
|
+
...(session.userCode !== undefined && { userCode: session.userCode }),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
pending 応答の案内文。
|
|
62
|
+
|
|
63
|
+
`promptData` は未確定の項目をキーごと data から落とす。
|
|
64
|
+
autofill URL(verificationUrlComplete)が未確定のときに、それを第一候補として案内すると、
|
|
65
|
+
応答に無い項目を案内することになる。
|
|
66
|
+
autofill 行は URL・コードより後の chunk で届くことがあり、揃うまでの間はこの分岐に入る。
|
|
67
|
+
*/
|
|
68
|
+
function pendingMessage(session) {
|
|
69
|
+
return (session.verificationUrlComplete === undefined
|
|
70
|
+
? 'デバイス認証を開始しました。verificationUrl をブラウザで開き、userCode を入力してください。'
|
|
71
|
+
: 'デバイス認証を開始しました。verificationUrlComplete をブラウザで開けば'
|
|
72
|
+
+ 'コード入力は要りません(verificationUrl を開いた場合は userCode を入力します)。')
|
|
73
|
+
+ '承認後に aws_sso_login_status で完了を確認してください';
|
|
74
|
+
}
|
|
75
|
+
function hintOf(category) {
|
|
76
|
+
// eslint-disable-next-line security/detect-object-injection -- category は FailureCategory の列挙値
|
|
77
|
+
return SSO_FAILURE_HINTS[category];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
失敗セッションを ExecutionResult にする。exitCode は必ず 1 以上になる。
|
|
81
|
+
*/
|
|
82
|
+
function failureResult(session, data) {
|
|
83
|
+
/* c8 ignore next -- レジストリは failed に必ず category を付ける。既定値は型を閉じるための防御網 */
|
|
84
|
+
const category = session.category ?? 'other';
|
|
85
|
+
const limited = limitOutput(session.output);
|
|
86
|
+
// awscli の終了コードをそのまま返す(許可リストのツールと同じ規約。SSO 設定なしなら 253)。
|
|
87
|
+
// シグナル終了・未終了は resolveExitCode が 1 へ畳む。0 以下は ok: false と同居させられないので、
|
|
88
|
+
// ここでも 1 にする。
|
|
89
|
+
const resolved = resolveExitCode(category, session.exitCode);
|
|
90
|
+
return {
|
|
91
|
+
ok: false,
|
|
92
|
+
// resolveExitCode は 'timeout' なら 124、'awscli-missing' なら 127、それ以外は session.exitCode(未設定なら 1)を返す。
|
|
93
|
+
// 0 以下にならず、false 分岐は型を閉じるための防御。
|
|
94
|
+
/* c8 ignore next */
|
|
95
|
+
exitCode: resolved > 0 ? resolved : UNKNOWN_FAILURE_EXIT_CODE,
|
|
96
|
+
category,
|
|
97
|
+
data: { ...data },
|
|
98
|
+
artifacts: [],
|
|
99
|
+
message: `SSO 認証が失敗しました (${category})。${hintOf(category)}`
|
|
100
|
+
+ (limited.truncated ? OUTPUT_TRUNCATION_NOTE : ''),
|
|
101
|
+
stderr: limited.text,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
時間切れセッションを ExecutionResult にする。
|
|
106
|
+
*/
|
|
107
|
+
function timedOutResult(data) {
|
|
108
|
+
return {
|
|
109
|
+
ok: false,
|
|
110
|
+
exitCode: TIMEOUT_EXIT_CODE,
|
|
111
|
+
category: 'timeout',
|
|
112
|
+
data: { ...data },
|
|
113
|
+
artifacts: [],
|
|
114
|
+
message: `SSO 認証が時間切れになりました。${hintOf('timeout')}`,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
async function startLogin(arguments_, registry) {
|
|
118
|
+
// バージョンの判定を先に行う。`--use-device-code` は awscli 2.22 以降にしか無い。
|
|
119
|
+
// 古い awscli では「不正な引数」として失敗し、そのままだと invalid-input になって対処法が伝わらない。
|
|
120
|
+
const probe = await ensureAwscli();
|
|
121
|
+
if (!probe.ok) {
|
|
122
|
+
return {
|
|
123
|
+
ok: false,
|
|
124
|
+
exitCode: resolveExitCode(probe.category),
|
|
125
|
+
category: probe.category,
|
|
126
|
+
data: {},
|
|
127
|
+
artifacts: [],
|
|
128
|
+
message: probe.message,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const session = await registry.start(profileOf(arguments_));
|
|
132
|
+
const base = { state: session.state, profile: session.profile };
|
|
133
|
+
switch (session.state) {
|
|
134
|
+
case 'pending': {
|
|
135
|
+
return {
|
|
136
|
+
ok: true,
|
|
137
|
+
exitCode: 0,
|
|
138
|
+
data: { ...promptData(session), ...base },
|
|
139
|
+
artifacts: [],
|
|
140
|
+
message: pendingMessage(session),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
case 'completed': {
|
|
144
|
+
return {
|
|
145
|
+
ok: true,
|
|
146
|
+
exitCode: 0,
|
|
147
|
+
data: { ...promptData(session), ...base },
|
|
148
|
+
artifacts: [],
|
|
149
|
+
message: 'デバイス認証を始める前から認証済みでした',
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
case 'timed-out': {
|
|
153
|
+
return timedOutResult(base);
|
|
154
|
+
}
|
|
155
|
+
case 'failed': {
|
|
156
|
+
return failureResult(session, base);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function loginStatus(arguments_, registry) {
|
|
161
|
+
const session = registry.get(profileOf(arguments_));
|
|
162
|
+
if (session === undefined) {
|
|
163
|
+
return {
|
|
164
|
+
ok: false,
|
|
165
|
+
exitCode: PRE_EXECUTION_EXIT_CODE,
|
|
166
|
+
category: 'invalid-input',
|
|
167
|
+
data: {},
|
|
168
|
+
artifacts: [],
|
|
169
|
+
message: '開始済みの SSO ログインがありません。aws_sso_login を先に呼んでください',
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const base = { state: session.state };
|
|
173
|
+
switch (session.state) {
|
|
174
|
+
case 'pending': {
|
|
175
|
+
return {
|
|
176
|
+
ok: true,
|
|
177
|
+
exitCode: 0,
|
|
178
|
+
data: { ...promptData(session), ...base },
|
|
179
|
+
artifacts: [],
|
|
180
|
+
message: 'まだ承認されていません。案内した URL での承認後に再度呼び出してください',
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
case 'completed': {
|
|
184
|
+
const limited = limitOutput(session.output);
|
|
185
|
+
return {
|
|
186
|
+
ok: true,
|
|
187
|
+
exitCode: 0,
|
|
188
|
+
data: { ...promptData(session), ...base, output: limited.text },
|
|
189
|
+
artifacts: [],
|
|
190
|
+
message: 'SSO 認証が完了しました'
|
|
191
|
+
+ (limited.truncated ? OUTPUT_TRUNCATION_NOTE : ''),
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
case 'timed-out': {
|
|
195
|
+
return timedOutResult(base);
|
|
196
|
+
}
|
|
197
|
+
case 'failed': {
|
|
198
|
+
return failureResult(session, base);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
SSO の 2 件を組み立てる。
|
|
204
|
+
|
|
205
|
+
ハンドラは ToolCallContext(signal)を使わない。tools/call のキャンセルで子を落とすと、
|
|
206
|
+
「開始だけして後で確認する」という 2 段構成の趣旨に反する。
|
|
207
|
+
クライアントの接続断は serve.ts の stdin end の処理が子を片付けるため、孤児は残らない。
|
|
208
|
+
*/
|
|
209
|
+
export function ssoTools(options = {}) {
|
|
210
|
+
// 既定の解決はここで済ませる。ハンドラ内で遅延解決すると、テストが注入したレジストリと
|
|
211
|
+
// 共有インスタンスのどちらを見るかが呼び出し時まで決まらない。
|
|
212
|
+
const registry = options.loginRegistry ?? sharedLoginRegistry();
|
|
213
|
+
return [
|
|
214
|
+
{
|
|
215
|
+
name: 'aws_sso_login',
|
|
216
|
+
config: {
|
|
217
|
+
title: 'SSO ログインの開始',
|
|
218
|
+
description: 'AWS SSO のデバイス認証を開始し、認証 URL とコードを即時に返す。完了は待たないため、'
|
|
219
|
+
+ '利用者の承認後に aws_sso_login_status で確認する',
|
|
220
|
+
inputSchema: z.object({ ...PROFILE_INPUT_SHAPE }),
|
|
221
|
+
outputSchema: TOOL_OUTPUT_SCHEMA,
|
|
222
|
+
annotations: LOGIN_ANNOTATIONS,
|
|
223
|
+
},
|
|
224
|
+
handler: async (arguments_) => toCallToolResult(await startLogin(arguments_, registry)),
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
name: 'aws_sso_login_status',
|
|
228
|
+
config: {
|
|
229
|
+
title: 'SSO ログインの完了確認',
|
|
230
|
+
description: 'aws_sso_login で開始した認証の状態(pending / completed / failed / timed-out)を返す。'
|
|
231
|
+
+ 'awscli は起動しない',
|
|
232
|
+
inputSchema: z.object({ ...PROFILE_INPUT_SHAPE }),
|
|
233
|
+
outputSchema: TOOL_OUTPUT_SCHEMA,
|
|
234
|
+
annotations: STATUS_ANNOTATIONS,
|
|
235
|
+
},
|
|
236
|
+
handler: (arguments_) => Promise.resolve(toCallToolResult(loginStatus(arguments_, registry))),
|
|
237
|
+
},
|
|
238
|
+
];
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=sso.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// STS 系のツール定義。
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { STS_GET_CALLER_IDENTITY } from '../../domain/allowlist.js';
|
|
4
|
+
import { allowlistedTool, COMMON_INPUT_SHAPE } from './_shared.js';
|
|
5
|
+
export function stsTools(options = {}) {
|
|
6
|
+
return [
|
|
7
|
+
allowlistedTool({
|
|
8
|
+
entry: STS_GET_CALLER_IDENTITY,
|
|
9
|
+
title: '呼び出し元 ID の確認',
|
|
10
|
+
description: '現在の認証情報が示すアカウント ID・ユーザ ID・ARN を返す。認証が通っているかの確認に使う',
|
|
11
|
+
inputSchema: z.object({ ...COMMON_INPUT_SHAPE }),
|
|
12
|
+
}, options),
|
|
13
|
+
];
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=sts.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
系列(major)ごとの最低版。2026-10-21 の Node.js セキュリティリリース
|
|
3
|
+
(Brotli 展開の RCE CVE-2026-111497 ほか)の修正版。25 系はサポート終了で修正版が無い。
|
|
4
|
+
次のセキュリティリリースで上げるときは、現行の版を次のコマンドで列挙する。
|
|
5
|
+
`grep -rn '24.22.1' plugins .githooks`(node_modules・アイコン SVG のヒットは除く)。
|
|
6
|
+
ヒットした箇所を同じ変更で更新する。
|
|
7
|
+
表・engines・フックの期待値・両プラグインの複製の一致は node-runtime.test.ts が検証する。
|
|
8
|
+
*/
|
|
9
|
+
export declare const MINIMUM_NODE_VERSIONS: Readonly<Record<number, string>>;
|
|
10
|
+
/**
|
|
11
|
+
案内に載せる更新先の版。表の最小 major の最低版。
|
|
12
|
+
*/
|
|
13
|
+
export declare function suggestedNodeVersion(): string;
|
|
14
|
+
/**
|
|
15
|
+
起動してよい版なら undefined、止めるべき版なら利用者向けの案内文を返す。
|
|
16
|
+
表に無い major は、表の最大 major より新しければ修正後のリリースとみなして許可し、
|
|
17
|
+
それ以外(24 未満・サポート終了の 25 系)は止める。
|
|
18
|
+
*/
|
|
19
|
+
export declare function checkNodeRuntime(version: string): string | undefined;
|
|
20
|
+
//# sourceMappingURL=node-runtime.d.ts.map
|