@tonyclaw/agent-inspector 2.0.41 → 2.0.43

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 (42) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-DCg6S2cl.js → CompareDrawer-CxM1gCfL.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-TtRG-0E7.js +117 -0
  4. package/.output/public/assets/{ReplayDialog-ClVgjSDE.js → ReplayDialog-UseUkucS.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-BhqvLQp9.js → RequestAnatomy-aPxgEJ2L.js} +1 -1
  6. package/.output/public/assets/{ResponseView-BZAJoK6B.js → ResponseView-DA-F4F97.js} +1 -1
  7. package/.output/public/assets/{StreamingChunkSequence-CaORmoKX.js → StreamingChunkSequence-JSQEPeNS.js} +1 -1
  8. package/.output/public/assets/_sessionId-BEXuCWq5.js +1 -0
  9. package/.output/public/assets/index-Bhsa_2xX.js +1 -0
  10. package/.output/public/assets/index-DOWlRJ0W.css +1 -0
  11. package/.output/public/assets/{main-CI3HFEcV.js → main-BpGVJcpB.js} +2 -2
  12. package/.output/server/{_sessionId-DQ0ljHQ8.mjs → _sessionId-DGn-TENM.mjs} +2 -2
  13. package/.output/server/_ssr/{CompareDrawer-nkVa9epn.mjs → CompareDrawer-CFElCSYY.mjs} +2 -2
  14. package/.output/server/_ssr/{ProxyViewerContainer-CXA7iH3H.mjs → ProxyViewerContainer-B7SR9mrD.mjs} +383 -76
  15. package/.output/server/_ssr/{ReplayDialog-CK71-ucq.mjs → ReplayDialog-DfKapj0k.mjs} +3 -3
  16. package/.output/server/_ssr/{RequestAnatomy-DDCUJJ3X.mjs → RequestAnatomy-CUxTCg31.mjs} +2 -2
  17. package/.output/server/_ssr/{ResponseView-C6ZA7V3B.mjs → ResponseView-BXY0w197.mjs} +2 -2
  18. package/.output/server/_ssr/{StreamingChunkSequence-DW5v_o6G.mjs → StreamingChunkSequence-CzMnES9H.mjs} +2 -2
  19. package/.output/server/_ssr/{index-Ckex98yq.mjs → index-CVlT-REW.mjs} +2 -2
  20. package/.output/server/_ssr/index.mjs +2 -2
  21. package/.output/server/_ssr/{router-ChJIVv7-.mjs → router-B2d1LUx6.mjs} +1313 -468
  22. package/.output/server/{_tanstack-start-manifest_v-CJ4__weU.mjs → _tanstack-start-manifest_v-Drpi28BM.mjs} +1 -1
  23. package/.output/server/index.mjs +60 -60
  24. package/README.md +36 -12
  25. package/package.json +1 -1
  26. package/src/components/ProxyViewer.tsx +156 -17
  27. package/src/components/ProxyViewerContainer.tsx +66 -4
  28. package/src/components/groups/GroupsDialog.tsx +11 -10
  29. package/src/components/providers/SettingsDialog.tsx +137 -0
  30. package/src/components/proxy-viewer/LogEntry.tsx +107 -56
  31. package/src/components/ui/dialog.tsx +1 -1
  32. package/src/lib/runContract.ts +3 -0
  33. package/src/mcp/currentContext.ts +65 -0
  34. package/src/mcp/mode.ts +56 -0
  35. package/src/mcp/server.ts +466 -15
  36. package/src/mcp/toolHandlers.ts +372 -0
  37. package/src/proxy/evidenceExporter.ts +1 -0
  38. package/src/proxy/runStore.ts +74 -22
  39. package/.output/public/assets/ProxyViewerContainer-DsU6QETm.js +0 -115
  40. package/.output/public/assets/_sessionId-BHqywvM3.js +0 -1
  41. package/.output/public/assets/index-B_LPYuM0.js +0 -1
  42. package/.output/public/assets/index-BfGJEb-2.css +0 -1
package/src/mcp/server.ts CHANGED
@@ -33,8 +33,10 @@ import {
33
33
  UpdateInspectorGroupInputSchema,
34
34
  } from "../lib/groupContract";
35
35
  import { InspectorRunStatusSchema, UpdateInspectorRunInputSchema } from "../lib/runContract";
36
- import { setCurrentPort } from "../lib/serverPort";
36
+ import { getCurrentPort, setCurrentPort } from "../lib/serverPort";
37
37
  import { JsonValueSchema } from "../contracts";
38
+ import { getCurrentContext } from "./currentContext";
39
+ import { getMcpModeInfo, isMcpWriteEnabled } from "./mode";
38
40
  import {
39
41
  getInspectorGroup,
40
42
  listInspectorGroups,
@@ -51,17 +53,24 @@ import { callApi } from "./loopback";
51
53
  import {
52
54
  addGroupSessionImpl,
53
55
  addProviderImpl,
56
+ diagnoseProviderTestImpl,
57
+ exportEvidenceBundleImpl,
54
58
  createGroupImpl,
55
59
  createRunImpl,
56
60
  createSessionKnowledgeImpl,
57
61
  deleteGroupImpl,
58
62
  exportEvidenceImpl,
63
+ getCurrentContextImpl,
64
+ getEvidenceFilesImpl,
59
65
  exportGroupEvidenceImpl,
66
+ exportGroupEvidenceBundleImpl,
67
+ getGroupEvidenceFilesImpl,
60
68
  getGroupImpl,
61
69
  getRecentFailuresImpl,
62
70
  getProjectContextImpl,
63
71
  getRunImpl,
64
72
  getSessionImpl,
73
+ getSessionTimelineImpl,
65
74
  getLogChunksImpl,
66
75
  getLogImpl,
67
76
  getProviderImpl,
@@ -76,10 +85,12 @@ import {
76
85
  safeCall,
77
86
  searchLogsImpl,
78
87
  searchKnowledgeImpl,
88
+ setCurrentContextImpl,
79
89
  testProviderImpl,
80
90
  updateGroupImpl,
81
91
  updateRunImpl,
82
92
  updateProviderImpl,
93
+ type ToolResult,
83
94
  } from "./toolHandlers";
84
95
 
85
96
  // ---------------------------------------------------------------------------
@@ -206,6 +217,140 @@ function jsonResource(uri: URL, data: unknown): ReadResourceResult {
206
217
  return textResource(uri, "application/json", JSON.stringify(data, null, 2));
207
218
  }
208
219
 
220
+ function mcpEndpointUrl(): string {
221
+ return `http://localhost:${String(getCurrentPort())}/api/mcp`;
222
+ }
223
+
224
+ function mcpHealth(): Record<string, unknown> {
225
+ return {
226
+ status: "ok",
227
+ serverInfo: {
228
+ name: "agent-inspector",
229
+ version: MCP_SERVER_VERSION,
230
+ },
231
+ transport: {
232
+ primary: "streamable-http",
233
+ endpoint: "/api/mcp",
234
+ stateless: true,
235
+ },
236
+ mode: getMcpModeInfo(),
237
+ catalog: {
238
+ tools: TOOL_NAMES.length,
239
+ resources: RESOURCE_NAMES.length,
240
+ prompts: PROMPT_NAMES.length,
241
+ },
242
+ };
243
+ }
244
+
245
+ const WRITE_TOOL_NAMES = new Set<string>([
246
+ "inspector_create_run",
247
+ "inspector_update_run",
248
+ "inspector_export_evidence",
249
+ "inspector_export_evidence_bundle",
250
+ "inspector_create_group",
251
+ "inspector_update_group",
252
+ "inspector_delete_group",
253
+ "inspector_add_group_session",
254
+ "inspector_export_group_evidence",
255
+ "inspector_export_group_evidence_bundle",
256
+ "inspector_set_current_context",
257
+ "inspector_replay_log",
258
+ "inspector_add_provider",
259
+ "inspector_update_provider",
260
+ "inspector_test_provider",
261
+ "inspector_diagnose_provider_test",
262
+ "inspector_create_session_knowledge",
263
+ "inspector_promote_knowledge_candidate",
264
+ ]);
265
+
266
+ function mcpCapabilities(): Record<string, unknown> {
267
+ const readTools = TOOL_NAMES.filter((name) => !WRITE_TOOL_NAMES.has(name));
268
+ const writeTools = TOOL_NAMES.filter((name) => WRITE_TOOL_NAMES.has(name));
269
+ return {
270
+ serverInfo: {
271
+ name: "agent-inspector",
272
+ version: MCP_SERVER_VERSION,
273
+ },
274
+ mode: getMcpModeInfo(),
275
+ tools: {
276
+ read: readTools,
277
+ writeOrAction: writeTools,
278
+ },
279
+ resources: RESOURCE_NAMES,
280
+ prompts: PROMPT_NAMES,
281
+ };
282
+ }
283
+
284
+ function mcpConfig(): Record<string, unknown> {
285
+ const endpoint = mcpEndpointUrl();
286
+ return {
287
+ streamableHttp: {
288
+ endpoint,
289
+ config: {
290
+ mcpServers: {
291
+ "agent-inspector": {
292
+ type: "streamableHttp",
293
+ url: endpoint,
294
+ },
295
+ },
296
+ },
297
+ },
298
+ stdioBridge: {
299
+ command: "agent-inspector-mcp",
300
+ args: ["stdio", "--url", endpoint],
301
+ config: {
302
+ mcpServers: {
303
+ "agent-inspector": {
304
+ command: "agent-inspector-mcp",
305
+ args: ["stdio", "--url", endpoint],
306
+ },
307
+ },
308
+ },
309
+ },
310
+ opencodeLocal: {
311
+ mcp: {
312
+ "agent-inspector": {
313
+ type: "local",
314
+ command: ["agent-inspector-mcp", "stdio", "--url", endpoint],
315
+ enabled: true,
316
+ },
317
+ },
318
+ },
319
+ networkNote:
320
+ "If the MCP client runs in another container or host, replace localhost with an address reachable from that client. Configure only one transport for the same Inspector instance.",
321
+ };
322
+ }
323
+
324
+ function disabledWriteTool(toolName: string): ToolResult {
325
+ return {
326
+ content: [
327
+ {
328
+ type: "text",
329
+ text: JSON.stringify(
330
+ {
331
+ error: "mcp-write-disabled",
332
+ tool: toolName,
333
+ mode: getMcpModeInfo(),
334
+ },
335
+ null,
336
+ 2,
337
+ ),
338
+ },
339
+ ],
340
+ isError: true,
341
+ };
342
+ }
343
+
344
+ function safeWriteCall(
345
+ toolName: string,
346
+ fn: () => ToolResult | Promise<ToolResult>,
347
+ ): Promise<ToolResult> {
348
+ return safeCall(() => {
349
+ if (!isMcpWriteEnabled()) return disabledWriteTool(toolName);
350
+ return fn();
351
+ });
352
+ }
353
+
209
354
  function variableString(variables: Variables, name: string): string | null {
210
355
  const value = variables[name];
211
356
  if (Array.isArray(value)) return value[0] ?? null;
@@ -256,6 +401,25 @@ async function listSessionResources(): Promise<ListResourcesResult> {
256
401
  }
257
402
  }
258
403
 
404
+ async function listSessionTimelineResources(): Promise<ListResourcesResult> {
405
+ try {
406
+ const response = await callApi("/api/sessions");
407
+ if (!response.ok) return listResult([]);
408
+ const parsed = z.array(z.string()).safeParse(await response.json());
409
+ if (!parsed.success) return listResult([]);
410
+ return listResult(
411
+ parsed.data.map((sessionId) => ({
412
+ uri: `inspector://sessions/${encodeURIComponent(sessionId)}/timeline`,
413
+ name: `session-timeline:${sessionId}`,
414
+ title: `Inspector session ${sessionId} timeline`,
415
+ mimeType: "application/json",
416
+ })),
417
+ );
418
+ } catch {
419
+ return listResult([]);
420
+ }
421
+ }
422
+
259
423
  async function listLogResources(): Promise<ListResourcesResult> {
260
424
  try {
261
425
  const response = await callApi("/api/logs?offset=0&limit=5&compact=1");
@@ -322,6 +486,20 @@ function listGroupEvidenceResources(): ListResourcesResult {
322
486
  );
323
487
  }
324
488
 
489
+ function listGroupEvidenceFileResources(): ListResourcesResult {
490
+ return listResult(
491
+ listInspectorGroups()
492
+ .groups.filter((group) => group.evidence !== null)
493
+ .map((group) => ({
494
+ uri: `inspector://groups/${encodeURIComponent(group.id)}/evidence/files`,
495
+ name: `group-evidence-files:${group.id}`,
496
+ title: `${group.title} evidence files`,
497
+ mimeType: "application/json",
498
+ description: group.evidence?.jsonPath,
499
+ })),
500
+ );
501
+ }
502
+
325
503
  function listEvidenceResources(): ListResourcesResult {
326
504
  return listResult(
327
505
  listInspectorRuns()
@@ -336,6 +514,20 @@ function listEvidenceResources(): ListResourcesResult {
336
514
  );
337
515
  }
338
516
 
517
+ function listEvidenceFileResources(): ListResourcesResult {
518
+ return listResult(
519
+ listInspectorRuns()
520
+ .runs.filter((run) => run.evidence !== null)
521
+ .map((run) => ({
522
+ uri: `inspector://evidence/${encodeURIComponent(run.id)}/files`,
523
+ name: `evidence-files:${run.id}`,
524
+ title: `${run.title} evidence files`,
525
+ mimeType: "application/json",
526
+ description: run.evidence?.jsonPath,
527
+ })),
528
+ );
529
+ }
530
+
339
531
  function userPrompt(text: string): GetPromptResult {
340
532
  return {
341
533
  messages: [
@@ -470,6 +662,59 @@ function registerTools(server: McpServer): void {
470
662
  (args) => safeCall(() => getSessionImpl(callApi, args)),
471
663
  );
472
664
 
665
+ server.registerTool(
666
+ "inspector_get_session_timeline",
667
+ {
668
+ title: "Get Inspector session timeline",
669
+ description:
670
+ "Returns a bounded chronological request timeline for one session with log ids, provider/model labels, statuses, latency, streaming timing, token usage, and previews. Use this when an agent needs the shape of a session before opening large logs.",
671
+ inputSchema: z.object({
672
+ sessionId: z.string().min(1).describe("The Inspector session id."),
673
+ offset: z.number().int().nonnegative().optional().describe("Skip this many matching logs."),
674
+ limit: z
675
+ .number()
676
+ .int()
677
+ .positive()
678
+ .max(50)
679
+ .optional()
680
+ .describe("Maximum timeline events to return. Default 20, max 50."),
681
+ }),
682
+ },
683
+ (args) => safeCall(() => getSessionTimelineImpl(callApi, args)),
684
+ );
685
+
686
+ server.registerTool(
687
+ "inspector_get_current_context",
688
+ {
689
+ title: "Get current Inspector MCP context",
690
+ description:
691
+ "Returns the current MCP context that an evaluator or coding agent can set to bind subsequent work to a group, run, session, model, provider, project, or task.",
692
+ inputSchema: z.object({}),
693
+ },
694
+ () => safeCall(() => getCurrentContextImpl()),
695
+ );
696
+
697
+ server.registerTool(
698
+ "inspector_set_current_context",
699
+ {
700
+ title: "Set current Inspector MCP context",
701
+ description:
702
+ "Updates the current MCP context for this local Inspector process. Use this at the start of a benchmark/eval turn so later tools can discover the active group/run/session labels.",
703
+ inputSchema: z.object({
704
+ groupId: z.string().min(1).nullable().optional(),
705
+ runId: z.string().min(1).nullable().optional(),
706
+ sessionId: z.string().min(1).nullable().optional(),
707
+ model: z.string().min(1).nullable().optional(),
708
+ provider: z.string().min(1).nullable().optional(),
709
+ agent: z.string().min(1).nullable().optional(),
710
+ project: z.string().min(1).nullable().optional(),
711
+ task: z.string().min(1).nullable().optional(),
712
+ metadata: z.record(z.string(), JsonValueSchema).optional(),
713
+ }),
714
+ },
715
+ (args) => safeWriteCall("inspector_set_current_context", () => setCurrentContextImpl(args)),
716
+ );
717
+
473
718
  server.registerTool(
474
719
  "inspector_create_run",
475
720
  {
@@ -483,6 +728,14 @@ function registerTools(server: McpServer): void {
483
728
  .min(1)
484
729
  .optional()
485
730
  .describe("Inspector session id to attach. Defaults to the run id."),
731
+ groupId: z
732
+ .string()
733
+ .min(1)
734
+ .nullable()
735
+ .optional()
736
+ .describe(
737
+ "Optional group id. When set with a real sessionId, the run is auto-attached to that group.",
738
+ ),
486
739
  title: z.string().min(1).optional().describe("Human-readable run title."),
487
740
  task: z.string().nullable().optional().describe("Task statement or benchmark case."),
488
741
  project: z.string().nullable().optional().describe("Project or repository under test."),
@@ -492,7 +745,7 @@ function registerTools(server: McpServer): void {
492
745
  metadata: z.record(z.string(), JsonValueSchema).optional().describe("JSON metadata."),
493
746
  }),
494
747
  },
495
- (args) => safeCall(() => createRunImpl(args)),
748
+ (args) => safeWriteCall("inspector_create_run", () => createRunImpl(args)),
496
749
  );
497
750
 
498
751
  server.registerTool(
@@ -518,7 +771,7 @@ function registerTools(server: McpServer): void {
518
771
  runId: z.string().min(1).describe("The Inspector run id."),
519
772
  }),
520
773
  },
521
- (args) => safeCall(() => updateRunImpl(args)),
774
+ (args) => safeWriteCall("inspector_update_run", () => updateRunImpl(args)),
522
775
  );
523
776
 
524
777
  server.registerTool(
@@ -542,7 +795,34 @@ function registerTools(server: McpServer): void {
542
795
  .describe("How many compact log summaries to include in the evidence pack. Max 50."),
543
796
  }),
544
797
  },
545
- (args) => safeCall(() => exportEvidenceImpl(args)),
798
+ (args) => safeWriteCall("inspector_export_evidence", () => exportEvidenceImpl(args)),
799
+ );
800
+
801
+ server.registerTool(
802
+ "inspector_get_evidence_files",
803
+ {
804
+ title: "Get run evidence file paths",
805
+ description:
806
+ "Returns the local JSON, Markdown, HTML, and byte-size status for an already exported run evidence pack. It does not create new files.",
807
+ inputSchema: z.object({
808
+ runId: z.string().min(1).describe("The Inspector run id."),
809
+ }),
810
+ },
811
+ (args) => safeCall(() => getEvidenceFilesImpl(args)),
812
+ );
813
+
814
+ server.registerTool(
815
+ "inspector_export_evidence_bundle",
816
+ {
817
+ title: "Export run evidence ZIP bundle",
818
+ description:
819
+ "Creates evidence.zip next to an already exported run evidence pack, bundling evidence.json, evidence.md, evidence.html, and a manifest.",
820
+ inputSchema: z.object({
821
+ runId: z.string().min(1).describe("The Inspector run id."),
822
+ }),
823
+ },
824
+ (args) =>
825
+ safeWriteCall("inspector_export_evidence_bundle", () => exportEvidenceBundleImpl(args)),
546
826
  );
547
827
 
548
828
  server.registerTool(
@@ -595,7 +875,7 @@ function registerTools(server: McpServer): void {
595
875
  metadata: z.record(z.string(), JsonValueSchema).optional().describe("JSON metadata."),
596
876
  }),
597
877
  },
598
- (args) => safeCall(() => createGroupImpl(args)),
878
+ (args) => safeWriteCall("inspector_create_group", () => createGroupImpl(args)),
599
879
  );
600
880
 
601
881
  server.registerTool(
@@ -621,7 +901,7 @@ function registerTools(server: McpServer): void {
621
901
  groupId: z.string().min(1).describe("The Inspector group id."),
622
902
  }),
623
903
  },
