@tonyclaw/agent-inspector 2.0.32 → 2.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-Dgi0hhg5.js → CompareDrawer-s5T7W5_w.js} +1 -1
  3. package/.output/public/assets/{ProxyViewerContainer-4dG0nLRp.js → ProxyViewerContainer-DfGfP9VH.js} +22 -22
  4. package/.output/public/assets/{ReplayDialog-BL6BwDuI.js → ReplayDialog-DIxp-ccL.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-DZMmiIiD.js → RequestAnatomy-tfdpiRgw.js} +1 -1
  6. package/.output/public/assets/{ResponseView-DJLOiTYq.js → ResponseView-DMZp3aLW.js} +1 -1
  7. package/.output/public/assets/{StreamingChunkSequence--SxZ5cxc.js → StreamingChunkSequence-xXzLVw7m.js} +1 -1
  8. package/.output/public/assets/_sessionId-Dfxcty_X.js +1 -0
  9. package/.output/public/assets/index-C_8PFAm2.css +1 -0
  10. package/.output/public/assets/index-DztLtWHr.js +1 -0
  11. package/.output/public/assets/{main-CbRIHhJ5.js → main-DHq8ZD95.js} +2 -2
  12. package/.output/server/_libs/ajv.mjs +827 -6191
  13. package/.output/server/_libs/cookie-es.mjs +7 -21
  14. package/.output/server/_libs/h3-v2.mjs +18 -7
  15. package/.output/server/_libs/json-schema-traverse.mjs +1 -90
  16. package/.output/server/_libs/seroval-plugins.mjs +5 -5
  17. package/.output/server/_libs/seroval.mjs +606 -596
  18. package/.output/server/_libs/srvx.mjs +10 -5
  19. package/.output/server/_libs/tanstack__history.mjs +55 -38
  20. package/.output/server/_libs/tanstack__router-core.mjs +4366 -4075
  21. package/.output/server/{_sessionId-DNfumR8F.mjs → _sessionId-Bow47H8m.mjs} +4 -4
  22. package/.output/server/_ssr/{CompareDrawer-CzgjhnUa.mjs → CompareDrawer-Ctn56NJX.mjs} +4 -4
  23. package/.output/server/_ssr/{ProxyViewerContainer-BqOcZ7en.mjs → ProxyViewerContainer-DgPsLI2Q.mjs} +131 -122
  24. package/.output/server/_ssr/{ReplayDialog-DmEknIL8.mjs → ReplayDialog-BD9_rksD.mjs} +5 -5
  25. package/.output/server/_ssr/{RequestAnatomy-DNoiMudY.mjs → RequestAnatomy-BJyzD8pO.mjs} +4 -4
  26. package/.output/server/_ssr/{ResponseView-C_cRrleT.mjs → ResponseView-lebGC0QX.mjs} +4 -4
  27. package/.output/server/_ssr/{StreamingChunkSequence-DHZ9Q_dL.mjs → StreamingChunkSequence-BcOLywzn.mjs} +4 -4
  28. package/.output/server/_ssr/{index-coYS9XyS.mjs → index-CgJOsItz.mjs} +4 -4
  29. package/.output/server/_ssr/index.mjs +20 -11
  30. package/.output/server/_ssr/{router-DUb5lKw1.mjs → router-BMv4lGQi.mjs} +5193 -5269
  31. package/.output/server/{_tanstack-start-manifest_v-xcG1o8Vt.mjs → _tanstack-start-manifest_v-D2LyT1-l.mjs} +1 -1
  32. package/.output/server/index.mjs +68 -68
  33. package/README.md +23 -0
  34. package/package.json +6 -2
  35. package/src/components/groups/GroupsDialog.tsx +132 -121
  36. package/src/lib/groupContract.ts +0 -2
  37. package/src/lib/runContract.ts +0 -3
  38. package/src/mcp/server.ts +101 -164
  39. package/src/mcp/toolHandlers.ts +80 -177
  40. package/src/routes/api/groups.$groupId.evidence.ts +14 -33
  41. package/src/routes/api/groups.$groupId.sessions.ts +9 -9
  42. package/src/routes/api/groups.$groupId.ts +19 -13
  43. package/src/routes/api/groups.ts +3 -3
  44. package/src/routes/api/runs.$runId.evidence.ts +14 -21
  45. package/src/routes/api/runs.$runId.ts +9 -9
  46. package/src/routes/api/runs.ts +9 -5
  47. package/src/services/groups.ts +110 -0
  48. package/src/services/result.ts +17 -0
  49. package/src/services/runs.ts +76 -0
  50. package/.output/public/assets/_sessionId-C4z6gu9i.js +0 -1
  51. package/.output/public/assets/index-Drpb2qR5.js +0 -1
  52. package/.output/public/assets/index-fUUi8iQF.css +0 -1
