Bug
In the production call path (cmd/mcp.go), the server is constructed via mcp.New() with no WithReadonly(...) option, so s.readonly defaults to false. Instructions are computed immediately at construction time:
Instructions: instructions(s.readonly), // s.readonly == false here
Then Start() is called, which sets s.readonly = !writeEnabled. When writeEnabled == false (the default, since FUNC_ENABLE_MCP_WRITE is unset), the server enters readonly mode, but the instructions sent to the MCP client during initialization do not contain the readonly warning, because they were computed when s.readonly was still false.
Impact
The MCP client (e.g. Claude Code) receives instructions that do not warn about readonly mode, even though the server is in readonly mode. The AI agent will attempt deploy/delete operations, receive runtime errors, and waste the user's time. The readonly warning in instructions.md is specifically designed to prevent this.
Fix
Pass WithReadonly(!writeEnabled) at construction time in cmd/mcp.go. writeEnabled is already known before mcp.New() is called, so the instructions can be computed with the correct readonly state.
Bug
In the production call path (
cmd/mcp.go), the server is constructed viamcp.New()with noWithReadonly(...)option, sos.readonlydefaults tofalse. Instructions are computed immediately at construction time:Then
Start()is called, which setss.readonly = !writeEnabled. WhenwriteEnabled == false(the default, sinceFUNC_ENABLE_MCP_WRITEis unset), the server enters readonly mode, but the instructions sent to the MCP client during initialization do not contain the readonly warning, because they were computed whens.readonlywas stillfalse.Impact
The MCP client (e.g. Claude Code) receives instructions that do not warn about readonly mode, even though the server is in readonly mode. The AI agent will attempt deploy/delete operations, receive runtime errors, and waste the user's time. The readonly warning in
instructions.mdis specifically designed to prevent this.Fix
Pass
WithReadonly(!writeEnabled)at construction time incmd/mcp.go.writeEnabledis already known beforemcp.New()is called, so the instructions can be computed with the correct readonly state.