624
- (args) => safeCall(() => updateGroupImpl(args)),
904
+ (args) => safeWriteCall("inspector_update_group", () => updateGroupImpl(args)),
625
905
  );
626
906
 
627
907
  server.registerTool(
@@ -634,7 +914,7 @@ function registerTools(server: McpServer): void {
634
914
  groupId: z.string().min(1).describe("The Inspector group id."),
635
915
  }),
636
916
  },
637
- (args) => safeCall(() => deleteGroupImpl(args)),
917
+ (args) => safeWriteCall("inspector_delete_group", () => deleteGroupImpl(args)),
638
918
  );
639
919
 
640
920
  server.registerTool(
@@ -647,7 +927,7 @@ function registerTools(server: McpServer): void {
647
927
  groupId: z.string().min(1).describe("The Inspector group id."),
648
928
  }),
649
929
  },
650
- (args) => safeCall(() => addGroupSessionImpl(args)),
930
+ (args) => safeWriteCall("inspector_add_group_session", () => addGroupSessionImpl(args)),
651
931
  );
652
932
 
653
933
  server.registerTool(
@@ -660,7 +940,36 @@ function registerTools(server: McpServer): void {
660
940
  groupId: z.string().min(1).describe("The Inspector group id."),
661
941
  }),
662
942
  },
663
- (args) => safeCall(() => exportGroupEvidenceImpl(args)),
943
+ (args) => safeWriteCall("inspector_export_group_evidence", () => exportGroupEvidenceImpl(args)),
944
+ );
945
+
946
+ server.registerTool(
947
+ "inspector_get_group_evidence_files",
948
+ {
949
+ title: "Get group evidence file paths",
950
+ description:
951
+ "Returns the local JSON, Markdown, HTML, and byte-size status for an already exported group evidence pack. It does not create new files.",
952
+ inputSchema: z.object({
953
+ groupId: z.string().min(1).describe("The Inspector group id."),
954
+ }),
955
+ },
956
+ (args) => safeCall(() => getGroupEvidenceFilesImpl(args)),
957
+ );
958
+
959
+ server.registerTool(
960
+ "inspector_export_group_evidence_bundle",
961
+ {
962
+ title: "Export group evidence ZIP bundle",
963
+ description:
964
+ "Creates group-evidence.zip next to an already exported group evidence pack, bundling evidence.json, evidence.md, evidence.html, and a manifest.",
965
+ inputSchema: z.object({
966
+ groupId: z.string().min(1).describe("The Inspector group id."),
967
+ }),
968
+ },
969
+ (args) =>
970
+ safeWriteCall("inspector_export_group_evidence_bundle", () =>
971
+ exportGroupEvidenceBundleImpl(args),
972
+ ),
664
973
  );
665
974
 
666
975
  server.registerTool(
@@ -718,7 +1027,7 @@ function registerTools(server: McpServer): void {
718
1027
  id: z.number().int().positive().describe("The log id to replay."),
719
1028
  }),
720
1029
  },
721
- (args) => safeCall(() => replayLogImpl(callApi, args)),
1030
+ (args) => safeWriteCall("inspector_replay_log", () => replayLogImpl(callApi, args)),
722
1031
  );
723
1032
 
724
1033
  // ----- Provider write tools -----
@@ -739,7 +1048,7 @@ function registerTools(server: McpServer): void {
739
1048
  apiDocsUrl: z.string().optional(),
740
1049
  }),
741
1050
  },
742
- (provider) => safeCall(() => addProviderImpl(callApi, provider)),
1051
+ (provider) => safeWriteCall("inspector_add_provider", () => addProviderImpl(callApi, provider)),
743
1052
  );
744
1053
 
745
1054
  server.registerTool(
@@ -762,7 +1071,7 @@ PATCH-style update: only the fields you supply are changed. Returns the updated
762
1071
  apiDocsUrl: z.string().optional(),
763
1072
  }),
764
1073
  },
765
- (input) => safeCall(() => updateProviderImpl(callApi, input)),
1074
+ (input) => safeWriteCall("inspector_update_provider", () => updateProviderImpl(callApi, input)),
766
1075
  );
