feat: publish plugin MCP descriptors
This commit is contained in:
parent
bf72cd160a
commit
911f3f70e0
@ -156,6 +156,26 @@ message PluginManifest {
|
|||||||
// HTTP handler) and merges them into the site sitemap. Requires
|
// HTTP handler) and merges them into the site sitemap. Requires
|
||||||
// has_http_handler.
|
// has_http_handler.
|
||||||
bool sitemap = 37;
|
bool sitemap = 37;
|
||||||
|
|
||||||
|
// mcp_tools is the descriptor-derived MCP surface for the plugin's own
|
||||||
|
// unary ConnectRPC methods. The Go guest binding captures these during
|
||||||
|
// DESCRIBE from the compiled protobuf descriptors; plugin authors do not
|
||||||
|
// duplicate schemas or procedure metadata by hand. The host still checks
|
||||||
|
// every procedure against rbac_method_roles before advertising or invoking
|
||||||
|
// it, so descriptor metadata cannot widen the plugin's authorization map.
|
||||||
|
repeated MCPToolDescriptor mcp_tools = 38;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MCPToolDescriptor is one unary ConnectRPC method prepared for the host MCP
|
||||||
|
// catalogue. Procedure, service, method, documentation, and the request JSON
|
||||||
|
// schema are all derived from protobuf reflection during DESCRIBE.
|
||||||
|
message MCPToolDescriptor {
|
||||||
|
string procedure = 1;
|
||||||
|
string service_full_name = 2;
|
||||||
|
string method_name = 3;
|
||||||
|
string description = 4;
|
||||||
|
string documentation = 5;
|
||||||
|
bytes input_schema_json = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PublicRoute is one site-root path claim (see PluginManifest.public_routes).
|
// PublicRoute is one site-root path claim (see PluginManifest.public_routes).
|
||||||
|
|||||||
@ -149,7 +149,14 @@ type PluginManifest struct {
|
|||||||
// entries from the plugin's well-known sitemap endpoint (served by its
|
// entries from the plugin's well-known sitemap endpoint (served by its
|
||||||
// HTTP handler) and merges them into the site sitemap. Requires
|
// HTTP handler) and merges them into the site sitemap. Requires
|
||||||
// has_http_handler.
|
// has_http_handler.
|
||||||
Sitemap bool `protobuf:"varint,37,opt,name=sitemap,proto3" json:"sitemap,omitempty"`
|
Sitemap bool `protobuf:"varint,37,opt,name=sitemap,proto3" json:"sitemap,omitempty"`
|
||||||
|
// mcp_tools is the descriptor-derived MCP surface for the plugin's own
|
||||||
|
// unary ConnectRPC methods. The Go guest binding captures these during
|
||||||
|
// DESCRIBE from the compiled protobuf descriptors; plugin authors do not
|
||||||
|
// duplicate schemas or procedure metadata by hand. The host still checks
|
||||||
|
// every procedure against rbac_method_roles before advertising or invoking
|
||||||
|
// it, so descriptor metadata cannot widen the plugin's authorization map.
|
||||||
|
McpTools []*MCPToolDescriptor `protobuf:"bytes,38,rep,name=mcp_tools,json=mcpTools,proto3" json:"mcp_tools,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
@ -443,6 +450,100 @@ func (x *PluginManifest) GetSitemap() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *PluginManifest) GetMcpTools() []*MCPToolDescriptor {
|
||||||
|
if x != nil {
|
||||||
|
return x.McpTools
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MCPToolDescriptor is one unary ConnectRPC method prepared for the host MCP
|
||||||
|
// catalogue. Procedure, service, method, documentation, and the request JSON
|
||||||
|
// schema are all derived from protobuf reflection during DESCRIBE.
|
||||||
|
type MCPToolDescriptor struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Procedure string `protobuf:"bytes,1,opt,name=procedure,proto3" json:"procedure,omitempty"`
|
||||||
|
ServiceFullName string `protobuf:"bytes,2,opt,name=service_full_name,json=serviceFullName,proto3" json:"service_full_name,omitempty"`
|
||||||
|
MethodName string `protobuf:"bytes,3,opt,name=method_name,json=methodName,proto3" json:"method_name,omitempty"`
|
||||||
|
Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"`
|
||||||
|
Documentation string `protobuf:"bytes,5,opt,name=documentation,proto3" json:"documentation,omitempty"`
|
||||||
|
InputSchemaJson []byte `protobuf:"bytes,6,opt,name=input_schema_json,json=inputSchemaJson,proto3" json:"input_schema_json,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *MCPToolDescriptor) Reset() {
|
||||||
|
*x = MCPToolDescriptor{}
|
||||||
|
mi := &file_v1_manifest_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *MCPToolDescriptor) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*MCPToolDescriptor) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *MCPToolDescriptor) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_v1_manifest_proto_msgTypes[1]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use MCPToolDescriptor.ProtoReflect.Descriptor instead.
|
||||||
|
func (*MCPToolDescriptor) Descriptor() ([]byte, []int) {
|
||||||
|
return file_v1_manifest_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *MCPToolDescriptor) GetProcedure() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Procedure
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *MCPToolDescriptor) GetServiceFullName() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.ServiceFullName
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *MCPToolDescriptor) GetMethodName() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.MethodName
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *MCPToolDescriptor) GetDescription() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Description
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *MCPToolDescriptor) GetDocumentation() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Documentation
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *MCPToolDescriptor) GetInputSchemaJson() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.InputSchemaJson
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// PublicRoute is one site-root path claim (see PluginManifest.public_routes).
|
// PublicRoute is one site-root path claim (see PluginManifest.public_routes).
|
||||||
type PublicRoute struct {
|
type PublicRoute struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
@ -459,7 +560,7 @@ type PublicRoute struct {
|
|||||||
|
|
||||||
func (x *PublicRoute) Reset() {
|
func (x *PublicRoute) Reset() {
|
||||||
*x = PublicRoute{}
|
*x = PublicRoute{}
|
||||||
mi := &file_v1_manifest_proto_msgTypes[1]
|
mi := &file_v1_manifest_proto_msgTypes[2]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -471,7 +572,7 @@ func (x *PublicRoute) String() string {
|
|||||||
func (*PublicRoute) ProtoMessage() {}
|
func (*PublicRoute) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *PublicRoute) ProtoReflect() protoreflect.Message {
|
func (x *PublicRoute) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_manifest_proto_msgTypes[1]
|
mi := &file_v1_manifest_proto_msgTypes[2]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -484,7 +585,7 @@ func (x *PublicRoute) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use PublicRoute.ProtoReflect.Descriptor instead.
|
// Deprecated: Use PublicRoute.ProtoReflect.Descriptor instead.
|
||||||
func (*PublicRoute) Descriptor() ([]byte, []int) {
|
func (*PublicRoute) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_manifest_proto_rawDescGZIP(), []int{1}
|
return file_v1_manifest_proto_rawDescGZIP(), []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *PublicRoute) GetPath() string {
|
func (x *PublicRoute) GetPath() string {
|
||||||
@ -513,7 +614,7 @@ type Dependency struct {
|
|||||||
|
|
||||||
func (x *Dependency) Reset() {
|
func (x *Dependency) Reset() {
|
||||||
*x = Dependency{}
|
*x = Dependency{}
|
||||||
mi := &file_v1_manifest_proto_msgTypes[2]
|
mi := &file_v1_manifest_proto_msgTypes[3]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -525,7 +626,7 @@ func (x *Dependency) String() string {
|
|||||||
func (*Dependency) ProtoMessage() {}
|
func (*Dependency) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Dependency) ProtoReflect() protoreflect.Message {
|
func (x *Dependency) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_manifest_proto_msgTypes[2]
|
mi := &file_v1_manifest_proto_msgTypes[3]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -538,7 +639,7 @@ func (x *Dependency) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use Dependency.ProtoReflect.Descriptor instead.
|
// Deprecated: Use Dependency.ProtoReflect.Descriptor instead.
|
||||||
func (*Dependency) Descriptor() ([]byte, []int) {
|
func (*Dependency) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_manifest_proto_rawDescGZIP(), []int{2}
|
return file_v1_manifest_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Dependency) GetPlugin() string {
|
func (x *Dependency) GetPlugin() string {
|
||||||
@ -581,7 +682,7 @@ type BlockMeta struct {
|
|||||||
|
|
||||||
func (x *BlockMeta) Reset() {
|
func (x *BlockMeta) Reset() {
|
||||||
*x = BlockMeta{}
|
*x = BlockMeta{}
|
||||||
mi := &file_v1_manifest_proto_msgTypes[3]
|
mi := &file_v1_manifest_proto_msgTypes[4]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -593,7 +694,7 @@ func (x *BlockMeta) String() string {
|
|||||||
func (*BlockMeta) ProtoMessage() {}
|
func (*BlockMeta) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *BlockMeta) ProtoReflect() protoreflect.Message {
|
func (x *BlockMeta) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_manifest_proto_msgTypes[3]
|
mi := &file_v1_manifest_proto_msgTypes[4]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -606,7 +707,7 @@ func (x *BlockMeta) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use BlockMeta.ProtoReflect.Descriptor instead.
|
// Deprecated: Use BlockMeta.ProtoReflect.Descriptor instead.
|
||||||
func (*BlockMeta) Descriptor() ([]byte, []int) {
|
func (*BlockMeta) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_manifest_proto_rawDescGZIP(), []int{3}
|
return file_v1_manifest_proto_rawDescGZIP(), []int{4}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BlockMeta) GetKey() string {
|
func (x *BlockMeta) GetKey() string {
|
||||||
@ -672,7 +773,7 @@ type BlockTemplateOverride struct {
|
|||||||
|
|
||||||
func (x *BlockTemplateOverride) Reset() {
|
func (x *BlockTemplateOverride) Reset() {
|
||||||
*x = BlockTemplateOverride{}
|
*x = BlockTemplateOverride{}
|
||||||
mi := &file_v1_manifest_proto_msgTypes[4]
|
mi := &file_v1_manifest_proto_msgTypes[5]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -684,7 +785,7 @@ func (x *BlockTemplateOverride) String() string {
|
|||||||
func (*BlockTemplateOverride) ProtoMessage() {}
|
func (*BlockTemplateOverride) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *BlockTemplateOverride) ProtoReflect() protoreflect.Message {
|
func (x *BlockTemplateOverride) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_manifest_proto_msgTypes[4]
|
mi := &file_v1_manifest_proto_msgTypes[5]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -697,7 +798,7 @@ func (x *BlockTemplateOverride) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use BlockTemplateOverride.ProtoReflect.Descriptor instead.
|
// Deprecated: Use BlockTemplateOverride.ProtoReflect.Descriptor instead.
|
||||||
func (*BlockTemplateOverride) Descriptor() ([]byte, []int) {
|
func (*BlockTemplateOverride) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_manifest_proto_rawDescGZIP(), []int{4}
|
return file_v1_manifest_proto_rawDescGZIP(), []int{5}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BlockTemplateOverride) GetTemplateKey() string {
|
func (x *BlockTemplateOverride) GetTemplateKey() string {
|
||||||
@ -733,7 +834,7 @@ type SystemTemplateMeta struct {
|
|||||||
|
|
||||||
func (x *SystemTemplateMeta) Reset() {
|
func (x *SystemTemplateMeta) Reset() {
|
||||||
*x = SystemTemplateMeta{}
|
*x = SystemTemplateMeta{}
|
||||||
mi := &file_v1_manifest_proto_msgTypes[5]
|
mi := &file_v1_manifest_proto_msgTypes[6]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -745,7 +846,7 @@ func (x *SystemTemplateMeta) String() string {
|
|||||||
func (*SystemTemplateMeta) ProtoMessage() {}
|
func (*SystemTemplateMeta) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *SystemTemplateMeta) ProtoReflect() protoreflect.Message {
|
func (x *SystemTemplateMeta) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_manifest_proto_msgTypes[5]
|
mi := &file_v1_manifest_proto_msgTypes[6]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -758,7 +859,7 @@ func (x *SystemTemplateMeta) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use SystemTemplateMeta.ProtoReflect.Descriptor instead.
|
// Deprecated: Use SystemTemplateMeta.ProtoReflect.Descriptor instead.
|
||||||
func (*SystemTemplateMeta) Descriptor() ([]byte, []int) {
|
func (*SystemTemplateMeta) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_manifest_proto_rawDescGZIP(), []int{5}
|
return file_v1_manifest_proto_rawDescGZIP(), []int{6}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SystemTemplateMeta) GetKey() string {
|
func (x *SystemTemplateMeta) GetKey() string {
|
||||||
@ -797,7 +898,7 @@ type PageTemplateMeta struct {
|
|||||||
|
|
||||||
func (x *PageTemplateMeta) Reset() {
|
func (x *PageTemplateMeta) Reset() {
|
||||||
*x = PageTemplateMeta{}
|
*x = PageTemplateMeta{}
|
||||||
mi := &file_v1_manifest_proto_msgTypes[6]
|
mi := &file_v1_manifest_proto_msgTypes[7]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -809,7 +910,7 @@ func (x *PageTemplateMeta) String() string {
|
|||||||
func (*PageTemplateMeta) ProtoMessage() {}
|
func (*PageTemplateMeta) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *PageTemplateMeta) ProtoReflect() protoreflect.Message {
|
func (x *PageTemplateMeta) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_manifest_proto_msgTypes[6]
|
mi := &file_v1_manifest_proto_msgTypes[7]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -822,7 +923,7 @@ func (x *PageTemplateMeta) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use PageTemplateMeta.ProtoReflect.Descriptor instead.
|
// Deprecated: Use PageTemplateMeta.ProtoReflect.Descriptor instead.
|
||||||
func (*PageTemplateMeta) Descriptor() ([]byte, []int) {
|
func (*PageTemplateMeta) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_manifest_proto_rawDescGZIP(), []int{6}
|
return file_v1_manifest_proto_rawDescGZIP(), []int{7}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *PageTemplateMeta) GetSystemKey() string {
|
func (x *PageTemplateMeta) GetSystemKey() string {
|
||||||
@ -876,7 +977,7 @@ type AdminPage struct {
|
|||||||
|
|
||||||
func (x *AdminPage) Reset() {
|
func (x *AdminPage) Reset() {
|
||||||
*x = AdminPage{}
|
*x = AdminPage{}
|
||||||
mi := &file_v1_manifest_proto_msgTypes[7]
|
mi := &file_v1_manifest_proto_msgTypes[8]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -888,7 +989,7 @@ func (x *AdminPage) String() string {
|
|||||||
func (*AdminPage) ProtoMessage() {}
|
func (*AdminPage) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *AdminPage) ProtoReflect() protoreflect.Message {
|
func (x *AdminPage) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_manifest_proto_msgTypes[7]
|
mi := &file_v1_manifest_proto_msgTypes[8]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -901,7 +1002,7 @@ func (x *AdminPage) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use AdminPage.ProtoReflect.Descriptor instead.
|
// Deprecated: Use AdminPage.ProtoReflect.Descriptor instead.
|
||||||
func (*AdminPage) Descriptor() ([]byte, []int) {
|
func (*AdminPage) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_manifest_proto_rawDescGZIP(), []int{7}
|
return file_v1_manifest_proto_rawDescGZIP(), []int{8}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AdminPage) GetKey() string {
|
func (x *AdminPage) GetKey() string {
|
||||||
@ -953,7 +1054,7 @@ type AiAction struct {
|
|||||||
|
|
||||||
func (x *AiAction) Reset() {
|
func (x *AiAction) Reset() {
|
||||||
*x = AiAction{}
|
*x = AiAction{}
|
||||||
mi := &file_v1_manifest_proto_msgTypes[8]
|
mi := &file_v1_manifest_proto_msgTypes[9]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -965,7 +1066,7 @@ func (x *AiAction) String() string {
|
|||||||
func (*AiAction) ProtoMessage() {}
|
func (*AiAction) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *AiAction) ProtoReflect() protoreflect.Message {
|
func (x *AiAction) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_manifest_proto_msgTypes[8]
|
mi := &file_v1_manifest_proto_msgTypes[9]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -978,7 +1079,7 @@ func (x *AiAction) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use AiAction.ProtoReflect.Descriptor instead.
|
// Deprecated: Use AiAction.ProtoReflect.Descriptor instead.
|
||||||
func (*AiAction) Descriptor() ([]byte, []int) {
|
func (*AiAction) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_manifest_proto_rawDescGZIP(), []int{8}
|
return file_v1_manifest_proto_rawDescGZIP(), []int{9}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AiAction) GetKey() string {
|
func (x *AiAction) GetKey() string {
|
||||||
@ -1028,7 +1129,7 @@ type CssManifest struct {
|
|||||||
|
|
||||||
func (x *CssManifest) Reset() {
|
func (x *CssManifest) Reset() {
|
||||||
*x = CssManifest{}
|
*x = CssManifest{}
|
||||||
mi := &file_v1_manifest_proto_msgTypes[9]
|
mi := &file_v1_manifest_proto_msgTypes[10]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -1040,7 +1141,7 @@ func (x *CssManifest) String() string {
|
|||||||
func (*CssManifest) ProtoMessage() {}
|
func (*CssManifest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *CssManifest) ProtoReflect() protoreflect.Message {
|
func (x *CssManifest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_manifest_proto_msgTypes[9]
|
mi := &file_v1_manifest_proto_msgTypes[10]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -1053,7 +1154,7 @@ func (x *CssManifest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use CssManifest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use CssManifest.ProtoReflect.Descriptor instead.
|
||||||
func (*CssManifest) Descriptor() ([]byte, []int) {
|
func (*CssManifest) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_manifest_proto_rawDescGZIP(), []int{9}
|
return file_v1_manifest_proto_rawDescGZIP(), []int{10}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CssManifest) GetNpmPackages() map[string]string {
|
func (x *CssManifest) GetNpmPackages() map[string]string {
|
||||||
@ -1094,7 +1195,7 @@ type DirectoryExtensions struct {
|
|||||||
|
|
||||||
func (x *DirectoryExtensions) Reset() {
|
func (x *DirectoryExtensions) Reset() {
|
||||||
*x = DirectoryExtensions{}
|
*x = DirectoryExtensions{}
|
||||||
mi := &file_v1_manifest_proto_msgTypes[10]
|
mi := &file_v1_manifest_proto_msgTypes[11]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -1106,7 +1207,7 @@ func (x *DirectoryExtensions) String() string {
|
|||||||
func (*DirectoryExtensions) ProtoMessage() {}
|
func (*DirectoryExtensions) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *DirectoryExtensions) ProtoReflect() protoreflect.Message {
|
func (x *DirectoryExtensions) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_manifest_proto_msgTypes[10]
|
mi := &file_v1_manifest_proto_msgTypes[11]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -1119,7 +1220,7 @@ func (x *DirectoryExtensions) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use DirectoryExtensions.ProtoReflect.Descriptor instead.
|
// Deprecated: Use DirectoryExtensions.ProtoReflect.Descriptor instead.
|
||||||
func (*DirectoryExtensions) Descriptor() ([]byte, []int) {
|
func (*DirectoryExtensions) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_manifest_proto_rawDescGZIP(), []int{10}
|
return file_v1_manifest_proto_rawDescGZIP(), []int{11}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *DirectoryExtensions) GetBooleanFilterFields() []string {
|
func (x *DirectoryExtensions) GetBooleanFilterFields() []string {
|
||||||
@ -1168,7 +1269,7 @@ type BadgeLabel struct {
|
|||||||
|
|
||||||
func (x *BadgeLabel) Reset() {
|
func (x *BadgeLabel) Reset() {
|
||||||
*x = BadgeLabel{}
|
*x = BadgeLabel{}
|
||||||
mi := &file_v1_manifest_proto_msgTypes[11]
|
mi := &file_v1_manifest_proto_msgTypes[12]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -1180,7 +1281,7 @@ func (x *BadgeLabel) String() string {
|
|||||||
func (*BadgeLabel) ProtoMessage() {}
|
func (*BadgeLabel) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *BadgeLabel) ProtoReflect() protoreflect.Message {
|
func (x *BadgeLabel) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_manifest_proto_msgTypes[11]
|
mi := &file_v1_manifest_proto_msgTypes[12]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -1193,7 +1294,7 @@ func (x *BadgeLabel) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use BadgeLabel.ProtoReflect.Descriptor instead.
|
// Deprecated: Use BadgeLabel.ProtoReflect.Descriptor instead.
|
||||||
func (*BadgeLabel) Descriptor() ([]byte, []int) {
|
func (*BadgeLabel) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_manifest_proto_rawDescGZIP(), []int{11}
|
return file_v1_manifest_proto_rawDescGZIP(), []int{12}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BadgeLabel) GetPositive() string {
|
func (x *BadgeLabel) GetPositive() string {
|
||||||
@ -1223,7 +1324,7 @@ type MasterPageDefinition struct {
|
|||||||
|
|
||||||
func (x *MasterPageDefinition) Reset() {
|
func (x *MasterPageDefinition) Reset() {
|
||||||
*x = MasterPageDefinition{}
|
*x = MasterPageDefinition{}
|
||||||
mi := &file_v1_manifest_proto_msgTypes[12]
|
mi := &file_v1_manifest_proto_msgTypes[13]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -1235,7 +1336,7 @@ func (x *MasterPageDefinition) String() string {
|
|||||||
func (*MasterPageDefinition) ProtoMessage() {}
|
func (*MasterPageDefinition) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *MasterPageDefinition) ProtoReflect() protoreflect.Message {
|
func (x *MasterPageDefinition) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_manifest_proto_msgTypes[12]
|
mi := &file_v1_manifest_proto_msgTypes[13]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -1248,7 +1349,7 @@ func (x *MasterPageDefinition) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use MasterPageDefinition.ProtoReflect.Descriptor instead.
|
// Deprecated: Use MasterPageDefinition.ProtoReflect.Descriptor instead.
|
||||||
func (*MasterPageDefinition) Descriptor() ([]byte, []int) {
|
func (*MasterPageDefinition) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_manifest_proto_rawDescGZIP(), []int{12}
|
return file_v1_manifest_proto_rawDescGZIP(), []int{13}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *MasterPageDefinition) GetKey() string {
|
func (x *MasterPageDefinition) GetKey() string {
|
||||||
@ -1295,7 +1396,7 @@ type MasterPageBlock struct {
|
|||||||
|
|
||||||
func (x *MasterPageBlock) Reset() {
|
func (x *MasterPageBlock) Reset() {
|
||||||
*x = MasterPageBlock{}
|
*x = MasterPageBlock{}
|
||||||
mi := &file_v1_manifest_proto_msgTypes[13]
|
mi := &file_v1_manifest_proto_msgTypes[14]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -1307,7 +1408,7 @@ func (x *MasterPageBlock) String() string {
|
|||||||
func (*MasterPageBlock) ProtoMessage() {}
|
func (*MasterPageBlock) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *MasterPageBlock) ProtoReflect() protoreflect.Message {
|
func (x *MasterPageBlock) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_manifest_proto_msgTypes[13]
|
mi := &file_v1_manifest_proto_msgTypes[14]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -1320,7 +1421,7 @@ func (x *MasterPageBlock) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use MasterPageBlock.ProtoReflect.Descriptor instead.
|
// Deprecated: Use MasterPageBlock.ProtoReflect.Descriptor instead.
|
||||||
func (*MasterPageBlock) Descriptor() ([]byte, []int) {
|
func (*MasterPageBlock) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_manifest_proto_rawDescGZIP(), []int{13}
|
return file_v1_manifest_proto_rawDescGZIP(), []int{14}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *MasterPageBlock) GetBlockKey() string {
|
func (x *MasterPageBlock) GetBlockKey() string {
|
||||||
@ -1377,7 +1478,7 @@ type CoreServiceBinding struct {
|
|||||||
|
|
||||||
func (x *CoreServiceBinding) Reset() {
|
func (x *CoreServiceBinding) Reset() {
|
||||||
*x = CoreServiceBinding{}
|
*x = CoreServiceBinding{}
|
||||||
mi := &file_v1_manifest_proto_msgTypes[14]
|
mi := &file_v1_manifest_proto_msgTypes[15]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -1389,7 +1490,7 @@ func (x *CoreServiceBinding) String() string {
|
|||||||
func (*CoreServiceBinding) ProtoMessage() {}
|
func (*CoreServiceBinding) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *CoreServiceBinding) ProtoReflect() protoreflect.Message {
|
func (x *CoreServiceBinding) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_manifest_proto_msgTypes[14]
|
mi := &file_v1_manifest_proto_msgTypes[15]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -1402,7 +1503,7 @@ func (x *CoreServiceBinding) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use CoreServiceBinding.ProtoReflect.Descriptor instead.
|
// Deprecated: Use CoreServiceBinding.ProtoReflect.Descriptor instead.
|
||||||
func (*CoreServiceBinding) Descriptor() ([]byte, []int) {
|
func (*CoreServiceBinding) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_manifest_proto_rawDescGZIP(), []int{14}
|
return file_v1_manifest_proto_rawDescGZIP(), []int{15}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CoreServiceBinding) GetServiceName() string {
|
func (x *CoreServiceBinding) GetServiceName() string {
|
||||||
@ -1423,7 +1524,7 @@ var File_v1_manifest_proto protoreflect.FileDescriptor
|
|||||||
|
|
||||||
const file_v1_manifest_proto_rawDesc = "" +
|
const file_v1_manifest_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\x11v1/manifest.proto\x12\x06abi.v1\"\xaf\x0e\n" +
|
"\x11v1/manifest.proto\x12\x06abi.v1\"\xe7\x0e\n" +
|
||||||
"\x0ePluginManifest\x12\x1f\n" +
|
"\x0ePluginManifest\x12\x1f\n" +
|
||||||
"\vabi_version\x18\x01 \x01(\rR\n" +
|
"\vabi_version\x18\x01 \x01(\rR\n" +
|
||||||
"abiVersion\x12\x12\n" +
|
"abiVersion\x12\x12\n" +
|
||||||
@ -1465,10 +1566,19 @@ const file_v1_manifest_proto_rawDesc = "" +
|
|||||||
"\rallowed_hosts\x18\" \x03(\tR\fallowedHosts\x12&\n" +
|
"\rallowed_hosts\x18\" \x03(\tR\fallowedHosts\x12&\n" +
|
||||||
"\x0fmax_response_mb\x18# \x01(\rR\rmaxResponseMb\x128\n" +
|
"\x0fmax_response_mb\x18# \x01(\rR\rmaxResponseMb\x128\n" +
|
||||||
"\rpublic_routes\x18$ \x03(\v2\x13.abi.v1.PublicRouteR\fpublicRoutes\x12\x18\n" +
|
"\rpublic_routes\x18$ \x03(\v2\x13.abi.v1.PublicRouteR\fpublicRoutes\x12\x18\n" +
|
||||||
"\asitemap\x18% \x01(\bR\asitemap\x1aB\n" +
|
"\asitemap\x18% \x01(\bR\asitemap\x126\n" +
|
||||||
|
"\tmcp_tools\x18& \x03(\v2\x19.abi.v1.MCPToolDescriptorR\bmcpTools\x1aB\n" +
|
||||||
"\x14RbacMethodRolesEntry\x12\x10\n" +
|
"\x14RbacMethodRolesEntry\x12\x10\n" +
|
||||||
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
|
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
|
||||||
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"9\n" +
|
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xf2\x01\n" +
|
||||||
|
"\x11MCPToolDescriptor\x12\x1c\n" +
|
||||||
|
"\tprocedure\x18\x01 \x01(\tR\tprocedure\x12*\n" +
|
||||||
|
"\x11service_full_name\x18\x02 \x01(\tR\x0fserviceFullName\x12\x1f\n" +
|
||||||
|
"\vmethod_name\x18\x03 \x01(\tR\n" +
|
||||||
|
"methodName\x12 \n" +
|
||||||
|
"\vdescription\x18\x04 \x01(\tR\vdescription\x12$\n" +
|
||||||
|
"\rdocumentation\x18\x05 \x01(\tR\rdocumentation\x12*\n" +
|
||||||
|
"\x11input_schema_json\x18\x06 \x01(\fR\x0finputSchemaJson\"9\n" +
|
||||||
"\vPublicRoute\x12\x12\n" +
|
"\vPublicRoute\x12\x12\n" +
|
||||||
"\x04path\x18\x01 \x01(\tR\x04path\x12\x16\n" +
|
"\x04path\x18\x01 \x01(\tR\x04path\x12\x16\n" +
|
||||||
"\x06prefix\x18\x02 \x01(\bR\x06prefix\"a\n" +
|
"\x06prefix\x18\x02 \x01(\bR\x06prefix\"a\n" +
|
||||||
@ -1566,52 +1676,54 @@ func file_v1_manifest_proto_rawDescGZIP() []byte {
|
|||||||
return file_v1_manifest_proto_rawDescData
|
return file_v1_manifest_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_v1_manifest_proto_msgTypes = make([]protoimpl.MessageInfo, 19)
|
var file_v1_manifest_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
|
||||||
var file_v1_manifest_proto_goTypes = []any{
|
var file_v1_manifest_proto_goTypes = []any{
|
||||||
(*PluginManifest)(nil), // 0: abi.v1.PluginManifest
|
(*PluginManifest)(nil), // 0: abi.v1.PluginManifest
|
||||||
(*PublicRoute)(nil), // 1: abi.v1.PublicRoute
|
(*MCPToolDescriptor)(nil), // 1: abi.v1.MCPToolDescriptor
|
||||||
(*Dependency)(nil), // 2: abi.v1.Dependency
|
(*PublicRoute)(nil), // 2: abi.v1.PublicRoute
|
||||||
(*BlockMeta)(nil), // 3: abi.v1.BlockMeta
|
(*Dependency)(nil), // 3: abi.v1.Dependency
|
||||||
(*BlockTemplateOverride)(nil), // 4: abi.v1.BlockTemplateOverride
|
(*BlockMeta)(nil), // 4: abi.v1.BlockMeta
|
||||||
(*SystemTemplateMeta)(nil), // 5: abi.v1.SystemTemplateMeta
|
(*BlockTemplateOverride)(nil), // 5: abi.v1.BlockTemplateOverride
|
||||||
(*PageTemplateMeta)(nil), // 6: abi.v1.PageTemplateMeta
|
(*SystemTemplateMeta)(nil), // 6: abi.v1.SystemTemplateMeta
|
||||||
(*AdminPage)(nil), // 7: abi.v1.AdminPage
|
(*PageTemplateMeta)(nil), // 7: abi.v1.PageTemplateMeta
|
||||||
(*AiAction)(nil), // 8: abi.v1.AiAction
|
(*AdminPage)(nil), // 8: abi.v1.AdminPage
|
||||||
(*CssManifest)(nil), // 9: abi.v1.CssManifest
|
(*AiAction)(nil), // 9: abi.v1.AiAction
|
||||||
(*DirectoryExtensions)(nil), // 10: abi.v1.DirectoryExtensions
|
(*CssManifest)(nil), // 10: abi.v1.CssManifest
|
||||||
(*BadgeLabel)(nil), // 11: abi.v1.BadgeLabel
|
(*DirectoryExtensions)(nil), // 11: abi.v1.DirectoryExtensions
|
||||||
(*MasterPageDefinition)(nil), // 12: abi.v1.MasterPageDefinition
|
(*BadgeLabel)(nil), // 12: abi.v1.BadgeLabel
|
||||||
(*MasterPageBlock)(nil), // 13: abi.v1.MasterPageBlock
|
(*MasterPageDefinition)(nil), // 13: abi.v1.MasterPageDefinition
|
||||||
(*CoreServiceBinding)(nil), // 14: abi.v1.CoreServiceBinding
|
(*MasterPageBlock)(nil), // 14: abi.v1.MasterPageBlock
|
||||||
nil, // 15: abi.v1.PluginManifest.RbacMethodRolesEntry
|
(*CoreServiceBinding)(nil), // 15: abi.v1.CoreServiceBinding
|
||||||
nil, // 16: abi.v1.CssManifest.NpmPackagesEntry
|
nil, // 16: abi.v1.PluginManifest.RbacMethodRolesEntry
|
||||||
nil, // 17: abi.v1.DirectoryExtensions.BadgeLabelsEntry
|
nil, // 17: abi.v1.CssManifest.NpmPackagesEntry
|
||||||
nil, // 18: abi.v1.CoreServiceBinding.MethodRolesEntry
|
nil, // 18: abi.v1.DirectoryExtensions.BadgeLabelsEntry
|
||||||
|
nil, // 19: abi.v1.CoreServiceBinding.MethodRolesEntry
|
||||||
}
|
}
|
||||||
var file_v1_manifest_proto_depIdxs = []int32{
|
var file_v1_manifest_proto_depIdxs = []int32{
|
||||||
2, // 0: abi.v1.PluginManifest.dependencies:type_name -> abi.v1.Dependency
|
3, // 0: abi.v1.PluginManifest.dependencies:type_name -> abi.v1.Dependency
|
||||||
3, // 1: abi.v1.PluginManifest.blocks:type_name -> abi.v1.BlockMeta
|
4, // 1: abi.v1.PluginManifest.blocks:type_name -> abi.v1.BlockMeta
|
||||||
4, // 2: abi.v1.PluginManifest.block_template_overrides:type_name -> abi.v1.BlockTemplateOverride
|
5, // 2: abi.v1.PluginManifest.block_template_overrides:type_name -> abi.v1.BlockTemplateOverride
|
||||||
5, // 3: abi.v1.PluginManifest.system_templates:type_name -> abi.v1.SystemTemplateMeta
|
6, // 3: abi.v1.PluginManifest.system_templates:type_name -> abi.v1.SystemTemplateMeta
|
||||||
6, // 4: abi.v1.PluginManifest.page_templates:type_name -> abi.v1.PageTemplateMeta
|
7, // 4: abi.v1.PluginManifest.page_templates:type_name -> abi.v1.PageTemplateMeta
|
||||||
7, // 5: abi.v1.PluginManifest.admin_pages:type_name -> abi.v1.AdminPage
|
8, // 5: abi.v1.PluginManifest.admin_pages:type_name -> abi.v1.AdminPage
|
||||||
12, // 6: abi.v1.PluginManifest.master_pages:type_name -> abi.v1.MasterPageDefinition
|
13, // 6: abi.v1.PluginManifest.master_pages:type_name -> abi.v1.MasterPageDefinition
|
||||||
8, // 7: abi.v1.PluginManifest.ai_actions:type_name -> abi.v1.AiAction
|
9, // 7: abi.v1.PluginManifest.ai_actions:type_name -> abi.v1.AiAction
|
||||||
15, // 8: abi.v1.PluginManifest.rbac_method_roles:type_name -> abi.v1.PluginManifest.RbacMethodRolesEntry
|
16, // 8: abi.v1.PluginManifest.rbac_method_roles:type_name -> abi.v1.PluginManifest.RbacMethodRolesEntry
|
||||||
9, // 9: abi.v1.PluginManifest.css_manifest:type_name -> abi.v1.CssManifest
|
10, // 9: abi.v1.PluginManifest.css_manifest:type_name -> abi.v1.CssManifest
|
||||||
10, // 10: abi.v1.PluginManifest.directory_extensions:type_name -> abi.v1.DirectoryExtensions
|
11, // 10: abi.v1.PluginManifest.directory_extensions:type_name -> abi.v1.DirectoryExtensions
|
||||||
14, // 11: abi.v1.PluginManifest.core_service_bindings:type_name -> abi.v1.CoreServiceBinding
|
15, // 11: abi.v1.PluginManifest.core_service_bindings:type_name -> abi.v1.CoreServiceBinding
|
||||||
1, // 12: abi.v1.PluginManifest.public_routes:type_name -> abi.v1.PublicRoute
|
2, // 12: abi.v1.PluginManifest.public_routes:type_name -> abi.v1.PublicRoute
|
||||||
16, // 13: abi.v1.CssManifest.npm_packages:type_name -> abi.v1.CssManifest.NpmPackagesEntry
|
1, // 13: abi.v1.PluginManifest.mcp_tools:type_name -> abi.v1.MCPToolDescriptor
|
||||||
17, // 14: abi.v1.DirectoryExtensions.badge_labels:type_name -> abi.v1.DirectoryExtensions.BadgeLabelsEntry
|
17, // 14: abi.v1.CssManifest.npm_packages:type_name -> abi.v1.CssManifest.NpmPackagesEntry
|
||||||
13, // 15: abi.v1.MasterPageDefinition.blocks:type_name -> abi.v1.MasterPageBlock
|
18, // 15: abi.v1.DirectoryExtensions.badge_labels:type_name -> abi.v1.DirectoryExtensions.BadgeLabelsEntry
|
||||||
18, // 16: abi.v1.CoreServiceBinding.method_roles:type_name -> abi.v1.CoreServiceBinding.MethodRolesEntry
|
14, // 16: abi.v1.MasterPageDefinition.blocks:type_name -> abi.v1.MasterPageBlock
|
||||||
11, // 17: abi.v1.DirectoryExtensions.BadgeLabelsEntry.value:type_name -> abi.v1.BadgeLabel
|
19, // 17: abi.v1.CoreServiceBinding.method_roles:type_name -> abi.v1.CoreServiceBinding.MethodRolesEntry
|
||||||
18, // [18:18] is the sub-list for method output_type
|
12, // 18: abi.v1.DirectoryExtensions.BadgeLabelsEntry.value:type_name -> abi.v1.BadgeLabel
|
||||||
18, // [18:18] is the sub-list for method input_type
|
19, // [19:19] is the sub-list for method output_type
|
||||||
18, // [18:18] is the sub-list for extension type_name
|
19, // [19:19] is the sub-list for method input_type
|
||||||
18, // [18:18] is the sub-list for extension extendee
|
19, // [19:19] is the sub-list for extension type_name
|
||||||
0, // [0:18] is the sub-list for field type_name
|
19, // [19:19] is the sub-list for extension extendee
|
||||||
|
0, // [0:19] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_v1_manifest_proto_init() }
|
func init() { file_v1_manifest_proto_init() }
|
||||||
@ -1619,14 +1731,14 @@ func file_v1_manifest_proto_init() {
|
|||||||
if File_v1_manifest_proto != nil {
|
if File_v1_manifest_proto != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
file_v1_manifest_proto_msgTypes[13].OneofWrappers = []any{}
|
file_v1_manifest_proto_msgTypes[14].OneofWrappers = []any{}
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_v1_manifest_proto_rawDesc), len(file_v1_manifest_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_v1_manifest_proto_rawDesc), len(file_v1_manifest_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 19,
|
NumMessages: 20,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -247,12 +247,14 @@ func (g *guest) captureServiceRegistration(m *abiv1.PluginManifest) {
|
|||||||
if coreBound[svc.Name()] {
|
if coreBound[svc.Name()] {
|
||||||
continue // declared via core_service_bindings, host mounts it
|
continue // declared via core_service_bindings, host mounts it
|
||||||
}
|
}
|
||||||
for method, role := range svc.MethodRoles() {
|
methodRoles := svc.MethodRoles()
|
||||||
|
for method, role := range methodRoles {
|
||||||
if m.RbacMethodRoles == nil {
|
if m.RbacMethodRoles == nil {
|
||||||
m.RbacMethodRoles = make(map[string]string)
|
m.RbacMethodRoles = make(map[string]string)
|
||||||
}
|
}
|
||||||
m.RbacMethodRoles[method] = string(role)
|
m.RbacMethodRoles[method] = string(role)
|
||||||
}
|
}
|
||||||
|
m.McpTools = append(m.McpTools, captureMCPTools(methodRoles)...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
206
plugin/wasmguest/mcp.go
Normal file
206
plugin/wasmguest/mcp.go
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
package wasmguest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
abiv1 "git.dev.alexdunmow.com/block/pluginsdk/abi/v1"
|
||||||
|
"git.dev.alexdunmow.com/block/pluginsdk/rbac"
|
||||||
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
"google.golang.org/protobuf/reflect/protoregistry"
|
||||||
|
)
|
||||||
|
|
||||||
|
// captureMCPTools resolves the plugin's registered Connect procedures through
|
||||||
|
// the protobuf registry compiled into the guest. It emits only unary methods
|
||||||
|
// that have an explicit RBAC mapping; the host repeats that RBAC intersection
|
||||||
|
// before adding the definitions to its live MCP catalogue.
|
||||||
|
func captureMCPTools(methodRoles map[string]rbac.Role) []*abiv1.MCPToolDescriptor {
|
||||||
|
procedures := make([]string, 0, len(methodRoles))
|
||||||
|
for procedure := range methodRoles {
|
||||||
|
procedures = append(procedures, procedure)
|
||||||
|
}
|
||||||
|
sort.Strings(procedures)
|
||||||
|
|
||||||
|
tools := make([]*abiv1.MCPToolDescriptor, 0, len(procedures))
|
||||||
|
for _, procedure := range procedures {
|
||||||
|
serviceName, methodName, ok := splitConnectProcedure(procedure)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
desc, err := protoregistry.GlobalFiles.FindDescriptorByName(protoreflect.FullName(serviceName))
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
service, ok := desc.(protoreflect.ServiceDescriptor)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
method := service.Methods().ByName(protoreflect.Name(methodName))
|
||||||
|
if method == nil || method.IsStreamingClient() || method.IsStreamingServer() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
schema, err := json.Marshal(schemaForMessage(method.Input(), map[protoreflect.FullName]bool{}))
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
description, documentation := methodDocumentation(method)
|
||||||
|
tools = append(tools, &abiv1.MCPToolDescriptor{
|
||||||
|
Procedure: procedure,
|
||||||
|
ServiceFullName: serviceName,
|
||||||
|
MethodName: methodName,
|
||||||
|
Description: description,
|
||||||
|
Documentation: documentation,
|
||||||
|
InputSchemaJson: schema,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return tools
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitConnectProcedure(procedure string) (serviceName, methodName string, ok bool) {
|
||||||
|
trimmed := strings.TrimPrefix(strings.TrimSpace(procedure), "/")
|
||||||
|
serviceName, methodName, ok = strings.Cut(trimmed, "/")
|
||||||
|
return serviceName, methodName, ok && serviceName != "" && methodName != "" && !strings.Contains(methodName, "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
func methodDocumentation(method protoreflect.MethodDescriptor) (description, documentation string) {
|
||||||
|
location := method.ParentFile().SourceLocations().ByDescriptor(method)
|
||||||
|
documentation = strings.TrimSpace(location.LeadingComments)
|
||||||
|
paragraph := documentation
|
||||||
|
if before, _, ok := strings.Cut(paragraph, "\n\n"); ok {
|
||||||
|
paragraph = before
|
||||||
|
}
|
||||||
|
paragraph = strings.TrimSpace(strings.ReplaceAll(paragraph, "\n", " "))
|
||||||
|
methodName := string(method.Name())
|
||||||
|
if strings.HasPrefix(paragraph, methodName+" ") {
|
||||||
|
paragraph = strings.TrimSpace(strings.TrimPrefix(paragraph, methodName+" "))
|
||||||
|
if paragraph != "" {
|
||||||
|
runes := []rune(paragraph)
|
||||||
|
runes[0] = unicode.ToUpper(runes[0])
|
||||||
|
paragraph = string(runes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if paragraph == "" {
|
||||||
|
paragraph = "Calls " + string(method.FullName()) + "."
|
||||||
|
}
|
||||||
|
return paragraph, documentation
|
||||||
|
}
|
||||||
|
|
||||||
|
func schemaForMessage(message protoreflect.MessageDescriptor, visited map[protoreflect.FullName]bool) map[string]any {
|
||||||
|
object := map[string]any{"type": "object"}
|
||||||
|
if message == nil || visited[message.FullName()] {
|
||||||
|
return object
|
||||||
|
}
|
||||||
|
visited[message.FullName()] = true
|
||||||
|
defer delete(visited, message.FullName())
|
||||||
|
|
||||||
|
properties := make(map[string]any, message.Fields().Len())
|
||||||
|
for i := range message.Fields().Len() {
|
||||||
|
field := message.Fields().Get(i)
|
||||||
|
properties[string(field.Name())] = fieldSchema(field, visited)
|
||||||
|
}
|
||||||
|
if len(properties) > 0 {
|
||||||
|
object["properties"] = properties
|
||||||
|
}
|
||||||
|
return object
|
||||||
|
}
|
||||||
|
|
||||||
|
func fieldSchema(field protoreflect.FieldDescriptor, visited map[protoreflect.FullName]bool) map[string]any {
|
||||||
|
var schema map[string]any
|
||||||
|
switch {
|
||||||
|
case field.IsMap():
|
||||||
|
schema = map[string]any{
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": singularFieldSchema(field.MapValue(), visited),
|
||||||
|
}
|
||||||
|
case field.IsList():
|
||||||
|
schema = map[string]any{"type": "array", "items": singularFieldSchema(field, visited)}
|
||||||
|
default:
|
||||||
|
schema = singularFieldSchema(field, visited)
|
||||||
|
}
|
||||||
|
|
||||||
|
location := field.ParentFile().SourceLocations().ByDescriptor(field)
|
||||||
|
if comment := strings.TrimSpace(strings.ReplaceAll(location.LeadingComments, "\n", " ")); comment != "" {
|
||||||
|
schema["description"] = comment
|
||||||
|
}
|
||||||
|
return schema
|
||||||
|
}
|
||||||
|
|
||||||
|
func singularFieldSchema(field protoreflect.FieldDescriptor, visited map[protoreflect.FullName]bool) map[string]any {
|
||||||
|
switch field.Kind() {
|
||||||
|
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||||
|
return wellKnownOrMessage(field.Message(), visited)
|
||||||
|
case protoreflect.EnumKind:
|
||||||
|
return enumSchema(field.Enum())
|
||||||
|
default:
|
||||||
|
return scalarSchema(field.Kind())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func scalarSchema(kind protoreflect.Kind) map[string]any {
|
||||||
|
switch kind {
|
||||||
|
case protoreflect.BoolKind:
|
||||||
|
return map[string]any{"type": "boolean"}
|
||||||
|
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind,
|
||||||
|
protoreflect.Uint32Kind, protoreflect.Fixed32Kind,
|
||||||
|
protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind,
|
||||||
|
protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
|
||||||
|
return map[string]any{"type": "integer"}
|
||||||
|
case protoreflect.FloatKind, protoreflect.DoubleKind:
|
||||||
|
return map[string]any{"type": "number"}
|
||||||
|
case protoreflect.StringKind:
|
||||||
|
return map[string]any{"type": "string"}
|
||||||
|
case protoreflect.BytesKind:
|
||||||
|
return map[string]any{"type": "string", "contentEncoding": "base64"}
|
||||||
|
default:
|
||||||
|
return map[string]any{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func enumSchema(enum protoreflect.EnumDescriptor) map[string]any {
|
||||||
|
schema := map[string]any{"type": "string"}
|
||||||
|
if enum == nil {
|
||||||
|
return schema
|
||||||
|
}
|
||||||
|
values := make([]any, 0, enum.Values().Len())
|
||||||
|
for i := range enum.Values().Len() {
|
||||||
|
values = append(values, string(enum.Values().Get(i).Name()))
|
||||||
|
}
|
||||||
|
if len(values) > 0 {
|
||||||
|
schema["enum"] = values
|
||||||
|
}
|
||||||
|
return schema
|
||||||
|
}
|
||||||
|
|
||||||
|
func wellKnownOrMessage(message protoreflect.MessageDescriptor, visited map[protoreflect.FullName]bool) map[string]any {
|
||||||
|
if message == nil {
|
||||||
|
return map[string]any{"type": "object"}
|
||||||
|
}
|
||||||
|
switch message.FullName() {
|
||||||
|
case "google.protobuf.Timestamp":
|
||||||
|
return map[string]any{"type": "string", "format": "date-time"}
|
||||||
|
case "google.protobuf.Duration", "google.protobuf.FieldMask":
|
||||||
|
return map[string]any{"type": "string"}
|
||||||
|
case "google.protobuf.Struct":
|
||||||
|
return map[string]any{"type": "object"}
|
||||||
|
case "google.protobuf.ListValue":
|
||||||
|
return map[string]any{"type": "array"}
|
||||||
|
case "google.protobuf.Value", "google.protobuf.Any":
|
||||||
|
return map[string]any{}
|
||||||
|
case "google.protobuf.Empty":
|
||||||
|
return map[string]any{"type": "object"}
|
||||||
|
case "google.protobuf.StringValue", "google.protobuf.BytesValue":
|
||||||
|
return map[string]any{"type": "string"}
|
||||||
|
case "google.protobuf.BoolValue":
|
||||||
|
return map[string]any{"type": "boolean"}
|
||||||
|
case "google.protobuf.Int32Value", "google.protobuf.UInt32Value",
|
||||||
|
"google.protobuf.Int64Value", "google.protobuf.UInt64Value":
|
||||||
|
return map[string]any{"type": "integer"}
|
||||||
|
case "google.protobuf.FloatValue", "google.protobuf.DoubleValue":
|
||||||
|
return map[string]any{"type": "number"}
|
||||||
|
default:
|
||||||
|
return schemaForMessage(message, visited)
|
||||||
|
}
|
||||||
|
}
|
||||||
100
plugin/wasmguest/mcp_test.go
Normal file
100
plugin/wasmguest/mcp_test.go
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package wasmguest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.dev.alexdunmow.com/block/pluginsdk/rbac"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
"google.golang.org/protobuf/reflect/protodesc"
|
||||||
|
"google.golang.org/protobuf/reflect/protoregistry"
|
||||||
|
"google.golang.org/protobuf/types/descriptorpb"
|
||||||
|
_ "google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCaptureMCPToolsUsesCompiledProtobufDescriptor(t *testing.T) {
|
||||||
|
registerMCPFixture(t)
|
||||||
|
procedure := "/mcpfixture.v1.WikiService/ListArticles"
|
||||||
|
tools := captureMCPTools(map[string]rbac.Role{procedure: rbac.RoleAdmin})
|
||||||
|
if len(tools) != 1 {
|
||||||
|
t.Fatalf("captureMCPTools() returned %d tools, want 1", len(tools))
|
||||||
|
}
|
||||||
|
tool := tools[0]
|
||||||
|
if tool.GetProcedure() != procedure || tool.GetServiceFullName() != "mcpfixture.v1.WikiService" || tool.GetMethodName() != "ListArticles" {
|
||||||
|
t.Fatalf("unexpected procedure metadata: %#v", tool)
|
||||||
|
}
|
||||||
|
if tool.GetDescription() != "Lists Wiki articles." || tool.GetDocumentation() != "ListArticles lists Wiki articles.\n\nSupports pagination." {
|
||||||
|
t.Fatalf("unexpected descriptor documentation: description=%q doc=%q", tool.GetDescription(), tool.GetDocumentation())
|
||||||
|
}
|
||||||
|
var schema map[string]any
|
||||||
|
if err := json.Unmarshal(tool.GetInputSchemaJson(), &schema); err != nil {
|
||||||
|
t.Fatalf("schema is not JSON: %v", err)
|
||||||
|
}
|
||||||
|
properties, ok := schema["properties"].(map[string]any)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("schema properties = %#v", schema["properties"])
|
||||||
|
}
|
||||||
|
assertSchemaType(t, properties, "search", "string")
|
||||||
|
assertSchemaType(t, properties, "page", "integer")
|
||||||
|
assertSchemaType(t, properties, "published_after", "string")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCaptureMCPToolsSkipsUnresolvableAndStreamingProcedures(t *testing.T) {
|
||||||
|
registerMCPFixture(t)
|
||||||
|
tools := captureMCPTools(map[string]rbac.Role{
|
||||||
|
"/mcpfixture.v1.WikiService/StreamArticles": rbac.RoleAdmin,
|
||||||
|
"/missing.v1.WikiService/ListArticles": rbac.RoleAdmin,
|
||||||
|
"not-a-procedure": rbac.RoleAdmin,
|
||||||
|
})
|
||||||
|
if len(tools) != 0 {
|
||||||
|
t.Fatalf("captureMCPTools() returned %d tools, want fail-closed omission", len(tools))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertSchemaType(t *testing.T, properties map[string]any, field, expected string) {
|
||||||
|
t.Helper()
|
||||||
|
property, ok := properties[field].(map[string]any)
|
||||||
|
if !ok || property["type"] != expected {
|
||||||
|
t.Fatalf("schema field %q = %#v, want type %q", field, properties[field], expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerMCPFixture(t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
if _, err := protoregistry.GlobalFiles.FindFileByPath("test/mcpfixture.proto"); err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
file, err := protodesc.NewFile(&descriptorpb.FileDescriptorProto{
|
||||||
|
Name: proto.String("test/mcpfixture.proto"),
|
||||||
|
Package: proto.String("mcpfixture.v1"),
|
||||||
|
Syntax: proto.String("proto3"),
|
||||||
|
Dependency: []string{"google/protobuf/timestamp.proto"},
|
||||||
|
MessageType: []*descriptorpb.DescriptorProto{{
|
||||||
|
Name: proto.String("ListArticlesRequest"),
|
||||||
|
Field: []*descriptorpb.FieldDescriptorProto{
|
||||||
|
{Name: proto.String("search"), Number: proto.Int32(1), Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), Type: descriptorpb.FieldDescriptorProto_TYPE_STRING.Enum()},
|
||||||
|
{Name: proto.String("page"), Number: proto.Int32(2), Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), Type: descriptorpb.FieldDescriptorProto_TYPE_INT32.Enum()},
|
||||||
|
{Name: proto.String("published_after"), Number: proto.Int32(3), Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(), Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(), TypeName: proto.String(".google.protobuf.Timestamp")},
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
Name: proto.String("ListArticlesResponse"),
|
||||||
|
}},
|
||||||
|
Service: []*descriptorpb.ServiceDescriptorProto{{
|
||||||
|
Name: proto.String("WikiService"),
|
||||||
|
Method: []*descriptorpb.MethodDescriptorProto{{
|
||||||
|
Name: proto.String("ListArticles"), InputType: proto.String(".mcpfixture.v1.ListArticlesRequest"), OutputType: proto.String(".mcpfixture.v1.ListArticlesResponse"),
|
||||||
|
}, {
|
||||||
|
Name: proto.String("StreamArticles"), InputType: proto.String(".mcpfixture.v1.ListArticlesRequest"), OutputType: proto.String(".mcpfixture.v1.ListArticlesResponse"), ServerStreaming: proto.Bool(true),
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
SourceCodeInfo: &descriptorpb.SourceCodeInfo{Location: []*descriptorpb.SourceCodeInfo_Location{{
|
||||||
|
Path: []int32{6, 0, 2, 0}, LeadingComments: proto.String("ListArticles lists Wiki articles.\n\nSupports pagination."),
|
||||||
|
}}},
|
||||||
|
}, protoregistry.GlobalFiles)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("create fixture descriptor: %v", err)
|
||||||
|
}
|
||||||
|
if err := protoregistry.GlobalFiles.RegisterFile(file); err != nil {
|
||||||
|
t.Fatalf("register fixture descriptor: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user