package/src/mcp/server.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * MCP (Model Context Protocol) server for agent-inspector.
3
3
  *
4
- * Exposes `inspector_*` tools that delegate to existing `/api/*` endpoints
5
- * via internal HTTP loopback (see `loopback.ts` for the rationale). Mounted
4
+ * Exposes `inspector_*` tools and resources. Mounted
6
5
  * at `POST /api/mcp` in the existing TanStack Start process using HTTP Streamable
7
6
  * transport. localhost-only, no auth in v1 — see
8
7
  * `openspec/changes/add-mcp-server/design.md` decisions D1, D2, D9.
@@ -11,8 +10,8 @@
11
10
  * instantiated once per process on first request and reused for all
12
11
  * subsequent requests (stateless mode — no `sessionIdGenerator`).
13
12
  *
14
- * Tool implementations live in `./toolHandlers.ts` so they can be unit
15
- * tested with a mock `callApi`. This file just wires them to the SDK.
13
+ * Tool implementations live in `./toolHandlers.ts`; this file wires them to
14
+ * the SDK and exposes MCP resources/prompts.
16
15
  */
17
16
 
18
17
  import { z } from "zod";
@@ -30,18 +29,24 @@ import {
30
29
  AddInspectorGroupSessionInputSchema,
31
30
  DeleteInspectorGroupOptionsSchema,
32
31
  GroupEvidenceExportOptionsSchema,
33
- InspectorGroupSchema,
34
32
  InspectorGroupStatusSchema,
35
- InspectorGroupsListResponseSchema,
36
33
  UpdateInspectorGroupInputSchema,
37
34
  } from "../lib/groupContract";
38
- import {
39
- InspectorRunSchema,
40
- InspectorRunStatusSchema,
41
- UpdateInspectorRunInputSchema,
42
- } from "../lib/runContract";
35
+ import { InspectorRunStatusSchema, UpdateInspectorRunInputSchema } from "../lib/runContract";
43
36
  import { setCurrentPort } from "../lib/serverPort";
44
37
  import { JsonValueSchema } from "../proxy/schemas";
38
+ import {
39
+ getInspectorGroup,
40
+ listInspectorGroups,
41
+ readInspectorGroupEvidence,
42
+ readInspectorGroupSessions,
43
+ } from "../services/groups";
44
+ import {
45
+ getInspectorRun,
46
+ listInspectorRecentFailures,
47
+ listInspectorRuns,
48
+ readInspectorRunEvidence,
49
+ } from "../services/runs";
45
50
  import { callApi } from "./loopback";
46
51
  import {
47
52
  addGroupSessionImpl,
@@ -179,22 +184,10 @@ Either preview field is null when the body is unknown format, unparseable, or th
179
184
  const PROVIDER_WRITE_WARNING =
180
185
  "⚠ This tool mutates provider configuration. Confirm with the user before invoking.";
181
186
 
182
- const RunsListResponseSchema = z.object({
183
- runs: z.array(InspectorRunSchema),
184
- });
185
-
186
187
  const LogResourceListResponseSchema = z.object({
187
188
  logs: z.array(z.object({ id: z.number().int().positive() })),
188
189
  });
189
190
 
190
- const EvidenceReadResponseSchema = z.object({
191
- markdown: z.string(),
192
- });
193
-
194
- const GroupEvidenceReadResponseSchema = z.object({
195
- markdown: z.string(),
196
- });
197
-
198
191
  type ResourceDescriptor = {
199
192
  uri: string;
200
193
  name: string;
@@ -236,6 +229,14 @@ async function readApiJsonResource(uri: URL, path: string): Promise<ReadResource
236
229
  }
237
230
  }
238
231
 
