Prompts trong client — UX cho slash commands

8 — MCPTrung cấp15 phút

Bạn có prompts on server. Cần UX để user trigger:

Bạn sẽ học được
  • Detect user slash commands trong chat
  • Call server's get_prompt API
  • Inject prompt messages vào conversation
  • Handle prompt args (interactive param collection)

Client pattern

async def handle_user_input(user_input: str, client: MCPClient):
    # Detect slash command
    if user_input.startswith("/"):
        return await handle_slash_command(user_input, client)
    
    # Normal chat
    return await normal_chat(user_input, client)


async def handle_slash_command(command: str, client: MCPClient):
    """Parse and execute slash command."""
    parts = command[1:].split()  # remove /
    cmd_name = parts[0]
    args_list = parts[1:]
    
    # Fetch prompt metadata
    prompts = await client.list_prompts()
    matching = next((p for p in prompts if p.name == cmd_name), None)
    
    if not matching:
        print(f"Unknown command: /{cmd_name}")
        print(f"Available: {', '.join(p.name for p in prompts)}")
        return None
    
    # Build args from positional (simple case)
    args = {}
    if matching.arguments:
        for i, arg_def in enumerate(matching.arguments):
            if i < len(args_list):
                args[arg_def.name] = args_list[i]
            else:
                # Prompt for missing args
                value = input(f"  {arg_def.name}: ")
                args[arg_def.name] = value
    
    # Fetch prompt
    prompt_result = await client.get_prompt(cmd_name, args)
    
    return prompt_result.messages  # list of messages to inject

Full integration

/format report.pdf:

  • Client fetch prompt → list[UserMessage]
  • Inject into messages
  • Call Claude như normal
  • Claude follow expert instruction → high quality output
async def run_chatbot(client: MCPClient):
    tools = await client.list_tools()
    tool_schemas = [tool_to_schema(t) for t in tools]
    
    prompts = await client.list_prompts()
    prompt_help = "Slash commands:\n" + "\n".join(
        f"  /{p.name} — {p.description}" for p in prompts
    )
    print(prompt_help)
    
    messages = []
    
    while True:
        user_input = input("\nYou: ").strip()
        if user_input in ("quit", "exit"):
            break
        
        # Inject prompt messages if slash command
        if user_input.startswith("/"):
            prompt_messages = await handle_slash_command(user_input, client)
            if prompt_messages:
                for pm in prompt_messages:
                    role = "user" if pm.role == "user" else "assistant"
                    content = pm.content.text if hasattr(pm.content, "text") else pm.content
                    messages.append({"role": role, "content": content})
            else:
                continue
        else:
            messages.append({"role": "user", "content": user_input})
        
        # Run conversation loop
        await process_turn(messages, client, tool_schemas)

Interactive arg collection

Nếu missing args, prompt user:

UI improvement: autocomplete, forms.

async def handle_slash_command(command, client):
    parts = command[1:].split(maxsplit=1)
    cmd_name = parts[0]
    
    # Get prompt schema
    prompts = await client.list_prompts()
    matching = next((p for p in prompts if p.name == cmd_name), None)
    
    if not matching:
        print(f"Unknown: /{cmd_name}")
        return None
    
    # Show required args
    if matching.arguments:
        print(f"\n/{cmd_name} requires:")
        args = {}
        for arg_def in matching.arguments:
            required = "*" if arg_def.required else ""
            value = input(f"  {arg_def.name}{required} ({arg_def.description}): ").strip()
            if value:
                args[arg_def.name] = value
            elif arg_def.required:
                print("Required, cancelling")
                return None
    else:
        args = {}
    
    prompt_result = await client.get_prompt(cmd_name, args)
    return prompt_result.messages

Help command

Built-in /help:

Self-documenting CLI.

if user_input.startswith("/help"):
    prompts = await client.list_prompts()
    print("Available commands:")
    for p in prompts:
        print(f"  /{p.name} — {p.description}")
        if p.arguments:
            for arg in p.arguments:
                req = "*" if arg.required else ""
                print(f"    {arg.name}{req}: {arg.description}")
    continue

Tab completion (advanced)

Parse user input, suggest commands:

Now /f<TAB> autocompletes /format.

import readline

prompts_list = []

def completer(text, state):
    options = [f"/{p.name}" for p in prompts_list if p.name.startswith(text[1:])]
    if state < len(options):
        return options[state]
    return None

readline.set_completer(completer)
readline.parse_and_bind("tab: complete")

Multi-server prompts

Nếu connect multiple MCP servers, namespace commands:

Parse prefix:

/github:list_issues
/slack:send_message
/docs:format report.pdf

Multi-server prompts (tiếp)

Avoid collision.

if ":" in cmd_name:
    server_name, cmd_name = cmd_name.split(":", 1)
    client = self.clients[server_name]
    # ...

When to expose prompts in client

✅ Great UX

⚠️ Skip

  • CLI tools
  • Slack/Discord bots (/slash convention)
  • Developer tools
  • Power users
  • Consumer chatbots (non-tech users confused)
  • Web widgets (no keyboard input norm)
  • Single-use apps

Anti-patterns

❌ Mix prompts and tools

"Is /format a tool or prompt?" → confusing.

Fix: Prompt = multi-step instruction. Tool = 1 action. Name carefully.

❌ Hidden prompts

User không biết / commands.

Fix: /help or onboarding shows list.

❌ Tough command names

/reformat_document_to_markdown_syntax

Fix: Short: /format.

Áp dụng ngay

Bài tập 1: Slash command detection (20 phút)

Update chatbot: detect /format, /summarize. Fetch prompts from server, inject.

Bài tập 2: /help command (10 phút)

Add /help showing all prompts + args.

Tóm tắt

🎯 Slash commands UX pattern cho MCP prompts.

🎯 Client flow: parse command → get_prompt(name, args) → inject messages.

🎯 Interactive args: prompt user for missing required args.

🎯 /help self-documenting.

🎯 Multi-server: namespace với /server:command.

Nội dung này có hữu ích không?