Phase 2: Refactor Prompts cluster to MCP SDK types

Replace ad hoc local types with MCP SDK schema types across the Prompts
group components and PromptsScreen, per the v2 UX interfaces plan.

- PromptListItem: accept `prompt: Prompt` instead of flat `name`/`description`;
  render `title ?? name` as primary label
- PromptControls: accept `Prompt[]` + `selectedName` instead of `PromptItem[]`;
  no-op on clicking already-selected prompt; search includes title field
- PromptArgumentsForm: accept `prompt: Prompt` instead of flat props;
  read `prompt.arguments` directly; display `title ?? name` as heading
- PromptMessagesDisplay: narrow type from `(PromptMessage | SamplingMessage)[]`
  to `PromptMessage[]` per spec
- PromptsScreen: accept `Prompt[]` + `selectedPromptName` + `GetPromptState`;
  derive selected prompt via `prompts.find()`; own `argumentValues` state
  locally; reset arguments on tool switch
- Delete local `PromptItem`, `SelectedPrompt`, `PromptArgument` types
- Update all stories with real SDK `Prompt` fixtures
- Update ConnectedView PromptsActive story

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
cliffhall 2026-04-18 17:49:27 -04:00
commit de40b3720e
2 changed files with 230 additions and 226 deletions

View file

@ -1,4 +1,5 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import type { Prompt } from "@modelcontextprotocol/sdk/types.js";
import { fn } from "storybook/test";
import { PromptControls } from "./PromptControls";
@ -15,28 +16,24 @@ const meta: Meta<typeof PromptControls> = {
export default meta;
type Story = StoryObj<typeof PromptControls>;
const samplePrompts = [
const samplePrompts: Prompt[] = [
{
name: "summarize",
description: "Summarize the given text into key points",
selected: false,
},
{
name: "translate",
description: "Translate text from one language to another",
selected: false,
},
{
name: "analyze",
description: "Analyze sentiment and tone of the text",
selected: false,
},
{
name: "code-review",
description: "Review code for issues",
selected: false,
},
{ name: "refactor", selected: false },
{ name: "refactor" },
];
export const Default: Story = {
@ -47,9 +44,8 @@ export const Default: Story = {
export const WithSelection: Story = {
args: {
prompts: samplePrompts.map((p) =>
p.name === "translate" ? { ...p, selected: true } : p,
),
prompts: samplePrompts,
selectedName: "translate",
},
};

View file

@ -1,22 +1,23 @@
import { useState } from "react";
import { Group, ScrollArea, Stack, TextInput, Title } from "@mantine/core";
import type { Prompt } from "@modelcontextprotocol/sdk/types.js";
import { ListChangedIndicator } from "../../elements/ListChangedIndicator/ListChangedIndicator";
import { PromptListItem } from "../PromptListItem/PromptListItem";
import type { PromptItem } from "../../screens/PromptsScreen/PromptsScreen";
export interface PromptControlsProps {
prompts: PromptItem[];
prompts: Prompt[];
selectedName?: string;
listChanged: boolean;
onRefreshList: () => void;
onSelectPrompt: (name: string) => void;
}
function listMaxHeight(): string {
return "calc(100vh - var(--app-shell-header-height, 0px) - var(--mantine-spacing-xl) * 2 - 160px)";
}
const LIST_MAX_HEIGHT =
"calc(100vh - var(--app-shell-header-height, 0px) - var(--mantine-spacing-xl) * 2 - 160px)";
export function PromptControls({
prompts,
selectedName,
listChanged,
onRefreshList,
onSelectPrompt,
@ -26,6 +27,7 @@ export function PromptControls({
const filteredPrompts = prompts.filter(
(p) =>
p.name.toLowerCase().includes(query) ||
(p.title?.toLowerCase().includes(query) ?? false) ||
(p.description?.toLowerCase().includes(query) ?? false),
);
@ -40,15 +42,16 @@ export function PromptControls({
value={searchText}
onChange={(e) => setSearchText(e.currentTarget.value)}
/>
<ScrollArea.Autosize mah={listMaxHeight()}>
<ScrollArea.Autosize mah={LIST_MAX_HEIGHT}>
<Stack gap="xs">
{filteredPrompts.map((prompt) => (
<PromptListItem
key={prompt.name}
name={prompt.name}
description={prompt.description}
selected={prompt.selected}
onClick={() => onSelectPrompt(prompt.name)}
prompt={prompt}
selected={prompt.name === selectedName}
onClick={() => {
if (prompt.name !== selectedName) onSelectPrompt(prompt.name);
}}
/>
))}
</Stack>