Skip to content

Response time of tool call#1466

Merged
matteo8p merged 3 commits intoMCPJam:mainfrom
EsshUwU:response-time
Feb 18, 2026
Merged

Response time of tool call#1466
matteo8p merged 3 commits intoMCPJam:mainfrom
EsshUwU:response-time

Conversation

@EsshUwU
Copy link
Copy Markdown
Contributor

@EsshUwU EsshUwU commented Feb 15, 2026

Added response time header in the result panel

@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Feb 15, 2026
@chelojimenez
Copy link
Copy Markdown
Contributor

chelojimenez commented Feb 15, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@dosubot dosubot Bot added the enhancement New feature or request label Feb 15, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 15, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Execution timing was added end-to-end. The server records startedAtMs on each ExecutionContext and exposes durationMs in tool responses (completed, elicitation_required, task_created); a new getExecutionDurationMs(context) helper computes elapsed time. The client tracks responseDurationMs in ToolsTab, resets it across reset/execute/elicitation flows, and uses duration values from responses. ResultsPanel now accepts responseDurationMs, formats it as "N ms" or "N.NN s", and displays a Clock3 badge when present. Tests assert durationMs is present and non-negative.

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
mcpjam-inspector/client/src/components/ToolsTab.tsx (1)

546-546: ⚠️ Potential issue | 🟡 Minor

Elicitation response timing measures only the elicitation round-trip, not end-to-end.

Date.now() is passed as startedAt here, so durationMs in handleExecutionResponse will reflect only the respondToElicitationApi call — not the cumulative time from the original tool invocation. If the intent is to show total elapsed time, capture the original executionStartTime and thread it through the elicitation flow. If per-round-trip is the intent, this is fine but may surprise users.

🧹 Nitpick comments (2)
mcpjam-inspector/client/src/components/tools/ResultsPanel.tsx (1)

64-75: Time badge shares the "Valid" badge's green styling — consider a neutral variant.

Both the validation "Valid" badge (line 53) and this timing badge use bg-green-600. Green connotes success; timing is purely informational. A neutral color (e.g., bg-blue-600 or the default badge variant without color override) would avoid implying that a fast response is "good" and prevent visual conflation with validation status.

♻️ Suggested diff
              <Badge
                variant="default"
-               className="bg-green-600 hover:bg-green-700"
+               className="bg-blue-600 hover:bg-blue-700"
              >
mcpjam-inspector/client/src/components/ToolsTab.tsx (1)

485-494: Network errors bypass duration capture.

When executeToolApi throws (e.g., timeout, DNS failure), the catch block sets the error message but never calls setResponseDurationMs. The user sees an error with no timing info. Since executionStartTime is already in scope, capturing the duration here would provide useful diagnostic signal even on failures.

