@argosvix/mcp-server 0.2.0-alpha.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.
- package/LICENSE +21 -0
- package/README.md +89 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -0
- package/dist/tools.d.ts +35 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +442 -0
- package/dist/tools.js.map +1 -0
- package/dist/tools.test.d.ts +2 -0
- package/dist/tools.test.d.ts.map +1 -0
- package/dist/tools.test.js +378 -0
- package/dist/tools.test.js.map +1 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yuto Makihara (Argosvix)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# @argosvix/mcp-server
|
|
2
|
+
|
|
3
|
+
**Phase 1 alpha** — Argosvix MCP server lets AI agents (Claude Desktop, Cursor, Codex CLI, custom MCP clients) query their LLM observability data directly from the conversation.
|
|
4
|
+
|
|
5
|
+
[](https://npmjs.com/package/@argosvix/mcp-server)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## Why
|
|
9
|
+
|
|
10
|
+
You're already sending LLM calls through `@argosvix/sdk` or the Python SDK. Now ask Claude / Cursor questions like:
|
|
11
|
+
|
|
12
|
+
- "What was my OpenAI cost over the past 24h?"
|
|
13
|
+
- "Which alerts are firing right now?"
|
|
14
|
+
- "Show me the 20 most expensive calls today."
|
|
15
|
+
|
|
16
|
+
No dashboard tab-switching. The agent fetches the data via this MCP server using your Argosvix API key.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g @argosvix/mcp-server
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Configure (Claude Desktop)
|
|
25
|
+
|
|
26
|
+
Edit your Claude Desktop config:
|
|
27
|
+
|
|
28
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
29
|
+
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"mcpServers": {
|
|
34
|
+
"argosvix": {
|
|
35
|
+
"command": "argosvix-mcp",
|
|
36
|
+
"env": {
|
|
37
|
+
"ARGOSVIX_API_KEY": "argosvix_live_..."
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Restart Claude Desktop. The tools appear as `argosvix__query_calls` / `argosvix__get_cost_summary` / `argosvix__list_alerts`.
|
|
45
|
+
|
|
46
|
+
## Configure (Cursor)
|
|
47
|
+
|
|
48
|
+
Edit `~/.cursor/mcp.json`:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"mcpServers": {
|
|
53
|
+
"argosvix": {
|
|
54
|
+
"command": "argosvix-mcp",
|
|
55
|
+
"env": {
|
|
56
|
+
"ARGOSVIX_API_KEY": "argosvix_live_..."
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Tools (Phase 2)
|
|
64
|
+
|
|
65
|
+
| Tool | Purpose | Type |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| `query_calls` | Recent LLM call records, filterable by provider / model / time range | read |
|
|
68
|
+
| `get_cost_summary` | Aggregate cost / calls / tokens by provider or model | read |
|
|
69
|
+
| `list_alerts` | Configured alerts + recent trigger status | read |
|
|
70
|
+
| `silence_alert` | Mute a specific alert (= temporary notification stop, default 24h) | write |
|
|
71
|
+
| `unsilence_alert` | Resume notifications for a previously muted alert | write |
|
|
72
|
+
|
|
73
|
+
Phase 3 backlog: `create_alert`, additional channel management, HTTP transport.
|
|
74
|
+
|
|
75
|
+
## Privacy
|
|
76
|
+
|
|
77
|
+
The MCP server sends queries to `https://ingest.argosvix.com` using your API key. **No prompts or completions are exposed** — only metadata (tokens, cost, latency, model name, your tags).
|
|
78
|
+
|
|
79
|
+
## Development
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm install
|
|
83
|
+
npm run build
|
|
84
|
+
npm test
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## License
|
|
88
|
+
|
|
89
|
+
MIT © Yuto Makihara (Argosvix). See [LICENSE](LICENSE).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Argosvix MCP server entry point。
|
|
4
|
+
*
|
|
5
|
+
* AI agent (= Claude Desktop / Cursor / Codex CLI 等) から Argosvix の
|
|
6
|
+
* traces / cost / alert を 直接 query するための Model Context Protocol server。
|
|
7
|
+
*
|
|
8
|
+
* Phase 1 (= 2026-05 v1.5 backlog 着手):
|
|
9
|
+
* - stdio transport のみ (= MCP standard、 Claude Desktop / Cursor 標準)
|
|
10
|
+
* - read-only tools (= query_calls / get_cost_summary / list_alerts)
|
|
11
|
+
* - auth = ARGOSVIX_API_KEY env var 経由
|
|
12
|
+
*
|
|
13
|
+
* Phase 2 (= 完了): 書き込み tools (= silence_alert / unsilence_alert)
|
|
14
|
+
* Phase 3 (= 完了): 書き込み tool create_alert (= 新規 alert ルール作成)
|
|
15
|
+
*
|
|
16
|
+
* 後続 phase:
|
|
17
|
+
* - acknowledge_alert
|
|
18
|
+
* - HTTP transport (= remote MCP server 構成)
|
|
19
|
+
* - prompts + resources (= traces / dashboards を 第一級 MCP entity に)
|
|
20
|
+
*
|
|
21
|
+
* Install + use (= Claude Desktop の場合):
|
|
22
|
+
* 1. npm install -g @argosvix/mcp-server
|
|
23
|
+
* 2. Claude Desktop の `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
24
|
+
* に 以下を追記:
|
|
25
|
+
* {
|
|
26
|
+
* "mcpServers": {
|
|
27
|
+
* "argosvix": {
|
|
28
|
+
* "command": "argosvix-mcp",
|
|
29
|
+
* "env": { "ARGOSVIX_API_KEY": "argosvix_live_..." }
|
|
30
|
+
* }
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
* 3. Claude Desktop 再起動 → tools として 自動認識される
|
|
34
|
+
*/
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Argosvix MCP server entry point。
|
|
4
|
+
*
|
|
5
|
+
* AI agent (= Claude Desktop / Cursor / Codex CLI 等) から Argosvix の
|
|
6
|
+
* traces / cost / alert を 直接 query するための Model Context Protocol server。
|
|
7
|
+
*
|
|
8
|
+
* Phase 1 (= 2026-05 v1.5 backlog 着手):
|
|
9
|
+
* - stdio transport のみ (= MCP standard、 Claude Desktop / Cursor 標準)
|
|
10
|
+
* - read-only tools (= query_calls / get_cost_summary / list_alerts)
|
|
11
|
+
* - auth = ARGOSVIX_API_KEY env var 経由
|
|
12
|
+
*
|
|
13
|
+
* Phase 2 (= 完了): 書き込み tools (= silence_alert / unsilence_alert)
|
|
14
|
+
* Phase 3 (= 完了): 書き込み tool create_alert (= 新規 alert ルール作成)
|
|
15
|
+
*
|
|
16
|
+
* 後続 phase:
|
|
17
|
+
* - acknowledge_alert
|
|
18
|
+
* - HTTP transport (= remote MCP server 構成)
|
|
19
|
+
* - prompts + resources (= traces / dashboards を 第一級 MCP entity に)
|
|
20
|
+
*
|
|
21
|
+
* Install + use (= Claude Desktop の場合):
|
|
22
|
+
* 1. npm install -g @argosvix/mcp-server
|
|
23
|
+
* 2. Claude Desktop の `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
24
|
+
* に 以下を追記:
|
|
25
|
+
* {
|
|
26
|
+
* "mcpServers": {
|
|
27
|
+
* "argosvix": {
|
|
28
|
+
* "command": "argosvix-mcp",
|
|
29
|
+
* "env": { "ARGOSVIX_API_KEY": "argosvix_live_..." }
|
|
30
|
+
* }
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
* 3. Claude Desktop 再起動 → tools として 自動認識される
|
|
34
|
+
*/
|
|
35
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
36
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
37
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
38
|
+
import { tools, dispatchTool } from "./tools.js";
|
|
39
|
+
const API_KEY = process.env["ARGOSVIX_API_KEY"];
|
|
40
|
+
const API_BASE = process.env["ARGOSVIX_API_BASE"] ?? "https://ingest.argosvix.com";
|
|
41
|
+
if (!API_KEY) {
|
|
42
|
+
console.error("[argosvix-mcp] ARGOSVIX_API_KEY env var is required. " +
|
|
43
|
+
"Get a key at https://dashboard.argosvix.com/api-keys");
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
const server = new Server({
|
|
47
|
+
name: "argosvix",
|
|
48
|
+
version: "0.2.0-alpha.1",
|
|
49
|
+
}, {
|
|
50
|
+
capabilities: {
|
|
51
|
+
tools: {},
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
55
|
+
tools,
|
|
56
|
+
}));
|
|
57
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
58
|
+
const { name, arguments: args } = request.params;
|
|
59
|
+
return dispatchTool({
|
|
60
|
+
name,
|
|
61
|
+
args: args ?? {},
|
|
62
|
+
apiKey: API_KEY,
|
|
63
|
+
apiBase: API_BASE,
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
const transport = new StdioServerTransport();
|
|
67
|
+
await server.connect(transport);
|
|
68
|
+
console.error("[argosvix-mcp] server ready on stdio transport");
|
|
69
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;AAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,6BAA6B,CAAC;AAEnF,IAAI,CAAC,OAAO,EAAE,CAAC;IACb,OAAO,CAAC,KAAK,CACX,uDAAuD;QACrD,sDAAsD,CACzD,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;IACE,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,eAAe;CACzB,EACD;IACE,YAAY,EAAE;QACZ,KAAK,EAAE,EAAE;KACV;CACF,CACF,CAAC;AAEF,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IAC5D,KAAK;CACN,CAAC,CAAC,CAAC;AAEJ,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IAChE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IACjD,OAAO,YAAY,CAAC;QAClB,IAAI;QACJ,IAAI,EAAE,IAAI,IAAI,EAAE;QAChB,MAAM,EAAE,OAAO;QACf,OAAO,EAAE,QAAQ;KAClB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAChC,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool definitions + dispatcher。
|
|
3
|
+
*
|
|
4
|
+
* 各 tool は JSON Schema で input を 定義し、 dispatch で Argosvix backend HTTP
|
|
5
|
+
* endpoint へ転送する。
|
|
6
|
+
*
|
|
7
|
+
* read tools:
|
|
8
|
+
* - query_calls = 直近の LLM 呼び出し record を filter + paginate で取得
|
|
9
|
+
* - get_cost_summary = 期間別 (= 24h / 7d / 30d) の cost / call / token 集計
|
|
10
|
+
* - list_alerts = 設定済 alert の一覧 + 直近 status
|
|
11
|
+
* - get_alert = 指定 alert の詳細 + 直近 trigger 履歴 (= Phase 3)
|
|
12
|
+
* - list_alert_events = alert 発火履歴を新しい順で取得 (= Phase 3)
|
|
13
|
+
*
|
|
14
|
+
* write tools:
|
|
15
|
+
* - silence_alert / unsilence_alert = alert のミュート操作 (= Phase 2)
|
|
16
|
+
* - create_alert = 新規 alert ルール作成 (= Phase 3)
|
|
17
|
+
*
|
|
18
|
+
* 残 (= acknowledge_alert / HTTP transport / resources・prompts) は後続 phase。
|
|
19
|
+
*/
|
|
20
|
+
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
21
|
+
export declare const tools: Tool[];
|
|
22
|
+
export interface DispatchInput {
|
|
23
|
+
name: string;
|
|
24
|
+
args: Record<string, unknown>;
|
|
25
|
+
apiKey: string;
|
|
26
|
+
apiBase: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function dispatchTool(input: DispatchInput): Promise<{
|
|
29
|
+
content: Array<{
|
|
30
|
+
type: "text";
|
|
31
|
+
text: string;
|
|
32
|
+
}>;
|
|
33
|
+
isError?: boolean;
|
|
34
|
+
}>;
|
|
35
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAoC/D,eAAO,MAAM,KAAK,EAAE,IAAI,EAqRvB,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC;IAChE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC,CAiFD"}
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool definitions + dispatcher。
|
|
3
|
+
*
|
|
4
|
+
* 各 tool は JSON Schema で input を 定義し、 dispatch で Argosvix backend HTTP
|
|
5
|
+
* endpoint へ転送する。
|
|
6
|
+
*
|
|
7
|
+
* read tools:
|
|
8
|
+
* - query_calls = 直近の LLM 呼び出し record を filter + paginate で取得
|
|
9
|
+
* - get_cost_summary = 期間別 (= 24h / 7d / 30d) の cost / call / token 集計
|
|
10
|
+
* - list_alerts = 設定済 alert の一覧 + 直近 status
|
|
11
|
+
* - get_alert = 指定 alert の詳細 + 直近 trigger 履歴 (= Phase 3)
|
|
12
|
+
* - list_alert_events = alert 発火履歴を新しい順で取得 (= Phase 3)
|
|
13
|
+
*
|
|
14
|
+
* write tools:
|
|
15
|
+
* - silence_alert / unsilence_alert = alert のミュート操作 (= Phase 2)
|
|
16
|
+
* - create_alert = 新規 alert ルール作成 (= Phase 3)
|
|
17
|
+
*
|
|
18
|
+
* 残 (= acknowledge_alert / HTTP transport / resources・prompts) は後続 phase。
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* 各 tool で URL 転送を許可する arg key 一覧。 LLM が schema 外の追加 arg
|
|
22
|
+
* (= e.g. `account_id` / `endpoint` 等) を 渡しても URL に乗らないように
|
|
23
|
+
* structural allowlist で防御 (= Codex r4 derive HIGH 4)。
|
|
24
|
+
* inputSchema にも additionalProperties: false を設定し MCP SDK 側で validate
|
|
25
|
+
* させる二重防御。
|
|
26
|
+
*/
|
|
27
|
+
const TOOL_ARG_ALLOWLIST = {
|
|
28
|
+
query_calls: ["limit", "provider", "model", "rangePreset"],
|
|
29
|
+
get_cost_summary: ["rangePreset", "groupBy"],
|
|
30
|
+
list_alerts: ["includeTriggered"],
|
|
31
|
+
// Phase 2 write tools = alertId は path 直前置換、 body field のみ allowlist
|
|
32
|
+
silence_alert: ["alertId", "until"],
|
|
33
|
+
unsilence_alert: ["alertId"],
|
|
34
|
+
// Phase 3 write tool = create_alert。 backend POST /v1/alerts の body field のみ
|
|
35
|
+
// allowlist (= account_id 等の injection を構造防御)。
|
|
36
|
+
create_alert: [
|
|
37
|
+
"name",
|
|
38
|
+
"alertType",
|
|
39
|
+
"thresholdValue",
|
|
40
|
+
"windowMinutes",
|
|
41
|
+
"filterProvider",
|
|
42
|
+
"filterModel",
|
|
43
|
+
"channelKinds",
|
|
44
|
+
"channelTargets",
|
|
45
|
+
"sleepMinutes",
|
|
46
|
+
"enabled",
|
|
47
|
+
],
|
|
48
|
+
// Phase 3 read tools = alertId は path 直前置換 (= GET /v1/alerts/:id)。
|
|
49
|
+
// list_alert_events は query param (limit / alertId) のみ allowlist。
|
|
50
|
+
get_alert: ["alertId"],
|
|
51
|
+
list_alert_events: ["limit", "alertId"],
|
|
52
|
+
};
|
|
53
|
+
export const tools = [
|
|
54
|
+
{
|
|
55
|
+
name: "query_calls",
|
|
56
|
+
description: "Argosvix にて記録された直近の LLM 呼び出し record を取得する。 " +
|
|
57
|
+
"provider / model / 期間 / tag で filter 可能。 デフォルトは 直近 24 時間 + 100 件。",
|
|
58
|
+
inputSchema: {
|
|
59
|
+
type: "object",
|
|
60
|
+
additionalProperties: false,
|
|
61
|
+
properties: {
|
|
62
|
+
limit: {
|
|
63
|
+
type: "integer",
|
|
64
|
+
description: "返却 record 数 (1-500、デフォルト 100)",
|
|
65
|
+
minimum: 1,
|
|
66
|
+
maximum: 500,
|
|
67
|
+
default: 100,
|
|
68
|
+
},
|
|
69
|
+
provider: {
|
|
70
|
+
type: "string",
|
|
71
|
+
description: "filter する provider (= openai / anthropic / gemini / mistral)。 省略で全 provider",
|
|
72
|
+
enum: ["openai", "anthropic", "gemini", "mistral"],
|
|
73
|
+
},
|
|
74
|
+
model: {
|
|
75
|
+
type: "string",
|
|
76
|
+
description: "filter する model 名 (= 部分一致)。 省略で全 model",
|
|
77
|
+
},
|
|
78
|
+
rangePreset: {
|
|
79
|
+
type: "string",
|
|
80
|
+
description: "期間 preset。 デフォルト 24h",
|
|
81
|
+
enum: ["24h", "7d", "30d", "90d"],
|
|
82
|
+
default: "24h",
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: "get_cost_summary",
|
|
89
|
+
description: "期間別の cost / call 数 / token 数 集計を返す。 provider 別 breakdown も同梱。",
|
|
90
|
+
inputSchema: {
|
|
91
|
+
type: "object",
|
|
92
|
+
additionalProperties: false,
|
|
93
|
+
properties: {
|
|
94
|
+
rangePreset: {
|
|
95
|
+
type: "string",
|
|
96
|
+
description: "集計期間。 デフォルト 7d",
|
|
97
|
+
enum: ["24h", "7d", "30d", "90d"],
|
|
98
|
+
default: "7d",
|
|
99
|
+
},
|
|
100
|
+
groupBy: {
|
|
101
|
+
type: "string",
|
|
102
|
+
description: "集計軸 (= 全体 sum / provider 別 / model 別)。 デフォルト provider",
|
|
103
|
+
enum: ["none", "provider", "model"],
|
|
104
|
+
default: "provider",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: "list_alerts",
|
|
111
|
+
description: "設定済 alert の一覧 + 直近 24 時間以内の trigger 履歴 を返す。",
|
|
112
|
+
inputSchema: {
|
|
113
|
+
type: "object",
|
|
114
|
+
additionalProperties: false,
|
|
115
|
+
properties: {
|
|
116
|
+
includeTriggered: {
|
|
117
|
+
type: "boolean",
|
|
118
|
+
description: "true = trigger 履歴 (= triggered_at last 24h) も同梱",
|
|
119
|
+
default: true,
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: "silence_alert",
|
|
126
|
+
description: "指定 alert を一時的にミュートする (= notification 送信を停止)。デフォルト 24 時間、 until に ISO-8601 タイムスタンプを指定すると 任意期限。 list_alerts で得た alertId を渡す。",
|
|
127
|
+
inputSchema: {
|
|
128
|
+
type: "object",
|
|
129
|
+
additionalProperties: false,
|
|
130
|
+
required: ["alertId"],
|
|
131
|
+
properties: {
|
|
132
|
+
alertId: {
|
|
133
|
+
type: "string",
|
|
134
|
+
description: "対象 alert の ID (= list_alerts で取得)",
|
|
135
|
+
pattern: "^[A-Za-z0-9-]{1,64}$",
|
|
136
|
+
},
|
|
137
|
+
until: {
|
|
138
|
+
type: "string",
|
|
139
|
+
description: "ミュート解除時刻 ISO-8601 (= 例: 2026-06-01T00:00:00Z)。省略で 24 時間後",
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: "unsilence_alert",
|
|
146
|
+
description: "ミュート中の alert を解除する。",
|
|
147
|
+
inputSchema: {
|
|
148
|
+
type: "object",
|
|
149
|
+
additionalProperties: false,
|
|
150
|
+
required: ["alertId"],
|
|
151
|
+
properties: {
|
|
152
|
+
alertId: {
|
|
153
|
+
type: "string",
|
|
154
|
+
description: "対象 alert の ID",
|
|
155
|
+
pattern: "^[A-Za-z0-9-]{1,64}$",
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: "create_alert",
|
|
162
|
+
description: "新しい alert ルールを作成する。 cost / error rate / latency / anomaly の閾値超過を監視し、 " +
|
|
163
|
+
"指定した通知チャンネルへ送信する。 例: 「1 日のコストが $10 を超えたら email で通知」。 " +
|
|
164
|
+
"channelKinds は有効化するチャンネル種別の配列、 channelTargets はその種別をキーにした宛先オブジェクト " +
|
|
165
|
+
"(= 例 channelKinds:[\"email\"], channelTargets:{\"email\":\"dev@example.com\"})。 channelKinds に挙げた全 kind の宛先を channelTargets に含めること。 " +
|
|
166
|
+
"anomaly_* タイプは thresholdValue を標準偏差の倍率 (0.5-10、 例 3 = 3σ) として解釈する。 " +
|
|
167
|
+
"Free プランは email チャンネルのみ + alert 3 件まで (超過時は backend が 403 を返す)。",
|
|
168
|
+
inputSchema: {
|
|
169
|
+
type: "object",
|
|
170
|
+
additionalProperties: false,
|
|
171
|
+
required: [
|
|
172
|
+
"name",
|
|
173
|
+
"alertType",
|
|
174
|
+
"thresholdValue",
|
|
175
|
+
"channelKinds",
|
|
176
|
+
"channelTargets",
|
|
177
|
+
],
|
|
178
|
+
properties: {
|
|
179
|
+
name: {
|
|
180
|
+
type: "string",
|
|
181
|
+
description: "alert の表示名 (1-100 文字、 改行不可)",
|
|
182
|
+
minLength: 1,
|
|
183
|
+
maxLength: 100,
|
|
184
|
+
// backend は CR/LF を含む name を拒否する (= email header / Slack text 注入防御)。
|
|
185
|
+
// schema 側でも弾いて無駄な 400 を避ける。
|
|
186
|
+
pattern: "^[^\\r\\n]{1,100}$",
|
|
187
|
+
},
|
|
188
|
+
alertType: {
|
|
189
|
+
type: "string",
|
|
190
|
+
description: "監視する指標。 cost_threshold=単発コスト閾値 / cost_daily=日次コスト / " +
|
|
191
|
+
"cost_monthly=月次コスト / error_rate=エラー率(%) / latency_p95=p95 レイテンシ(ms) / " +
|
|
192
|
+
"anomaly_cost / anomaly_latency / anomaly_error_rate=異常検知 (= windowMinutes は 60 固定)",
|
|
193
|
+
enum: [
|
|
194
|
+
"cost_threshold",
|
|
195
|
+
"cost_daily",
|
|
196
|
+
"cost_monthly",
|
|
197
|
+
"error_rate",
|
|
198
|
+
"latency_p95",
|
|
199
|
+
"anomaly_cost",
|
|
200
|
+
"anomaly_latency",
|
|
201
|
+
"anomaly_error_rate",
|
|
202
|
+
],
|
|
203
|
+
},
|
|
204
|
+
thresholdValue: {
|
|
205
|
+
type: "number",
|
|
206
|
+
description: "閾値 (= 0 以上)。 cost 系は USD、 error_rate は %、 latency_p95 は ms。 " +
|
|
207
|
+
"anomaly 系は標準偏差の倍率 (= 例 3 = 3σ)",
|
|
208
|
+
minimum: 0,
|
|
209
|
+
},
|
|
210
|
+
windowMinutes: {
|
|
211
|
+
type: "integer",
|
|
212
|
+
description: "集計時間窓 (分、5-43200)。 デフォルト 60。 anomaly 系では無視され 60 固定。",
|
|
213
|
+
minimum: 5,
|
|
214
|
+
maximum: 43200,
|
|
215
|
+
default: 60,
|
|
216
|
+
},
|
|
217
|
+
filterProvider: {
|
|
218
|
+
type: "string",
|
|
219
|
+
description: "この provider のみを対象にする (= openai / anthropic / gemini / mistral)。 省略で全 provider",
|
|
220
|
+
enum: ["openai", "anthropic", "gemini", "mistral"],
|
|
221
|
+
},
|
|
222
|
+
filterModel: {
|
|
223
|
+
type: "string",
|
|
224
|
+
description: "この model 名のみを対象にする (= 部分一致)。 省略で全 model",
|
|
225
|
+
maxLength: 128,
|
|
226
|
+
},
|
|
227
|
+
channelKinds: {
|
|
228
|
+
type: "array",
|
|
229
|
+
description: "有効化する通知チャンネル種別の配列 (= channelTargets に同名キーの宛先が必要)。 " +
|
|
230
|
+
"Free プランは email のみ利用可。",
|
|
231
|
+
minItems: 1,
|
|
232
|
+
items: {
|
|
233
|
+
type: "string",
|
|
234
|
+
enum: ["email", "slack", "webhook", "discord", "teams"],
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
channelTargets: {
|
|
238
|
+
type: "object",
|
|
239
|
+
additionalProperties: false,
|
|
240
|
+
description: "チャンネル種別をキー、宛先を値とするオブジェクト (= channelKinds に挙げた各 kind の宛先を必ず含める)。 " +
|
|
241
|
+
"例: {\"email\": \"dev@example.com\"}。 email はメールアドレス、 " +
|
|
242
|
+
"slack/discord/teams/webhook は各サービスの webhook URL。",
|
|
243
|
+
properties: {
|
|
244
|
+
email: { type: "string", description: "通知先メールアドレス" },
|
|
245
|
+
slack: {
|
|
246
|
+
type: "string",
|
|
247
|
+
description: "Slack Incoming Webhook URL (https://hooks.slack.com/services/...)",
|
|
248
|
+
},
|
|
249
|
+
webhook: { type: "string", description: "汎用 webhook URL (https)" },
|
|
250
|
+
discord: {
|
|
251
|
+
type: "string",
|
|
252
|
+
description: "Discord webhook URL (https://discord.com/api/webhooks/...)",
|
|
253
|
+
},
|
|
254
|
+
teams: {
|
|
255
|
+
type: "string",
|
|
256
|
+
description: "Microsoft Teams Incoming Webhook URL",
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
sleepMinutes: {
|
|
261
|
+
type: "integer",
|
|
262
|
+
description: "連続通知の抑制時間 (分、5-10080)。 一度発火したら この時間は再通知しない。 デフォルト 60。",
|
|
263
|
+
minimum: 5,
|
|
264
|
+
maximum: 10080,
|
|
265
|
+
default: 60,
|
|
266
|
+
},
|
|
267
|
+
enabled: {
|
|
268
|
+
type: "boolean",
|
|
269
|
+
description: "作成直後に有効化するか。 デフォルト true。",
|
|
270
|
+
default: true,
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
name: "get_alert",
|
|
277
|
+
description: "指定 alert の詳細設定と直近の trigger 履歴を返す。 list_alerts で得た alertId を渡す。 " +
|
|
278
|
+
"閾値 / 通知チャンネル / silence 状態 / いつ発火したかを確認するのに使う。",
|
|
279
|
+
inputSchema: {
|
|
280
|
+
type: "object",
|
|
281
|
+
additionalProperties: false,
|
|
282
|
+
required: ["alertId"],
|
|
283
|
+
properties: {
|
|
284
|
+
alertId: {
|
|
285
|
+
type: "string",
|
|
286
|
+
description: "対象 alert の ID (= list_alerts で取得)",
|
|
287
|
+
pattern: "^[A-Za-z0-9-]{1,64}$",
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
name: "list_alert_events",
|
|
294
|
+
description: "alert の発火 (trigger) 履歴を新しい順で返す。 account 横断 (= 全 alert の最近の発火) が " +
|
|
295
|
+
"デフォルト。 alertId を指定すると その alert のみに絞る。 「最近どの alert が何回発火したか」 " +
|
|
296
|
+
"「コスト超過アラートはいつ鳴ったか」 等の確認に使う。",
|
|
297
|
+
inputSchema: {
|
|
298
|
+
type: "object",
|
|
299
|
+
additionalProperties: false,
|
|
300
|
+
properties: {
|
|
301
|
+
limit: {
|
|
302
|
+
type: "integer",
|
|
303
|
+
description: "返却する event 数 (1-100、 デフォルト 20)",
|
|
304
|
+
minimum: 1,
|
|
305
|
+
maximum: 100,
|
|
306
|
+
default: 20,
|
|
307
|
+
},
|
|
308
|
+
alertId: {
|
|
309
|
+
type: "string",
|
|
310
|
+
description: "特定 alert に絞る場合の ID。 省略で全 alert の発火履歴",
|
|
311
|
+
pattern: "^[A-Za-z0-9_-]{1,64}$",
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
];
|
|
317
|
+
export async function dispatchTool(input) {
|
|
318
|
+
const { name, args, apiKey, apiBase } = input;
|
|
319
|
+
try {
|
|
320
|
+
const allowed = TOOL_ARG_ALLOWLIST[name];
|
|
321
|
+
if (!allowed) {
|
|
322
|
+
return errorResponse(`unknown tool: ${name}`);
|
|
323
|
+
}
|
|
324
|
+
// allowlist 外の key を 落とす (= LLM が schema 外 arg を渡しても URL に
|
|
325
|
+
// 乗らない、 account_id 等の injection を 構造防御)
|
|
326
|
+
const safeArgs = {};
|
|
327
|
+
for (const key of allowed) {
|
|
328
|
+
if (key in args)
|
|
329
|
+
safeArgs[key] = args[key];
|
|
330
|
+
}
|
|
331
|
+
switch (name) {
|
|
332
|
+
case "query_calls":
|
|
333
|
+
return await callApi(apiBase, "/v1/query/calls", safeArgs, apiKey);
|
|
334
|
+
case "get_cost_summary":
|
|
335
|
+
return await callApi(apiBase, "/v1/query/aggregate", safeArgs, apiKey);
|
|
336
|
+
case "list_alerts":
|
|
337
|
+
return await callApi(apiBase, "/v1/alerts", safeArgs, apiKey);
|
|
338
|
+
case "silence_alert": {
|
|
339
|
+
const alertId = validateAlertId(safeArgs["alertId"]);
|
|
340
|
+
if (!alertId) {
|
|
341
|
+
return errorResponse("alertId required (pattern: [A-Za-z0-9-]{1,64})");
|
|
342
|
+
}
|
|
343
|
+
const body = {};
|
|
344
|
+
if (typeof safeArgs["until"] === "string")
|
|
345
|
+
body["until"] = safeArgs["until"];
|
|
346
|
+
return await callApi(apiBase, `/v1/alerts/${encodeURIComponent(alertId)}/silence`, {}, apiKey, { method: "POST", jsonBody: body });
|
|
347
|
+
}
|
|
348
|
+
case "unsilence_alert": {
|
|
349
|
+
const alertId = validateAlertId(safeArgs["alertId"]);
|
|
350
|
+
if (!alertId) {
|
|
351
|
+
return errorResponse("alertId required (pattern: [A-Za-z0-9-]{1,64})");
|
|
352
|
+
}
|
|
353
|
+
return await callApi(apiBase, `/v1/alerts/${encodeURIComponent(alertId)}/silence`, {}, apiKey, { method: "DELETE" });
|
|
354
|
+
}
|
|
355
|
+
case "create_alert": {
|
|
356
|
+
// safeArgs は既に allowlist 済 (= account_id 等は混入しない)。 そのまま
|
|
357
|
+
// JSON body として POST する。 値の妥当性 (= alertType enum / 閾値範囲 /
|
|
358
|
+
// channelKinds と channelTargets の整合 / plan 上限) は backend validateCreate +
|
|
359
|
+
// plan gate が最終判定し、 NG は 4xx で返る (= 二重防御)。
|
|
360
|
+
return await callApi(apiBase, "/v1/alerts", {}, apiKey, {
|
|
361
|
+
method: "POST",
|
|
362
|
+
jsonBody: safeArgs,
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
case "get_alert": {
|
|
366
|
+
const alertId = validateAlertId(safeArgs["alertId"]);
|
|
367
|
+
if (!alertId) {
|
|
368
|
+
return errorResponse("alertId required (pattern: [A-Za-z0-9-]{1,64})");
|
|
369
|
+
}
|
|
370
|
+
return await callApi(apiBase, `/v1/alerts/${encodeURIComponent(alertId)}`, {}, apiKey);
|
|
371
|
+
}
|
|
372
|
+
case "list_alert_events": {
|
|
373
|
+
// limit / alertId は query param で /v1/alerts/events へ。 alertId は backend
|
|
374
|
+
// 側でも [A-Za-z0-9_-]+ で再 validate されるが、 schema pattern で先弾き済。
|
|
375
|
+
return await callApi(apiBase, "/v1/alerts/events", safeArgs, apiKey);
|
|
376
|
+
}
|
|
377
|
+
default:
|
|
378
|
+
return errorResponse(`unknown tool: ${name}`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
catch (err) {
|
|
382
|
+
return errorResponse(`tool dispatch error: ${err instanceof Error ? err.message : String(err)}`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
async function callApi(base, path, args, apiKey, opts) {
|
|
386
|
+
const url = new URL(path, base);
|
|
387
|
+
for (const [key, value] of Object.entries(args)) {
|
|
388
|
+
if (value === undefined || value === null)
|
|
389
|
+
continue;
|
|
390
|
+
url.searchParams.set(key, String(value));
|
|
391
|
+
}
|
|
392
|
+
const method = opts?.method ?? "GET";
|
|
393
|
+
const headers = {
|
|
394
|
+
Authorization: `Bearer ${apiKey}`,
|
|
395
|
+
Accept: "application/json",
|
|
396
|
+
"User-Agent": "argosvix-mcp-server/0.1.0",
|
|
397
|
+
};
|
|
398
|
+
const init = {
|
|
399
|
+
method,
|
|
400
|
+
headers,
|
|
401
|
+
redirect: "error",
|
|
402
|
+
};
|
|
403
|
+
if (opts?.jsonBody !== undefined && method !== "GET") {
|
|
404
|
+
headers["Content-Type"] = "application/json";
|
|
405
|
+
init.body = JSON.stringify(opts.jsonBody);
|
|
406
|
+
}
|
|
407
|
+
const res = await fetch(url.toString(), init);
|
|
408
|
+
if (!res.ok) {
|
|
409
|
+
const body = await res.text().catch(() => "");
|
|
410
|
+
return errorResponse(`Argosvix API ${path} returned ${res.status}: ${body.slice(0, 300)}`);
|
|
411
|
+
}
|
|
412
|
+
// 204 No Content (= silence DELETE 等) でも safely handle
|
|
413
|
+
if (res.status === 204) {
|
|
414
|
+
return {
|
|
415
|
+
content: [{ type: "text", text: JSON.stringify({ ok: true, status: 204 }, null, 2) }],
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
const json = await res.json();
|
|
419
|
+
return {
|
|
420
|
+
content: [
|
|
421
|
+
{
|
|
422
|
+
type: "text",
|
|
423
|
+
text: JSON.stringify(json, null, 2),
|
|
424
|
+
},
|
|
425
|
+
],
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
/** alertId は backend regex (= [A-Za-z0-9-]{1,64}) で validate、 path injection 防御。 */
|
|
429
|
+
function validateAlertId(value) {
|
|
430
|
+
if (typeof value !== "string")
|
|
431
|
+
return null;
|
|
432
|
+
if (!/^[A-Za-z0-9-]{1,64}$/.test(value))
|
|
433
|
+
return null;
|
|
434
|
+
return value;
|
|
435
|
+
}
|
|
436
|
+
function errorResponse(message) {
|
|
437
|
+
return {
|
|
438
|
+
content: [{ type: "text", text: message }],
|
|
439
|
+
isError: true,
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.test.d.ts","sourceRoot":"","sources":["../src/tools.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { dispatchTool, tools } from "./tools.js";
|
|
3
|
+
describe("MCP tools metadata", () => {
|
|
4
|
+
it("exposes 8 tools (5 read + 3 write)", () => {
|
|
5
|
+
expect(tools.map((t) => t.name).sort()).toEqual([
|
|
6
|
+
"create_alert",
|
|
7
|
+
"get_alert",
|
|
8
|
+
"get_cost_summary",
|
|
9
|
+
"list_alert_events",
|
|
10
|
+
"list_alerts",
|
|
11
|
+
"query_calls",
|
|
12
|
+
"silence_alert",
|
|
13
|
+
"unsilence_alert",
|
|
14
|
+
]);
|
|
15
|
+
});
|
|
16
|
+
it("each tool has description + inputSchema", () => {
|
|
17
|
+
for (const t of tools) {
|
|
18
|
+
expect(t.description).toBeTruthy();
|
|
19
|
+
expect(t.inputSchema).toBeTruthy();
|
|
20
|
+
expect(t.inputSchema.type).toBe("object");
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
it("create_alert.alertType enum matches backend ALERT_TYPES (= enum drift 回帰防止)", () => {
|
|
24
|
+
// backend packages/backend/src/types.ts ALERT_TYPES と完全一致させる。
|
|
25
|
+
// ここが drift すると mismatch した type の create_alert が backend で 400 になる。
|
|
26
|
+
const BACKEND_ALERT_TYPES = [
|
|
27
|
+
"cost_threshold",
|
|
28
|
+
"cost_daily",
|
|
29
|
+
"cost_monthly",
|
|
30
|
+
"error_rate",
|
|
31
|
+
"latency_p95",
|
|
32
|
+
"anomaly_cost",
|
|
33
|
+
"anomaly_latency",
|
|
34
|
+
"anomaly_error_rate",
|
|
35
|
+
];
|
|
36
|
+
const createAlert = tools.find((t) => t.name === "create_alert");
|
|
37
|
+
const schema = createAlert?.inputSchema;
|
|
38
|
+
const enumValues = schema?.properties?.alertType?.enum ?? [];
|
|
39
|
+
expect([...enumValues].sort()).toEqual([...BACKEND_ALERT_TYPES].sort());
|
|
40
|
+
});
|
|
41
|
+
it("create_alert.channelTargets is an object keyed by channel kind (not array)", () => {
|
|
42
|
+
const createAlert = tools.find((t) => t.name === "create_alert");
|
|
43
|
+
const schema = createAlert?.inputSchema;
|
|
44
|
+
expect(schema?.properties?.channelTargets?.type).toBe("object");
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe("dispatchTool", () => {
|
|
48
|
+
beforeEach(() => {
|
|
49
|
+
vi.stubGlobal("fetch", vi.fn(async (url) => {
|
|
50
|
+
if (url.includes("/v1/query/calls")) {
|
|
51
|
+
return new Response(JSON.stringify({ records: [], total: 0 }), {
|
|
52
|
+
status: 200,
|
|
53
|
+
headers: { "content-type": "application/json" },
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (url.includes("/v1/query/aggregate")) {
|
|
57
|
+
return new Response(JSON.stringify({ groups: [{ provider: "openai", costUsd: 1.23 }] }), { status: 200, headers: { "content-type": "application/json" } });
|
|
58
|
+
}
|
|
59
|
+
if (url.includes("/v1/alerts")) {
|
|
60
|
+
return new Response(JSON.stringify({ alerts: [] }), {
|
|
61
|
+
status: 200,
|
|
62
|
+
headers: { "content-type": "application/json" },
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return new Response("not found", { status: 404 });
|
|
66
|
+
}));
|
|
67
|
+
});
|
|
68
|
+
afterEach(() => {
|
|
69
|
+
vi.unstubAllGlobals();
|
|
70
|
+
});
|
|
71
|
+
it("query_calls forwards args as query params + returns JSON text", async () => {
|
|
72
|
+
const res = await dispatchTool({
|
|
73
|
+
name: "query_calls",
|
|
74
|
+
args: { limit: 10, provider: "openai" },
|
|
75
|
+
apiKey: "argosvix_live_test",
|
|
76
|
+
apiBase: "https://ingest.example.com",
|
|
77
|
+
});
|
|
78
|
+
expect(res.isError).toBeUndefined();
|
|
79
|
+
expect(res.content[0]?.type).toBe("text");
|
|
80
|
+
const parsed = JSON.parse(res.content[0]?.text ?? "{}");
|
|
81
|
+
expect(parsed.records).toEqual([]);
|
|
82
|
+
// fetch URL に query params が乗っているか
|
|
83
|
+
const fetchMock = global.fetch;
|
|
84
|
+
const fetchedUrl = String(fetchMock.mock.calls[0]?.[0]);
|
|
85
|
+
expect(fetchedUrl).toContain("limit=10");
|
|
86
|
+
expect(fetchedUrl).toContain("provider=openai");
|
|
87
|
+
});
|
|
88
|
+
it("get_cost_summary uses /v1/query/aggregate endpoint", async () => {
|
|
89
|
+
const res = await dispatchTool({
|
|
90
|
+
name: "get_cost_summary",
|
|
91
|
+
args: { rangePreset: "7d", groupBy: "provider" },
|
|
92
|
+
apiKey: "argosvix_live_test",
|
|
93
|
+
apiBase: "https://ingest.example.com",
|
|
94
|
+
});
|
|
95
|
+
expect(res.isError).toBeUndefined();
|
|
96
|
+
const parsed = JSON.parse(res.content[0]?.text ?? "{}");
|
|
97
|
+
expect(parsed.groups[0].provider).toBe("openai");
|
|
98
|
+
});
|
|
99
|
+
it("list_alerts uses /v1/alerts endpoint", async () => {
|
|
100
|
+
const res = await dispatchTool({
|
|
101
|
+
name: "list_alerts",
|
|
102
|
+
args: { includeTriggered: true },
|
|
103
|
+
apiKey: "argosvix_live_test",
|
|
104
|
+
apiBase: "https://ingest.example.com",
|
|
105
|
+
});
|
|
106
|
+
expect(res.isError).toBeUndefined();
|
|
107
|
+
});
|
|
108
|
+
it("unknown tool returns isError", async () => {
|
|
109
|
+
const res = await dispatchTool({
|
|
110
|
+
name: "nonexistent_tool",
|
|
111
|
+
args: {},
|
|
112
|
+
apiKey: "argosvix_live_test",
|
|
113
|
+
apiBase: "https://ingest.example.com",
|
|
114
|
+
});
|
|
115
|
+
expect(res.isError).toBe(true);
|
|
116
|
+
expect(res.content[0]?.text).toContain("unknown tool");
|
|
117
|
+
});
|
|
118
|
+
it("forwards Bearer apiKey + UA header", async () => {
|
|
119
|
+
await dispatchTool({
|
|
120
|
+
name: "query_calls",
|
|
121
|
+
args: {},
|
|
122
|
+
apiKey: "argosvix_live_secret",
|
|
123
|
+
apiBase: "https://ingest.example.com",
|
|
124
|
+
});
|
|
125
|
+
const fetchMock = global.fetch;
|
|
126
|
+
const init = fetchMock.mock.calls[0]?.[1];
|
|
127
|
+
expect(init.headers.Authorization).toBe("Bearer argosvix_live_secret");
|
|
128
|
+
expect(init.headers["User-Agent"]).toContain("argosvix-mcp-server");
|
|
129
|
+
});
|
|
130
|
+
it("non-200 response returns isError with status code", async () => {
|
|
131
|
+
vi.stubGlobal("fetch", vi.fn(async () => new Response("boom", { status: 500 })));
|
|
132
|
+
const res = await dispatchTool({
|
|
133
|
+
name: "query_calls",
|
|
134
|
+
args: {},
|
|
135
|
+
apiKey: "argosvix_live_test",
|
|
136
|
+
apiBase: "https://ingest.example.com",
|
|
137
|
+
});
|
|
138
|
+
expect(res.isError).toBe(true);
|
|
139
|
+
expect(res.content[0]?.text).toContain("500");
|
|
140
|
+
});
|
|
141
|
+
it("skips null/undefined query param values", async () => {
|
|
142
|
+
await dispatchTool({
|
|
143
|
+
name: "query_calls",
|
|
144
|
+
args: { limit: 10, provider: null, model: undefined },
|
|
145
|
+
apiKey: "argosvix_live_test",
|
|
146
|
+
apiBase: "https://ingest.example.com",
|
|
147
|
+
});
|
|
148
|
+
const fetchMock = global.fetch;
|
|
149
|
+
const fetchedUrl = String(fetchMock.mock.calls[0]?.[0]);
|
|
150
|
+
expect(fetchedUrl).toContain("limit=10");
|
|
151
|
+
expect(fetchedUrl).not.toContain("provider=");
|
|
152
|
+
expect(fetchedUrl).not.toContain("model=");
|
|
153
|
+
});
|
|
154
|
+
it("drops non-allowlisted args (= injection 防御 / Codex r4 HIGH 4 carry)", async () => {
|
|
155
|
+
await dispatchTool({
|
|
156
|
+
name: "query_calls",
|
|
157
|
+
args: {
|
|
158
|
+
limit: 50,
|
|
159
|
+
account_id: "acc_other_user",
|
|
160
|
+
endpoint: "/v1/admin/internal",
|
|
161
|
+
__proto__: { malicious: true },
|
|
162
|
+
},
|
|
163
|
+
apiKey: "argosvix_live_test",
|
|
164
|
+
apiBase: "https://ingest.example.com",
|
|
165
|
+
});
|
|
166
|
+
const fetchMock = global.fetch;
|
|
167
|
+
const fetchedUrl = String(fetchMock.mock.calls[0]?.[0]);
|
|
168
|
+
expect(fetchedUrl).toContain("limit=50");
|
|
169
|
+
expect(fetchedUrl).not.toContain("account_id");
|
|
170
|
+
expect(fetchedUrl).not.toContain("endpoint");
|
|
171
|
+
expect(fetchedUrl).not.toContain("__proto__");
|
|
172
|
+
// path 自体は固定の /v1/query/calls (= injection で 変えられない)
|
|
173
|
+
expect(fetchedUrl).toContain("/v1/query/calls");
|
|
174
|
+
expect(fetchedUrl).not.toContain("/v1/admin/internal");
|
|
175
|
+
});
|
|
176
|
+
it("each tool inputSchema declares additionalProperties: false", () => {
|
|
177
|
+
for (const t of tools) {
|
|
178
|
+
const schema = t.inputSchema;
|
|
179
|
+
expect(schema.additionalProperties).toBe(false);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
it("silence_alert POSTs to /v1/alerts/:id/silence with JSON body", async () => {
|
|
183
|
+
vi.stubGlobal("fetch", vi.fn(async () => new Response(JSON.stringify({ silencedUntil: "2026-06-01T00:00:00Z" }), {
|
|
184
|
+
status: 200,
|
|
185
|
+
headers: { "content-type": "application/json" },
|
|
186
|
+
})));
|
|
187
|
+
const res = await dispatchTool({
|
|
188
|
+
name: "silence_alert",
|
|
189
|
+
args: { alertId: "alt-abc123", until: "2026-06-01T00:00:00Z" },
|
|
190
|
+
apiKey: "argosvix_live_test",
|
|
191
|
+
apiBase: "https://ingest.example.com",
|
|
192
|
+
});
|
|
193
|
+
expect(res.isError).toBeUndefined();
|
|
194
|
+
const fetchMock = global.fetch;
|
|
195
|
+
const url = String(fetchMock.mock.calls[0]?.[0]);
|
|
196
|
+
expect(url).toContain("/v1/alerts/alt-abc123/silence");
|
|
197
|
+
const init = fetchMock.mock.calls[0]?.[1];
|
|
198
|
+
expect(init.method).toBe("POST");
|
|
199
|
+
expect(init.headers["Content-Type"]).toBe("application/json");
|
|
200
|
+
expect(JSON.parse(init.body)).toEqual({
|
|
201
|
+
until: "2026-06-01T00:00:00Z",
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
it("unsilence_alert sends DELETE without body", async () => {
|
|
205
|
+
vi.stubGlobal("fetch", vi.fn(async () => new Response(null, { status: 204 })));
|
|
206
|
+
const res = await dispatchTool({
|
|
207
|
+
name: "unsilence_alert",
|
|
208
|
+
args: { alertId: "alt-xyz789" },
|
|
209
|
+
apiKey: "argosvix_live_test",
|
|
210
|
+
apiBase: "https://ingest.example.com",
|
|
211
|
+
});
|
|
212
|
+
expect(res.isError).toBeUndefined();
|
|
213
|
+
// 204 path = ok:true JSON で carry される
|
|
214
|
+
const parsed = JSON.parse(res.content[0]?.text ?? "{}");
|
|
215
|
+
expect(parsed.ok).toBe(true);
|
|
216
|
+
expect(parsed.status).toBe(204);
|
|
217
|
+
const fetchMock = global.fetch;
|
|
218
|
+
const init = fetchMock.mock.calls[0]?.[1];
|
|
219
|
+
expect(init.method).toBe("DELETE");
|
|
220
|
+
expect(init.body).toBeUndefined();
|
|
221
|
+
});
|
|
222
|
+
it("silence_alert rejects invalid alertId (= path injection 防御)", async () => {
|
|
223
|
+
const res = await dispatchTool({
|
|
224
|
+
name: "silence_alert",
|
|
225
|
+
args: { alertId: "../../admin/internal" },
|
|
226
|
+
apiKey: "argosvix_live_test",
|
|
227
|
+
apiBase: "https://ingest.example.com",
|
|
228
|
+
});
|
|
229
|
+
expect(res.isError).toBe(true);
|
|
230
|
+
expect(res.content[0]?.text).toContain("alertId required");
|
|
231
|
+
});
|
|
232
|
+
it("silence_alert rejects missing alertId", async () => {
|
|
233
|
+
const res = await dispatchTool({
|
|
234
|
+
name: "silence_alert",
|
|
235
|
+
args: { until: "2026-06-01T00:00:00Z" },
|
|
236
|
+
apiKey: "argosvix_live_test",
|
|
237
|
+
apiBase: "https://ingest.example.com",
|
|
238
|
+
});
|
|
239
|
+
expect(res.isError).toBe(true);
|
|
240
|
+
});
|
|
241
|
+
it("create_alert POSTs allowlisted body to /v1/alerts", async () => {
|
|
242
|
+
vi.stubGlobal("fetch", vi.fn(async () => new Response(JSON.stringify({ id: "alert-new" }), {
|
|
243
|
+
status: 200,
|
|
244
|
+
headers: { "content-type": "application/json" },
|
|
245
|
+
})));
|
|
246
|
+
const res = await dispatchTool({
|
|
247
|
+
name: "create_alert",
|
|
248
|
+
args: {
|
|
249
|
+
name: "Daily cost > $10",
|
|
250
|
+
alertType: "cost_daily",
|
|
251
|
+
thresholdValue: 10,
|
|
252
|
+
windowMinutes: 1440,
|
|
253
|
+
channelKinds: ["email"],
|
|
254
|
+
channelTargets: { email: "dev@example.com" },
|
|
255
|
+
},
|
|
256
|
+
apiKey: "argosvix_live_test",
|
|
257
|
+
apiBase: "https://ingest.example.com",
|
|
258
|
+
});
|
|
259
|
+
expect(res.isError).toBeUndefined();
|
|
260
|
+
const fetchMock = global.fetch;
|
|
261
|
+
const url = String(fetchMock.mock.calls[0]?.[0]);
|
|
262
|
+
expect(url).toContain("/v1/alerts");
|
|
263
|
+
const init = fetchMock.mock.calls[0]?.[1];
|
|
264
|
+
expect(init.method).toBe("POST");
|
|
265
|
+
const sent = JSON.parse(init.body);
|
|
266
|
+
expect(sent.name).toBe("Daily cost > $10");
|
|
267
|
+
expect(sent.alertType).toBe("cost_daily");
|
|
268
|
+
expect(sent.channelKinds).toEqual(["email"]);
|
|
269
|
+
expect(sent.channelTargets).toEqual({ email: "dev@example.com" });
|
|
270
|
+
});
|
|
271
|
+
it("create_alert drops non-allowlisted body fields (= injection 防御)", async () => {
|
|
272
|
+
vi.stubGlobal("fetch", vi.fn(async () => new Response(JSON.stringify({ id: "alert-new" }), {
|
|
273
|
+
status: 200,
|
|
274
|
+
headers: { "content-type": "application/json" },
|
|
275
|
+
})));
|
|
276
|
+
await dispatchTool({
|
|
277
|
+
name: "create_alert",
|
|
278
|
+
args: {
|
|
279
|
+
name: "x",
|
|
280
|
+
alertType: "error_rate",
|
|
281
|
+
thresholdValue: 5,
|
|
282
|
+
channelKinds: ["email"],
|
|
283
|
+
channelTargets: { email: "a@b.co" },
|
|
284
|
+
account_id: "acc_evil",
|
|
285
|
+
enabled: true,
|
|
286
|
+
},
|
|
287
|
+
apiKey: "argosvix_live_test",
|
|
288
|
+
apiBase: "https://ingest.example.com",
|
|
289
|
+
});
|
|
290
|
+
const fetchMock = global.fetch;
|
|
291
|
+
const init = fetchMock.mock.calls[0]?.[1];
|
|
292
|
+
const sent = JSON.parse(init.body);
|
|
293
|
+
expect(sent.account_id).toBeUndefined();
|
|
294
|
+
expect(sent.enabled).toBe(true);
|
|
295
|
+
});
|
|
296
|
+
it("create_alert propagates a backend 403 (= plan 上限) as isError", async () => {
|
|
297
|
+
vi.stubGlobal("fetch", vi.fn(async () => new Response(JSON.stringify({ error: "alert limit reached" }), {
|
|
298
|
+
status: 403,
|
|
299
|
+
headers: { "content-type": "application/json" },
|
|
300
|
+
})));
|
|
301
|
+
const res = await dispatchTool({
|
|
302
|
+
name: "create_alert",
|
|
303
|
+
args: {
|
|
304
|
+
name: "x",
|
|
305
|
+
alertType: "cost_daily",
|
|
306
|
+
thresholdValue: 1,
|
|
307
|
+
channelKinds: ["email"],
|
|
308
|
+
channelTargets: { email: "a@b.co" },
|
|
309
|
+
},
|
|
310
|
+
apiKey: "argosvix_live_test",
|
|
311
|
+
apiBase: "https://ingest.example.com",
|
|
312
|
+
});
|
|
313
|
+
expect(res.isError).toBe(true);
|
|
314
|
+
});
|
|
315
|
+
it("get_alert GETs /v1/alerts/:id with the alertId in the path", async () => {
|
|
316
|
+
vi.stubGlobal("fetch", vi.fn(async () => new Response(JSON.stringify({ id: "alt-abc", name: "Cost" }), {
|
|
317
|
+
status: 200,
|
|
318
|
+
headers: { "content-type": "application/json" },
|
|
319
|
+
})));
|
|
320
|
+
const res = await dispatchTool({
|
|
321
|
+
name: "get_alert",
|
|
322
|
+
args: { alertId: "alt-abc" },
|
|
323
|
+
apiKey: "argosvix_live_test",
|
|
324
|
+
apiBase: "https://ingest.example.com",
|
|
325
|
+
});
|
|
326
|
+
expect(res.isError).toBeUndefined();
|
|
327
|
+
const fetchMock = global.fetch;
|
|
328
|
+
const url = String(fetchMock.mock.calls[0]?.[0]);
|
|
329
|
+
expect(url).toContain("/v1/alerts/alt-abc");
|
|
330
|
+
const init = fetchMock.mock.calls[0]?.[1];
|
|
331
|
+
expect(init.method ?? "GET").toBe("GET");
|
|
332
|
+
});
|
|
333
|
+
it("get_alert rejects an invalid alertId (= path injection 防御)", async () => {
|
|
334
|
+
const res = await dispatchTool({
|
|
335
|
+
name: "get_alert",
|
|
336
|
+
args: { alertId: "../../admin" },
|
|
337
|
+
apiKey: "argosvix_live_test",
|
|
338
|
+
apiBase: "https://ingest.example.com",
|
|
339
|
+
});
|
|
340
|
+
expect(res.isError).toBe(true);
|
|
341
|
+
expect(res.content[0]?.text).toContain("alertId required");
|
|
342
|
+
});
|
|
343
|
+
it("list_alert_events GETs /v1/alerts/events with limit + alertId query", async () => {
|
|
344
|
+
vi.stubGlobal("fetch", vi.fn(async () => new Response(JSON.stringify({ events: [] }), {
|
|
345
|
+
status: 200,
|
|
346
|
+
headers: { "content-type": "application/json" },
|
|
347
|
+
})));
|
|
348
|
+
const res = await dispatchTool({
|
|
349
|
+
name: "list_alert_events",
|
|
350
|
+
args: { limit: 5, alertId: "alt-abc" },
|
|
351
|
+
apiKey: "argosvix_live_test",
|
|
352
|
+
apiBase: "https://ingest.example.com",
|
|
353
|
+
});
|
|
354
|
+
expect(res.isError).toBeUndefined();
|
|
355
|
+
const fetchMock = global.fetch;
|
|
356
|
+
const url = String(fetchMock.mock.calls[0]?.[0]);
|
|
357
|
+
expect(url).toContain("/v1/alerts/events");
|
|
358
|
+
expect(url).toContain("limit=5");
|
|
359
|
+
expect(url).toContain("alertId=alt-abc");
|
|
360
|
+
});
|
|
361
|
+
it("list_alert_events drops non-allowlisted args (= injection 防御)", async () => {
|
|
362
|
+
vi.stubGlobal("fetch", vi.fn(async () => new Response(JSON.stringify({ events: [] }), {
|
|
363
|
+
status: 200,
|
|
364
|
+
headers: { "content-type": "application/json" },
|
|
365
|
+
})));
|
|
366
|
+
await dispatchTool({
|
|
367
|
+
name: "list_alert_events",
|
|
368
|
+
args: { limit: 5, account_id: "acc_evil" },
|
|
369
|
+
apiKey: "argosvix_live_test",
|
|
370
|
+
apiBase: "https://ingest.example.com",
|
|
371
|
+
});
|
|
372
|
+
const fetchMock = global.fetch;
|
|
373
|
+
const url = String(fetchMock.mock.calls[0]?.[0]);
|
|
374
|
+
expect(url).toContain("limit=5");
|
|
375
|
+
expect(url).not.toContain("account_id");
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
//# sourceMappingURL=tools.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.test.js","sourceRoot":"","sources":["../src/tools.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@argosvix/mcp-server",
|
|
3
|
+
"version": "0.2.0-alpha.1",
|
|
4
|
+
"description": "Argosvix MCP server — AI agent から traces / cost / alert を直接 query するための Model Context Protocol server (stdio transport).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"bin": {
|
|
9
|
+
"argosvix-mcp": "dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc -p tsconfig.json",
|
|
18
|
+
"dev": "tsc -p tsconfig.json --watch",
|
|
19
|
+
"start": "node dist/index.js",
|
|
20
|
+
"test": "vitest run"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"mcp",
|
|
24
|
+
"model-context-protocol",
|
|
25
|
+
"argosvix",
|
|
26
|
+
"llm",
|
|
27
|
+
"observability",
|
|
28
|
+
"ai-agent"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=20"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^22.0.0",
|
|
38
|
+
"typescript": "^5.4.0",
|
|
39
|
+
"vitest": "^2.1.0"
|
|
40
|
+
},
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://github.com/argosvix/Argosvix.git",
|
|
44
|
+
"directory": "packages/mcp-server"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://argosvix.com",
|
|
47
|
+
"bugs": {
|
|
48
|
+
"url": "https://github.com/argosvix/Argosvix/issues"
|
|
49
|
+
}
|
|
50
|
+
}
|