232
+ function readServiceJsonResource<T>(
233
+ uri: URL,
234
+ result: { ok: true; value: T } | { ok: false; message: string },
235
+ ): ReadResourceResult {
236
+ if (!result.ok) return textResource(uri, "text/plain", result.message);
237
+ return jsonResource(uri, result.value);
238
+ }
239
+
239
240
  async function listSessionResources(): Promise<ListResourcesResult> {
240
241
  try {
241
242
  const response = await callApi("/api/sessions");
@@ -274,105 +275,65 @@ async function listLogResources(): Promise<ListResourcesResult> {
274
275
  }
275
276
  }
276
277
 
277
- async function listRunResources(): Promise<ListResourcesResult> {
278
- try {
279
- const response = await callApi("/api/runs");
280
- if (!response.ok) return listResult([]);
281
- const parsed = RunsListResponseSchema.safeParse(await response.json());
282
- if (!parsed.success) return listResult([]);
283
- return listResult(
284
- parsed.data.runs.map((run) => ({
285
- uri: `inspector://runs/${encodeURIComponent(run.id)}`,
286
- name: `run:${run.id}`,
287
- title: run.title,
288
- mimeType: "application/json",
289
- })),
290
- );
291
- } catch {
292
- return listResult([]);
293
- }
278
+ function listRunResources(): ListResourcesResult {
279
+ return listResult(
280
+ listInspectorRuns().runs.map((run) => ({
281
+ uri: `inspector://runs/${encodeURIComponent(run.id)}`,
282
+ name: `run:${run.id}`,
283
+ title: run.title,
284
+ mimeType: "application/json",
285
+ })),
286
+ );
294
287
  }
295
288
 
296
- async function listGroupResources(): Promise<ListResourcesResult> {
297
- try {
298
- const response = await callApi("/api/groups");
299
- if (!response.ok) return listResult([]);
300
- const parsed = InspectorGroupsListResponseSchema.safeParse(await response.json());
301
- if (!parsed.success) return listResult([]);
302
- return listResult(
303
- parsed.data.groups.map((group) => ({
304
- uri: `inspector://groups/${encodeURIComponent(group.id)}`,
305
- name: `group:${group.id}`,
306
- title: group.title,
307
- mimeType: "application/json",
308
- })),
309
- );
310
- } catch {
311
- return listResult([]);
312
- }
289
+ function listGroupResources(): ListResourcesResult {
290
+ return listResult(
291
+ listInspectorGroups().groups.map((group) => ({
292
+ uri: `inspector://groups/${encodeURIComponent(group.id)}`,
293
+ name: `group:${group.id}`,
294
+ title: group.title,
295
+ mimeType: "application/json",
296
+ })),
297
+ );
313
298
  }
314
299
 
315
- async function listGroupSessionResources(): Promise<ListResourcesResult> {
316
- try {
317
- const response = await callApi("/api/groups");
318
- if (!response.ok) return listResult([]);
319
- const parsed = InspectorGroupsListResponseSchema.safeParse(await response.json());
320
- if (!parsed.success) return listResult([]);
321
- return listResult(
322
- parsed.data.groups.map((group) => ({
323
- uri: `inspector://groups/${encodeURIComponent(group.id)}/sessions`,
324
- name: `group-sessions:${group.id}`,
325
- title: `${group.title} sessions`,
326
- mimeType: "application/json",
327
- })),
328
- );
329
- } catch {
330
- return listResult([]);
331
- }
300
+ function listGroupSessionResources(): ListResourcesResult {
301
+ return listResult(
302
+ listInspectorGroups().groups.map((group) => ({
303
+ uri: `inspector://groups/${encodeURIComponent(group.id)}/sessions`,
304
+ name: `group-sessions:${group.id}`,
305
+ title: `${group.title} sessions`,
306
+ mimeType: "application/json",
307
+ })),
308
+ );
332
309
  }
333
310
 
334
- async function listGroupEvidenceResources(): Promise<ListResourcesResult> {
335
- try {
336
- const response = await callApi("/api/groups");
337
- if (!response.ok) return listResult([]);
338
- const parsed = InspectorGroupsListResponseSchema.safeParse(await response.json());
339
- if (!parsed.success) return listResult([]);
340
- return listResult(
341
- parsed.data.groups
342
- .filter((group) => group.evidence !== null)
343
- .map((group) => ({
344
- uri: `inspector://groups/${encodeURIComponent(group.id)}/evidence`,
345
- name: `group-evidence:${group.id}`,
346
- title: `${group.title} evidence pack`,
347
- mimeType: "text/markdown",
348
- description: group.evidence?.markdownPath,
349
- })),
350
- );
351
- } catch {
352
- return listResult([]);
353
- }
311
+ function listGroupEvidenceResources(): ListResourcesResult {
312
+ return listResult(
313
+ listInspectorGroups()
314
+ .groups.filter((group) => group.evidence !== null)
315
+ .map((group) => ({
316
+ uri: `inspector://groups/${encodeURIComponent(group.id)}/evidence`,
317
+ name: `group-evidence:${group.id}`,
318
+ title: `${group.title} evidence pack`,
319
+ mimeType: "text/markdown",
320
+ description: group.evidence?.markdownPath,
321
+ })),
322
+ );
354
323
  }
355
324
 
356
- async function listEvidenceResources(): Promise<ListResourcesResult> {
357
- try {
358
- const response = await callApi("/api/runs");
359
- if (!response.ok) return listResult([]);
360
- const parsed = RunsListResponseSchema.safeParse(await response.json());
361
- if (!parsed.success) return listResult([]);
362
- return listResult(
363
- parsed.data.runs
364
- .filter((run) => run.evidence !== null)
365
- .map((run) => ({
366
- uri: `inspector://evidence/${encodeURIComponent(run.id)}`,
367
- name: `evidence:${run.id}`,
368
- title: `${run.title} evidence pack`,
369
- mimeType: "text/markdown",
370
- description: run.evidence?.markdownPath,
371
- })),
372
- );
373
- } catch {
374
- return listResult([]);
375
- }
325
+ function listEvidenceResources(): ListResourcesResult {
326
+ return listResult(
327
+ listInspectorRuns()
328
+ .runs.filter((run) => run.evidence !== null)
329
+ .map((run) => ({
330
+ uri: `inspector://evidence/${encodeURIComponent(run.id)}`,
331
+ name: `evidence:${run.id}`,
332
+ title: `${run.title} evidence pack`,
333
+ mimeType: "text/markdown",
334
+ description: run.evidence?.markdownPath,
335
+ })),
336
+ );
376
337
  }
377
338
 
378
339
  function userPrompt(text: string): GetPromptResult {
@@ -531,7 +492,7 @@ function registerTools(server: McpServer): void {
531
492
  metadata: z.record(z.string(), JsonValueSchema).optional().describe("JSON metadata."),
532
493
  }),
533
494
  },
534
- (args) => safeCall(() => createRunImpl(callApi, args)),
495
+ (args) => safeCall(() => createRunImpl(args)),
535
496
  );
536
497
 
537
498
  server.registerTool(
@@ -544,7 +505,7 @@ function registerTools(server: McpServer): void {
544
505
  runId: z.string().min(1).describe("The Inspector run id."),
545
506
  }),
546
507
  },
547
- (args) => safeCall(() => getRunImpl(callApi, args)),
508
+ (args) => safeCall(() => getRunImpl(args)),
548
509
  );
549
510
 
550
511
  server.registerTool(
@@ -557,7 +518,7 @@ function registerTools(server: McpServer): void {
557
518
  runId: z.string().min(1).describe("The Inspector run id."),
558
519
  }),
559
520
  },
560
- (args) => safeCall(() => updateRunImpl(callApi, args)),
521
+ (args) => safeCall(() => updateRunImpl(args)),
561
522
  );
