返回 DeepSeek-Reasonix
mcp_availability.go
根目录 / internal / agent / mcp_availability.go
1 package agent
2
3 import (
4 "errors"
5 "fmt"
6 "strings"
7
8 "reasonix/internal/config"
9 "reasonix/internal/plugin"
10 )
11
12 func (r *MCPCapabilityRuntime) serverRegistered(server string) bool {
13 if r == nil {
14 return false
15 }
16 r.mu.RLock()
17 _, ok := r.servers[strings.TrimSpace(server)]
18 r.mu.RUnlock()
19 return ok
20 }
21
22 func mcpServerUnregisteredMessage(server string) string {
23 return fmt.Sprintf("MCP server %q is not registered in this session", server)
24 }
25
26 func mcpServerDisabledMessage(server string) string {
27 return fmt.Sprintf("MCP server %q is disabled in this session", server)
28 }
29
30 // mcpServerOffMessage carries the host's reason a server is off. One the
31 // project declared waits for the user, and only the user can change that.
32 func mcpServerOffMessage(server string, decision config.MCPDecision) string {
33 if !decision.AwaitsUser() {
34 return mcpServerDisabledMessage(server)
35 }
36 return fmt.Sprintf("MCP server %q is off [%s]: this project declares it, and it starts only after the user reviews and enables it (reasonix mcp enable %s, /mcp connect, or the MCP panel). Tell the user if it is needed.", server, decision.Code(), server)
37 }
38
39 // serverDecision resolves why entry is off; an enabled server is simply on.
40 func serverDecision(entry config.PluginEntry, spec plugin.Spec, enabled bool) config.MCPDecision {
41 if enabled {
42 return config.MCPDecisionOn
43 }
44 if d := config.MCPServerDecision(entry, spec.WorkspaceRoot); d.AwaitsUser() {
45 return d
46 }
47 return config.MCPDecisionOff
48 }
49
50 func mcpServerUnregisteredError(server string) error {
51 return errors.New(mcpServerUnregisteredMessage(server))
52 }
53
54 func mcpServerOffError(server string, decision config.MCPDecision) error {
55 return errors.New(mcpServerOffMessage(server, decision))
56 }
57
58 func (t *UseCapabilityTool) serverRegistered(server string) bool {
59 if t.runtime != nil {
60 return t.runtime.serverRegistered(server)
61 }
62 // Standalone proxies have no authoritative runtime inventory to miss from.
63 return true
64 }
65
66 // serverUnavailableReason distinguishes a disabled server from one this
67 // session never registered so the refusal points to the correct remedy.
68 func (t *UseCapabilityTool) serverUnavailableReason(server string) string {
69 if !t.serverRegistered(server) {
70 return mcpServerUnregisteredMessage(server)
71 }
72 if t.runtime != nil {
73 t.runtime.mu.RLock()
74 configured := t.runtime.servers[strings.TrimSpace(server)]
75 t.runtime.mu.RUnlock()
76 return mcpServerOffMessage(server, configured.decision)
77 }
78 return mcpServerDisabledMessage(server)
79 }
80
80 lines GO