Repository navigation
Closed as not planned
Closed as not planned
Copy link
Description
Description
Summary
MCP local server tools return result: null in the execute runtime; the actual response text is emitted to Logs instead of being available as the tool result. All 42 tools from the same MCP server exhibit the identical behavior.
Environment
- opencode version: 2.0.3
- OS: Windows_NT 10.0.26200 (MINGW64_NT-10.0-26200, win32 x64)
- Terminal: xterm-256color (MINGW64 / Git Bash)
- Shell: /usr/bin/bash (Git Bash), COMSPEC: C:\WINDOWS\system32\cmd.exe
- Install/channel: npm global, latest
- Active plugins: none (all disabled in config)
- MCP server: @cocaxcode/[email protected] (local, via npx)
- MCP SDK (server side): @modelcontextprotocol/[email protected]
Reproduction
- Configure a local MCP server in opencode.jsonc:
"api-testing": {
"type": "local",
"command": ["npx", "-y", "@cocaxcode/api-testing-mcp@latest"],
"enabled": true
} - Start opencode, open a session.
- In a tools code block, call any MCP tool, e.g.:
const result = await tools["api-testing"].env_list();
console.log(result); // null - Observe the output:
result: null
Logs: [ { "name": "local_dev", ... } ]
Expected Behavior
result should contain the parsed tool response (the array of environments), matching what the MCP server returns:
{ "content": [{ "type": "text", "text": "[{ "name": "local_dev", ... }]" }] }
The content[0].text value should be parsed and returned as the tool result, not logged separately.
Actual Behavior
Every MCP tool call returns result: null. The actual response text appears under a Logs: heading in the output. This is consistent across all 42 tools from the api-testing MCP server.
Sample output:
null
Logs:
[
{
"name": "local_dev",
"active": true,
"default": true,
"group": "rh-front",
"variableCount": 2,
"spec": "rh-remote-v3"
}
]
The MCP server's response format is correct per the MCP protocol — the issue is on the OpenCode client side, which fails to pass content[0].text through as the tool return value.
Additional Context
- The MCP server logs show mcp connected server=api-testing tools=42 — connection and tool registration succeed.
- No errors in ~/.local/share/opencode/log/opencode.log related to MCP.
- All 42 tools (env_list, api_spec_list, api_import, collection_list, etc.) exhibit the same result: null behavior.
- Tool validation errors (wrong argument names/types) DO return proper error messages — only successful calls produce null.
- The MCP server uses @modelcontextprotocol/[email protected]; OpenCode's bundled MCP client version is unknown but should be compatible.
- Config: opencode.jsonc with "type": "local" MCP, shell "sh", "lsp": false.
Plugins
No response
OpenCode version
v2.0.3
Steps to reproduce
No response
Screenshot and/or share link
No response
Operating System
No response
Terminal
No response
Metadata
Metadata
Assignees
Labels
No labels
Activity
VishvakR commentedon Sep 14, 2026
had a look and i don't think this is a bug, the snippet just doesn't return anything.
executeuses the program's return value as the result, and when there's noreturnit takes the last top-level expression, which here isconsole.log(result). that'sundefined, andtoDatainpackages/codemode/src/data.tsturns an undefined execution result intonull. so you getnulland then whatever was logged.the array under
Logs:isresultitself, so the MCP call did come back fine (JSON text from schemaless tools gets parsed into an object since #48357, which is in 2.0.3). ending the block withreturn resultshould give you the array as the result.didn't run it against your server, went off the v2.0.3 source. if you've got a call that still comes back null with an explicit return i'd like to see it, otherwise this is probably ok to close.
Hotragn commentedon Sep 14, 2026
I think the tool call is actually working here, and the
nullis coming from the script rather than from MCP.In
packages/opencode/src/tool/code-mode.ts, the tool output is built from the script's return value, andconsole.logoutput is appended separately underLogs::Your script is:
That returns nothing, so the script's value is
undefined, normalized tonullon the way out of the sandbox (copyOut(..., undefinedAsNull)inpackages/codemode/src/tool-runtime.ts) and serialized asnull. Meanwhile the array underLogs:is exactly whatconsole.log(result)printed — which meansresultdid hold the parsed response, notnull.Ending the script with the value should give you what you expect:
For what it's worth,
projectMcpResultin the same file does already handle the case you describe — it collectstextblocks and returnstext.join("\n"), and prefersstructuredContentwhen present.If you do return the value and still get
null, then something else is going on and it's worth digging further — in that case thecontentarray your server sends for one specific call would help.neriousy commentedon Oct 20, 2026
End the script with
return result;instead ofconsole.log(result);to return the MCP response; console output appears separately under Logs. Closing this as an answered question; if an explicit return still produces null, please open a new issue with that reproduction.