562
523
 
563
524
  server.registerTool(
@@ -581,7 +542,7 @@ function registerTools(server: McpServer): void {
581
542
  .describe("How many compact log summaries to include in the evidence pack. Max 50."),
582
543
  }),
583
544
  },
584
- (args) => safeCall(() => exportEvidenceImpl(callApi, args)),
545
+ (args) => safeCall(() => exportEvidenceImpl(args)),
585
546
  );
586
547
 
587
548
  server.registerTool(
@@ -600,7 +561,7 @@ function registerTools(server: McpServer): void {
600
561
  .describe("Maximum failures to return. Default 5, max 20."),
601
562
  }),
602
563
  },
603
- (args) => safeCall(() => getRecentFailuresImpl(callApi, args)),
564
+ (args) => safeCall(() => getRecentFailuresImpl(args)),
604
565
  );
605
566
 
606
567
  server.registerTool(
@@ -611,7 +572,7 @@ function registerTools(server: McpServer): void {
611
572
  "Lists declared Inspector groups. Groups aggregate multiple sessions/runs, commonly one evaluation matrix spanning several providers or models.",
612
573
  inputSchema: z.object({}),
613
574
  },
614
- () => safeCall(() => listGroupsImpl(callApi)),
575
+ () => safeCall(() => listGroupsImpl()),
615
576
  );
616
577
 
617
578
  server.registerTool(
@@ -634,7 +595,7 @@ function registerTools(server: McpServer): void {
634
595
  metadata: z.record(z.string(), JsonValueSchema).optional().describe("JSON metadata."),
635
596
  }),
636
597
  },
637
- (args) => safeCall(() => createGroupImpl(callApi, args)),
598
+ (args) => safeCall(() => createGroupImpl(args)),
638
599
  );
639
600
 
640
601
  server.registerTool(
@@ -647,7 +608,7 @@ function registerTools(server: McpServer): void {
647
608
  groupId: z.string().min(1).describe("The Inspector group id."),
648
609
  }),
649
610
  },
650
- (args) => safeCall(() => getGroupImpl(callApi, args)),
611
+ (args) => safeCall(() => getGroupImpl(args)),
651
612
  );
652
613
 
653
614
  server.registerTool(
@@ -660,7 +621,7 @@ function registerTools(server: McpServer): void {
660
621
  groupId: z.string().min(1).describe("The Inspector group id."),
661
622
  }),
662
623
  },
663
- (args) => safeCall(() => updateGroupImpl(callApi, args)),
624
+ (args) => safeCall(() => updateGroupImpl(args)),
664
625
  );
665
626
 
666
627
  server.registerTool(
@@ -673,7 +634,7 @@ function registerTools(server: McpServer): void {
673
634
  groupId: z.string().min(1).describe("The Inspector group id."),
674
635
  }),
675
636
  },
676
- (args) => safeCall(() => deleteGroupImpl(callApi, args)),
637
+ (args) => safeCall(() => deleteGroupImpl(args)),
677
638
  );
678
639
 
679
640
  server.registerTool(
@@ -686,7 +647,7 @@ function registerTools(server: McpServer): void {
686
647
  groupId: z.string().min(1).describe("The Inspector group id."),
687
648
  }),
688
649
  },
689
- (args) => safeCall(() => addGroupSessionImpl(callApi, args)),
650
+ (args) => safeCall(() => addGroupSessionImpl(args)),
690
651
  );
691
652
 
692
653
  server.registerTool(
@@ -699,7 +660,7 @@ function registerTools(server: McpServer): void {
699
660
  groupId: z.string().min(1).describe("The Inspector group id."),
700
661
  }),
701
662
  },
702
- (args) => safeCall(() => exportGroupEvidenceImpl(callApi, args)),
663
+ (args) => safeCall(() => exportGroupEvidenceImpl(args)),
703
664
  );
704
665
 
705
666
  server.registerTool(
@@ -942,7 +903,7 @@ function registerResources(server: McpServer): void {
942
903
  description: "Declared Inspector evaluation runs.",
943
904
  mimeType: "application/json",
944
905
  },
945
- (uri) => readApiJsonResource(uri, "/api/runs"),
906
+ (uri) => jsonResource(uri, listInspectorRuns()),
946
907
  );
947
908
 
948
909
  server.registerResource(
@@ -953,7 +914,7 @@ function registerResources(server: McpServer): void {
953
914
  description: "Declared Inspector groups aggregating multiple sessions or runs.",
954
915
  mimeType: "application/json",
955
916
  },
956
- (uri) => readApiJsonResource(uri, "/api/groups"),
917
+ (uri) => jsonResource(uri, listInspectorGroups()),
957
918
  );
958
919
 
959
920
  server.registerResource(
@@ -967,7 +928,7 @@ function registerResources(server: McpServer): void {
967
928
  (uri, variables) => {
968
929
  const groupId = variableString(variables, "groupId");
969
930
  if (groupId === null) return textResource(uri, "text/plain", "Missing groupId");
970
- return readApiJsonResource(uri, `/api/groups/${encodeURIComponent(groupId)}`);
931
+ return readServiceJsonResource(uri, getInspectorGroup(groupId));
971
932
  },
972
933
  );
973
934
 
@@ -984,7 +945,7 @@ function registerResources(server: McpServer): void {
984
945
  (uri, variables) => {
985
946
  const groupId = variableString(variables, "groupId");
986
947
  if (groupId === null) return textResource(uri, "text/plain", "Missing groupId");
987
- return readApiJsonResource(uri, `/api/groups/${encodeURIComponent(groupId)}/sessions`);
948
+ return readServiceJsonResource(uri, readInspectorGroupSessions(groupId));
988
949
  },
989
950
  );
990
951
 
@@ -997,7 +958,7 @@ function registerResources(server: McpServer): void {
997
958
  "Recent declared runs with failed/cancelled status or non-success exported evidence.",
998
959
  mimeType: "application/json",
999
960
  },
1000
- (uri) => readApiJsonResource(uri, "/api/runs?failures=1&limit=10"),
961
+ (uri) => jsonResource(uri, listInspectorRecentFailures(10)),
1001
962
  );
