opencode icon indicating copy to clipboard operation
opencode copied to clipboard

[FEATURE]: MCP Tool Output

Open xpcmdshell opened this issue 3 months ago • 5 comments

Feature hasn't been suggested before.

  • [x] I have verified this feature I'm about to request hasn't been suggested before.

Describe the enhancement you want to request

Description:

MCP tool outputs are not displayed in the TUI. When using any MCP server, you only see the tool name and input parameters, but never the actual output/result. I often times want to see what the tool actually returned. You end up having to rely on manually asking the model to duplicate all the output for you.

Root cause:

GenericTool in packages/opencode/src/cli/cmd/tui/routes/session/index.tsx (lines 1515-1520) ignores props.output:

  function GenericTool(props: ToolProps<any>) {
    return (
      <ToolTitle icon="⚙" fallback="Writing command..." when={true}>
        {props.tool} {input(props.input)}
      </ToolTitle>
    )
  }

Built-in tools like bash and patch render their output, but MCP tools fall back to GenericTool which discards it.

Suggested fix:

Add output rendering to GenericTool, gated by the existing tool_details_visibility setting (or a new config option):

  function GenericTool(props: ToolProps<any>) {
    const { theme } = useTheme()
    return (
      <>
        <ToolTitle icon="⚙" fallback="Writing command..." when={true}>
          {props.tool} {input(props.input)}
        </ToolTitle>
        <Show when={props.output}>
          <box>
            <text fg={theme.text}>{props.output?.trim()}</text>
          </box>
        </Show>
      </>
    )
  }

This follows the same pattern used by the patch tool renderer (lines 1838-1856).

Ideally this would be configurable - either via the existing tool_details keybind toggle, or a separate config option like tui.mcp_tool_output: true/false.

Impact:

Anyone using MCP servers cannot see tool results in the TUI, making it difficult to understand what the model is working with.

xpcmdshell avatar Jan 01 '26 22:01 xpcmdshell

This issue might be a duplicate of existing issues. Please check:

  • #5358: [FEATURE]: Tool output preview - Requests ability to see tool output (webfetch, etc.) via a preview dialog
  • #3790: [FEATURE]: Have the ability to show tool raw output in OpenCode UI - Requests the ability to see custom tool output in the UI
  • #3065: Bug: Tool Calls are not shown directly if tool details are toggled off - Related issue about tool visibility/details toggle
  • #1736: TUI: Bash tool calls only show description, not actual command - Similar issue about tool information not being displayed

Feel free to ignore if your request has specific requirements not addressed by these issues.

github-actions[bot] avatar Jan 01 '26 22:01 github-actions[bot]

I searched all over but couldn't find the relevant settings, which is very important for us (agent development).

ai-llt avatar Jan 05 '26 04:01 ai-llt

I tried to find the most standard way to write the MCP format, but still couldn't view the return content from other tools.

ai-llt avatar Jan 05 '26 04:01 ai-llt

Could it be relevant that GitHub MCP get_file_contents only returns "successfully downloaded" without actually returning actual file contents to the model?

kostrse avatar Jan 10 '26 19:01 kostrse

I think it would be better if the output is collapsible (just like the output of the bash tool). Some tools return long output and it becomes cluttered when output is displayed directly.

I've tested the following version:

function GenericTool(props: ToolProps<any>) {
  const { theme } = useTheme()
  const output = createMemo(() => props.output?.trim() ?? "")
  const [expanded, setExpanded] = createSignal(false)
  const lines = createMemo(() => output().split("\n"))
  const maxLines = 3
  const overflow = createMemo(() => lines().length > maxLines)
  const limited = createMemo(() => {
    if (expanded() || !overflow()) return output()
    return [...lines().slice(0, maxLines), "…"].join("\n")
  })

  return (
    <Show
      when={props.output}
      fallback={
        <InlineTool icon="⚙" pending="Writing command..." complete={true} part={props.part}>
          {props.tool} {input(props.input)}
        </InlineTool>
      }
    >
      <BlockTool
        title={`# ${props.tool} ${input(props.input)}`}
        part={props.part}
        onClick={overflow() ? () => setExpanded((prev) => !prev) : undefined}
      >
        <box gap={1}>
          <text fg={theme.text}>{limited()}</text>
          <Show when={overflow()}>
            <text fg={theme.textMuted}>{expanded() ? "Click to collapse" : "Click to expand"}</text>
          </Show>
        </box>
      </BlockTool>
    </Show>
  )
}

Here is how it looks (websearch-ddgs is a custom tool and tmux_list-session is an MCP tool):

https://github.com/user-attachments/assets/74eb8292-2ffc-44da-8a21-81624bd802a9

yanosh-k avatar Jan 18 '26 12:01 yanosh-k