767
1076
 
768
1077
  server.registerTool(
@@ -775,7 +1084,23 @@ PATCH-style update: only the fields you supply are changed. Returns the updated
775
1084
  id: z.string().describe("The provider id to test."),
776
1085
  }),
777
1086
  },
778
- ({ id }) => safeCall(() => testProviderImpl(callApi, id)),
1087
+ ({ id }) => safeWriteCall("inspector_test_provider", () => testProviderImpl(callApi, id)),
1088
+ );
1089
+
1090
+ server.registerTool(
1091
+ "inspector_diagnose_provider_test",
1092
+ {
1093
+ title: "Run provider test with diagnostics",
1094
+ description:
1095
+ "Runs Provider Test and returns the raw result plus MCP-friendly diagnostic issues and hints for timeout, auth, base URL, container networking, and non-streaming/streaming mismatches.",
1096
+ inputSchema: z.object({
1097
+ id: z.string().describe("The provider id to test."),
1098
+ }),
1099
+ },
1100
+ ({ id }) =>
1101
+ safeWriteCall("inspector_diagnose_provider_test", () =>
1102
+ diagnoseProviderTestImpl(callApi, id),
1103
+ ),
779
1104
  );
780
1105
 
781
1106
  // ----- Knowledge bridge tools -----
@@ -790,7 +1115,10 @@ PATCH-style update: only the fields you supply are changed. Returns the updated
790
1115
  sessionId: z.string().min(1).describe("The Inspector session id to distill."),
791
1116
  }),
792
1117
  },
793
- (args) => safeCall(() => createSessionKnowledgeImpl(callApi, args)),
1118
+ (args) =>
1119
+ safeWriteCall("inspector_create_session_knowledge", () =>
1120
+ createSessionKnowledgeImpl(callApi, args),
1121
+ ),
794
1122
  );
795
1123
 
796
1124
  server.registerTool(
@@ -814,7 +1142,10 @@ PATCH-style update: only the fields you supply are changed. Returns the updated
814
1142
  candidateId: z.string().min(1).describe("The candidate id to promote."),
815
1143
  }),
