Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions internal/httpapi/contracts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,10 @@ func (m *MockServerController) GetConfig() (*config.Config, error) {
}, nil
}

func (m *MockServerController) DefaultInstructions() string {
return "test built-in default: use retrieve_tools to discover tools"
}

// Readiness method
func (m *MockServerController) IsReady() bool { return true }

Expand Down
30 changes: 30 additions & 0 deletions internal/httpapi/routing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,33 @@ func TestHandleGetStatus_IncludesRoutingMode(t *testing.T) {
assert.Equal(t, config.RoutingModeRetrieveTools, resp.Data["routing_mode"])
})
}

// TestHandleGetStatus_IncludesDefaultInstructions verifies the status response
// exposes the built-in default MCP instructions so the Web UI can render them as
// the instructions textarea placeholder without hardcoding the text (MCP-2176).
func TestHandleGetStatus_IncludesDefaultInstructions(t *testing.T) {
logger := zap.NewNop().Sugar()
mockCtrl := &mockRoutingController{apiKey: "test-key", routingMode: ""}
srv := NewServer(mockCtrl, logger, nil)

req := httptest.NewRequest(http.MethodGet, "/api/v1/status", nil)
req.Header.Set("X-API-Key", "test-key")
w := httptest.NewRecorder()

srv.ServeHTTP(w, req)

assert.Equal(t, http.StatusOK, w.Code)

var resp struct {
Success bool `json:"success"`
Data map[string]interface{} `json:"data"`
}
err := json.NewDecoder(w.Body).Decode(&resp)
require.NoError(t, err)
require.True(t, resp.Success)

defaultInstructions, ok := resp.Data["default_instructions"].(string)
require.True(t, ok, "default_instructions must be present and a string")
assert.NotEmpty(t, defaultInstructions)
assert.Contains(t, defaultInstructions, "retrieve_tools")
}
3 changes: 3 additions & 0 deletions internal/httpapi/security_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,3 +361,6 @@ func (m *baseController) GetOnboardingState() (*storage.OnboardingState, error)
}
func (m *baseController) SaveOnboardingState(_ *storage.OnboardingState) error { return nil }
func (m *baseController) GetActivationFirstMCPClient() (bool, []string) { return false, nil }
func (m *baseController) DefaultInstructions() string {
return "test built-in default: use retrieve_tools to discover tools"
}
9 changes: 9 additions & 0 deletions internal/httpapi/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ type ServerController interface {
ValidateConfig(cfg *config.Config) ([]config.ValidationError, error)
ApplyConfig(cfg *config.Config, cfgPath string) (*internalRuntime.ConfigApplyResult, error)
GetConfig() (*config.Config, error)
// DefaultInstructions returns the built-in default MCP instructions text
// (independent of any user-configured custom value), so /api/v1/status can
// surface it to the Web UI as the instructions placeholder (MCP-2176).
DefaultInstructions() string

// Token statistics
GetTokenSavings() (*contracts.ServerTokenMetrics, error)
Expand Down Expand Up @@ -912,6 +916,11 @@ func (s *Server) handleGetStatus(w http.ResponseWriter, _ *http.Request) {
"status": s.controller.GetStatus(),
"routing_mode": routingMode,
"timestamp": time.Now().Unix(),
// MCP-2176: built-in default MCP instructions. The Web UI renders this
// as the instructions textarea placeholder so the displayed default
// never drifts from the backend's resolveInstructions("") value. Always
// the built-in default, never the user's current custom value.
"default_instructions": s.controller.DefaultInstructions(),
}

// Spec 044 (FR-018): expose process-level env_kind + env_markers so the
Expand Down
9 changes: 9 additions & 0 deletions internal/server/mcp_instructions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ func TestResolveInstructions_Custom(t *testing.T) {
assert.Equal(t, custom, result)
}

// TestServer_DefaultInstructions verifies the controller exposes the built-in
// default (not a user's custom value) so /api/v1/status can surface it to the
// Web UI placeholder without drift (MCP-2176).
func TestServer_DefaultInstructions(t *testing.T) {
s := &Server{}
assert.Equal(t, defaultInstructions, s.DefaultInstructions())
assert.Contains(t, s.DefaultInstructions(), "retrieve_tools")
}

func TestDefaultInstructions_ContainsKeyTerms(t *testing.T) {
assert.Contains(t, defaultInstructions, "retrieve_tools")
assert.Contains(t, defaultInstructions, "search_servers")
Expand Down
9 changes: 9 additions & 0 deletions internal/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2205,6 +2205,15 @@ func (s *Server) GetConfig() (*config.Config, error) {
return s.runtime.GetConfig()
}

// DefaultInstructions returns the built-in default MCP instructions text,
// independent of any user-configured custom value. It backs the
// /api/v1/status `default_instructions` field so the Web UI can render the
// built-in default as the instructions placeholder without hardcoding the
// text (MCP-2176). This mirrors resolveInstructions("").
func (s *Server) DefaultInstructions() string {
return defaultInstructions
}

// ValidateConfig validates a configuration
func (s *Server) ValidateConfig(cfg *config.Config) ([]config.ValidationError, error) {
return s.runtime.ValidateConfig(cfg)
Expand Down
Loading