这是indexloc提供的服务,不要输入任何密码
Skip to content
Closed
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
27 changes: 27 additions & 0 deletions acp/api/v1alpha1/mcpserver_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,33 @@ type MCPTool struct {
// +kubebuilder:pruning:PreserveUnknownFields
// +optional
InputSchema runtime.RawExtension `json:"inputSchema,omitempty"`

// Annotations provides additional metadata about the tool's behavior
// +optional
Annotations *MCPToolAnnotations `json:"annotations,omitempty"`
}

// MCPToolAnnotations provides metadata about a tool's behavior
type MCPToolAnnotations struct {
// Title is a human-readable title for the tool
// +optional
Title string `json:"title,omitempty"`

// ReadOnlyHint indicates if the tool does not modify its environment
// +optional
ReadOnlyHint bool `json:"readOnlyHint,omitempty"`

// DestructiveHint indicates if the tool may perform destructive updates
// +optional
DestructiveHint bool `json:"destructiveHint,omitempty"`

// IdempotentHint indicates if repeated calls with same args have no additional effect
// +optional
IdempotentHint bool `json:"idempotentHint,omitempty"`

// OpenWorldHint indicates if the tool interacts with external entities
// +optional
OpenWorldHint bool `json:"openWorldHint,omitempty"`
}

// MCPServerStatus defines the observed state of MCPServer
Expand Down
20 changes: 20 additions & 0 deletions acp/api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions acp/config/crd/bases/acp.humanlayer.dev_mcpservers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,30 @@ spec:
items:
description: MCPTool represents a tool provided by an MCP server
properties:
annotations:
description: Annotations provides additional metadata about
the tool's behavior
properties:
destructiveHint:
description: DestructiveHint indicates if the tool may perform
destructive updates
type: boolean
idempotentHint:
description: IdempotentHint indicates if repeated calls
with same args have no additional effect
type: boolean
openWorldHint:
description: OpenWorldHint indicates if the tool interacts
with external entities
type: boolean
readOnlyHint:
description: ReadOnlyHint indicates if the tool does not
modify its environment
type: boolean
title:
description: Title is a human-readable title for the tool
type: string
type: object
description:
description: Description of the tool
type: string
Expand Down
2 changes: 1 addition & 1 deletion acp/config/localdev/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ patches:
images:
- name: controller
newName: controller
newTag: "202505141822"
newTag: "202505201737"
16 changes: 16 additions & 0 deletions acp/config/samples/mcp_github.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: acp.humanlayer.dev/v1alpha1
kind: MCPServer
metadata:
name: github
spec:
transport: stdio
command: npx
args:
- -y
- "@modelcontextprotocol/server-github"
env:
- name: GITHUB_PERSONAL_ACCESS_TOKEN
valueFrom:
secretKeyRef:
name: github-token
key: token
15 changes: 5 additions & 10 deletions acp/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ module github.com/humanlayer/agentcontrolplane/acp
go 1.24.0

require (
github.com/mark3labs/mcp-go v0.15.0
github.com/gin-gonic/gin v1.10.0
github.com/mark3labs/mcp-go v0.29.0
github.com/onsi/ginkgo/v2 v2.23.2
github.com/onsi/gomega v1.36.2
github.com/openai/openai-go v0.1.0-alpha.59
github.com/tmc/langchaingo v0.1.13
go.opentelemetry.io/otel v1.34.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0
Expand All @@ -33,12 +33,10 @@ require (
github.com/bytedance/sonic v1.13.2 // indirect
github.com/bytedance/sonic/loader v0.2.4 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/dlclark/regexp2 v1.10.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/gage-technologies/mistral-go v1.1.0 // indirect
github.com/gin-contrib/sse v1.1.0 // indirect
github.com/gin-gonic/gin v1.10.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.26.0 // indirect
Expand All @@ -53,10 +51,7 @@ require (
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pkoukk/tiktoken-go v0.1.6 // indirect
github.com/tidwall/gjson v1.14.4 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
Expand Down Expand Up @@ -106,7 +101,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.19.1 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
Expand All @@ -119,7 +114,7 @@ require (
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0
go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.34.0
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
Expand Down
8 changes: 6 additions & 2 deletions acp/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0
github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
Expand Down Expand Up @@ -176,8 +178,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mark3labs/mcp-go v0.15.0 h1:lViiC4dk6chJHZccezaTzZLMOQVUXJDGNQPtzExr5NQ=
github.com/mark3labs/mcp-go v0.15.0/go.mod h1:xBB350hekQsJAK7gJAii8bcEoWemboLm2mRm5/+KBaU=
github.com/mark3labs/mcp-go v0.29.0 h1:sH1NBcumKskhxqYzhXfGc201D7P76TVXiT0fGVhabeI=
github.com/mark3labs/mcp-go v0.29.0/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down Expand Up @@ -212,6 +214,8 @@ github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoG
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
Expand Down
12 changes: 12 additions & 0 deletions acp/internal/controller/mcpserver/mcpserver_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ var _ = Describe("MCPServer Controller", func() {
{
Name: "test-tool",
Description: "A test tool",
Annotations: &acp.MCPToolAnnotations{
Title: "Test Tool",
ReadOnlyHint: true,
DestructiveHint: false,
IdempotentHint: true,
OpenWorldHint: false,
},
},
}, true
},
Expand Down Expand Up @@ -147,6 +154,11 @@ var _ = Describe("MCPServer Controller", func() {
}
return createdMCPServer.Status.Connected &&
len(createdMCPServer.Status.Tools) == 1 &&
createdMCPServer.Status.Tools[0].Name == "test-tool" &&
createdMCPServer.Status.Tools[0].Annotations != nil &&
createdMCPServer.Status.Tools[0].Annotations.Title == "Test Tool" &&
createdMCPServer.Status.Tools[0].Annotations.ReadOnlyHint == true &&
createdMCPServer.Status.Tools[0].Annotations.IdempotentHint == true &&
createdMCPServer.Status.Status == "Ready"
}, time.Second*10, time.Millisecond*250).Should(BeTrue())
})
Expand Down
18 changes: 13 additions & 5 deletions acp/internal/mcpmanager/mcpmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,20 @@ func (m *MCPServerManager) ConnectServer(ctx context.Context, mcpServer *acp.MCP
}
}

// Create annotations based on tool properties
annotations := &acp.MCPToolAnnotations{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential nil pointer dereference: tool.Annotations is used without checking if it's nil. Consider adding a nil check before accessing its fields.

Title: tool.Annotations.Title,
ReadOnlyHint: tool.Annotations.ReadOnlyHint != nil && *tool.Annotations.ReadOnlyHint,
DestructiveHint: tool.Annotations.DestructiveHint != nil && *tool.Annotations.DestructiveHint,
IdempotentHint: tool.Annotations.IdempotentHint != nil && *tool.Annotations.IdempotentHint,
OpenWorldHint: tool.Annotations.OpenWorldHint != nil && *tool.Annotations.OpenWorldHint,
}

tools = append(tools, acp.MCPTool{
Name: tool.Name,
Description: tool.Description,
InputSchema: runtime.RawExtension{Raw: inputSchemaBytes},
Annotations: annotations,
})
}

Expand Down Expand Up @@ -282,11 +292,9 @@ func (m *MCPServerManager) CallTool(ctx context.Context, serverName, toolName st

result, err := conn.Client.CallTool(ctx, mcp.CallToolRequest{
Params: struct {
Name string `json:"name"`
Arguments map[string]interface{} `json:"arguments,omitempty"`
Meta *struct {
ProgressToken mcp.ProgressToken `json:"progressToken,omitempty"`
} `json:"_meta,omitempty"`
Name string `json:"name"`
Arguments interface{} `json:"arguments,omitempty"`
Meta *mcp.Meta `json:"_meta,omitempty"`
}{
Name: toolName,
Arguments: arguments,
Expand Down
21 changes: 21 additions & 0 deletions acp/internal/mcpmanager/mcpmanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ import (
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"

acp "github.com/humanlayer/agentcontrolplane/acp/api/v1alpha1"
mcpclient "github.com/mark3labs/mcp-go/client"
"github.com/mark3labs/mcp-go/mcp"
)

// MockMCPClient mocks the mcpclient.MCPClient interface for testing
var _ mcpclient.MCPClient = &MockMCPClient{}

type MockMCPClient struct {
// Results
initResult *mcp.InitializeResult
Expand Down Expand Up @@ -74,6 +77,12 @@ func (m *MockMCPClient) ListTools(ctx context.Context, req mcp.ListToolsRequest)
return m.toolsResult, m.toolsError
}

// ListToolsByPage implements mcpclient.MCPClient
func (m *MockMCPClient) ListToolsByPage(ctx context.Context, req mcp.ListToolsRequest) (*mcp.ListToolsResult, error) {
m.toolsCallCount++
return m.toolsResult, m.toolsError
}

// CallTool implements mcpclient.MCPClient
func (m *MockMCPClient) CallTool(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
m.callToolCallCount++
Expand All @@ -95,10 +104,18 @@ func (m *MockMCPClient) ListResources(ctx context.Context, req mcp.ListResources
return nil, nil
}

func (m *MockMCPClient) ListResourcesByPage(ctx context.Context, req mcp.ListResourcesRequest) (*mcp.ListResourcesResult, error) {
return nil, nil
}

func (m *MockMCPClient) ListResourceTemplates(ctx context.Context, req mcp.ListResourceTemplatesRequest) (*mcp.ListResourceTemplatesResult, error) {
return nil, nil
}

func (m *MockMCPClient) ListResourceTemplatesByPage(ctx context.Context, req mcp.ListResourceTemplatesRequest) (*mcp.ListResourceTemplatesResult, error) {
return nil, nil
}

func (m *MockMCPClient) ReadResource(ctx context.Context, req mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
return nil, nil
}
Expand All @@ -111,6 +128,10 @@ func (m *MockMCPClient) ListPrompts(ctx context.Context, req mcp.ListPromptsRequ
return nil, nil
}

func (m *MockMCPClient) ListPromptsByPage(ctx context.Context, req mcp.ListPromptsRequest) (*mcp.ListPromptsResult, error) {
return nil, nil
}

func (m *MockMCPClient) GetPrompt(ctx context.Context, req mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
return nil, nil
}
Expand Down
Loading