Commit graph inspector/client/src/components/ToolsTab.tsx
Author SHA1 Message Date
cliffhall
f64a7ea6e3 Fix review issues from Claude's code review
- Default taskSupport fallback to "forbidden" per MCP spec (was "optional")
- Fix import path to use @/ alias consistently
- Fix misleading "type guard" comment on getTaskSupport
- Extract getTaskSupport to a variable to avoid duplicate calls in render
- Export ExtendedTool and import in tests instead of duplicating

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:15:53 -05:00
Cliff Hall
4bcffe456b
Merge branch 'main' into hide-run-as-task-if-not-supported 2026-02-23 10:32:22 -05:00
Cliff Hall
49bcbbe276
Merge branch 'main' into fix/apps-tool-result 2026-02-16 15:36:01 -05:00
Ruben Casas
a31ae3e767 feat call tool result from tools tab 2026-02-16 16:44:33 +00:00
Cliff Hall
6d18cf3711
Merge branch 'main' into hide-run-as-task-if-not-supported 2026-02-14 10:53:28 -05:00
Ola Hungerford
d1824ca3f9
Merge branch 'main' into feature/tool-annotations-display 2026-02-07 16:44:55 -07:00
olaservo
43426f3c8e feat(client): use consistent slate styling for annotation badges
Replace value-based green/gray badge coloring with uniform slate
colors, relying on checkmark/cross icons and opacity to convey state.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 10:49:51 -07:00
cliffhall
96b1b586f9 Manage display of "Run as Task" checkbox on Tools Tab
* In ToolsTab.tsx
  - define ExtendedTool interface for augmenting with execution, meta, icons
  - in hasMeta function,
    - cast tool as ExtendedTool
  - add getTaskSupport function
    - returns forbidden if input is not a tool
    - returns the setting of execution.taskSupport if set and valid
    - returns optional otherwise
    - in useEffect map callback
      - set runAsTask to true if getTaskSupport returns "required", else false
    - in IconDisplay instances cast tool as ExtendedTool instead of as WithIcons
    - hide "Run as Task" checkbox if getTaskSupport returns "forbidden" for the selected tool
    - disable the "Run as Task" checkbox if getTaskSupport returns "required"
* In ToolsTab.test.tsx
  - added unit test
    - "should show/hide/disable run-as-task checkbox based on taskSupport"
      - tests checkbox checked and disabled states for "forbidden", "required", and "optional" states
2026-02-06 16:30:23 -05:00
claude[bot]
d73fb1c30f fix: display tool title field in Inspector UI
Display the MCP tool 'title' field when present in the Inspector UI, with fallback to 'name' when not present. This aligns with the MCP specification where 'title' is the human-friendly display name and 'name' is the programmatic identifier.

Changes:
- Updated tool list rendering to display tool.title || tool.name
- Updated tool details header to display selectedTool.title || selectedTool.name

Fixes #1053

Co-authored-by: Ola Hungerford <olaservo@users.noreply.github.com>
2026-02-04 12:36:30 +00:00
Murat Dzhulkuttiev
885c8bc732
fix(client): circular function calls leads to memory leak (#1049)
* fix(client): circular function call leads to memory leak

* allow children validation
2026-02-03 10:50:50 -07:00
olaservo
1cadda06c0 feat(client): add MCP spec descriptions to annotation tooltips
Enhance tooltips to include descriptions from the MCP specification:
- Read-only: Tool does not modify its environment
- Destructive: Tool may perform destructive updates (delete/overwrite data)
- Idempotent: Calling repeatedly with same args has no additional effect
- Open-world: Tool may interact with external entities beyond its local environment

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 07:03:21 -07:00
olaservo
dad17c6cc2 feat(client): show all tool annotations with explicit/implied states
Display all 4 tool annotation badges (Read-only, Destructive, Idempotent,
Open-world) for every tool, showing:
- ✓/✗ prefix to indicate true/false value
- Green badge for true, gray for false
- Solid border for explicitly set values
- Dashed border + dimmed for implied defaults
- Tooltip explaining if value is explicit or implied

Follows MCP spec defaults:
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: true

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 06:57:56 -07:00
olaservo
3549220acc feat(client): display tool annotation badges in Tools tab
Add visual badges to show tool annotations (readOnlyHint, destructiveHint,
idempotentHint, openWorldHint) when a tool is selected. Badges appear below
the tool description with color-coded styling:
- Read-only: blue
- Destructive: red
- Idempotent: gray outline
- Open-world: purple

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 06:09:08 -07:00
Cliff Hall
7ef0971c81
Add Tasks support (#1013)
* ### client/src/App.tsx

- Imports:
  - Added: `Task` and `GetTaskResultSchema` to the same import block.
  - UI Icons: Added `ListTodo` from `lucide-react` to the icon imports.
  - Components: Added `TasksTab` import beside `ToolsTab`.
  - Config utils: Added `getMCPTaskTtl` to the config utils import block.

- State additions:
  - `const [tasks, setTasks] = useState<Task[]>([]);`
  - Extended `errors` state to include a `tasks` key: `tasks: null,`
  - `const [selectedTask, setSelectedTask] = useState<Task | null>(null);`
  - `const [isPollingTask, setIsPollingTask] = useState(false);`
  - `const [nextTaskCursor, setNextTaskCursor] = useState<string | undefined>();`

- Hook: `useConnection({...})` return value usage extended
  - Added destructured functions: `cancelTask: cancelMcpTask` and `listTasks: listMcpTasks` from the custom hook.

- Notification handling:
  - In `onNotification`, added:
    - If `method === "notifications/tasks/list_changed"`, call `listTasks()` (voided).
    - If `method === "notifications/tasks/status"`, treat `notification.params` as a `Task` and update `tasks` state: replace if exists by `taskId`, otherwise prepend. Also update `selectedTask` if it’s the same `taskId`.

- Tab routing:
  - When computing valid tabs, added `tasks` when server declares capability: `...(serverCapabilities?.tasks ? ["tasks"] : []),`
  - When choosing a default tab, added a branch to fall back to `"tasks"` if neither resources/prompts/tools are present but tasks are.

- Effect for Tasks tab:
  - When `mcpClient` is connected and `activeTab === "tasks"`, invoke `listTasks()`.

- Tools → task-augmented calls integration in `callTool`:
  - Parameter signature supports `runAsTask?: boolean` (already present in this file), but now:
    - If `runAsTask` is true, augment the `tools/call` request’s `params` with a `task` object: `{ task: { ttl: getMCPTaskTtl(config) } }`.
  - Use a permissive result schema for tool call: `sendMCPRequest(request, z.any(), "tools")` to avoid version-mismatch schema issues.
  - Task reference detection introduced:
    - `isTaskResult` helper checks for a nested `task` object with `taskId` (i.e., `response.task.taskId`).
  - When task is detected:
    - Set `isPollingTask(true)`.
    - Immediately set a temporary `toolResult` that includes text content “Task created: … Polling for status…” and `_meta` with `"io.modelcontextprotocol/related-task": { taskId }`.
    - Start a polling loop:
      - Delay 1s between polls.
      - Call `tasks/get` with `GetTaskResultSchema` for status.
      - If status is `completed`: call `tasks/result` with `z.any()` to retrieve the final result and set it as `toolResult`; call `listTasks()`.
      - If status is `failed` or `cancelled`: set an error `toolResult` content that includes the status + `statusMessage`; call `listTasks()`.
      - Else (still running): update `toolResult` content with current `status`/`statusMessage` and preserve `_meta` related-task.
    - After loop, set `isPollingTask(false)`.
  - When not a task response, set `toolResult` directly from response (cast to `CompatibilityCallToolResult`).

- Tasks list + cancel helpers in App:
  - `listTasks`: uses `listMcpTasks(nextTaskCursor)` from the hook, updates `tasks`, `nextTaskCursor`, and clears `errors.tasks`.
  - `cancelTask`: calls `cancelMcpTask(taskId)`, updates `tasks` array by `taskId`, updates `selectedTask` if it matches, and clears `errors.tasks`.

- UI integration:
  - Added a `TabsTrigger` for “Tasks” with `<ListTodo />` icon, disabled unless server supports tasks.
  - Added `<TasksTab />` to the main `TabsContent` block, passing: `tasks`, `listTasks`, `clearTasks`, `cancelTask`, `selectedTask`, `setSelectedTask`, `error={errors.tasks}`, `nextCursor={nextTaskCursor}`.
  - Passed `isPollingTask={isPollingTask}` and `toolResult` into `ToolsTab` so the Tools tab can show the live “Polling Task…” state and block reruns while polling.

Note: The raw diff is long; the key hunks align with the above bullet points (imports, state, notifications, tab wiring, request augmentation, polling loop, UI additions).

---

### client/src/components/ToolsTab.tsx

- Props shape changed:
  - Added `isPollingTask?: boolean` prop in the destructured props and in the prop types.
  - The `callTool` callback signature is now `(name, params, metadata?, runAsTask?) => Promise<void>` (runAsTask added earlier; test updates elsewhere reflect this).

- Local state additions:
  - `const [runAsTask, setRunAsTask] = useState(false);`

- Reset behavior:
  - When switching tools (`useEffect` on `selectedTool`), reset `runAsTask(false)`.
  - When clearing the list in `ListPane.clearItems`, also call `setRunAsTask(false)`.

- UI additions:
  - New checkbox control block to toggle “Run as task”:
    - Checkbox `id="run-as-task"`, bound to `runAsTask`, with `onCheckedChange` → `setRunAsTask(checked)`.
    - Label “Run as task”.
  - Run button disabling conditions expanded to include `isPollingTask`.
  - Run button text shows spinner with conditional label:
    - If `isToolRunning || isPollingTask` → show spinner and text `isPollingTask ? "Polling Task..." : "Running..."`.

- Call invocation change:
  - When clicking “Run Tool”, the `callTool` is invoked with `(selectedTool.name, params, metadata?, runAsTask)`.

- ToolResults relay:
  - Passes `isPollingTask` to `<ToolResults />`.

---

### client/src/components/ToolResults.tsx

- Props shape changed:
  - Added optional prop: `isPollingTask?: boolean`.

- Task-running banner logic:
  - Extracts related task from the tool result’s `_meta["io.modelcontextprotocol/related-task"]` if present.
  - Computes `isTaskRunning` as `isPollingTask ||` a text-heuristic against `structuredResult.content` entries that contain text like “Polling” or “Task status”.
  - Header “Tool Result:” now conditionally shows:
    - `Error` (red) if `isError` is true, else
    - `Task Running` (yellow) if `isTaskRunning`, else
    - `Success` (green).

No other changes to validation or rendering of content blocks.

---

### client/src/components/TasksTab.tsx (new file)

- A brand new tab to list and inspect tasks.
- Key elements:
  - Imports `Task` type and multiple status icons.
  - `TaskStatusIcon` component maps task `status` to an icon and color.
  - Main `TasksTab` props: `tasks`, `listTasks`, `clearTasks`, `cancelTask`, `selectedTask`, `setSelectedTask`, `error`, `nextCursor`.
  - Left column (`ListPane`): lists tasks, shows status icon, `taskId`, `status`, and last update time; button text changes to “List More Tasks” if `nextCursor` present; disables button if no cursor and list non-empty.
  - Right column:
    - Shows error `Alert` if `error` prop provided.
    - If a task is selected: header with `Task Details`, a Cancel button when `status === "working"` (shows a spinner while cancelling), and a grid of task fields: Status (with colored label and icon), Last Updated, Created At, TTL (shows “Infinite” if `ttl === null`, otherwise shows numeric with `s` suffix), optional Status Message, and full task JSON via `JsonView`.
    - If no task is selected: centered empty state with a “Refresh Tasks” button.

---

### client/src/lib/hooks/useConnection.ts

- Imports added from `@modelcontextprotocol/sdk/types.js`:
  - `ListTasksResultSchema`, `CancelTaskResultSchema`, `TaskStatusNotificationSchema`.

- Client capabilities on `connect`:
  - Added `tasks: { list: {}, cancel: {} }` into the `clientCapabilities` passed to `new Client(...)`.

- Notification handling setup:
  - The hook’s notification schema registration now includes the `TaskStatusNotificationSchema` in the `setNotificationHandler` list so the app receives `notifications/tasks/status`.

- New hook functions:
  - `cancelTask(taskId: string)` sends `tasks/cancel` with `CancelTaskResultSchema`.
  - `listTasks(cursor?: string)` sends `tasks/list` with `ListTasksResultSchema`.

- Exports:
  - Returned object now includes `cancelTask` and `listTasks`.

---

### client/src/utils/configUtils.ts

- Added a new getter:
  - `export const getMCPTaskTtl = (config: InspectorConfig): number => { return config.MCP_TASK_TTL.value as number; };`

---

### client/src/lib/configurationTypes.ts

- `InspectorConfig` type extended with a new item:
  - `MCP_TASK_TTL: ConfigItem;`
  - Includes descriptive JSDoc about default TTL in milliseconds for newly created tasks.

---

### client/src/lib/constants.ts

- `DEFAULT_INSPECTOR_CONFIG` extended with a default for task TTL:
  - Key: `MCP_TASK_TTL`
  - Label: `"Task TTL"`
  - Description: `"Default Time-to-Live (TTL) in milliseconds for newly created tasks"`
  - Default `value: 60000`
  - `is_session_item: false`

---

### client/src/components/__tests__/ToolsTab.test.tsx

- Expectations updated due to new `callTool` signature (4th arg `runAsTask`). Everywhere the test asserts a `callTool` invocation, an additional trailing `false` argument was added to reflect the default state when the box isn’t checked.
  - Examples of added trailing `false` at various assertion points (line offsets from diff): after calls around prior lines 132, 157, 193, 236, 257, 279, 297, 818, 1082 (now passing 4 arguments: name, params, metadata-or-undefined, false).

---

### Additional notes

- The Tasks feature is wired end-to-end:
  - Client capability declaration (list/cancel)
  - Notification handler for `notifications/tasks/status`
  - Tools call augmentation with `task` `{ ttl }`
  - Polling loop using `tasks/get` and `tasks/result`
  - UI feedback in Tools and dedicated Tasks tab
  - Configurable TTL via new config item and getter

* Fix issue where displayed task on task tab was not updated when task completes, leaving the cancel task button available.

* Handle button the same when input_requred or working state

* ### What changed
- Added **receiver-side (client-side) Tasks support** to the Inspector client for task-augmented **server → client** requests.
- When the server sends `sampling/createMessage` or `elicitation/create` with `params.task`, the client now:
  - Creates a local task and immediately returns a `CreateTaskResult` (`{ task: ... }`).
  - Runs the underlying user-driven flow asynchronously.
  - Updates task state to `completed` / `failed` and makes the final payload available via `tasks/result`.
- Implemented server polling handlers backed by the local task store:
  - `tasks/get`
  - `tasks/result` (blocks until payload is ready)
  - `tasks/list`
  - `tasks/cancel`
- Advertises task-augmented request capabilities via `capabilities.tasks.requests.sampling.createMessage` and `capabilities.tasks.requests.elicitation.create` when the corresponding callbacks are provided.
- Emits best-effort `notifications/tasks/status` updates as local task status changes.

* Fix review requests.

* In the ToolsTab, when a tool call results in an elicitation request, the app automatically switches to the elicitation tab, and once submitted, switches back to the ToolsTab to view the result of the tool call.

However, when a tool call results in a sampling request, it does not switch automatically to the SamplingTab and when the sampling request form is submitted it does not automatically switch back to the ToolsTab to view the result of the tool call.

These changes make the sampling use case work like the elicitation one. Tests were added.
2026-01-22 21:40:59 -07:00
Jesse Lumarie
a114db85bd mcp: update resources + icon alignment 2025-11-24 13:04:05 -07:00
Cliff Hall
35286a24c6
Merge branch 'main' into jesselumarie/test-SEP-974 2025-11-19 16:21:26 -05:00
Konstantin Konstantinov
a5d5593c97
Merge branch 'main' into meta_properies_in_tools 2025-11-15 01:34:22 +02:00
Konstantin Konstantinov
a45247a4f2
add validations against spec, add reserved metadata key validations 2025-11-15 01:26:13 +02:00
Cliff Hall
54484e7e8e
Merge branch 'main' into fix-default-null-array-input 2025-10-30 12:04:47 -04:00
Cliff Hall
3044d8f14c
Merge branch 'main' into meta_properies_in_tools 2025-10-30 11:55:46 -04:00
cliffhall
37acee9283 Handle nullable arrays in tool inputSchemas
* In DynamicJsonForm.tsx
  - In debouncedUpdateParent, formatJson, and validateJson,
    - when trimming the JSON value, use ?.trim() in case the field is null

* In jsonUtils.ts
  - in tryParseJson
    - use ?.trim() in case the field is null

* In schemaUtils.ts
  - in normalizeUnionType
    - add condition to handle the case where there is an anyOf with array or null as options

* In ToolsTab.tsx
  - for nullable fields, in null checkbox, in onCheckedChange handler
    - when not checked, if prop type is array, set to undefined (empty input field that can be edited rather than the word "null" as the default could provide

Fixes #846
2025-10-29 14:28:49 -04:00
lorenzo.neumann
8f28ea791b Aligned naming 2025-10-27 12:22:49 +01:00
lorenzo.neumann
159a049f94 Renamed mata schema to only meta 2025-10-27 12:09:44 +01:00
yanOO1497
fb7fae1436 fix: resolve $ref references in tool input schema properties 2025-10-25 17:02:25 +08:00
lorenzo.neumann
caa1a2e1f5 Merge remote-tracking branch 'origin2/main' into meta_properies_in_tools 2025-10-24 15:04:38 +02:00
lorenzo.neumann
b9963014a0 Fixed naming 2025-10-24 14:02:41 +02:00
Cliff Hall
a45a291919
Merge branch 'main' into jesselumarie/test-SEP-974 2025-10-20 15:19:29 -04:00
olaservo
acf30b077a Handle tri state nullable boolean in null checkbox 2025-10-19 11:01:37 -07:00
olaservo
93fc8cc97e Support tri-state nullable boolean 2025-10-19 05:47:33 -07:00
Jesse Lumarie
9dc3b748a8 mcp: add icons 2025-10-18 20:42:46 -06:00
Greg Saab
3adddfb9f1 merge 2025-10-10 19:08:16 -04:00
Cliff Hall
ece0e27ad4
Merge pull request #823 from ksinder/main
`ToolsTab`: truncate longer tool descriptions for nicer rendering
2025-10-10 14:23:39 -04:00
Cliff Hall
8bfd164358
Merge branch 'main' into add-dropdowns-for-enums 2025-10-10 14:11:40 -04:00
anilkumar
653e0f87d1 fix: prevent long unbreakable words in alert messages from overflowing container 2025-10-09 00:03:32 +05:30
Greg Saab
6facce3fc1 conditionally render the checkbox 2025-10-08 13:04:50 -04:00
Greg Saab
3fd0feb75a if a field is nullable, provide a means of specifying null 2025-10-08 12:22:47 -04:00
olaservo
01adbe5f10 Merge branch 'main' into ksinder/main
Resolved conflicts in ToolsTab.tsx by combining:
- Error alert display from main
- Description styling improvements from PR #823 (whitespace-pre-wrap, max-h-48, overflow-y-auto)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 22:30:03 -07:00
olaservo
3d3a79e109 Add enum parameter support in ToolsTab component and corresponding tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 20:57:42 -07:00
lorenzo.neumann
78c56b350b Fixed failing tests 2025-10-02 09:36:56 +02:00
lorenzo.neumann
7624eefc1e Merge remote-tracking branch 'origin2/main' into meta_properies_in_tools 2025-10-02 09:26:18 +02:00
olaservo
5abf1d5052 Clear validation errors after tool execution and adjust error display in ToolsTab 2025-09-27 22:09:44 -07:00
olaservo
69c294c0ae Let servers validate invalid input 2025-09-27 21:05:00 -07:00
olaservo
2b49ab7aaf Merge remote-tracking branch 'upstream/main' into omit-optional-empty-strings-updated 2025-09-27 20:53:06 -07:00
olaservo
45a1bde010 Refactor ToolsTab to handle cleared fields as undefined instead of empty strings; update tests for new behavior 2025-09-27 20:21:03 -07:00
olaservo
754c97956f Omit optional fields with empty strings from tool calls 2025-09-24 07:01:04 -07:00
Nandha Reddy
8d149b2673 Add real-time JSON validation and prevent tool execution on invalid input 2025-09-24 00:25:06 +10:00
Nandha Reddy
119922b8b5
Merge branch 'main' into fix/validate-json-on-tool-execution 2025-09-23 20:10:59 +10:00
Kenneth Sinder
5bec008b81 ToolsTab: truncate tool descriptions for nicer rendering 2025-09-21 10:05:40 -07:00
Alejandro Borbolla
16e0077090
fix: Assess PR comments (typo) 2025-09-01 18:31:52 +02:00
lorenzo.neumann
77a1b426a4 Fixed spacing 2025-09-01 11:07:14 +02:00