mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-06-19 07:43:46 +08:00
Introduce support for Model Context Protocol (MCP) servers in the discourse-ai plugin, allowing AI agents to connect to external tool servers via the MCP standard. Key additions: - AiMcpServer model with CRUD admin UI, health tracking, and tool caching (hourly refresh via scheduled job) - MCP client (Streamable HTTP transport) with session management and tool invocation - Full OAuth 2.1 flow support (discovery, dynamic registration, authorization code grant, token refresh, and disconnect) - MCP tool type for AI agents that proxies tool calls to remote MCP servers at runtime - Agent editor updated to show combined tool/token counts from both local tools and MCP servers - Agent import/export includes MCP server associations - Admin secrets UI updated to surface MCP server usage - Comprehensive specs for models, controllers, client, tool registry, and OAuth flow
111 lines
3.1 KiB
Ruby
Vendored
111 lines
3.1 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
class LocalizedAiAgentSerializer < ApplicationSerializer
|
|
root "ai_agent"
|
|
|
|
attributes :id,
|
|
:name,
|
|
:description,
|
|
:enabled,
|
|
:system,
|
|
:priority,
|
|
:tools,
|
|
:system_prompt,
|
|
:allowed_group_ids,
|
|
:temperature,
|
|
:top_p,
|
|
:default_llm_id,
|
|
:user_id,
|
|
:max_context_posts,
|
|
:vision_enabled,
|
|
:vision_max_pixels,
|
|
:rag_chunk_tokens,
|
|
:rag_chunk_overlap_tokens,
|
|
:rag_conversation_chunks,
|
|
:rag_llm_model_id,
|
|
:show_thinking,
|
|
:forced_tool_count,
|
|
:allow_chat_channel_mentions,
|
|
:allow_chat_direct_messages,
|
|
:allow_topic_mentions,
|
|
:allow_personal_messages,
|
|
:force_default_llm,
|
|
:execution_mode,
|
|
:max_turn_tokens,
|
|
:compression_threshold,
|
|
:require_approval,
|
|
:mcp_server_ids,
|
|
:mcp_server_tool_names,
|
|
:mcp_servers,
|
|
:response_format,
|
|
:examples,
|
|
:features
|
|
|
|
has_one :user, serializer: BasicUserSerializer, embed: :object
|
|
has_many :rag_uploads, serializer: UploadSerializer, embed: :object
|
|
has_one :default_llm, serializer: BasicLlmModelSerializer, embed: :object
|
|
|
|
def rag_uploads
|
|
object.uploads
|
|
end
|
|
|
|
def name
|
|
object.class_instance.name
|
|
end
|
|
|
|
def description
|
|
object.class_instance.description
|
|
end
|
|
|
|
def default_llm
|
|
LlmModel.find_by(id: object.default_llm_id)
|
|
end
|
|
|
|
def features
|
|
object.features.map do |feature|
|
|
{ id: feature.module_id, module_name: feature.module_name, name: feature.name }
|
|
end
|
|
end
|
|
|
|
def mcp_server_ids
|
|
enabled_mcp_server_assignments.filter_map(&:ai_mcp_server_id)
|
|
end
|
|
|
|
def mcp_server_tool_names
|
|
enabled_mcp_server_assignments.each_with_object({}) do |assignment, hash|
|
|
next if assignment.all_tools_enabled?
|
|
|
|
hash[assignment.ai_mcp_server_id.to_s] = assignment.selected_tool_names
|
|
end
|
|
end
|
|
|
|
def mcp_servers
|
|
sorted_enabled_mcp_server_assignments.map do |assignment|
|
|
server = assignment.ai_mcp_server
|
|
{
|
|
id: server.id,
|
|
name: server.name,
|
|
tool_count: server.tool_count,
|
|
token_count: server.token_count,
|
|
selected_tool_names: assignment.selected_tool_names,
|
|
selected_tool_count: assignment.tool_count,
|
|
selected_token_count: assignment.token_count,
|
|
all_tools_enabled: assignment.all_tools_enabled?,
|
|
last_health_status: server.last_health_status,
|
|
last_checked_at: server.last_checked_at,
|
|
}
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def enabled_mcp_server_assignments
|
|
@enabled_mcp_server_assignments ||=
|
|
object.ai_agent_mcp_servers.select { |assignment| assignment.ai_mcp_server&.enabled? }
|
|
end
|
|
|
|
def sorted_enabled_mcp_server_assignments
|
|
@sorted_enabled_mcp_server_assignments ||=
|
|
enabled_mcp_server_assignments.sort_by { |assignment| assignment.ai_mcp_server.name.downcase }
|
|
end
|
|
end
|