Address PR #1212 code review feedback

- Fix hasAnyAnnotation checking annotations.title which is never rendered
- Reset formValues when switching tools via onSelectTool handler
- Extract ToolProgress type from ToolDetailPanel, reuse in ToolsScreen
- Fix contradictory readOnlyHint + destructiveHint in story fixture
- Replace listMaxHeight function with LIST_MAX_HEIGHT constant

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
cliffhall 2026-04-18 17:12:02 -04:00
commit 16f4d9b50f
4 changed files with 20 additions and 22 deletions

View file

@ -12,9 +12,8 @@ export interface ToolControlsProps {
onSelectTool: (name: string) => void; onSelectTool: (name: string) => void;
} }
function listMaxHeight(): string { const LIST_MAX_HEIGHT =
return "calc(100vh - var(--app-shell-header-height, 0px) - var(--mantine-spacing-xl) * 2 - 160px)"; "calc(100vh - var(--app-shell-header-height, 0px) - var(--mantine-spacing-xl) * 2 - 160px)";
}
export function ToolControls({ export function ToolControls({
tools, tools,
@ -44,7 +43,7 @@ export function ToolControls({
value={searchText} value={searchText}
onChange={(e) => setSearchText(e.currentTarget.value)} onChange={(e) => setSearchText(e.currentTarget.value)}
/> />
<ScrollArea.Autosize mah={listMaxHeight()}> <ScrollArea.Autosize mah={LIST_MAX_HEIGHT}>
<Stack gap="xs"> <Stack gap="xs">
{filteredTools.map((tool) => ( {filteredTools.map((tool) => (
<ToolListItem <ToolListItem

View file

@ -50,7 +50,6 @@ const deleteRecordsTool: Tool = {
name: "delete_records", name: "delete_records",
description: "Deletes records matching the given criteria", description: "Deletes records matching the given criteria",
annotations: { annotations: {
readOnlyHint: true,
destructiveHint: true, destructiveHint: true,
}, },
inputSchema: { inputSchema: {

View file

@ -8,14 +8,16 @@ import { AnnotationBadge } from "../../elements/AnnotationBadge/AnnotationBadge"
import { ProgressDisplay } from "../../elements/ProgressDisplay/ProgressDisplay"; import { ProgressDisplay } from "../../elements/ProgressDisplay/ProgressDisplay";
import { SchemaForm } from "../SchemaForm/SchemaForm"; import { SchemaForm } from "../SchemaForm/SchemaForm";
export type ToolProgress = Pick<
ProgressNotification["params"],
"progress" | "total" | "message"
>;
export interface ToolDetailPanelProps { export interface ToolDetailPanelProps {
tool: Tool; tool: Tool;
formValues: Record<string, unknown>; formValues: Record<string, unknown>;
isExecuting: boolean; isExecuting: boolean;
progress?: Pick< progress?: ToolProgress;
ProgressNotification["params"],
"progress" | "total" | "message"
>;
onFormChange: (values: Record<string, unknown>) => void; onFormChange: (values: Record<string, unknown>) => void;
onExecute: () => void; onExecute: () => void;
onCancel: () => void; onCancel: () => void;
@ -44,8 +46,7 @@ function resolveTitle(name: string, title?: string): string {
function hasAnyAnnotation(annotations?: ToolAnnotations): boolean { function hasAnyAnnotation(annotations?: ToolAnnotations): boolean {
return !!( return !!(
annotations && annotations &&
(annotations.title || (annotations.readOnlyHint ||
annotations.readOnlyHint ||
annotations.destructiveHint || annotations.destructiveHint ||
annotations.idempotentHint || annotations.idempotentHint ||
annotations.openWorldHint) annotations.openWorldHint)

View file

@ -1,22 +1,18 @@
import { useState } from "react"; import { useState } from "react";
import { Card, Flex, Stack, Text } from "@mantine/core"; import { Card, Flex, Stack, Text } from "@mantine/core";
import type { import type { CallToolResult, Tool } from "@modelcontextprotocol/sdk/types.js";
CallToolResult,
ProgressNotification,
Tool,
} from "@modelcontextprotocol/sdk/types.js";
import { ToolControls } from "../../groups/ToolControls/ToolControls"; import { ToolControls } from "../../groups/ToolControls/ToolControls";
import { ToolDetailPanel } from "../../groups/ToolDetailPanel/ToolDetailPanel"; import {
ToolDetailPanel,
type ToolProgress,
} from "../../groups/ToolDetailPanel/ToolDetailPanel";
import { ToolResultPanel } from "../../groups/ToolResultPanel/ToolResultPanel"; import { ToolResultPanel } from "../../groups/ToolResultPanel/ToolResultPanel";
export interface ToolCallState { export interface ToolCallState {
status: "idle" | "pending" | "ok" | "error"; status: "idle" | "pending" | "ok" | "error";
result?: CallToolResult; result?: CallToolResult;
error?: string; error?: string;
progress?: Pick< progress?: ToolProgress;
ProgressNotification["params"],
"progress" | "total" | "message"
>;
} }
export interface ToolsScreenProps { export interface ToolsScreenProps {
@ -86,7 +82,10 @@ export function ToolsScreen({
selectedName={selectedToolName} selectedName={selectedToolName}
listChanged={listChanged} listChanged={listChanged}
onRefreshList={onRefreshList} onRefreshList={onRefreshList}
onSelectTool={onSelectTool} onSelectTool={(name) => {
setFormValues({});
onSelectTool(name);
}}
/> />
</SidebarCard> </SidebarCard>
</Sidebar> </Sidebar>