@tonyclaw/agent-inspector 2.1.6 → 2.1.8
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/.output/cli.js +274 -140
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-Djazxhew.js → CompareDrawer-CHkT7kun.js} +1 -1
- package/.output/public/assets/{ProxyViewerContainer-BC-z9RPh.js → ProxyViewerContainer-BiZ2_tMC.js} +36 -36
- package/.output/public/assets/{ReplayDialog-BaD4R6ac.js → ReplayDialog-C85cakjx.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-w6uGdqYp.js → RequestAnatomy-Dn_pMMoX.js} +1 -1
- package/.output/public/assets/{ResponseView-VPed-Yif.js → ResponseView-DzcxCUBf.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-CPB8FgHI.js → StreamingChunkSequence-BamtvkgZ.js} +1 -1
- package/.output/public/assets/_sessionId-xBBbFH1M.js +1 -0
- package/.output/public/assets/index-6udjwQO1.js +1 -0
- package/.output/public/assets/{main-CIV3Chb5.js → main-Dc2qVWpb.js} +2 -2
- package/.output/server/{_sessionId-CIXQGim9.mjs → _sessionId-BnimGger.mjs} +3 -3
- package/.output/server/_ssr/{CompareDrawer-_uFgjkB2.mjs → CompareDrawer-CwVFykVF.mjs} +3 -3
- package/.output/server/_ssr/{ProxyViewerContainer-D8YjQDNj.mjs → ProxyViewerContainer-X3S2TWBJ.mjs} +236 -136
- package/.output/server/_ssr/{ReplayDialog-CFwKM7jc.mjs → ReplayDialog-BxC12XUj.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-2Vr84GxT.mjs → RequestAnatomy-CWWS8Qh7.mjs} +3 -3
- package/.output/server/_ssr/{ResponseView-CSBWBHRJ.mjs → ResponseView-BewErHF-.mjs} +3 -3
- package/.output/server/_ssr/{StreamingChunkSequence-Dr4JApqs.mjs → StreamingChunkSequence-BlmCVryW.mjs} +3 -3
- package/.output/server/_ssr/{index-WnsY1fh_.mjs → index-5qbGuoFX.mjs} +3 -3
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-sy38X5AX.mjs → router-s78S54MU.mjs} +554 -124
- package/.output/server/{_tanstack-start-manifest_v-Dde-eACV.mjs → _tanstack-start-manifest_v-DTxpr3KE.mjs} +1 -1
- package/.output/server/index.mjs +61 -61
- package/README.md +10 -6
- package/package.json +1 -1
- package/src/cli/detect-tools.ts +2 -1
- package/src/cli/onboard.ts +334 -167
- package/src/components/groups/GroupsDialog.tsx +9 -4
- package/src/components/providers/SettingsDialog.tsx +67 -0
- package/src/components/proxy-viewer/ConversationGroup.tsx +28 -0
- package/src/components/proxy-viewer/ConversationHeader.tsx +34 -0
- package/src/components/proxy-viewer/LogEntryHeader.tsx +3 -12
- package/src/mcp/server.ts +18 -4
- package/src/proxy/sessionArchive.ts +410 -0
- package/src/proxy/store.ts +121 -6
- package/src/routes/api/logs.ts +2 -0
- package/src/routes/api/sessions.ts +2 -2
- package/.output/public/assets/_sessionId-mnr0O0Ri.js +0 -1
- package/.output/public/assets/index-DH1DjJOl.js +0 -1
|
@@ -1016,9 +1016,14 @@ function MemberRow({
|
|
|
1016
1016
|
<ExternalLink className="size-3 shrink-0 text-muted-foreground" />
|
|
1017
1017
|
</a>
|
|
1018
1018
|
) : (
|
|
1019
|
-
<
|
|
1020
|
-
|
|
1021
|
-
|
|
1019
|
+
<button
|
|
1020
|
+
type="button"
|
|
1021
|
+
className="inline-flex max-w-full min-w-0 items-center gap-2 rounded-sm font-mono text-xs text-foreground outline-none hover:underline focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
|
1022
|
+
title={`Show evidence snapshot for ${sessionLabel}`}
|
|
1023
|
+
aria-label={`Show evidence snapshot for ${sessionLabel}`}
|
|
1024
|
+
onClick={() => {
|
|
1025
|
+
onToggleDetails(member.id);
|
|
1026
|
+
}}
|
|
1022
1027
|
>
|
|
1023
1028
|
<span className="min-w-0 truncate">{sessionLabel}</span>
|
|
1024
1029
|
<Badge
|
|
@@ -1027,7 +1032,7 @@ function MemberRow({
|
|
|
1027
1032
|
>
|
|
1028
1033
|
evidence
|
|
1029
1034
|
</Badge>
|
|
1030
|
-
</
|
|
1035
|
+
</button>
|
|
1031
1036
|
)}
|
|
1032
1037
|
</div>
|
|
1033
1038
|
<div className="mt-0.5 truncate text-[11px] text-muted-foreground">
|
|
@@ -123,6 +123,9 @@ type LogStorageStats = {
|
|
|
123
123
|
chunkDir: string;
|
|
124
124
|
chunkFileCount: number;
|
|
125
125
|
chunkBytes: number;
|
|
126
|
+
sessionArchiveDir: string;
|
|
127
|
+
sessionArchiveFileCount: number;
|
|
128
|
+
sessionArchiveBytes: number;
|
|
126
129
|
};
|
|
127
130
|
|
|
128
131
|
const LogStorageStatsSchema = z.object({
|
|
@@ -133,6 +136,9 @@ const LogStorageStatsSchema = z.object({
|
|
|
133
136
|
chunkDir: z.string(),
|
|
134
137
|
chunkFileCount: z.number(),
|
|
135
138
|
chunkBytes: z.number(),
|
|
139
|
+
sessionArchiveDir: z.string(),
|
|
140
|
+
sessionArchiveFileCount: z.number(),
|
|
141
|
+
sessionArchiveBytes: z.number(),
|
|
136
142
|
});
|
|
137
143
|
|
|
138
144
|
function formatBytes(bytes: number): string {
|
|
@@ -213,6 +219,13 @@ function StorageSettingsTab(): JSX.Element {
|
|
|
213
219
|
copiedId={copiedId}
|
|
214
220
|
onCopy={handleCopy}
|
|
215
221
|
/>
|
|
222
|
+
<CopyableSetupValue
|
|
223
|
+
id="session-archive-dir"
|
|
224
|
+
label="Session archive storage path"
|
|
225
|
+
value={stats.sessionArchiveDir}
|
|
226
|
+
copiedId={copiedId}
|
|
227
|
+
onCopy={handleCopy}
|
|
228
|
+
/>
|
|
216
229
|
<div className="rounded-md border border-border bg-muted/20 px-3 py-2">
|
|
217
230
|
<div className="font-medium">In-memory logs</div>
|
|
218
231
|
<div className="mt-1 font-mono text-muted-foreground">
|
|
@@ -231,6 +244,13 @@ function StorageSettingsTab(): JSX.Element {
|
|
|
231
244
|
{stats.chunkFileCount.toLocaleString()} files / {formatBytes(stats.chunkBytes)}
|
|
232
245
|
</div>
|
|
233
246
|
</div>
|
|
247
|
+
<div className="rounded-md border border-border bg-muted/20 px-3 py-2">
|
|
248
|
+
<div className="font-medium">Session archives</div>
|
|
249
|
+
<div className="mt-1 font-mono text-muted-foreground">
|
|
250
|
+
{stats.sessionArchiveFileCount.toLocaleString()} files /{" "}
|
|
251
|
+
{formatBytes(stats.sessionArchiveBytes)}
|
|
252
|
+
</div>
|
|
253
|
+
</div>
|
|
234
254
|
</div>
|
|
235
255
|
)}
|
|
236
256
|
|
|
@@ -311,6 +331,18 @@ function OnboardingSettingsTab(): JSX.Element {
|
|
|
311
331
|
},
|
|
312
332
|
{ id: "opencode-verify", label: "OpenCode verify", value: "opencode mcp list" },
|
|
313
333
|
{ id: "opencode-proxy", label: "OpenCode proxy", value: `LLM_BASE_URL=${origin}/proxy` },
|
|
334
|
+
{
|
|
335
|
+
id: "mimo-config",
|
|
336
|
+
label: "MiMo Code config",
|
|
337
|
+
value: "agent-inspector onboard --mimo-only",
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
id: "mimo-status",
|
|
341
|
+
label: "MiMo Code status",
|
|
342
|
+
value: "agent-inspector onboard --status --mimo-only",
|
|
343
|
+
},
|
|
344
|
+
{ id: "mimo-verify", label: "MiMo Code verify", value: "mimo mcp list" },
|
|
345
|
+
{ id: "mimo-proxy", label: "MiMo Code proxy", value: `OPENAI_BASE_URL=${origin}/proxy` },
|
|
314
346
|
{ id: "mcp", label: "MCP URL", value: `${origin}/api/mcp` },
|
|
315
347
|
{ id: "proxy", label: "Proxy URL", value: `${origin}/proxy` },
|
|
316
348
|
{ id: "anthropic", label: "Anthropic base", value: `ANTHROPIC_BASE_URL=${origin}/proxy` },
|
|
@@ -382,6 +414,24 @@ function OnboardingSettingsTab(): JSX.Element {
|
|
|
382
414
|
.
|
|
383
415
|
</span>
|
|
384
416
|
</div>
|
|
417
|
+
<div className="flex items-start gap-2">
|
|
418
|
+
<Check className="mt-0.5 size-3.5 text-emerald-500" />
|
|
419
|
+
<span>
|
|
420
|
+
MiMo Code onboarding safely merges{" "}
|
|
421
|
+
<code className="rounded bg-muted px-1 py-0.5 font-mono text-[11px] text-foreground">
|
|
422
|
+
mcp.agent-inspector
|
|
423
|
+
</code>{" "}
|
|
424
|
+
into{" "}
|
|
425
|
+
<code className="rounded bg-muted px-1 py-0.5 font-mono text-[11px] text-foreground">
|
|
426
|
+
mimocode.jsonc
|
|
427
|
+
</code>
|
|
428
|
+
, then route OpenAI-format traffic with{" "}
|
|
429
|
+
<code className="rounded bg-muted px-1 py-0.5 font-mono text-[11px] text-foreground">
|
|
430
|
+
OPENAI_BASE_URL
|
|
431
|
+
</code>
|
|
432
|
+
.
|
|
433
|
+
</span>
|
|
434
|
+
</div>
|
|
385
435
|
<div className="flex items-start gap-2">
|
|
386
436
|
<Check className="mt-0.5 size-3.5 text-emerald-500" />
|
|
387
437
|
<span>
|
|
@@ -478,6 +528,23 @@ function McpSettingsTab(): JSX.Element {
|
|
|
478
528
|
2,
|
|
479
529
|
),
|
|
480
530
|
},
|
|
531
|
+
{
|
|
532
|
+
id: "mimo-local",
|
|
533
|
+
label: "MiMo Code local MCP",
|
|
534
|
+
value: JSON.stringify(
|
|
535
|
+
{
|
|
536
|
+
mcp: {
|
|
537
|
+
"agent-inspector": {
|
|
538
|
+
type: "local",
|
|
539
|
+
command: ["agent-inspector-mcp", "stdio", "--url", endpoint],
|
|
540
|
+
enabled: true,
|
|
541
|
+
},
|
|
542
|
+
},
|
|
543
|
+
},
|
|
544
|
+
null,
|
|
545
|
+
2,
|
|
546
|
+
),
|
|
547
|
+
},
|
|
481
548
|
{
|
|
482
549
|
id: "codex-toml",
|
|
483
550
|
label: "Codex TOML",
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
hasMixedApiFormat,
|
|
9
9
|
type ConversationGroupData,
|
|
10
10
|
} from "./ConversationHeader";
|
|
11
|
+
import { detectProvider } from "../providers/ProviderLogo";
|
|
11
12
|
import { TurnGroup } from "./TurnGroup";
|
|
12
13
|
import { AgentTraceSummary } from "./AgentTraceSummary";
|
|
13
14
|
import type { CacheTrendEntry } from "./cacheTrend";
|
|
@@ -56,6 +57,31 @@ function computeStats(logs: CapturedLog[]): {
|
|
|
56
57
|
return { totalInputTokens: totalInput, totalOutputTokens: totalOutput };
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
/** Bucket each log's model under its detected provider and return one entry
|
|
61
|
+
* per provider with the deduplicated model names. Used by the session
|
|
62
|
+
* header to render one logo per provider used in the session. */
|
|
63
|
+
function collectProviders(logs: CapturedLog[]): {
|
|
64
|
+
provider: import("../providers/ProviderLogo").Provider;
|
|
65
|
+
models: string[];
|
|
66
|
+
}[] {
|
|
67
|
+
const buckets = new Map<import("../providers/ProviderLogo").Provider, Set<string>>();
|
|
68
|
+
for (const log of logs) {
|
|
69
|
+
if (log.model === null) continue;
|
|
70
|
+
const provider = detectProvider(log.model);
|
|
71
|
+
if (provider === "unknown") continue;
|
|
72
|
+
let models = buckets.get(provider);
|
|
73
|
+
if (models === undefined) {
|
|
74
|
+
models = new Set();
|
|
75
|
+
buckets.set(provider, models);
|
|
76
|
+
}
|
|
77
|
+
models.add(log.model);
|
|
78
|
+
}
|
|
79
|
+
return [...buckets.entries()].map(([provider, models]) => ({
|
|
80
|
+
provider,
|
|
81
|
+
models: [...models],
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
|
|
59
85
|
export const ConversationGroup = memo(function ({
|
|
60
86
|
group,
|
|
61
87
|
viewMode = "simple",
|
|
@@ -84,6 +110,7 @@ export const ConversationGroup = memo(function ({
|
|
|
84
110
|
[onExpandedChange],
|
|
85
111
|
);
|
|
86
112
|
const stats = useMemo(() => computeStats(group.logs), [group.logs]);
|
|
113
|
+
const providers = useMemo(() => collectProviders(group.logs), [group.logs]);
|
|
87
114
|
const startTime = group.logs[0]?.timestamp ?? new Date().toISOString();
|
|
88
115
|
const endTime = group.logs[group.logs.length - 1]?.timestamp ?? new Date().toISOString();
|
|
89
116
|
const mixed = hasMixedApiFormat(group.logs);
|
|
@@ -122,6 +149,7 @@ export const ConversationGroup = memo(function ({
|
|
|
122
149
|
expanded={expanded}
|
|
123
150
|
onToggle={() => setExpanded(!expanded)}
|
|
124
151
|
hideApiFormat={mixed}
|
|
152
|
+
providers={providers}
|
|
125
153
|
isLoading={isLoading}
|
|
126
154
|
userAgent={group.logs[0]?.userAgent ?? null}
|
|
127
155
|
timeDisplayFormat={timeDisplayFormat}
|
|
@@ -18,6 +18,8 @@ import { cn, formatTokens } from "../../lib/utils";
|
|
|
18
18
|
import type { CapturedLog } from "../../contracts";
|
|
19
19
|
import { Badge } from "../ui/badge";
|
|
20
20
|
import { ConfirmDialog } from "../ui/confirm-dialog";
|
|
21
|
+
import { ProviderLogo, type Provider } from "../providers/ProviderLogo";
|
|
22
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/tooltip";
|
|
21
23
|
import { resolveLogFormat } from "./log-formats";
|
|
22
24
|
|
|
23
25
|
const API_FORMAT_LABELS: Record<"anthropic" | "openai" | "unknown", string> = {
|
|
@@ -39,6 +41,11 @@ export type ConversationHeaderProps = {
|
|
|
39
41
|
/** Hide the API format badge on the header (used when the group contains
|
|
40
42
|
* mixed formats - the per-log badges are shown instead). */
|
|
41
43
|
hideApiFormat?: boolean;
|
|
44
|
+
/** Unique providers whose models appear in this group, with their distinct
|
|
45
|
+
* model names. Rendered as a row of provider logos next to the header —
|
|
46
|
+
* one per provider so model-switching inside a single session is visible
|
|
47
|
+
* at a glance. `undefined` hides the strip (default). */
|
|
48
|
+
providers?: { provider: Provider; models: string[] }[];
|
|
42
49
|
/** When true and the group is collapsed, show a spinner instead of the
|
|
43
50
|
* expand chevron to indicate an in-flight request inside the group. */
|
|
44
51
|
isLoading?: boolean;
|
|
@@ -62,6 +69,7 @@ export function ConversationHeader({
|
|
|
62
69
|
expanded,
|
|
63
70
|
onToggle,
|
|
64
71
|
hideApiFormat = false,
|
|
72
|
+
providers,
|
|
65
73
|
isLoading = false,
|
|
66
74
|
userAgent,
|
|
67
75
|
timeDisplayFormat,
|
|
@@ -152,6 +160,32 @@ export function ConversationHeader({
|
|
|
152
160
|
</Badge>
|
|
153
161
|
)}
|
|
154
162
|
|
|
163
|
+
{/* Provider logos — one per unique provider used in this session. When
|
|
164
|
+
a session switched models mid-stream (e.g. claude-3-5 → deepseek-v4)
|
|
165
|
+
multiple logos appear side-by-side; tooltip lists every distinct
|
|
166
|
+
model name. */}
|
|
167
|
+
{providers !== undefined && providers.length > 0 && (
|
|
168
|
+
<TooltipProvider delayDuration={150}>
|
|
169
|
+
<span
|
|
170
|
+
className="flex items-center gap-0.5 shrink-0"
|
|
171
|
+
aria-label="Models used in this session"
|
|
172
|
+
>
|
|
173
|
+
{providers.map(({ provider, models }) => (
|
|
174
|
+
<Tooltip key={provider}>
|
|
175
|
+
<TooltipTrigger asChild>
|
|
176
|
+
<span className="shrink-0">
|
|
177
|
+
<ProviderLogo provider={provider} className="size-4" />
|
|
178
|
+
</span>
|
|
179
|
+
</TooltipTrigger>
|
|
180
|
+
<TooltipContent>
|
|
181
|
+
{models.length === 1 ? models[0] : models.join(", ")}
|
|
182
|
+
</TooltipContent>
|
|
183
|
+
</Tooltip>
|
|
184
|
+
))}
|
|
185
|
+
</span>
|
|
186
|
+
</TooltipProvider>
|
|
187
|
+
)}
|
|
188
|
+
|
|
155
189
|
{/* Time range */}
|
|
156
190
|
<span className="flex items-center gap-1 text-muted-foreground text-xs shrink-0">
|
|
157
191
|
<Clock className="size-3" />
|
|
@@ -30,7 +30,6 @@ import { cn, formatTokens, getStatusCategory, type StatusCategory } from "../../
|
|
|
30
30
|
import type { CapturedLog } from "../../contracts";
|
|
31
31
|
import { Badge } from "../ui/badge";
|
|
32
32
|
import { Button } from "../ui/button";
|
|
33
|
-
import { ProviderLogo, detectProvider } from "../providers/ProviderLogo";
|
|
34
33
|
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "../ui/tooltip";
|
|
35
34
|
import type { CacheTrend } from "./cacheTrend";
|
|
36
35
|
|
|
@@ -199,17 +198,9 @@ export const LogEntryHeader = memo(function ({
|
|
|
199
198
|
</span>
|
|
200
199
|
</span>
|
|
201
200
|
|
|
202
|
-
{/* Model
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
<TooltipTrigger asChild>
|
|
206
|
-
<span className="shrink-0">
|
|
207
|
-
<ProviderLogo provider={detectProvider(log.model)} className="size-4" />
|
|
208
|
-
</span>
|
|
209
|
-
</TooltipTrigger>
|
|
210
|
-
<TooltipContent>{log.model}</TooltipContent>
|
|
211
|
-
</Tooltip>
|
|
212
|
-
)}
|
|
201
|
+
{/* Model logo moved to the session/conversation header — per-log rows
|
|
202
|
+
no longer render the logo (sessions with many logs would show the
|
|
203
|
+
same provider logo dozens of times). */}
|
|
213
204
|
|
|
214
205
|
{/* Response Status — only shown for non-200 or pending. Each category
|
|
215
206
|
carries a distinct icon in addition to color so the meaning is
|
package/src/mcp/server.ts
CHANGED
|
@@ -316,6 +316,15 @@ function mcpConfig(): Record<string, unknown> {
|
|
|
316
316
|
},
|
|
317
317
|
},
|
|
318
318
|
},
|
|
319
|
+
mimoCodeLocal: {
|
|
320
|
+
mcp: {
|
|
321
|
+
"agent-inspector": {
|
|
322
|
+
type: "local",
|
|
323
|
+
command: ["agent-inspector-mcp", "stdio", "--url", endpoint],
|
|
324
|
+
enabled: true,
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
},
|
|
319
328
|
networkNote:
|
|
320
329
|
"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
330
|
};
|
|
@@ -739,7 +748,11 @@ function registerTools(server: McpServer): void {
|
|
|
739
748
|
title: z.string().min(1).optional().describe("Human-readable run title."),
|
|
740
749
|
task: z.string().nullable().optional().describe("Task statement or benchmark case."),
|
|
741
750
|
project: z.string().nullable().optional().describe("Project or repository under test."),
|
|
742
|
-
agent: z
|
|
751
|
+
agent: z
|
|
752
|
+
.string()
|
|
753
|
+
.nullable()
|
|
754
|
+
.optional()
|
|
755
|
+
.describe("Coding agent name, e.g. Codex/OpenCode/MiMo Code."),
|
|
743
756
|
status: InspectorRunStatusSchema.optional().describe("Initial run status."),
|
|
744
757
|
tags: z.array(z.string()).optional().describe("Free-form run labels."),
|
|
745
758
|
metadata: z.record(z.string(), JsonValueSchema).optional().describe("JSON metadata."),
|
|
@@ -860,7 +873,7 @@ function registerTools(server: McpServer): void {
|
|
|
860
873
|
{
|
|
861
874
|
title: "Create or declare an Inspector group",
|
|
862
875
|
description:
|
|
863
|
-
"Creates an evaluation/batch group that external systems can use to aggregate multiple
|
|
876
|
+
"Creates an evaluation/batch group that external systems can use to aggregate multiple Codex, OpenCode, or MiMo Code sessions across models such as MiniMax, DeepSeek, or GLM.",
|
|
864
877
|
inputSchema: z.object({
|
|
865
878
|
groupId: z.string().min(1).optional().describe("Stable group id. Generated when omitted."),
|
|
866
879
|
title: z.string().min(1).optional().describe("Human-readable group title."),
|
|
@@ -922,7 +935,7 @@ function registerTools(server: McpServer): void {
|
|
|
922
935
|
{
|
|
923
936
|
title: "Attach a session to an Inspector group",
|
|
924
937
|
description:
|
|
925
|
-
"Adds or updates one group member. Use it after each
|
|
938
|
+
"Adds or updates one group member. Use it after each coding-agent process discovers its session id, or while an evaluation matrix is running to attach model/provider labels.",
|
|
926
939
|
inputSchema: AddInspectorGroupSessionInputSchema.extend({
|
|
927
940
|
groupId: z.string().min(1).describe("The Inspector group id."),
|
|
928
941
|
}),
|
|
@@ -1204,7 +1217,8 @@ function registerResources(server: McpServer): void {
|
|
|
1204
1217
|
"inspector://mcp/config",
|
|
1205
1218
|
{
|
|
1206
1219
|
title: "Inspector MCP client config",
|
|
1207
|
-
description:
|
|
1220
|
+
description:
|
|
1221
|
+
"Streamable HTTP, stdio bridge, OpenCode, and MiMo Code MCP configuration snippets.",
|
|
1208
1222
|
mimeType: "application/json",
|
|
1209
1223
|
},
|
|
1210
1224
|
(uri) => jsonResource(uri, mcpConfig()),
|