basic-host: filter app-only tools, prioritize UI tools (#262)
* basic-host: filter non-ui tools * basic-host: filter app-only tools, prioritize UI tools - Filter out tools with visibility: ['app'] from host tool list - Sort tools to show UI-enabled tools first, then alphabetically - Add local isToolVisibleToModel helper in basic-host
This commit is contained in:
parent
bd892b6ce4
commit
8fa2961ffc
1 changed files with 35 additions and 4 deletions
|
|
@ -1,9 +1,30 @@
|
|||
import { getToolUiResourceUri, McpUiToolMetaSchema } from "@modelcontextprotocol/ext-apps/app-bridge";
|
||||
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
||||
import { Component, type ErrorInfo, type ReactNode, StrictMode, Suspense, use, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { callTool, connectToServer, hasAppHtml, initializeApp, loadSandboxProxy, log, newAppBridge, type ServerInfo, type ToolCallInfo, type ModelContext, type AppMessage } from "./implementation";
|
||||
import styles from "./index.module.css";
|
||||
|
||||
/**
|
||||
* Check if a tool is visible to the model (not app-only).
|
||||
* Tools with `visibility: ["app"]` should not be shown in tool lists.
|
||||
*/
|
||||
function isToolVisibleToModel(tool: { _meta?: Record<string, unknown> }): boolean {
|
||||
const result = McpUiToolMetaSchema.safeParse(tool._meta?.ui);
|
||||
if (!result.success) return true; // default: visible to model
|
||||
const visibility = result.data.visibility;
|
||||
if (!visibility) return true; // default: visible to model
|
||||
return visibility.includes("model");
|
||||
}
|
||||
|
||||
/** Compare tools: UI-enabled first, then alphabetically by name. */
|
||||
function compareTools(a: Tool, b: Tool): number {
|
||||
const aHasUi = !!getToolUiResourceUri(a);
|
||||
const bHasUi = !!getToolUiResourceUri(b);
|
||||
if (aHasUi && !bHasUi) return -1;
|
||||
if (!aHasUi && bHasUi) return 1;
|
||||
return a.name.localeCompare(b.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract default values from a tool's JSON Schema inputSchema.
|
||||
|
|
@ -80,7 +101,13 @@ function CallToolPanel({ serversPromise, addToolCall }: CallToolPanelProps) {
|
|||
const [selectedTool, setSelectedTool] = useState("");
|
||||
const [inputJson, setInputJson] = useState("{}");
|
||||
|
||||
const toolNames = selectedServer ? Array.from(selectedServer.tools.keys()) : [];
|
||||
// Filter out app-only tools, prioritize tools with UIs
|
||||
const toolNames = selectedServer
|
||||
? Array.from(selectedServer.tools.values())
|
||||
.filter((tool) => isToolVisibleToModel(tool))
|
||||
.sort(compareTools)
|
||||
.map((tool) => tool.name)
|
||||
: [];
|
||||
|
||||
const isValidJson = useMemo(() => {
|
||||
try {
|
||||
|
|
@ -93,10 +120,14 @@ function CallToolPanel({ serversPromise, addToolCall }: CallToolPanelProps) {
|
|||
|
||||
const handleServerSelect = (server: ServerInfo) => {
|
||||
setSelectedServer(server);
|
||||
const [firstTool] = server.tools.keys();
|
||||
setSelectedTool(firstTool ?? "");
|
||||
// Filter out app-only tools, prioritize tools with UIs
|
||||
const visibleTools = Array.from(server.tools.values())
|
||||
.filter((tool) => isToolVisibleToModel(tool))
|
||||
.sort(compareTools);
|
||||
const firstTool = visibleTools[0]?.name ?? "";
|
||||
setSelectedTool(firstTool);
|
||||
// Set input JSON to tool defaults (if any)
|
||||
setInputJson(getToolDefaults(server.tools.get(firstTool ?? "")));
|
||||
setInputJson(getToolDefaults(server.tools.get(firstTool)));
|
||||
};
|
||||
|
||||
const handleToolSelect = (toolName: string) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue