Aligned naming
This commit is contained in:
parent
159a049f94
commit
8f28ea791b
4 changed files with 54 additions and 51 deletions
|
|
@ -808,7 +808,7 @@ const App = () => {
|
||||||
const callTool = async (
|
const callTool = async (
|
||||||
name: string,
|
name: string,
|
||||||
params: Record<string, unknown>,
|
params: Record<string, unknown>,
|
||||||
meta?: Record<string, unknown>,
|
metadata?: Record<string, unknown>,
|
||||||
) => {
|
) => {
|
||||||
lastToolCallOriginTabRef.current = currentTabRef.current;
|
lastToolCallOriginTabRef.current = currentTabRef.current;
|
||||||
|
|
||||||
|
|
@ -824,7 +824,7 @@ const App = () => {
|
||||||
const mergedMeta = {
|
const mergedMeta = {
|
||||||
...metadata, // General metadata first
|
...metadata, // General metadata first
|
||||||
progressToken: progressTokenRef.current++,
|
progressToken: progressTokenRef.current++,
|
||||||
...(meta ?? {}), // Tool-specific metadata overrides
|
...(metadata ?? {}), // Tool-specific metadata overrides
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await sendMCPRequest(
|
const response = await sendMCPRequest(
|
||||||
|
|
@ -1148,11 +1148,11 @@ const App = () => {
|
||||||
callTool={async (
|
callTool={async (
|
||||||
name: string,
|
name: string,
|
||||||
params: Record<string, unknown>,
|
params: Record<string, unknown>,
|
||||||
meta?: Record<string, unknown>,
|
metadata?: Record<string, unknown>,
|
||||||
) => {
|
) => {
|
||||||
clearError("tools");
|
clearError("tools");
|
||||||
setToolResult(null);
|
setToolResult(null);
|
||||||
await callTool(name, params, meta);
|
await callTool(name, params, metadata);
|
||||||
}}
|
}}
|
||||||
selectedTool={selectedTool}
|
selectedTool={selectedTool}
|
||||||
setSelectedTool={(tool) => {
|
setSelectedTool={(tool) => {
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ const ToolsTab = ({
|
||||||
callTool: (
|
callTool: (
|
||||||
name: string,
|
name: string,
|
||||||
params: Record<string, unknown>,
|
params: Record<string, unknown>,
|
||||||
meta?: Record<string, unknown>,
|
metadata?: Record<string, unknown>,
|
||||||
) => Promise<void>;
|
) => Promise<void>;
|
||||||
selectedTool: Tool | null;
|
selectedTool: Tool | null;
|
||||||
setSelectedTool: (tool: Tool | null) => void;
|
setSelectedTool: (tool: Tool | null) => void;
|
||||||
|
|
@ -76,8 +76,8 @@ const ToolsTab = ({
|
||||||
const [params, setParams] = useState<Record<string, unknown>>({});
|
const [params, setParams] = useState<Record<string, unknown>>({});
|
||||||
const [isToolRunning, setIsToolRunning] = useState(false);
|
const [isToolRunning, setIsToolRunning] = useState(false);
|
||||||
const [isOutputSchemaExpanded, setIsOutputSchemaExpanded] = useState(false);
|
const [isOutputSchemaExpanded, setIsOutputSchemaExpanded] = useState(false);
|
||||||
const [isMetaExpanded, setIsMetaExpanded] = useState(false);
|
const [isMetadataExpanded, setIsMetadataExpanded] = useState(false);
|
||||||
const [metaEntries, setMetaEntries] = useState<
|
const [metadataEntries, setMetadataEntries] = useState<
|
||||||
{ id: string; key: string; value: string }[]
|
{ id: string; key: string; value: string }[]
|
||||||
>([]);
|
>([]);
|
||||||
const [hasValidationErrors, setHasValidationErrors] = useState(false);
|
const [hasValidationErrors, setHasValidationErrors] = useState(false);
|
||||||
|
|
@ -400,7 +400,7 @@ const ToolsTab = ({
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="h-6 px-2"
|
className="h-6 px-2"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setMetaEntries((prev) => [
|
setMetadataEntries((prev) => [
|
||||||
...prev,
|
...prev,
|
||||||
{
|
{
|
||||||
id:
|
id:
|
||||||
|
|
@ -419,30 +419,30 @@ const ToolsTab = ({
|
||||||
Add Pair
|
Add Pair
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{metaEntries.length === 0 ? (
|
{metadataEntries.length === 0 ? (
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
No meta pairs.
|
No metadata pairs.
|
||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{metaEntries.map((entry, index) => (
|
{metadataEntries.map((entry, index) => (
|
||||||
<div
|
<div
|
||||||
key={entry.id}
|
key={entry.id}
|
||||||
className="flex items-center gap-2 w-full"
|
className="flex items-center gap-2 w-full"
|
||||||
>
|
>
|
||||||
<Label
|
<Label
|
||||||
htmlFor={`meta-key-${entry.id}`}
|
htmlFor={`metadata-key-${entry.id}`}
|
||||||
className="text-xs shrink-0"
|
className="text-xs shrink-0"
|
||||||
>
|
>
|
||||||
Key
|
Key
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
id={`meta-key-${entry.id}`}
|
id={`metadata-key-${entry.id}`}
|
||||||
value={entry.key}
|
value={entry.key}
|
||||||
placeholder="e.g. requestId"
|
placeholder="e.g. requestId"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
setMetaEntries((prev) =>
|
setMetadataEntries((prev) =>
|
||||||
prev.map((m, i) =>
|
prev.map((m, i) =>
|
||||||
i === index ? { ...m, key: value } : m,
|
i === index ? { ...m, key: value } : m,
|
||||||
),
|
),
|
||||||
|
|
@ -451,18 +451,18 @@ const ToolsTab = ({
|
||||||
className="h-8 flex-1"
|
className="h-8 flex-1"
|
||||||
/>
|
/>
|
||||||
<Label
|
<Label
|
||||||
htmlFor={`meta-value-${entry.id}`}
|
htmlFor={`metadata-value-${entry.id}`}
|
||||||
className="text-xs shrink-0"
|
className="text-xs shrink-0"
|
||||||
>
|
>
|
||||||
Value
|
Value
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
id={`meta-value-${entry.id}`}
|
id={`metadata-value-${entry.id}`}
|
||||||
value={entry.value}
|
value={entry.value}
|
||||||
placeholder="e.g. 12345"
|
placeholder="e.g. 12345"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
setMetaEntries((prev) =>
|
setMetadataEntries((prev) =>
|
||||||
prev.map((m, i) =>
|
prev.map((m, i) =>
|
||||||
i === index ? { ...m, value } : m,
|
i === index ? { ...m, value } : m,
|
||||||
),
|
),
|
||||||
|
|
@ -475,7 +475,7 @@ const ToolsTab = ({
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
className="h-8 w-8 p-0 ml-auto shrink-0"
|
className="h-8 w-8 p-0 ml-auto shrink-0"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setMetaEntries((prev) =>
|
setMetadataEntries((prev) =>
|
||||||
prev.filter((_, i) => i !== index),
|
prev.filter((_, i) => i !== index),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -533,10 +533,12 @@ const ToolsTab = ({
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => setIsMetaExpanded(!isMetaExpanded)}
|
onClick={() =>
|
||||||
|
setIsMetadataExpanded(!isMetadataExpanded)
|
||||||
|
}
|
||||||
className="h-6 px-2"
|
className="h-6 px-2"
|
||||||
>
|
>
|
||||||
{isMetaExpanded ? (
|
{isMetadataExpanded ? (
|
||||||
<>
|
<>
|
||||||
<ChevronUp className="h-3 w-3 mr-1" />
|
<ChevronUp className="h-3 w-3 mr-1" />
|
||||||
Collapse
|
Collapse
|
||||||
|
|
@ -551,7 +553,9 @@ const ToolsTab = ({
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`transition-all ${
|
className={`transition-all ${
|
||||||
isMetaExpanded ? "" : "max-h-[8rem] overflow-y-auto"
|
isMetadataExpanded
|
||||||
|
? ""
|
||||||
|
: "max-h-[8rem] overflow-y-auto"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<JsonView data={selectedTool._meta} />
|
<JsonView data={selectedTool._meta} />
|
||||||
|
|
@ -565,17 +569,16 @@ const ToolsTab = ({
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsToolRunning(true);
|
setIsToolRunning(true);
|
||||||
const meta = metaEntries.reduce<Record<string, unknown>>(
|
const metadata = metadataEntries.reduce<
|
||||||
(acc, { key, value }) => {
|
Record<string, unknown>
|
||||||
if (key.trim() !== "") acc[key] = value;
|
>((acc, { key, value }) => {
|
||||||
return acc;
|
if (key.trim() !== "") acc[key] = value;
|
||||||
},
|
return acc;
|
||||||
{},
|
}, {});
|
||||||
);
|
|
||||||
await callTool(
|
await callTool(
|
||||||
selectedTool.name,
|
selectedTool.name,
|
||||||
params,
|
params,
|
||||||
Object.keys(meta).length ? meta : undefined,
|
Object.keys(metadata).length ? metadata : undefined,
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
setIsToolRunning(false);
|
setIsToolRunning(false);
|
||||||
|
|
|
||||||
|
|
@ -716,10 +716,10 @@ describe("ToolsTab", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Meta Display", () => {
|
describe("Metadata Display", () => {
|
||||||
const toolWithMeta = {
|
const toolWithMetadata = {
|
||||||
name: "metaTool",
|
name: "metaTool",
|
||||||
description: "Tool with meta",
|
description: "Tool with metadata",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object" as const,
|
type: "object" as const,
|
||||||
properties: {
|
properties: {
|
||||||
|
|
@ -732,10 +732,10 @@ describe("ToolsTab", () => {
|
||||||
},
|
},
|
||||||
} as unknown as Tool;
|
} as unknown as Tool;
|
||||||
|
|
||||||
it("should display meta section when tool has _meta", () => {
|
it("should display metadata section when tool has _meta", () => {
|
||||||
renderToolsTab({
|
renderToolsTab({
|
||||||
tools: [toolWithMeta],
|
tools: [toolWithMetadata],
|
||||||
selectedTool: toolWithMeta,
|
selectedTool: toolWithMetadata,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(screen.getByText("Meta:")).toBeInTheDocument();
|
expect(screen.getByText("Meta:")).toBeInTheDocument();
|
||||||
|
|
@ -744,10 +744,10 @@ describe("ToolsTab", () => {
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should toggle meta schema expansion", () => {
|
it("should toggle metadata schema expansion", () => {
|
||||||
renderToolsTab({
|
renderToolsTab({
|
||||||
tools: [toolWithMeta],
|
tools: [toolWithMetadata],
|
||||||
selectedTool: toolWithMeta,
|
selectedTool: toolWithMetadata,
|
||||||
});
|
});
|
||||||
|
|
||||||
// There might be multiple Expand buttons (Output Schema, Meta). We need the one within Meta section
|
// There might be multiple Expand buttons (Output Schema, Meta). We need the one within Meta section
|
||||||
|
|
@ -777,13 +777,13 @@ describe("ToolsTab", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Meta submission", () => {
|
describe("Metadata submission", () => {
|
||||||
it("should send meta values when provided", async () => {
|
it("should send metadata values when provided", async () => {
|
||||||
const callToolMock = jest.fn(async () => {});
|
const callToolMock = jest.fn(async () => {});
|
||||||
|
|
||||||
renderToolsTab({ selectedTool: mockTools[0], callTool: callToolMock });
|
renderToolsTab({ selectedTool: mockTools[0], callTool: callToolMock });
|
||||||
|
|
||||||
// Add a meta key/value pair
|
// Add a metadata key/value pair
|
||||||
const addPairButton = screen.getByRole("button", { name: /add pair/i });
|
const addPairButton = screen.getByRole("button", { name: /add pair/i });
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
fireEvent.click(addPairButton);
|
fireEvent.click(addPairButton);
|
||||||
|
|
@ -815,19 +815,19 @@ describe("ToolsTab", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("ToolResults Meta", () => {
|
describe("ToolResults Metadata", () => {
|
||||||
it("should display meta information when present in toolResult", () => {
|
it("should display metadata information when present in toolResult", () => {
|
||||||
const resultWithMeta = {
|
const resultWithMetadata = {
|
||||||
content: [],
|
content: [],
|
||||||
_meta: { info: "details", version: 2 },
|
_meta: { info: "details", version: 2 },
|
||||||
};
|
};
|
||||||
|
|
||||||
renderToolsTab({
|
renderToolsTab({
|
||||||
selectedTool: mockTools[0],
|
selectedTool: mockTools[0],
|
||||||
toolResult: resultWithMeta,
|
toolResult: resultWithMetadata,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Only ToolResults meta should be present since selectedTool has no _meta
|
// Only ToolResults metadata should be present since selectedTool has no _meta
|
||||||
expect(screen.getAllByText("Meta:")).toHaveLength(1);
|
expect(screen.getAllByText("Meta:")).toHaveLength(1);
|
||||||
expect(screen.getByText(/info/i)).toBeInTheDocument();
|
expect(screen.getByText(/info/i)).toBeInTheDocument();
|
||||||
expect(screen.getByText(/version/i)).toBeInTheDocument();
|
expect(screen.getByText(/version/i)).toBeInTheDocument();
|
||||||
|
|
|
||||||
|
|
@ -167,9 +167,9 @@ export function useConnection({
|
||||||
|
|
||||||
// Add metadata to the request if available, but skip for tool calls
|
// Add metadata to the request if available, but skip for tool calls
|
||||||
// as they handle metadata merging separately
|
// as they handle metadata merging separately
|
||||||
const shouldAddGeneralMeta =
|
const shouldAddGeneralMetadata =
|
||||||
request.method !== "tools/call" && Object.keys(metadata).length > 0;
|
request.method !== "tools/call" && Object.keys(metadata).length > 0;
|
||||||
const requestWithMeta = shouldAddGeneralMeta
|
const requestWithMetadata = shouldAddGeneralMetadata
|
||||||
? {
|
? {
|
||||||
...request,
|
...request,
|
||||||
params: {
|
params: {
|
||||||
|
|
@ -208,16 +208,16 @@ export function useConnection({
|
||||||
let response;
|
let response;
|
||||||
try {
|
try {
|
||||||
response = await mcpClient.request(
|
response = await mcpClient.request(
|
||||||
requestWithMeta,
|
requestWithMetadata,
|
||||||
schema,
|
schema,
|
||||||
mcpRequestOptions,
|
mcpRequestOptions,
|
||||||
);
|
);
|
||||||
|
|
||||||
pushHistory(requestWithMeta, response);
|
pushHistory(requestWithMetadata, response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorMessage =
|
const errorMessage =
|
||||||
error instanceof Error ? error.message : String(error);
|
error instanceof Error ? error.message : String(error);
|
||||||
pushHistory(requestWithMeta, { error: errorMessage });
|
pushHistory(requestWithMetadata, { error: errorMessage });
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue