Commit graph inspector/client/src/components/ToolsTab.tsx
Author SHA1 Message Date
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
Ola Hungerford
6505468fbe
Merge branch 'main' into alejandro.borbolla/copy-input 2025-08-31 20:38:40 -07:00
lorenzo.neumann
1c406eafbd Added UI to provide additional _meta values 2025-08-29 15:52:31 +02:00
olaservo
8ce1bbd346 Resolve merge conflicts in DynamicJsonForm.tsx and ToolsTab.tsx
- Merged JSON validation functionality from PR branch with enhanced form features from main
- Preserved validateJson method and DynamicJsonFormRef interface for tool validation
- Added support for oneOf schemas, enum dropdowns, and enhanced string field types
- Integrated meta display functionality and resource content props
- Maintained JSON validation before tool execution to prevent invalid data submission
2025-08-05 05:48:04 -07:00
Mats Julius Funke
f73d8e6f8a
fix: support FastMCP union types in tool parameter forms 2025-08-02 15:59:45 +02:00
Alejandro Borbolla
5bbd9f736d
feat: Copy the input parameters of tools 2025-07-31 17:41:33 +02:00
Eric Horacek
444c6b5704 Fix lint 2025-07-13 18:25:53 -07:00
Eric Horacek
5dd661513b feat: Add _meta field support to tool UI
Shows [_meta](https://modelcontextprotocol.io/specification/2025-06-18/basic/index#meta) fields if present when listing and calling tools
2025-07-13 14:33:39 -07:00
Nandha Reddy
0dc7a50218
feat: Enhance ResourceLinkView with expandable resource content view
Add click-to-expand functionality for inline resource content display
2025-07-09 05:15:46 +10:00
Nandha Reddy
236dee0dca
Fix code style 2025-07-07 13:53:10 +10:00
Nandha Reddy
98580cd5a9
Merge branch 'main' into fix/validate-json-on-tool-execution 2025-07-01 17:25:13 +10:00
Mark Anthony Cianfrani
9eb5e7b8c2
Merge branch 'main' into main 2025-06-27 20:06:31 -04:00