Phase 2: Refactor Sampling/Elicitation cluster to MCP SDK types

Replace ad hoc local types with SDK schema types across the Sampling
and Elicitation group components.

- SamplingRequestPanel: accept `request: CreateMessageRequestParams` +
  `draftResult: CreateMessageResult` instead of 16 flat props; derive
  messages, model preferences, and parameters from the request object;
  drop `tools`/`toolChoice` (not in MCP 2025-11-25 CreateMessageRequest)
- InlineSamplingRequest: accept `request: CreateMessageRequestParams`;
  derive messagePreview and modelHints from the request
- ElicitationFormPanel: accept `request: ElicitRequest['params']` +
  `serverName`; pass requestedSchema directly to SchemaForm
- ElicitationUrlPanel: rename `elicitationId` to `requestId`
- InlineElicitationRequest: accept `request: ElicitRequest['params']`;
  discriminate form vs URL mode on request shape instead of `mode` prop
- PendingClientRequests: unchanged (children-based wrapper)
- Delete local `SamplingTool` type
- Update all stories with real SDK type fixtures

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
cliffhall 2026-04-20 19:57:58 -04:00
commit c1a63cb37d
2 changed files with 326 additions and 299 deletions

View file

@ -1,4 +1,5 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import type { ElicitRequest } from "@modelcontextprotocol/sdk/types.js";
import { fn } from "storybook/test";
import { ElicitationFormPanel } from "./ElicitationFormPanel";
@ -10,7 +11,6 @@ const meta: Meta<typeof ElicitationFormPanel> = {
onSubmit: fn(),
onCancel: fn(),
serverName: "postgres-server",
message: "Please provide database connection details.",
values: {},
},
};
@ -18,49 +18,55 @@ const meta: Meta<typeof ElicitationFormPanel> = {
export default meta;
type Story = StoryObj<typeof ElicitationFormPanel>;
export const SimpleForm: Story = {
args: {
schema: {
type: "object",
properties: {
host: { type: "string", title: "Host" },
port: { type: "integer", title: "Port" },
database: { type: "string", title: "Database" },
},
required: ["host", "port"],
const dbRequest = {
message: "Please provide database connection details.",
requestedSchema: {
type: "object" as const,
properties: {
host: { type: "string" as const, title: "Host" },
port: { type: "string" as const, title: "Port" },
database: { type: "string" as const, title: "Database" },
},
},
} satisfies ElicitRequest["params"];
const sslRequest = {
message: "Please select your SSL mode preference.",
requestedSchema: {
type: "object" as const,
properties: {
sslMode: {
type: "string" as const,
title: "SSL Mode",
enum: ["disable", "require", "verify-full"],
},
},
},
} satisfies ElicitRequest["params"];
const deployRequest = {
message: "Please confirm the deployment.",
requestedSchema: {
type: "object" as const,
properties: {
environment: {
type: "string" as const,
title: "Environment",
enum: ["staging", "production"],
},
confirm: { type: "boolean" as const, title: "Confirm deployment" },
},
},
} satisfies ElicitRequest["params"];
export const SimpleForm: Story = {
args: { request: dbRequest },
};
export const WithEnums: Story = {
args: {
schema: {
type: "object",
properties: {
sslMode: {
type: "string",
title: "SSL Mode",
oneOf: [
{ const: "disable", title: "Disable" },
{ const: "require", title: "Require" },
{ const: "verify-full", title: "Verify Full" },
],
},
},
},
},
args: { request: sslRequest },
};
export const AllRequired: Story = {
args: {
schema: {
type: "object",
properties: {
host: { type: "string", title: "Host" },
port: { type: "integer", title: "Port" },
database: { type: "string", title: "Database" },
},
required: ["host", "port", "database"],
},
},
export const BooleanField: Story = {
args: { request: deployRequest },
};

View file

@ -1,12 +1,12 @@
import { Alert, Button, Divider, Group, Stack, Text } from "@mantine/core";
import type { JsonSchema } from "../SchemaForm/SchemaForm";
import type { ElicitRequest } from "@modelcontextprotocol/sdk/types.js";
import { SchemaForm } from "../SchemaForm/SchemaForm";
import type { JsonSchema } from "../SchemaForm/SchemaForm";
export interface ElicitationFormPanelProps {
message: string;
schema: JsonSchema;
values: Record<string, unknown>;
request: ElicitRequest["params"];
serverName: string;
values: Record<string, unknown>;
onChange: (values: Record<string, unknown>) => void;
onSubmit: () => void;
onCancel: () => void;
@ -26,19 +26,27 @@ function formatWarning(serverName: string): string {
}
export function ElicitationFormPanel({
message,
schema,
values,
request,
serverName,
values,
onChange,
onSubmit,
onCancel,
}: ElicitationFormPanelProps) {
const schema =
"requestedSchema" in request ? request.requestedSchema : undefined;
return (
<Stack gap="md">
<QuotedMessage>{formatQuoted(message)}</QuotedMessage>
<QuotedMessage>{formatQuoted(request.message)}</QuotedMessage>
<Divider />
<SchemaForm schema={schema} values={values} onChange={onChange} />
{schema && (
<SchemaForm
schema={schema as JsonSchema}
values={values}
onChange={onChange}
/>
)}
<Alert color="yellow" title="Warning">
{formatWarning(serverName)}
</Alert>