77
88 "github.com/modelcontextprotocol/go-sdk/mcp"
99
10+ "github.com/docker/cagent/pkg/agent"
1011 "github.com/docker/cagent/pkg/agentfile"
1112 "github.com/docker/cagent/pkg/cli"
1213 "github.com/docker/cagent/pkg/config"
@@ -27,7 +28,7 @@ type ToolOutput struct {
2728}
2829
2930func StartMCPServer (ctx context.Context , out * cli.Printer , agentFilename string , runConfig config.RuntimeConfig ) error {
30- slog .Debug ("Starting MCP server" , "agent_ref " , agentFilename )
31+ slog .Debug ("Starting MCP server" , "agent " , agentFilename )
3132
3233 agentFilename , err := agentfile .Resolve (ctx , out , agentFilename )
3334 if err != nil {
@@ -54,21 +55,29 @@ func StartMCPServer(ctx context.Context, out *cli.Printer, agentFilename string,
5455 slog .Debug ("Adding MCP tools for agents" , "count" , len (agentNames ))
5556
5657 for _ , agentName := range agentNames {
57- agent , err := t .Agent (agentName )
58+ ag , err := t .Agent (agentName )
5859 if err != nil {
5960 return fmt .Errorf ("failed to get agent %s: %w" , agentName , err )
6061 }
6162
62- description := agent .Description ()
63+ description := ag .Description ()
6364 if description == "" {
6465 description = fmt .Sprintf ("Run the %s agent" , agentName )
6566 }
6667
6768 slog .Debug ("Adding MCP tool" , "agent" , agentName , "description" , description )
6869
70+ readOnly , err := isReadOnlyAgent (ctx , ag )
71+ if err != nil {
72+ return fmt .Errorf ("failed to determine if agent %s is read-only: %w" , agentName , err )
73+ }
74+
6975 toolDef := & mcp.Tool {
70- Name : agentName ,
71- Description : description ,
76+ Name : agentName ,
77+ Description : description ,
78+ Annotations : & mcp.ToolAnnotations {
79+ ReadOnlyHint : readOnly ,
80+ },
7281 InputSchema : tools .MustSchemaFor [ToolInput ](),
7382 OutputSchema : tools .MustSchemaFor [ToolOutput ](),
7483 }
@@ -89,14 +98,14 @@ func CreateToolHandler(t *team.Team, agentName, agentFilename string) func(conte
8998 return func (ctx context.Context , req * mcp.CallToolRequest , input ToolInput ) (* mcp.CallToolResult , ToolOutput , error ) {
9099 slog .Debug ("MCP tool called" , "agent" , agentName , "message" , input .Message )
91100
92- agent , err := t .Agent (agentName )
101+ ag , err := t .Agent (agentName )
93102 if err != nil {
94103 return nil , ToolOutput {}, fmt .Errorf ("failed to get agent: %w" , err )
95104 }
96105
97106 sess := session .New (
98107 session .WithTitle ("MCP tool call" ),
99- session .WithMaxIterations (agent .MaxIterations ()),
108+ session .WithMaxIterations (ag .MaxIterations ()),
100109 session .WithUserMessage (agentFilename , input .Message ),
101110 session .WithToolsApproved (true ),
102111 )
@@ -125,3 +134,18 @@ func CreateToolHandler(t *team.Team, agentName, agentFilename string) func(conte
125134 return nil , ToolOutput {Response : result }, nil
126135 }
127136}
137+
138+ func isReadOnlyAgent (ctx context.Context , ag * agent.Agent ) (bool , error ) {
139+ allTolls , err := ag .Tools (ctx )
140+ if err != nil {
141+ return false , err
142+ }
143+
144+ for _ , tool := range allTolls {
145+ if ! tool .Annotations .ReadOnlyHint {
146+ return false , nil
147+ }
148+ }
149+
150+ return true , nil
151+ }
0 commit comments