816
1144
  },
817
- (args) => safeCall(() => promoteKnowledgeCandidateImpl(callApi, args)),
1145
+ (args) =>
1146
+ safeWriteCall("inspector_promote_knowledge_candidate", () =>
1147
+ promoteKnowledgeCandidateImpl(callApi, args),
1148
+ ),
818
1149
  );
819
1150
 
820
1151
  server.registerTool(
@@ -846,6 +1177,50 @@ PATCH-style update: only the fields you supply are changed. Returns the updated
846
1177
  }
847
1178
 
848
1179
  function registerResources(server: McpServer): void {
1180
+ server.registerResource(
1181
+ "inspector_mcp_health",
1182
+ "inspector://mcp/health",
1183
+ {
1184
+ title: "Inspector MCP health",
1185
+ description: "MCP server version, transport, mode, and catalog counts.",
1186
+ mimeType: "application/json",
1187
+ },
1188
+ (uri) => jsonResource(uri, mcpHealth()),
1189
+ );
1190
+
1191
+ server.registerResource(
1192
+ "inspector_mcp_capabilities",
1193
+ "inspector://mcp/capabilities",
1194
+ {
1195
+ title: "Inspector MCP capabilities",
1196
+ description: "Machine-readable Inspector MCP tools, resources, prompts, and write mode.",
1197
+ mimeType: "application/json",
1198
+ },
1199
+ (uri) => jsonResource(uri, mcpCapabilities()),
1200
+ );
1201
+
1202
+ server.registerResource(
1203
+ "inspector_mcp_config",
1204
+ "inspector://mcp/config",
1205
+ {
1206
+ title: "Inspector MCP client config",
1207
+ description: "Streamable HTTP, stdio bridge, and OpenCode MCP configuration snippets.",
1208
+ mimeType: "application/json",
1209
+ },
1210
+ (uri) => jsonResource(uri, mcpConfig()),
1211
+ );
1212
+
1213
+ server.registerResource(
1214
+ "inspector_current_context",
1215
+ "inspector://context/current",
1216
+ {
1217
+ title: "Inspector current context",
1218
+ description: "Current group/run/session/model/provider context set through MCP.",
1219
+ mimeType: "application/json",
1220
+ },
1221
+ (uri) => jsonResource(uri, getCurrentContext()),
1222
+ );
1223
+
849
1224
  server.registerResource(
850
1225
  "inspector_sessions",
851
1226
  "inspector://sessions",
@@ -874,6 +1249,27 @@ function registerResources(server: McpServer): void {
874
1249
  },
875
1250
  );
876
1251
 
1252
+ server.registerResource(
1253
+ "inspector_session_timeline",
1254
+ new ResourceTemplate("inspector://sessions/{sessionId}/timeline", {
1255
+ list: listSessionTimelineResources,
1256
+ }),
1257
+ {
1258
+ title: "Inspector session timeline",
1259
+ description:
1260
+ "Bounded chronological request timeline for a session with log ids, timings, status, tokens, and previews.",
1261
+ mimeType: "application/json",
1262
+ },
1263
+ async (uri, variables) => {
1264
+ const sessionId = variableString(variables, "sessionId");
1265
+ if (sessionId === null) return textResource(uri, "text/plain", "Missing sessionId");
1266
+ const result = await getSessionTimelineImpl(callApi, { sessionId, limit: 50 });
1267
+ const first = result.content[0];
1268
+ const text = first?.text ?? "";
1269
+ return textResource(uri, result.isError === true ? "text/plain" : "application/json", text);
1270
+ },
1271
+ );
1272
+
877
1273
  server.registerResource(
878
1274
  "inspector_log",
879
1275
  new ResourceTemplate("inspector://logs/{id}", { list: listLogResources }),
@@ -994,6 +1390,26 @@ function registerResources(server: McpServer): void {
994
1390
  },
995
1391
  );
996
1392
 
1393
+ server.registerResource(
1394
+ "inspector_evidence_files",
1395
+ new ResourceTemplate("inspector://evidence/{runId}/files", {
1396
+ list: listEvidenceFileResources,
1397
+ }),
1398
+ {
1399
+ title: "Inspector evidence files",
1400
+ description: "Local file paths and byte sizes for a run evidence pack.",
1401
+ mimeType: "application/json",
1402
+ },
1403
+ (uri, variables) => {
1404
+ const runId = variableString(variables, "runId");
1405
+ if (runId === null) return textResource(uri, "text/plain", "Missing runId");
1406
+ const result = getEvidenceFilesImpl({ runId });
1407
+ const first = result.content[0];
1408
+ const text = first?.text ?? "";
1409
+ return textResource(uri, result.isError === true ? "text/plain" : "application/json", text);
1410
+ },
1411
+ );
1412
+
997
1413
  server.registerResource(
998
1414
  "inspector_group_evidence",
999
1415
  new ResourceTemplate("inspector://groups/{groupId}/evidence", {
@@ -1013,6 +1429,26 @@ function registerResources(server: McpServer): void {
1013
1429
  return textResource(uri, "text/markdown", evidence.value.markdown);
1014
1430
  },
1015
1431
  );
1432
+
1433
+ server.registerResource(
1434
+ "inspector_group_evidence_files",
1435
+ new ResourceTemplate("inspector://groups/{groupId}/evidence/files", {
1436
+ list: listGroupEvidenceFileResources,
1437
+ }),
1438
+ {
1439
+ title: "Inspector group evidence files",
1440
+ description: "Local file paths and byte sizes for a group evidence pack.",
1441
+ mimeType: "application/json",
1442
+ },
1443
+ (uri, variables) => {
1444
+ const groupId = variableString(variables, "groupId");
1445
+ if (groupId === null) return textResource(uri, "text/plain", "Missing groupId");
1446
+ const result = getGroupEvidenceFilesImpl({ groupId });
1447
+ const first = result.content[0];
1448
+ const text = first?.text ?? "";
1449
+ return textResource(uri, result.isError === true ? "text/plain" : "application/json", text);
1450
+ },
1451
+ );
1016
1452
  }
1017
1453
 
1018
1454
  function registerPrompts(server: McpServer): void {
@@ -1167,10 +1603,15 @@ export const TOOL_NAMES = [
1167
1603
  "inspector_get_log_chunks",
1168
1604
  "inspector_list_sessions",
1169
1605
  "inspector_get_session",
1606
+ "inspector_get_session_timeline",
1607
+ "inspector_get_current_context",
1608
+ "inspector_set_current_context",
1170
1609
  "inspector_create_run",
1171
1610
  "inspector_get_run",
1172
1611
  "inspector_update_run",
1173
1612
  "inspector_export_evidence",
1613
+ "inspector_get_evidence_files",
1614
+ "inspector_export_evidence_bundle",
1174
1615
  "inspector_get_recent_failures",
1175
1616
  "inspector_list_groups",
1176
1617
  "inspector_create_group",
@@ -1179,6 +1620,8 @@ export const TOOL_NAMES = [
1179
1620
  "inspector_delete_group",
1180
1621
  "inspector_add_group_session",
1181
1622
  "inspector_export_group_evidence",
1623
+ "inspector_get_group_evidence_files",
1624
+ "inspector_export_group_evidence_bundle",
1182
1625
  "inspector_list_models",
1183
1626
  "inspector_list_providers",
1184
1627
  "inspector_get_provider",
@@ -1186,6 +1629,7 @@ export const TOOL_NAMES = [
1186
1629
  "inspector_add_provider",
1187
1630
  "inspector_update_provider",
1188
1631
  "inspector_test_provider",
1632
+ "inspector_diagnose_provider_test",
1189
1633
  "inspector_create_session_knowledge",
1190
1634
  "inspector_list_knowledge_candidates",
1191
1635
  "inspector_promote_knowledge_candidate",
@@ -1194,17 +1638,24 @@ export const TOOL_NAMES = [
1194
1638
  ] as const;
1195
1639
 
1196
1640
  export const RESOURCE_NAMES = [
1641
+ "inspector_mcp_health",
1642
+ "inspector_mcp_capabilities",
1643
+ "inspector_mcp_config",
1644
+ "inspector_current_context",
1197
1645
  "inspector_sessions",
1198
1646
  "inspector_session",
1647
+ "inspector_session_timeline",
1199
1648
  "inspector_log",
1200
1649
  "inspector_runs",
1201
1650
  "inspector_recent_failures",
1202
1651
  "inspector_run",
1203
1652
  "inspector_evidence",
1653
+ "inspector_evidence_files",
1204
1654
  "inspector_groups",
1205
1655
  "inspector_group",
1206
1656
  "inspector_group_sessions",
1207
1657
  "inspector_group_evidence",
1658
+ "inspector_group_evidence_files",
1208
1659
  ] as const;
1209
1660
 
1210
1661
  export const PROMPT_NAMES = [