@argosvix/mcp-server 0.9.3-alpha.1 → 0.10.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -104,7 +104,25 @@ Prompts are reusable templates the user can launch as slash commands.
104
104
  | `alert_audit` | Audit current alert rules and propose improvements |
105
105
  | `incident_triage` | Investigate recent error / latency anomalies (default last 24h) |
106
106
 
107
- Phase 3 backlog (= not yet shipped): `subscribe` / `listChanged` (= MCP spec real-time update).
107
+ ## Subscriptions (= v0.10, stdio only)
108
+
109
+ `resources.subscribe` capability is declared in stdio mode. Clients can subscribe to one or more of the static resources below; the server polls each subscribed resource every 60 seconds and emits `notifications/resources/updated` when the content hash changes.
110
+
111
+ Subscribable URIs (resource templates such as `argosvix://calls/{id}` are **not** subscribable):
112
+
113
+ - `argosvix://account`
114
+ - `argosvix://alerts/active`
115
+ - `argosvix://cost/today`
116
+
117
+ HTTP transport (= `argosvix-mcp --http`) does not declare `subscribe` and rejects subscribe requests, since per-request stateless mode cannot keep a subscription set or deliver server-initiated notifications. Use stdio for live updates.
118
+
119
+ `listChanged` is intentionally not declared: the resource list is fixed for the server lifetime.
120
+
121
+ Implementation notes (v0.10):
122
+ - Single-flight guard: a slow polling cycle does not start a concurrent next cycle (= no overlapping `readResource` calls).
123
+ - Unsubscribe / shutdown race: per-URI re-check before fetch and before notify, plus an `isShuttingDown` flag, so notifications are not emitted for URIs removed mid-cycle.
124
+ - Failure handling: fetch and notify failures are silent (next cycle retries). With `ARGOSVIX_MCP_DEBUG=1` the server logs `{ uri, errorClass }` to stderr — error messages are intentionally **not** logged to avoid leaking upstream payload text.
125
+ - Tests: 110 unit tests (incl. overlap single-flight + unsubscribe / shutdown race + invalid URI → `McpError(InvalidParams)`).
108
126
 
109
127
  ## Privacy
110
128
 
package/dist/index.js CHANGED
@@ -53,6 +53,7 @@ else {
53
53
  const { tools, dispatchTool } = await import("./tools.js");
54
54
  const { resources, resourceTemplates, readResource, ResourceNotFoundError, } = await import("./resources.js");
55
55
  const { prompts, getPrompt, PromptNotFoundError } = await import("./prompts.js");
56
+ const { setupSubscribe } = await import("./subscriptions.js");
56
57
  const { MCP_VERSION } = await import("./version.js");
57
58
  const API_KEY = process.env["ARGOSVIX_API_KEY"];
58
59
  const API_BASE = process.env["ARGOSVIX_API_BASE"] ?? "https://ingest.argosvix.com";
@@ -69,7 +70,12 @@ else {
69
70
  }, {
70
71
  capabilities: {
71
72
  tools: {},
72
- resources: {},
73
+ // v0.10.0-alpha.1 = stdio transport 限定で resources.subscribe を carry。
74
+ // polling 60 秒 で 3 static resources (= account / alerts/active /
75
+ // cost/today) の hash 比較で 変化検出 → notifications/resources/updated。
76
+ // HTTP transport (= packages/mcp-server/src/http.ts) では per-request
77
+ // stateless なので subscribe declare せず、 setupSubscribe も呼ばない。
78
+ resources: { subscribe: true },
73
79
  prompts: {},
74
80
  },
75
81
  });
@@ -127,10 +133,21 @@ else {
127
133
  throw new McpError(ErrorCode.InternalError, err instanceof Error ? err.message : String(err));
128
134
  }
129
135
  });
136
+ const subscribeManager = setupSubscribe({
137
+ server,
138
+ apiKey: API_KEY,
139
+ apiBase: API_BASE,
140
+ });
141
+ const handleShutdown = () => {
142
+ subscribeManager.shutdown();
143
+ };
144
+ process.on("SIGINT", handleShutdown);
145
+ process.on("SIGTERM", handleShutdown);
146
+ process.on("beforeExit", handleShutdown);
130
147
  const transport = new StdioServerTransport();
131
148
  await server.connect(transport);
132
149
  // eslint-disable-next-line no-console
133
- console.error(`[argosvix-mcp] argosvix@${MCP_VERSION} ready on stdio transport`);
150
+ console.error(`[argosvix-mcp] argosvix@${MCP_VERSION} ready on stdio transport (subscribe: 3 resources, poll 60s)`);
134
151
  }
135
152
  export {};
136
153
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * MCP resources/subscribe 軽量 carry (= v0.10.0-alpha.1、 v0.8 backlog 倒し込み)。
3
+ *
4
+ * MCP spec の `resources.subscribe` capability を stdio transport で carry する。
5
+ * client が `resources/subscribe` で URI を 登録すると、 polling cycle で 当該
6
+ * resource の hash を 比較し、 変化を 検出した時に `notifications/resources/updated`
7
+ * を send する。
8
+ *
9
+ * 対応 URI (= 3 static resources のみ、 resource templates = calls/{id} 等は対象外):
10
+ * - argosvix://account
11
+ * - argosvix://alerts/active
12
+ * - argosvix://cost/today
13
+ *
14
+ * 設計選択:
15
+ * - polling = 60 秒 interval (= backend 負荷と更新遅延の妥協点)
16
+ * - HTTP transport では setupSubscribe を call しない (= per-request stateless で
17
+ * subscription state が 持てない、 capabilities でも subscribe 宣言なし)
18
+ * - shutdown / 接続切断時 = polling timer stop + subscription set 全削除
19
+ * - subscription set は 単一 server instance 単位 (= stdio = 1 client 1 process)
20
+ * - fetch 失敗 (= 401 / network) は silent skip (= 次回 cycle で 再試行)、 hash は
21
+ * 前回値 keep (= 「fetch 不可 = 変化なし」 と扱い 不要 notify 抑制)
22
+ * - hash = JSON.stringify + djb2-like rolling 32bit (= 軽量、 暗号目的ではない)
23
+ *
24
+ * Codex / 実装 backlog (= v0.10 では carry しない):
25
+ * - resource templates の per-id subscribe (= calls/{id} 等、 LLM が個別 call の
26
+ * 更新を 監視する path)
27
+ * - listChanged notification (= resource list 自体は server lifecycle 内 固定で 不要)
28
+ * - WebSocket / SSE 経由の HTTP subscribe (= persistent connection 必要、 重い)
29
+ * - polling interval の env-driven 設定 (= MCP_SUBSCRIBE_POLL_MS で override 可能化)
30
+ */
31
+ import type { Server } from "@modelcontextprotocol/sdk/server/index.js";
32
+ interface SubscribeContext {
33
+ server: Server;
34
+ apiKey: string;
35
+ apiBase: string;
36
+ /** test 用 override (= 60 秒は long すぎるため unit test では小さい値で carry)。 */
37
+ pollIntervalMs?: number;
38
+ }
39
+ export interface SubscribeManager {
40
+ subscribe(uri: string): void;
41
+ unsubscribe(uri: string): void;
42
+ /** shutdown / 切断時 = polling 停止 + subscription set クリア。 */
43
+ shutdown(): void;
44
+ /** test 用 = polling cycle を 1 回 即時 trigger する。 */
45
+ pollNow(): Promise<void>;
46
+ /** test 用 = 現 subscription set snapshot。 */
47
+ snapshot(): {
48
+ uris: string[];
49
+ pollerActive: boolean;
50
+ };
51
+ }
52
+ export declare function setupSubscribe(ctx: SubscribeContext): SubscribeManager;
53
+ export declare const SUBSCRIBABLE_URIS_FOR_TEST: ReadonlySet<string>;
54
+ export {};
55
+ //# sourceMappingURL=subscriptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscriptions.d.ts","sourceRoot":"","sources":["../src/subscriptions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAkBxE,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAkBD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,0DAA0D;IAC1D,QAAQ,IAAI,IAAI,CAAC;IACjB,kDAAkD;IAClD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,4CAA4C;IAC5C,QAAQ,IAAI;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,YAAY,EAAE,OAAO,CAAA;KAAE,CAAC;CACvD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,gBAAgB,GAAG,gBAAgB,CAuKtE;AAED,eAAO,MAAM,0BAA0B,EAAE,WAAW,CAAC,MAAM,CAAqB,CAAC"}
@@ -0,0 +1,219 @@
1
+ /**
2
+ * MCP resources/subscribe 軽量 carry (= v0.10.0-alpha.1、 v0.8 backlog 倒し込み)。
3
+ *
4
+ * MCP spec の `resources.subscribe` capability を stdio transport で carry する。
5
+ * client が `resources/subscribe` で URI を 登録すると、 polling cycle で 当該
6
+ * resource の hash を 比較し、 変化を 検出した時に `notifications/resources/updated`
7
+ * を send する。
8
+ *
9
+ * 対応 URI (= 3 static resources のみ、 resource templates = calls/{id} 等は対象外):
10
+ * - argosvix://account
11
+ * - argosvix://alerts/active
12
+ * - argosvix://cost/today
13
+ *
14
+ * 設計選択:
15
+ * - polling = 60 秒 interval (= backend 負荷と更新遅延の妥協点)
16
+ * - HTTP transport では setupSubscribe を call しない (= per-request stateless で
17
+ * subscription state が 持てない、 capabilities でも subscribe 宣言なし)
18
+ * - shutdown / 接続切断時 = polling timer stop + subscription set 全削除
19
+ * - subscription set は 単一 server instance 単位 (= stdio = 1 client 1 process)
20
+ * - fetch 失敗 (= 401 / network) は silent skip (= 次回 cycle で 再試行)、 hash は
21
+ * 前回値 keep (= 「fetch 不可 = 変化なし」 と扱い 不要 notify 抑制)
22
+ * - hash = JSON.stringify + djb2-like rolling 32bit (= 軽量、 暗号目的ではない)
23
+ *
24
+ * Codex / 実装 backlog (= v0.10 では carry しない):
25
+ * - resource templates の per-id subscribe (= calls/{id} 等、 LLM が個別 call の
26
+ * 更新を 監視する path)
27
+ * - listChanged notification (= resource list 自体は server lifecycle 内 固定で 不要)
28
+ * - WebSocket / SSE 経由の HTTP subscribe (= persistent connection 必要、 重い)
29
+ * - polling interval の env-driven 設定 (= MCP_SUBSCRIBE_POLL_MS で override 可能化)
30
+ */
31
+ import { ErrorCode, McpError, SubscribeRequestSchema, UnsubscribeRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
32
+ import { isDebugEnabled } from "./debug.js";
33
+ import { readResource } from "./resources.js";
34
+ const DEFAULT_POLL_INTERVAL_MS = 60 * 1000;
35
+ const SUBSCRIBABLE_URIS = new Set([
36
+ "argosvix://account",
37
+ "argosvix://alerts/active",
38
+ "argosvix://cost/today",
39
+ ]);
40
+ /**
41
+ * 軽量 32bit hash (= djb2 風)。 暗号目的ではなく、 等価判定の高速軸として carry。
42
+ * 衝突確率は内容比較で十分低いが、 重大判定 (= 課金 / 認証) には使わない。
43
+ */
44
+ function hashString(s) {
45
+ let h = 5381;
46
+ for (let i = 0; i < s.length; i++) {
47
+ h = ((h << 5) + h + s.charCodeAt(i)) | 0;
48
+ }
49
+ return h >>> 0;
50
+ }
51
+ function resourceHash(contents) {
52
+ return hashString(JSON.stringify(contents));
53
+ }
54
+ export function setupSubscribe(ctx) {
55
+ const subscriptions = new Set();
56
+ const lastHashes = new Map();
57
+ const pollIntervalMs = ctx.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
58
+ let pollTimer = null;
59
+ // Codex round 1 HIGH 1 fix carry = single-flight guard。 setInterval は 前 cycle
60
+ // が終わっていなくても 次の cycle を 並列 起動するため、 遅い fetch 1 つ
61
+ // (= 5xx + 長 retry / 60 秒 超過 latency) で polling が overlap し、
62
+ // backend 負荷 spike + 重複 notification を 起こす。
63
+ let pollInFlight = false;
64
+ // Codex round 1 HIGH 2 fix carry = shutdown race 防御。 cycle 開始後に
65
+ // shutdown が来た場合、 残り URI に対する notify を 全 skip する。
66
+ let isShuttingDown = false;
67
+ async function pollOnce() {
68
+ if (pollInFlight)
69
+ return;
70
+ if (subscriptions.size === 0)
71
+ return;
72
+ pollInFlight = true;
73
+ try {
74
+ const uris = Array.from(subscriptions);
75
+ for (const uri of uris) {
76
+ // Codex round 1 HIGH 2 fix carry = cycle 内 unsubscribe / shutdown 検出。
77
+ // uris snapshot 取得後に unsubscribe された URI に対しては notify しない。
78
+ if (isShuttingDown)
79
+ return;
80
+ if (!subscriptions.has(uri))
81
+ continue;
82
+ let result;
83
+ try {
84
+ result = await readResource({
85
+ uri,
86
+ apiKey: ctx.apiKey,
87
+ apiBase: ctx.apiBase,
88
+ });
89
+ }
90
+ catch (err) {
91
+ // 401 / network / 5xx 等の 一時的 failure は silent skip (= 次回 cycle で
92
+ // 再試行)。 hash 更新しない (= 「fetch 不可 = 変化なし」 扱いで 不要
93
+ // notification 抑制)。 debug 時のみ stderr に carry。
94
+ //
95
+ // Codex round 2 LOW 3 fix carry = error.message は upstream の
96
+ // response body / 内部実装文字列を含む可能性があるため、 default は
97
+ // errorClass のみ log。 full message が必要な場合は別途 redact pattern
98
+ // 軸で carry path (= 現状 carry なし)。
99
+ if (isDebugEnabled()) {
100
+ // eslint-disable-next-line no-console
101
+ console.error(`[argosvix-mcp] subscribe poll fetch failed (silent skip)`, {
102
+ uri,
103
+ errorClass: err instanceof Error ? err.constructor.name : typeof err,
104
+ });
105
+ }
106
+ continue;
107
+ }
108
+ if (isShuttingDown || !subscriptions.has(uri))
109
+ continue;
110
+ const h = resourceHash(result.contents);
111
+ const prev = lastHashes.get(uri);
112
+ if (prev === undefined) {
113
+ lastHashes.set(uri, h);
114
+ continue;
115
+ }
116
+ if (prev !== h) {
117
+ lastHashes.set(uri, h);
118
+ try {
119
+ await ctx.server.notification({
120
+ method: "notifications/resources/updated",
121
+ params: { uri },
122
+ });
123
+ }
124
+ catch (err) {
125
+ // notification 送信失敗 (= transport 切断 / 一時的 error) は silent
126
+ // skip だが、 fetch 失敗と path を分けて log carry (= MEDIUM 2 fix、
127
+ // operational blind spot 解消)。 次回 cycle で 変化検出すれば 再 notify
128
+ // される。 LOW 3 fix carry = errorClass のみ log (= upstream message
129
+ // 経由の情報漏洩 構造防御)。
130
+ if (isDebugEnabled()) {
131
+ // eslint-disable-next-line no-console
132
+ console.error(`[argosvix-mcp] subscribe notify failed (silent skip)`, {
133
+ uri,
134
+ errorClass: err instanceof Error ? err.constructor.name : typeof err,
135
+ });
136
+ }
137
+ }
138
+ }
139
+ }
140
+ }
141
+ finally {
142
+ pollInFlight = false;
143
+ }
144
+ }
145
+ function startPolling() {
146
+ if (pollTimer !== null)
147
+ return;
148
+ pollTimer = setInterval(() => {
149
+ void pollOnce();
150
+ }, pollIntervalMs);
151
+ // Node.js では setInterval の timer が default で event loop に登録される。
152
+ // unref で 「他に pending task が無くなれば process 終了可能」 にする
153
+ // (= shutdown 漏れ 防御)。 setInterval の戻り値型は Node では unref を
154
+ // 持つが TS 型では optional のため guard。
155
+ if (typeof pollTimer.unref === "function") {
156
+ pollTimer.unref();
157
+ }
158
+ }
159
+ function stopPolling() {
160
+ if (pollTimer === null)
161
+ return;
162
+ clearInterval(pollTimer);
163
+ pollTimer = null;
164
+ }
165
+ ctx.server.setRequestHandler(SubscribeRequestSchema, async (request) => {
166
+ const uri = request.params.uri;
167
+ if (!SUBSCRIBABLE_URIS.has(uri)) {
168
+ // Codex round 1 MEDIUM 1 fix carry = McpError(InvalidParams) で throw して
169
+ // client に正しい -32602 を返す (= 旧実装は raw Error で SDK が
170
+ // InternalError に変換、 InvalidParams semantic が落ちる)。
171
+ throw new McpError(ErrorCode.InvalidParams, `Resource ${uri} does not support subscriptions. Subscribable URIs: ${Array.from(SUBSCRIBABLE_URIS).join(", ")}`);
172
+ }
173
+ subscriptions.add(uri);
174
+ if (subscriptions.size === 1)
175
+ startPolling();
176
+ return {};
177
+ });
178
+ ctx.server.setRequestHandler(UnsubscribeRequestSchema, async (request) => {
179
+ const uri = request.params.uri;
180
+ subscriptions.delete(uri);
181
+ lastHashes.delete(uri);
182
+ if (subscriptions.size === 0)
183
+ stopPolling();
184
+ return {};
185
+ });
186
+ return {
187
+ subscribe(uri) {
188
+ if (!SUBSCRIBABLE_URIS.has(uri))
189
+ return;
190
+ subscriptions.add(uri);
191
+ if (subscriptions.size === 1)
192
+ startPolling();
193
+ },
194
+ unsubscribe(uri) {
195
+ subscriptions.delete(uri);
196
+ lastHashes.delete(uri);
197
+ if (subscriptions.size === 0)
198
+ stopPolling();
199
+ },
200
+ shutdown() {
201
+ // Codex round 1 HIGH 2 fix carry = in-flight cycle が ある 場合に
202
+ // notify suppress を 即時有効化。 stopPolling() 後の cycle 内 残 URI
203
+ // への notify を 構造防御。
204
+ isShuttingDown = true;
205
+ stopPolling();
206
+ subscriptions.clear();
207
+ lastHashes.clear();
208
+ },
209
+ pollNow: pollOnce,
210
+ snapshot() {
211
+ return {
212
+ uris: Array.from(subscriptions),
213
+ pollerActive: pollTimer !== null,
214
+ };
215
+ },
216
+ };
217
+ }
218
+ export const SUBSCRIBABLE_URIS_FOR_TEST = SUBSCRIBABLE_URIS;
219
+ //# sourceMappingURL=subscriptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscriptions.js","sourceRoot":"","sources":["../src/subscriptions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=subscriptions.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscriptions.test.d.ts","sourceRoot":"","sources":["../src/subscriptions.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,344 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { ErrorCode, McpError, SubscribeRequestSchema, UnsubscribeRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
3
+ import { setupSubscribe, SUBSCRIBABLE_URIS_FOR_TEST, } from "./subscriptions.js";
4
+ /**
5
+ * resources.subscribe 軽量 carry の regression 防御。
6
+ *
7
+ * stub server で setRequestHandler / notification の call を capture して、
8
+ * subscribe → polling → 変化検出 → notification の flow を 確認する。
9
+ * 実 polling は 60 秒 interval = unit test では pollNow() で 1 cycle を 即時
10
+ * trigger する。
11
+ */
12
+ const ALLOWED_URI = "argosvix://account";
13
+ const DISALLOWED_URI = "argosvix://calls/abc123";
14
+ function createStubServer() {
15
+ const handlers = new Map();
16
+ return {
17
+ handlers,
18
+ setRequestHandler: vi.fn((schema, handler) => {
19
+ handlers.set(schema, handler);
20
+ }),
21
+ notification: vi.fn(async () => undefined),
22
+ };
23
+ }
24
+ describe("setupSubscribe", () => {
25
+ // CI tsc は vi.spyOn(globalThis, "fetch") の MockInstance<fetch overloads> と
26
+ // generic default の MockInstance<(this: unknown, ...args: unknown[]) => unknown>
27
+ // が assignment 不可。 typed alias 経路は globalThis の prop key narrow で別 fail
28
+ // のため、 test スコープ限定で any cast で carry (= 型安全性 loss は test
29
+ // isolation 内に閉じる)。
30
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
+ let stubFetch;
32
+ beforeEach(() => {
33
+ // global fetch を stub。 1 回目 = {value: 1}、 2 回目 = {value: 2} で 変化検出を
34
+ // simulate。 readResource は /v1/account を 内部 で fetch する。
35
+ let callCount = 0;
36
+ stubFetch = vi
37
+ .spyOn(globalThis, "fetch")
38
+ .mockImplementation(async () => {
39
+ callCount += 1;
40
+ const payload = {
41
+ account: {
42
+ id: "acc_test",
43
+ plan: "free",
44
+ retentionDays: 7,
45
+ createdAt: "2026-05-31T00:00:00.000Z",
46
+ },
47
+ usage: {
48
+ recordsThisMonth: callCount,
49
+ quotaRecordsPerMonth: 10000,
50
+ yearMonth: "2026-05",
51
+ },
52
+ };
53
+ return new Response(JSON.stringify(payload), {
54
+ status: 200,
55
+ headers: { "Content-Type": "application/json" },
56
+ });
57
+ });
58
+ });
59
+ afterEach(() => {
60
+ stubFetch.mockRestore();
61
+ });
62
+ it("subscribable URI を 列挙する", () => {
63
+ expect(SUBSCRIBABLE_URIS_FOR_TEST.has("argosvix://account")).toBe(true);
64
+ expect(SUBSCRIBABLE_URIS_FOR_TEST.has("argosvix://alerts/active")).toBe(true);
65
+ expect(SUBSCRIBABLE_URIS_FOR_TEST.has("argosvix://cost/today")).toBe(true);
66
+ });
67
+ it("subscribe → polling 1 cycle で hash 確立、 2 cycle 目で変化 detect → notification", async () => {
68
+ const server = createStubServer();
69
+ const mgr = setupSubscribe({
70
+ server: server,
71
+ apiKey: "argk_test",
72
+ apiBase: "https://ingest.test",
73
+ pollIntervalMs: 60_000,
74
+ });
75
+ mgr.subscribe(ALLOWED_URI);
76
+ expect(mgr.snapshot().uris).toEqual([ALLOWED_URI]);
77
+ expect(mgr.snapshot().pollerActive).toBe(true);
78
+ // 1 cycle = baseline hash 確立 = notification なし
79
+ await mgr.pollNow();
80
+ expect(server.notification).not.toHaveBeenCalled();
81
+ // 2 cycle = recordsThisMonth が 2 に増えて hash 変化 = notification 1 回
82
+ await mgr.pollNow();
83
+ expect(server.notification).toHaveBeenCalledTimes(1);
84
+ expect(server.notification.mock.calls[0]?.[0]).toEqual({
85
+ method: "notifications/resources/updated",
86
+ params: { uri: ALLOWED_URI },
87
+ });
88
+ mgr.shutdown();
89
+ });
90
+ it("unsubscribe で polling 停止 + 後続 cycle で notification なし", async () => {
91
+ const server = createStubServer();
92
+ const mgr = setupSubscribe({
93
+ server: server,
94
+ apiKey: "argk_test",
95
+ apiBase: "https://ingest.test",
96
+ pollIntervalMs: 60_000,
97
+ });
98
+ mgr.subscribe(ALLOWED_URI);
99
+ await mgr.pollNow();
100
+ mgr.unsubscribe(ALLOWED_URI);
101
+ expect(mgr.snapshot().uris).toEqual([]);
102
+ expect(mgr.snapshot().pollerActive).toBe(false);
103
+ await mgr.pollNow();
104
+ expect(server.notification).not.toHaveBeenCalled();
105
+ mgr.shutdown();
106
+ });
107
+ it("非 subscribable URI は subscribe で silent skip (= 公開 API)", () => {
108
+ const server = createStubServer();
109
+ const mgr = setupSubscribe({
110
+ server: server,
111
+ apiKey: "argk_test",
112
+ apiBase: "https://ingest.test",
113
+ pollIntervalMs: 60_000,
114
+ });
115
+ mgr.subscribe(DISALLOWED_URI);
116
+ expect(mgr.snapshot().uris).toEqual([]);
117
+ mgr.shutdown();
118
+ });
119
+ it("非 subscribable URI を MCP request 経由で subscribe = McpError InvalidParams で throw", async () => {
120
+ const server = createStubServer();
121
+ setupSubscribe({
122
+ server: server,
123
+ apiKey: "argk_test",
124
+ apiBase: "https://ingest.test",
125
+ pollIntervalMs: 60_000,
126
+ });
127
+ // Codex round 1 MEDIUM 4 fix carry = schema identity で handler を取得 (=
128
+ // 旧設計は Array index 0 だったため registration 順序変化で fragile)。
129
+ const subscribeHandler = server.handlers.get(SubscribeRequestSchema);
130
+ expect(subscribeHandler).toBeDefined();
131
+ let caught = null;
132
+ try {
133
+ await subscribeHandler?.({ params: { uri: DISALLOWED_URI } });
134
+ }
135
+ catch (err) {
136
+ caught = err;
137
+ }
138
+ expect(caught).toBeInstanceOf(McpError);
139
+ expect(caught.code).toBe(ErrorCode.InvalidParams);
140
+ expect(caught.message).toMatch(/does not support subscriptions/);
141
+ });
142
+ it("unsubscribe が cycle 中の URI に対する notify を抑制", async () => {
143
+ const server = createStubServer();
144
+ const mgr = setupSubscribe({
145
+ server: server,
146
+ apiKey: "argk_test",
147
+ apiBase: "https://ingest.test",
148
+ pollIntervalMs: 60_000,
149
+ });
150
+ mgr.subscribe(ALLOWED_URI);
151
+ await mgr.pollNow(); // baseline 確立
152
+ // 2 cycle 中で fetch 完了直前 (= 直後の re-check 直前) に unsubscribe シナリオは
153
+ // 実機では race だが、 unsubscribe を pollNow の 前に 呼んで 直後 cycle で
154
+ // notification 抑制を 確認 (= 「unsubscribe 後 cycle で notify 0」)。
155
+ mgr.unsubscribe(ALLOWED_URI);
156
+ await mgr.pollNow();
157
+ expect(server.notification).not.toHaveBeenCalled();
158
+ mgr.shutdown();
159
+ });
160
+ it("shutdown 後の polling は notify を抑制", async () => {
161
+ const server = createStubServer();
162
+ const mgr = setupSubscribe({
163
+ server: server,
164
+ apiKey: "argk_test",
165
+ apiBase: "https://ingest.test",
166
+ pollIntervalMs: 60_000,
167
+ });
168
+ mgr.subscribe(ALLOWED_URI);
169
+ await mgr.pollNow();
170
+ mgr.shutdown();
171
+ await mgr.pollNow(); // shutdown 後の cycle = 0 notify
172
+ expect(server.notification).not.toHaveBeenCalled();
173
+ });
174
+ it("setRequestHandler は SubscribeRequestSchema + UnsubscribeRequestSchema を登録 (= identity 軸 verify)", () => {
175
+ const server = createStubServer();
176
+ setupSubscribe({
177
+ server: server,
178
+ apiKey: "argk_test",
179
+ apiBase: "https://ingest.test",
180
+ pollIntervalMs: 60_000,
181
+ });
182
+ expect(server.handlers.has(SubscribeRequestSchema)).toBe(true);
183
+ expect(server.handlers.has(UnsubscribeRequestSchema)).toBe(true);
184
+ });
185
+ // Codex round 2 LOW 1 fix carry = overlap single-flight 検証。 deferred promise
186
+ // で fetch を block して、 並列 pollNow() を 2 回 trigger、 1 つ目だけ fetch
187
+ // 開始 + 2 つ目は即 return を 確認。 fetch 解放後に 3 回目 pollNow() が 通常
188
+ // 動作するか までを 1 sequence で verify。
189
+ it("polling overlap = single-flight guard で 2 回目 cycle skip + 解放後の 3 回目は通常 carry", async () => {
190
+ stubFetch.mockRestore();
191
+ let fetchEntered = 0;
192
+ let releaseFetch = () => {
193
+ /* placeholder replaced by Promise constructor below */
194
+ };
195
+ const fetchGate = new Promise((resolve) => {
196
+ releaseFetch = resolve;
197
+ });
198
+ stubFetch = vi
199
+ .spyOn(globalThis, "fetch")
200
+ .mockImplementation(async () => {
201
+ fetchEntered += 1;
202
+ await fetchGate;
203
+ return new Response(JSON.stringify({
204
+ account: {
205
+ id: "acc_test",
206
+ plan: "free",
207
+ retentionDays: 7,
208
+ createdAt: "2026-05-31T00:00:00.000Z",
209
+ },
210
+ usage: {
211
+ recordsThisMonth: fetchEntered,
212
+ quotaRecordsPerMonth: 10000,
213
+ yearMonth: "2026-05",
214
+ },
215
+ }), { status: 200, headers: { "Content-Type": "application/json" } });
216
+ });
217
+ const server = createStubServer();
218
+ const mgr = setupSubscribe({
219
+ server: server,
220
+ apiKey: "argk_test",
221
+ apiBase: "https://ingest.test",
222
+ pollIntervalMs: 60_000,
223
+ });
224
+ mgr.subscribe(ALLOWED_URI);
225
+ // 並列に 2 回 trigger、 1 つ目だけ fetch entry。 2 つ目は pollInFlight ガード
226
+ // で 即 return。
227
+ const p1 = mgr.pollNow();
228
+ const p2 = mgr.pollNow();
229
+ // microtask だけ進めて fetchEntered を確認 (= まだ 解放してない = 1 のまま)
230
+ await Promise.resolve();
231
+ await Promise.resolve();
232
+ expect(fetchEntered).toBe(1);
233
+ // fetch 解放、 1 cycle 完了
234
+ releaseFetch();
235
+ await p1;
236
+ await p2;
237
+ // 3 回目 pollNow() は guard 解除済 + cycle 通常 carry
238
+ await mgr.pollNow();
239
+ expect(fetchEntered).toBe(2);
240
+ mgr.shutdown();
241
+ });
242
+ it("shutdown で subscription set クリア + polling 停止", () => {
243
+ const server = createStubServer();
244
+ const mgr = setupSubscribe({
245
+ server: server,
246
+ apiKey: "argk_test",
247
+ apiBase: "https://ingest.test",
248
+ pollIntervalMs: 60_000,
249
+ });
250
+ mgr.subscribe(ALLOWED_URI);
251
+ expect(mgr.snapshot().pollerActive).toBe(true);
252
+ mgr.shutdown();
253
+ expect(mgr.snapshot().uris).toEqual([]);
254
+ expect(mgr.snapshot().pollerActive).toBe(false);
255
+ });
256
+ it("fetch 失敗時 (= network error) は silent skip + hash 更新なし", async () => {
257
+ // beforeEach の stubFetch を 直接 mockImplementation で override (= 再 assign
258
+ // を避けて vi.spyOn の type 不整合 を 構造防御)。 afterEach の mockRestore で
259
+ // baseline (= success path) に戻る。
260
+ stubFetch.mockImplementation(async () => {
261
+ throw new Error("network error");
262
+ });
263
+ const server = createStubServer();
264
+ const mgr = setupSubscribe({
265
+ server: server,
266
+ apiKey: "argk_test",
267
+ apiBase: "https://ingest.test",
268
+ pollIntervalMs: 60_000,
269
+ });
270
+ mgr.subscribe(ALLOWED_URI);
271
+ await mgr.pollNow();
272
+ await mgr.pollNow();
273
+ expect(server.notification).not.toHaveBeenCalled();
274
+ mgr.shutdown();
275
+ });
276
+ });
277
+ // ============================================================
278
+ // Codex round 2 LOW 2 fix carry = wire-level JSON-RPC -32602 mapping verify。
279
+ // 既存 test は McpError instance + code で 検査していたが、 SDK protocol が
280
+ // 実際に JSON-RPC error response の `error.code = -32602` を carry するか は
281
+ // in-memory transport pair の wire 経由で 確認しないと regression を捕捉できない。
282
+ // ============================================================
283
+ describe("subscribe wire-level error mapping (= JSON-RPC -32602)", () => {
284
+ it("非 subscribable URI は wire error.code = -32602 で reject", async () => {
285
+ const { Server } = await import("@modelcontextprotocol/sdk/server/index.js");
286
+ const { Client } = await import("@modelcontextprotocol/sdk/client/index.js");
287
+ const { InMemoryTransport } = await import("@modelcontextprotocol/sdk/inMemory.js");
288
+ const { EmptyResultSchema } = await import("@modelcontextprotocol/sdk/types.js");
289
+ const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
290
+ const server = new Server({ name: "argosvix-test", version: "0.0.0-test" }, { capabilities: { resources: { subscribe: true } } });
291
+ setupSubscribe({
292
+ server,
293
+ apiKey: "argk_test",
294
+ apiBase: "https://ingest.test",
295
+ pollIntervalMs: 60_000,
296
+ });
297
+ await server.connect(serverTransport);
298
+ const client = new Client({ name: "argosvix-wire-test-client", version: "0.0.0-test" }, { capabilities: {} });
299
+ await client.connect(clientTransport);
300
+ let caught = null;
301
+ try {
302
+ await client.request({
303
+ method: "resources/subscribe",
304
+ params: { uri: "argosvix://calls/abc123" },
305
+ }, EmptyResultSchema);
306
+ }
307
+ catch (err) {
308
+ caught = err;
309
+ }
310
+ expect(caught).toBeInstanceOf(McpError);
311
+ expect(caught.code).toBe(ErrorCode.InvalidParams);
312
+ // ErrorCode.InvalidParams は JSON-RPC spec の -32602 と一致 (= SDK が
313
+ // McpError.code を そのまま wire error.code に carry する)。
314
+ expect(ErrorCode.InvalidParams).toBe(-32602);
315
+ expect(caught.message).toMatch(/does not support subscriptions/);
316
+ await client.close();
317
+ await server.close();
318
+ });
319
+ it("subscribable URI は wire 経由でも accept + {} return", async () => {
320
+ const { Server } = await import("@modelcontextprotocol/sdk/server/index.js");
321
+ const { Client } = await import("@modelcontextprotocol/sdk/client/index.js");
322
+ const { InMemoryTransport } = await import("@modelcontextprotocol/sdk/inMemory.js");
323
+ const { EmptyResultSchema } = await import("@modelcontextprotocol/sdk/types.js");
324
+ const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
325
+ const server = new Server({ name: "argosvix-test", version: "0.0.0-test" }, { capabilities: { resources: { subscribe: true } } });
326
+ setupSubscribe({
327
+ server,
328
+ apiKey: "argk_test",
329
+ apiBase: "https://ingest.test",
330
+ pollIntervalMs: 60_000,
331
+ });
332
+ await server.connect(serverTransport);
333
+ const client = new Client({ name: "argosvix-wire-test-client", version: "0.0.0-test" }, { capabilities: {} });
334
+ await client.connect(clientTransport);
335
+ const result = await client.request({
336
+ method: "resources/subscribe",
337
+ params: { uri: "argosvix://account" },
338
+ }, EmptyResultSchema);
339
+ expect(result).toEqual({});
340
+ await client.close();
341
+ await server.close();
342
+ });
343
+ });
344
+ //# sourceMappingURL=subscriptions.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscriptions.test.js","sourceRoot":"","sources":["../src/subscriptions.test.ts"],"names":[],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -11,5 +11,5 @@
11
11
  * 2. packages/mcp-server/package.json の `version` も同 値に更新
12
12
  * 3. `npm run build && npx vitest run` を pass させてから commit
13
13
  */
14
- export declare const MCP_VERSION: "0.9.3-alpha.1";
14
+ export declare const MCP_VERSION: "0.10.0-alpha.4";
15
15
  //# sourceMappingURL=version.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,WAAW,EAAG,eAAwB,CAAC"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,WAAW,EAAG,gBAAyB,CAAC"}
package/dist/version.js CHANGED
@@ -11,5 +11,5 @@
11
11
  * 2. packages/mcp-server/package.json の `version` も同 値に更新
12
12
  * 3. `npm run build && npx vitest run` を pass させてから commit
13
13
  */
14
- export const MCP_VERSION = "0.9.3-alpha.1";
14
+ export const MCP_VERSION = "0.10.0-alpha.4";
15
15
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG,eAAwB,CAAC"}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG,gBAAyB,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@argosvix/mcp-server",
3
- "version": "0.9.3-alpha.1",
4
- "description": "Argosvix MCP server — AI agent から traces / cost / alert を直接 query / 監査 / 受領するための Model Context Protocol server (stdio + HTTP transport、 tools 9 件 / resources 3 件 + template 3 件 / prompts 3 ).",
3
+ "version": "0.10.0-alpha.4",
4
+ "description": "Argosvix MCP server — AI agent から traces / cost / alert を直接 query / 監査 / 受領するための Model Context Protocol server (stdio + HTTP transport、 tools 9 件 / resources 3 件 + template 3 件 / prompts 3 件、 stdio で resources subscribe + polling 60s 更新通知).",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",