♻️ Suggested fix
     } catch (err) {
       const message = err instanceof Error ? err.message : "Unknown error";
       logger.error("Tool execution network error", {
         toolName: selectedTool,
         error: message,
       });
+      setResponseDurationMs(Date.now() - executionStartTime);
       setError(message);
     } finally {

Copy link
Copy Markdown
Contributor

@matteo8p matteo8p left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for putting up a PR for this. I would love to have a feature that shows execution time.

Right now, it's being calculated on the client side React, which I don't think is accurate because it also accounts for time it takes for the Hono server to send it to the client.

Instead, a more accurate way of measuring latency would be to calculate the duration on the Hono server endpoint in /api/mcp/tools/execute, then pass the duration to the client.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
mcpjam-inspector/server/routes/mcp/tools.ts (2)

304-353: getExecutionDurationMs(context) called after resetExecution — safe but worth a note.

resetExecution removes the context from the activeExecutions map and clears its queue/waiter, but does not mutate startedAtMs. Since you still hold a reference to the context object, the duration calculation remains valid. This is correct, though a brief inline comment would save future readers from the same mental double-take.


367-370: No durationMs in error responses — intentional?

The catch block delegates to jsonError, which has no access to context.startedAtMs. If timing data on failures would aid debugging (e.g., distinguishing timeouts from instant rejections), consider threading durationMs into the error payload. Not blocking — just a thought for observability.

mcpjam-inspector/client/src/components/ToolsTab.tsx (1)

408-437: responseDurationMs not set on the task_created path — acceptable since the view navigates away.

The window.location.hash = "tasks" redirect at line 435 means the ResultsPanel (which displays duration) is never rendered for this case. If the UX ever changes to remain on the tools panel after task creation, this would need revisiting.

Comment thread mcpjam-inspector/client/src/components/tools/ResultsPanel.tsx Outdated
Comment thread mcpjam-inspector/client/src/components/tools/ResultsPanel.tsx Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
mcpjam-inspector/client/src/components/ToolsTab.tsx (1)

408-437: ⚠️ Potential issue | 🟡 Minor

setResponseDurationMs not called in the task_created branch.

Every other branch (completed, elicitation_required, error) updates responseDurationMs, but task_created only logs the duration and then navigates away. If window.location.hash = "tasks" is ever removed or delayed, the state will be stale. A one-liner for symmetry:

Proposed fix
     if ("status" in response && response.status === "task_created") {
       const { task, modelImmediateResponse } = response;
+      setResponseDurationMs(durationMs);

       // Track the task locally so it appears in the Tasks tab
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mcpjam-inspector/client/src/components/ToolsTab.tsx` around lines 408 - 437,
The task_created branch fails to update the component state with the response
duration; call setResponseDurationMs(durationMs ?? undefined) before navigating
away so responseDurationMs matches other branches; modify the block handling
("status" in response && response.status === "task_created")—where task,
modelImmediateResponse, logger.info, and window.location.hash are used—to invoke
setResponseDurationMs with the same durationMs value used in the log just prior
to setting window.location.hash = "tasks".
mcpjam-inspector/server/routes/mcp/tools.ts (1)

304-353: ⚠️ Potential issue | 🟡 Minor

durationMs absent from error responses — intentional?

In the /execute catch block (Line 368) and /respond catch block (Line 434), jsonError does not include durationMs. Every success and elicitation path carries timing data, yet failures—arguably the most diagnostically interesting cases—do not. If the client wants to display duration regardless of outcome, this omission will surface as null.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mcpjam-inspector/server/routes/mcp/tools.ts` around lines 304 - 353, The
error responses from the /execute and /respond catch blocks omit timing info;
update the jsonError payloads (the calls to jsonError in the catch handlers for
these routes) to include durationMs: getExecutionDurationMs(context) so error
responses mirror success paths and elicitation responses; locate and modify the
catch blocks that call jsonError to add a durationMs field derived via
getExecutionDurationMs(context).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@mcpjam-inspector/client/src/components/ToolsTab.tsx`:
- Around line 408-437: The task_created branch fails to update the component
state with the response duration; call setResponseDurationMs(durationMs ??
undefined) before navigating away so responseDurationMs matches other branches;
modify the block handling ("status" in response && response.status ===
"task_created")—where task, modelImmediateResponse, logger.info, and
window.location.hash are used—to invoke setResponseDurationMs with the same
durationMs value used in the log just prior to setting window.location.hash =
"tasks".

In `@mcpjam-inspector/server/routes/mcp/tools.ts`:
- Around line 304-353: The error responses from the /execute and /respond catch
blocks omit timing info; update the jsonError payloads (the calls to jsonError
in the catch handlers for these routes) to include durationMs:
getExecutionDurationMs(context) so error responses mirror success paths and
elicitation responses; locate and modify the catch blocks that call jsonError to
add a durationMs field derived via getExecutionDurationMs(context).

matteo8p
matteo8p previously approved these changes Feb 18, 2026
Copy link
Copy Markdown
Contributor

@matteo8p matteo8p left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ship!

@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label Feb 18, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
mcpjam-inspector/server/routes/mcp/tools.ts (1)

367-370: Error responses from jsonError omit durationMs.

The client's handleExecutionResponse is wired to extract and display durationMs on error paths (ToolsTab.tsx, line 438), but jsonError never includes it. If you'd like duration visible even on failures, a small addition suffices:

Suggested enhancement
   } catch (error) {
     resetExecution(context, () => manager.clearElicitationHandler(serverId));
-    return jsonError(c, error, 500);
+    const details = serializeMcpError(error);
+    const status =
+      typeof (error as any)?.status === "number"
+        ? (error as any).status
+        : 500;
+    return c.json(
+      {
+        error: details.message as string,
+        mcpError: details,
+        durationMs: getExecutionDurationMs(context),
+      },
+      status,
+    );
   }

The same pattern applies to the /respond catch block (line 434–439).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mcpjam-inspector/server/routes/mcp/tools.ts` around lines 367 - 370, The
error responses returned by the catch blocks call jsonError without including
durationMs, so the client's handleExecutionResponse (ToolsTab.tsx) can't show
execution duration on failure; compute durationMs (e.g. Date.now() -
(context.executionStart ?? Date.now())) inside those catch blocks and pass it
into jsonError so the response includes { durationMs } (update the two locations
that call jsonError in the catch handlers that also call
resetExecution/manager.clearElicitationHandler and the /respond catch block).
mcpjam-inspector/client/src/components/ToolsTab.tsx (1)

406-434: responseDurationMs intentionally not set for task_created — worth a brief comment.

Since window.location.hash = "tasks" navigates the user away immediately, omitting setResponseDurationMs is correct. A one-line comment clarifying "no need to set duration — navigating away" would prevent a future contributor from adding it "just to be consistent."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mcpjam-inspector/client/src/components/ToolsTab.tsx` around lines 406 - 434,
Add a one-line comment explaining why response duration (e.g.,
responseDurationMs / durationMs) is intentionally not set for the "task_created"
branch to avoid future confusion; locate the block handling response.status ===
"task_created" (inside the same conditional that calls trackTask and logger.info
and then sets window.location.hash = "tasks") and insert a brief comment like
"no need to set response duration because we navigate away immediately"
immediately before the navigation/return so future contributors understand the
omission.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@mcpjam-inspector/client/src/components/ToolsTab.tsx`:
- Around line 406-434: Add a one-line comment explaining why response duration
(e.g., responseDurationMs / durationMs) is intentionally not set for the
"task_created" branch to avoid future confusion; locate the block handling
response.status === "task_created" (inside the same conditional that calls
trackTask and logger.info and then sets window.location.hash = "tasks") and
insert a brief comment like "no need to set response duration because we
navigate away immediately" immediately before the navigation/return so future
contributors understand the omission.

In `@mcpjam-inspector/server/routes/mcp/tools.ts`:
- Around line 367-370: The error responses returned by the catch blocks call
jsonError without including durationMs, so the client's handleExecutionResponse
(ToolsTab.tsx) can't show execution duration on failure; compute durationMs
(e.g. Date.now() - (context.executionStart ?? Date.now())) inside those catch
blocks and pass it into jsonError so the response includes { durationMs }
(update the two locations that call jsonError in the catch handlers that also
call resetExecution/manager.clearElicitationHandler and the /respond catch
block).

Copy link
Copy Markdown
Contributor

@matteo8p matteo8p left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ship

@matteo8p matteo8p merged commit bc55e15 into MCPJam:main Feb 18, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request lgtm This PR has been approved by a maintainer size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants