feat: implement auto-generation for MCP server description

- Add MCP_SERVER_DESCRIPTION_GENERATE_PROMPT template in prompts.py with detailed guidelines and examples
- Implement generate_mcp_description method in LLMGenerator class for AI-powered description generation
- Add AppMCPServerGenerateDescriptionController API endpoint for auto-generation functionality
- Integrate auto-generate button in MCP server modal frontend with loading state
- Add i18n support for auto-generate feature across multiple languages (en-US, zh-Hans, zh-Hant, ja-JP, ko-KR)
- Include comprehensive fallback mechanism when LLM generation fails
- Extract app features and characteristics for better description quality

Fixes #22443
pull/22452/head
baonudesifeizhai 10 months ago
parent b690a9d839
commit ab63d87b09

@ -103,5 +103,113 @@ class AppMCPServerRefreshController(Resource):
return server
class AppMCPServerGenerateDescriptionController(Resource):
@setup_required
@login_required
@account_initialization_required
@get_app_model
def post(self, app_model):
"""Generate MCP server description automatically based on app information"""
if not current_user.is_editor:
raise NotFound()
from core.llm_generator.llm_generator import LLMGenerator
# Extract app information for description generation
app_name = app_model.name
app_description = app_model.description or ""
app_type = app_model.mode or ""
# Provide default descriptions if app_description is empty
if not app_description:
if app_type == "chat":
app_description = "An interactive conversational AI application for natural language communication"
elif app_type == "completion":
app_description = "A text generation application for creating high-quality content"
elif app_type == "agent-chat":
app_description = "An intelligent agent application with autonomous tool capabilities"
elif app_type == "workflow":
app_description = "A workflow-based application for automated task processing"
elif app_type == "advanced-chat":
app_description = "An advanced conversational AI with enhanced memory and reasoning"
else:
app_description = "An AI-powered application providing intelligent assistance"
# Get key features from app configuration
key_features = ""
if app_model.app_model_config:
model_config = app_model.app_model_config.to_dict()
features = []
# Basic app features based on mode
if app_type == "chat":
features.append("Interactive chat conversations")
elif app_type == "completion":
features.append("Text generation and completion")
elif app_type == "agent-chat":
features.append("Intelligent agent with tool capabilities")
elif app_type == "workflow":
features.append("Workflow-based automation")
elif app_type == "advanced-chat":
features.append("Advanced conversational AI with memory")
# Configuration-based features
if model_config.get("opening_statement"):
features.append("Custom greeting messages")
if model_config.get("suggested_questions"):
features.append("Suggested conversation starters")
if model_config.get("speech_to_text", {}).get("enabled"):
features.append("Voice input support")
if model_config.get("text_to_speech", {}).get("enabled"):
features.append("Voice response output")
if model_config.get("retriever_resource"):
features.append("Knowledge base integration")
if model_config.get("annotation_reply", {}).get("enabled"):
features.append("Enhanced response annotations")
if model_config.get("more_like_this", {}).get("enabled"):
features.append("Similar content suggestions")
if model_config.get("sensitive_word_avoidance", {}).get("enabled"):
features.append("Content moderation")
# Model-based capabilities
if model_config.get("model", {}).get("name"):
model_name = model_config.get("model", {}).get("name", "")
if "gpt-4" in model_name.lower():
features.append("Advanced reasoning capabilities")
elif "claude" in model_name.lower():
features.append("Enhanced text analysis")
key_features = ", ".join(features) if features else "AI-powered assistance"
try:
# Generate description using LLM
description = LLMGenerator.generate_mcp_description(
tenant_id=current_user.current_tenant_id,
app_name=app_name,
app_description=app_description,
app_type=app_type,
key_features=key_features,
app_id=app_model.id,
)
return {"description": description}
except Exception as e:
# Log the error for debugging
import logging
logging.exception("MCP description generation failed")
# Fallback to a basic description if generation fails
fallback_description = (
f"A {app_type or 'AI'} application '{app_name}' that provides "
f"intelligent assistance and automated capabilities for enhanced "
f"user productivity and task completion."
)
return {"description": fallback_description, "error": str(e), "fallback": True}
api.add_resource(AppMCPServerController, "/apps/<uuid:app_id>/server")
api.add_resource(AppMCPServerRefreshController, "/apps/<uuid:server_id>/server/refresh")
api.add_resource(AppMCPServerGenerateDescriptionController, "/apps/<uuid:app_id>/server/generate-description")

@ -11,6 +11,7 @@ from core.llm_generator.prompts import (
CONVERSATION_TITLE_PROMPT,
GENERATOR_QA_PROMPT,
JAVASCRIPT_CODE_GENERATOR_PROMPT_TEMPLATE,
MCP_SERVER_DESCRIPTION_GENERATE_PROMPT,
PYTHON_CODE_GENERATOR_PROMPT_TEMPLATE,
SYSTEM_STRUCTURED_OUTPUT_GENERATE,
WORKFLOW_RULE_CONFIG_PROMPT_GENERATE_TEMPLATE,
@ -394,3 +395,100 @@ class LLMGenerator:
except Exception as e:
logging.exception(f"Failed to invoke LLM model, model: {model_config.get('name')}")
return {"output": "", "error": f"An unexpected error occurred: {str(e)}"}
@classmethod
def generate_mcp_description(
cls,
tenant_id: str,
app_name: str,
app_description: str = "",
app_type: str = "",
key_features: str = "",
app_id: Optional[str] = None,
) -> str:
"""
Generate MCP server description based on application information.
Args:
tenant_id: The tenant ID
app_name: The application name
app_description: The application description
app_type: The application type
key_features: Key features of the application
app_id: Optional application ID for tracing
Returns:
Generated description string
"""
try:
# Prepare the prompt with application information
prompt_template = PromptTemplateParser(template=MCP_SERVER_DESCRIPTION_GENERATE_PROMPT)
prompt = prompt_template.format(
{
"APP_NAME": app_name,
"APP_DESCRIPTION": app_description or "Not provided",
"APP_TYPE": app_type or "Not specified",
"KEY_FEATURES": key_features or "Not specified",
}
)
model_manager = ModelManager()
model_instance = model_manager.get_default_model_instance(
tenant_id=tenant_id,
model_type=ModelType.LLM,
)
prompts = [UserPromptMessage(content=prompt)]
with measure_time() as timer:
response = cast(
LLMResult,
model_instance.invoke_llm(
prompt_messages=list(prompts),
model_parameters={"max_tokens": 150, "temperature": 0.7},
stream=False,
),
)
generated_description = cast(str, response.message.content).strip()
# Clean up the description (remove quotes if present)
if generated_description.startswith('"') and generated_description.endswith('"'):
generated_description = generated_description[1:-1]
# Limit length to 200 characters
if len(generated_description) > 200:
generated_description = generated_description[:197] + "..."
# Add tracing if app_id is provided
if app_id:
trace_manager = TraceQueueManager(app_id=app_id)
trace_manager.add_trace_task(
TraceTask(
TraceTaskName.GENERATE_NAME_TRACE, # Reusing existing trace type
generate_conversation_name=f"MCP Description: {generated_description}",
inputs=prompt,
timer=timer,
tenant_id=tenant_id,
)
)
return generated_description
except Exception as e:
logging.exception(f"Failed to generate MCP description for app: {app_name}")
# Return a more detailed fallback description
fallback_desc = (
f"A comprehensive {app_type or 'AI'} application called '{app_name}' "
f"designed to provide intelligent assistance and advanced automation "
f"capabilities. This MCP server enables seamless integration with AI "
f"assistants, offering {key_features or 'powerful AI features'} to "
f"enhance productivity and streamline workflows for users across "
f"various tasks and scenarios."
)
# Limit fallback length to 600 characters
if len(fallback_desc) > 600:
fallback_desc = fallback_desc[:597] + "..."
return fallback_desc

@ -309,3 +309,58 @@ eg:
Here is the JSON schema:
{{schema}}
""" # noqa: E501
MCP_SERVER_DESCRIPTION_GENERATE_PROMPT = """You are an expert technical writer specializing in creating clear and
comprehensive descriptions for MCP (Model Context Protocol) servers.
Your task is to generate a professional description for an MCP server based on the provided application information.
## Guidelines:
1. The description should be comprehensive (200-600 characters)
2. Focus on the core functionality and purpose
3. Use clear, professional language
4. Include key features and capabilities
5. Make it user-friendly and understandable
6. Explain how the MCP server enhances the application's functionality
7. Provide enough detail to help users understand the value proposition
## Input Information:
- Application Name: {{APP_NAME}}
- Application Description: {{APP_DESCRIPTION}}
- Application Type: {{APP_TYPE}}
- Key Features: {{KEY_FEATURES}}
## Instructions:
1. Analyze the application information provided
2. Identify the core purpose and main functionality
3. Generate a detailed description that explains what this MCP server does
4. Include specific capabilities and how they benefit users
5. Explain the integration value for AI assistants
6. Focus on practical benefits and use cases
7. Keep the language accessible to both technical and non-technical users
## Output Format:
Return only the description text without any additional formatting, quotes, or explanations.
## Examples:
### For a Task Manager:
A comprehensive productivity MCP server that enables intelligent task management through automated
organization, deadline tracking, and priority optimization. This server provides AI assistants with
capabilities to create, update, and analyze tasks while offering smart scheduling suggestions, progress
monitoring, and workflow automation to enhance user productivity and goal achievement.
### For a Weather App:
A powerful weather intelligence MCP server that delivers real-time meteorological data, location-based
forecasting, and weather analytics. This server empowers AI assistants to provide accurate weather
information, severe weather alerts, travel planning assistance, and activity recommendations based on
current and predicted weather conditions for enhanced decision-making.
### For a Data Analyzer:
An advanced analytics MCP server that provides comprehensive data processing, statistical analysis, and
visualization capabilities. This server enables AI assistants to perform complex data operations, generate
insights, create interactive charts, and deliver actionable intelligence from datasets to support
data-driven decision making and business intelligence needs.
Generate description:
"""

@ -1,7 +1,7 @@
'use client'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { RiCloseLine } from '@remixicon/react'
import { RiCloseLine, RiMagicLine } from '@remixicon/react'
import Modal from '@/app/components/base/modal'
import Button from '@/app/components/base/button'
import Textarea from '@/app/components/base/textarea'
@ -12,6 +12,7 @@ import type {
} from '@/app/components/tools/types'
import {
useCreateMCPServer,
useGenerateMCPDescription,
useInvalidateMCPServerDetail,
useUpdateMCPServer,
} from '@/service/use-tools'
@ -35,6 +36,7 @@ const MCPServerModal = ({
const { t } = useTranslation()
const { mutateAsync: createMCPServer, isPending: creating } = useCreateMCPServer()
const { mutateAsync: updateMCPServer, isPending: updating } = useUpdateMCPServer()
const { mutateAsync: generateDescription, isPending: generating } = useGenerateMCPDescription()
const invalidateMCPServerDetail = useInvalidateMCPServerDetail()
const [description, setDescription] = React.useState(data?.description || '')
@ -56,6 +58,17 @@ const MCPServerModal = ({
return res
}
const handleGenerateDescription = async () => {
try {
const result: any = await generateDescription({ appID })
if (result?.description)
setDescription(result.description)
}
catch (error) {
console.error('Failed to generate description:', error)
}
}
const submit = async () => {
if (!data) {
await createMCPServer({
@ -92,9 +105,23 @@ const MCPServerModal = ({
</div>
<div className='space-y-5 px-6 py-3'>
<div className='space-y-0.5'>
<div className='flex h-6 items-center gap-1'>
<div className='flex h-6 items-center justify-between'>
<div className='flex items-center gap-1'>
<div className='system-sm-medium text-text-secondary'>{t('tools.mcp.server.modal.description')}</div>
<div className='system-xs-regular text-text-destructive-secondary'>*</div>
</div>
<Button
size='small'
variant='ghost'
onClick={handleGenerateDescription}
disabled={generating}
className='!h-6 !px-2 !py-1'
>
<RiMagicLine className='h-3 w-3' />
<span className='system-xs-medium text-text-tertiary'>
{generating ? t('tools.mcp.server.modal.generating') : t('tools.mcp.server.modal.generate')}
</span>
</Button>
</div>
<Textarea
className='h-[96px] resize-none'

@ -224,6 +224,8 @@ const translation = {
editTitle: 'Edit description',
description: 'Description',
descriptionPlaceholder: 'Explain what this tool does and how it should be used by the LLM',
generate: 'Generate',
generating: 'Generating...',
parameters: 'Parameters',
parametersTip: 'Add descriptions for each parameter to help the LLM understand their purpose and constraints.',
parametersPlaceholder: 'Parameter purpose and constraints',

@ -219,11 +219,13 @@ const translation = {
addTitle: 'MCPサーバーを有効化するための説明を追加',
editTitle: '説明を編集',
description: '説明',
descriptionPlaceholder: 'このツールの機能とLLM大規模言語モデルでの使用方法を説明してください。',
descriptionPlaceholder: 'このツールが何をするのか、LLMがどのように使用すべきかを説明してください',
generate: '自動生成',
generating: '生成中...',
parameters: 'パラメータ',
parametersTip: '各パラメータの説明を追加して、LLMがその目的と制約を理解できるようにします。',
parametersPlaceholder: 'パラメータの目的と制約',
confirm: 'MCPサーバーを有効にする',
confirm: 'MCPサーバーを有効',
},
publishTip: 'アプリが公開されていません。まずアプリを公開してください。',
},

@ -216,13 +216,15 @@ const translation = {
addDescription: '설명 추가',
edit: '설명 수정',
modal: {
addTitle: 'MCP 서버를 활성화하기 위 설명 추가',
editTitle: '설명 수정',
addTitle: 'MCP 서버를 활성화하기 위 설명 추가',
editTitle: '설명 편집',
description: '설명',
descriptionPlaceholder: '이 도구가 수행하는 작업과 LLM이 사용하는 방법을 설명하세요.',
descriptionPlaceholder: '이 도구가 무엇을 하는지, LLM이 어떻게 사용해야 하는지 설명하세요',
generate: '자동 생성',
generating: '생성 중...',
parameters: '매개변수',
parametersTip: '각 매개변수의 설명을 추가하여 LLM이 목적과 제한 사항을 이해할 수 있도록 도와주세요.',
parametersPlaceholder: '매개변수의 목적 및 제한 사항',
parametersTip: '각 매개변수에 대한 설명을 추가하여 LLM이 목적과 제약사항을 이해할 수 있도록 도움을 주세요.',
parametersPlaceholder: '매개변수 목적 및 제약사항',
confirm: 'MCP 서버 활성화',
},
publishTip: '앱이 게시되지 않았습니다. 먼저 앱을 게시하십시오.',

@ -224,6 +224,8 @@ const translation = {
editTitle: '编辑 MCP 服务描述',
description: '描述',
descriptionPlaceholder: '解释此工具的功能以及 LLM 应如何使用它',
generate: '自动生成',
generating: '生成中...',
parameters: '参数',
parametersTip: '为每个参数添加描述,以帮助 LLM 理解其目的和约束条件。',
parametersPlaceholder: '参数的用途和约束条件',

@ -220,6 +220,8 @@ const translation = {
editTitle: '編輯描述',
description: '描述',
descriptionPlaceholder: '說明此工具的用途及如何被 LLM 使用',
generate: '自動生成',
generating: '生成中...',
parameters: '參數',
parametersTip: '為每個參數添加描述,以幫助 LLM 理解其目的和約束。',
parametersPlaceholder: '參數的目的和約束',

@ -306,3 +306,15 @@ export const useRemoveProviderCredentials = ({
onSuccess,
})
}
export const useGenerateMCPDescription = () => {
return useMutation({
mutationKey: [NAME_SPACE, 'generate-mcp-description'],
mutationFn: (payload: {
appID: string
}) => {
const { appID } = payload
return post(`apps/${appID}/server/generate-description`)
},
})
}

Loading…
Cancel
Save