1002
963
 
1003
964
  server.registerResource(
@@ -1011,7 +972,7 @@ function registerResources(server: McpServer): void {
1011
972
  (uri, variables) => {
1012
973
  const runId = variableString(variables, "runId");
1013
974
  if (runId === null) return textResource(uri, "text/plain", "Missing runId");
1014
- return readApiJsonResource(uri, `/api/runs/${encodeURIComponent(runId)}`);
975
+ return readServiceJsonResource(uri, getInspectorRun(runId));
1015
976
  },
1016
977
  );
1017
978
 
@@ -1024,24 +985,12 @@ function registerResources(server: McpServer): void {
1024
985
  "Markdown evidence pack for a declared Inspector run. Generate it first with inspector_export_evidence.",
1025
986
  mimeType: "text/markdown",
1026
987
  },
1027
- async (uri, variables) => {
988
+ (uri, variables) => {
1028
989
  const runId = variableString(variables, "runId");
1029
990
  if (runId === null) return textResource(uri, "text/plain", "Missing runId");
1030
- const path = `/api/runs/${encodeURIComponent(runId)}/evidence`;
1031
- try {
1032
- const response = await callApi(path);
1033
- if (!response.ok) {
1034
- return textResource(uri, "text/plain", `GET ${path} returned ${response.status}`);
1035
- }
1036
- const parsed = EvidenceReadResponseSchema.safeParse(await response.json());
1037
- if (!parsed.success) {
1038
- return textResource(uri, "text/plain", "Evidence endpoint returned an unparseable body");
1039
- }
1040
- return textResource(uri, "text/markdown", parsed.data.markdown);
1041
- } catch (err) {
1042
- const message = err instanceof Error ? err.message : String(err);
1043
- return textResource(uri, "text/plain", `Resource read failed: ${message}`);
1044
- }
991
+ const evidence = readInspectorRunEvidence(runId);
992
+ if (!evidence.ok) return textResource(uri, "text/plain", evidence.message);
993
+ return textResource(uri, "text/markdown", evidence.value.markdown);
1045
994
  },
1046
995
  );
1047
996
 
@@ -1056,24 +1005,12 @@ function registerResources(server: McpServer): void {
1056
1005
  "Markdown evidence pack for an Inspector group. Generate it first with inspector_export_group_evidence.",
1057
1006
  mimeType: "text/markdown",
1058
1007
  },
1059
- async (uri, variables) => {
1008
+ (uri, variables) => {
1060
1009
  const groupId = variableString(variables, "groupId");
1061
1010
  if (groupId === null) return textResource(uri, "text/plain", "Missing groupId");
1062
- const path = `/api/groups/${encodeURIComponent(groupId)}/evidence`;
1063
- try {
1064
- const response = await callApi(path);
1065
- if (!response.ok) {
1066
- return textResource(uri, "text/plain", `GET ${path} returned ${response.status}`);
1067
- }
1068
- const parsed = GroupEvidenceReadResponseSchema.safeParse(await response.json());
1069
- if (!parsed.success) {
1070
- return textResource(uri, "text/plain", "Evidence endpoint returned an unparseable body");
1071
- }
1072
- return textResource(uri, "text/markdown", parsed.data.markdown);
1073
- } catch (err) {
1074
- const message = err instanceof Error ? err.message : String(err);
1075
- return textResource(uri, "text/plain", `Resource read failed: ${message}`);
1076
- }
1011
+ const evidence = readInspectorGroupEvidence(groupId);
1012
+ if (!evidence.ok) return textResource(uri, "text/plain", evidence.message);
1013
+ return textResource(uri, "text/markdown", evidence.value.markdown);
1077
1014
  },
1078
1015
  );
1079
1016
  }