Files
miku-discord/readmes/MCP_TOOL_CALLING_ANALYSIS.md
koko210Serve c708770266 reorganize: consolidate all documentation into readmes/
- Moved 20 root-level markdown files to readmes/
- Includes COMMANDS.md, CONFIG_README.md, all UNO docs, all completion reports
- Added new: MEMORY_EDITOR_FEATURE.md, MEMORY_EDITOR_ESCAPING_FIX.md,
  CONFIG_SOURCES_ANALYSIS.md, MCP_TOOL_CALLING_ANALYSIS.md, and others
- Root directory is now clean of documentation clutter
2026-03-04 00:19:49 +02:00

17 KiB

MCP Tool Calling Analysis: Jaison-core vs Miku Bot

Executive Summary

After analyzing both your Miku bot's autonomous system and jaison-core's MCP tool calling approach, here's my evaluation:

Verdict: Your current system is MORE SUITABLE for Miku's autonomous personality than MCP tool calling.

However, MCP could be complementary for extending Miku's capabilities in specific scenarios.


Architecture Comparison

Your Current System (Miku Bot)

Philosophy: Rule-based autonomous decision engine with personality-driven behavior

Decision Making:

Context Signals → Heuristic Rules → Action Selection → LLM for Content

Key Components:

  1. AutonomousEngine (autonomous_engine.py):

    • Tracks lightweight context signals (message frequency, user presence, mood)
    • Makes decisions using deterministic heuristics + mood-based probabilities
    • No LLM needed for WHEN to act
    • Actions: join_conversation, engage_user, share_tweet, general, change_profile_picture
  2. Personality-Driven:

    • Mood profiles define energy, sociability, impulsiveness (0-1 scales)
    • 14 different moods: bubbly, sleepy, curious, shy, flirty, angry, etc.
    • Each mood adjusts decision thresholds dynamically
  3. Context Awareness:

    • Message momentum tracking (5min/1hr windows)
    • FOMO detection (feeling left out)
    • Activity-based triggers (users playing games, status changes)
    • Time-based patterns (hour of day, weekend)

Strengths:

  • Fast decisions (no LLM latency for decision-making)
  • Consistent personality (mood-driven behavior)
  • Predictable resource usage
  • True autonomy (doesn't need constant prompting)
  • Works perfectly for social interaction scenarios

Limitations:

  • Cannot dynamically discover new actions
  • Limited to predefined action types
  • Cannot interact with external services autonomously

Jaison-core MCP System

Philosophy: LLM-driven tool discovery and execution with Model Context Protocol

Decision Making:

User Input → LLM analyzes context → LLM suggests tools → Execute tools → LLM responds with enriched context

Key Components:

  1. MCPManager (mcp/manager.py):

    • Manages MCP servers (external tool providers)
    • Servers expose tools, resources, and URI templates
    • LLM receives tool descriptions and decides which to call
  2. Tool Calling Flow:

    # 1. LLM is given system prompt with all available tools
    tooling_prompt = self.mcp_manager.get_tooling_prompt()
    
    # 2. LLM decides which tools to call (separate MCP-role LLM)
    mcp_response = await llm_call(tooling_prompt, user_context)
    
    # 3. Parse tool calls from LLM response
    tool_calls = parse_tool_calls(mcp_response)  # e.g., "<internet> name='Limit'"
    
    # 4. Execute tools via MCP servers
    results = await mcp_manager.use(tool_calls)
    
    # 5. Inject results into conversation context
    prompter.add_mcp_results(results)
    
    # 6. Main LLM generates final response with enriched context
    response = await main_llm_call(system_prompt, conversation + tool_results)
    
  3. Tool Format:

    • MCP servers expose tools with JSON schemas
    • Example tools: web search, memory retrieval, calendar access, file operations
    • LLM receives descriptions like: "<internet> Search the internet for information"

Strengths:

  • Dynamic tool discovery (add new capabilities without code changes)
  • Flexible external integrations
  • Rich ecosystem of MCP servers
  • Good for task-oriented interactions (research, data retrieval)

Limitations:

  • Requires LLM call for EVERY decision (slower, more expensive)
  • Tool selection depends on LLM reasoning quality
  • Not designed for autonomous social interaction
  • Personality consistency depends on prompt engineering
  • Cannot make mood-driven decisions without complex prompting

Detailed Comparison

1. Decision-Making Speed

Miku Bot:

# Instant decision (no LLM)
action_type = autonomous_engine.should_take_action(guild_id)
# → Returns "join_conversation" in <1ms

# LLM only called AFTER decision made
if action_type == "join_conversation":
    response = await llm_call(...)  # Generate WHAT to say

Jaison-core MCP:

# Must call LLM to decide which tools to use
tooling_response = await mcp_llm_call(context)  # ~500ms-2s
tool_results = await execute_tools(tooling_response)  # Variable
final_response = await main_llm_call(context + results)  # ~500ms-2s
# Total: 1-5+ seconds per decision

Winner: Miku Bot (for real-time social interaction)


2. Personality Consistency

Miku Bot:

# Mood directly controls decision thresholds
mood = "sleepy"
profile = {"energy": 0.2, "sociability": 0.3, "impulsiveness": 0.1}

# Low energy = longer silence before action
min_silence = 1800 * (2.0 - profile["energy"])  # 3,240s = 54 minutes

# Low sociability = higher bar for joining conversations
threshold = 0.6 * (2.0 - profile["sociability"])  # 1.02 (very high)

Jaison-core MCP:

# Personality must be consistently prompted
system_prompt = f"""
You are {character_name} in {mood} mood.
{character_prompt}
{scene_prompt}
Consider these tools: {tooling_prompt}
"""
# Personality consistency depends on LLM following instructions

Winner: Miku Bot (explicit mood-driven behavior guarantees)


3. Autonomous Behavior

Miku Bot:

# True autonomy - tracks context passively
autonomous_engine.track_message(guild_id, author_is_bot=False)

# Periodically checks if action needed (no LLM)
@scheduler.scheduled_job('interval', minutes=5)
async def autonomous_tick():
    for guild_id in servers:
        action = autonomous_engine.should_take_action(guild_id)
        if action:
            await execute_action(action, guild_id)

Jaison-core MCP:

# Reactive - waits for user input
async def response_pipeline(user_message):
    # Only acts when user sends message
    mcp_results = await mcp_manager.use(user_message)
    response = await generate_response(user_message, mcp_results)
    return response

Winner: Miku Bot (designed for autonomous, unprompted actions)


4. Extensibility

Miku Bot:

# Add new action type requires code change
def _should_play_music(self, ctx, profile, debug):
    # New heuristic function
    quiet_ok = ctx.messages_last_hour < 3
    mood_ok = ctx.current_mood in ["excited", "happy"]
    return quiet_ok and mood_ok and random.random() < 0.1

# Then add to should_take_action()
if self._should_play_music(ctx, profile, debug):
    return "play_music"

Jaison-core MCP:

# Add new tool - just configure in YAML
mcp:
  - id: music_player
    command: python
    args: ["music_mcp_server.py"]
    cwd: "models/mcp/music"

# Tool automatically available to LLM
# No code changes needed

Winner: Jaison-core MCP (easier to extend capabilities)


5. Resource Usage

Miku Bot:

  • Decision: 0 LLM calls (heuristics only)
  • Content generation: 1 LLM call
  • Total per action: 1 LLM call

Jaison-core MCP:

  • Tool selection: 1 LLM call (MCP-role LLM)
  • Tool execution: 0-N external calls
  • Final response: 1 LLM call (main LLM)
  • Total per action: 2+ LLM calls minimum

Winner: Miku Bot (more cost-effective for high-frequency autonomous actions)


Key Philosophical Differences

Miku Bot: Personality-First Design

"Miku feels lonely" → Break silence autonomously → Ask LLM to generate message
"Miku feels FOMO" → Join conversation → Ask LLM to respond to recent messages
"Miku is sleepy" → Wait 54 minutes before any action

Jaison-core: Tool-First Design

User: "What's the weather?" → LLM sees <weather_tool> → Calls tool → Responds with data
User: "Remember this" → LLM sees <memory_tool> → Stores information → Confirms
User: "Play music" → LLM sees <music_tool> → Starts playback → Responds

When to Use Each System

Use Your Current System (Miku Bot) For:

Social autonomous actions

  • Joining conversations naturally
  • Reacting to user presence/status changes
  • Mood-driven spontaneous messages
  • FOMO-based engagement

Performance-critical decisions

  • Real-time reactions (emoji responses)
  • High-frequency checks (every message)
  • Low-latency autonomous ticks

Personality consistency

  • Mood-based behavior patterns
  • Predictable energy/sociability curves
  • Character trait enforcement

Use MCP Tool Calling For:

External data retrieval

  • Web searches for questions
  • Weather/news lookups
  • Database queries
  • API integrations

Complex task execution

  • File operations
  • Calendar management
  • Email/notification sending
  • Multi-step workflows

User-requested actions

  • "Look up X for me"
  • "Remember this fact"
  • "Check my schedule"
  • "Search Twitter for Y"

Hybrid Approach Recommendation

Best Solution: Keep your autonomous system, add MCP for specific capabilities.

Architecture:

# 1. Autonomous engine decides WHEN to act (current system)
action_type = autonomous_engine.should_take_action(guild_id)

if action_type == "join_conversation":
    # 2. Get recent conversation context
    recent_messages = get_recent_messages(channel)
    
    # 3. Check if user asked a question that needs tools
    if requires_external_data(recent_messages):
        # 4. Use MCP tool calling
        tool_results = await mcp_manager.analyze_and_use_tools(recent_messages)
        context = f"{recent_messages}\n\nAdditional info: {tool_results}"
    else:
        # 4. Regular personality-driven response
        context = recent_messages
    
    # 5. Generate response with enriched context
    response = await llm_call(miku_personality + mood + context)
    await channel.send(response)

Integration Plan:

  1. Add MCPManager to Miku:

    # bot/utils/mcp_integration.py
    from jaison_mcp import MCPManager
    
    class MikuMCPManager:
        def __init__(self):
            self.mcp = MCPManager()
    
        async def should_use_tools(self, message: str) -> bool:
            """Decide if message needs external tools"""
            keywords = ["search", "look up", "weather", "news", "remember"]
            return any(kw in message.lower() for kw in keywords)
    
        async def get_tool_results(self, message: str, mood: str):
            """Use MCP tools and format results for Miku's personality"""
            raw_results = await self.mcp.use(message)
            # Add personality flair to tool results
            return self._format_with_personality(raw_results, mood)
    
  2. Use MCP Selectively:

    # Only for user-initiated queries, not autonomous actions
    async def handle_message(message):
        if is_miku_addressed(message):
            # Check if question needs tools
            if await mcp_manager.should_use_tools(message.content):
                mood = get_current_mood(message.guild.id)
                tool_results = await mcp_manager.get_tool_results(
                    message.content, 
                    mood
                )
                context = f"User question: {message.content}\n"
                context += f"Info I found: {tool_results}"
            else:
                context = message.content
    
            response = await generate_miku_response(context, mood)
            await message.reply(response)
    
  3. Useful MCP Tools for Miku:

    • Internet search: Answer factual questions
    • Memory/notes: Store user preferences/facts
    • Image search: Find relevant images to share
    • Calendar: Track server events
    • Twitter API: Better tweet integration
    • YouTube API: Music/video recommendations

Conclusion

Your autonomous system is superior for Miku's core personality-driven behavior.

The MCP tool calling in jaison-core is designed for a different use case:

  • Jaison-core: AI assistant that responds to user requests with helpful tools
  • Miku: Autonomous AI companion with consistent personality and spontaneous behavior

Recommendations:

  1. Keep your current autonomous engine

    • It's perfectly designed for social autonomous behavior
    • Fast, cost-effective, personality-consistent
    • Already handles mood-driven decisions beautifully
  2. Add selective MCP integration

    • Only for user questions that need external data
    • Not for autonomous decision-making
    • Use it to enhance responses, not replace your system
  3. Don't replace your system with MCP

    • Would lose personality consistency
    • Much slower for real-time social interaction
    • Expensive for high-frequency autonomous checks
    • Not designed for unprompted autonomous actions

Next Steps (if interested in MCP integration):

  1. Extract MCP components from jaison-core
  2. Create a lightweight wrapper for Miku's use cases
  3. Add configuration for specific MCP servers (search, memory, etc.)
  4. Integrate at the response generation stage, not decision stage
  5. Test with non-critical features first

Your bot's autonomous system is already excellent for its purpose. MCP would be a nice-to-have addon for specific query types, not a replacement.


Code Example: Hybrid Implementation

# bot/utils/hybrid_autonomous.py

from utils.autonomous_engine import autonomous_engine
from utils.mcp_integration import MikuMCPManager

class HybridAutonomousSystem:
    def __init__(self):
        self.engine = autonomous_engine
        self.mcp = MikuMCPManager()
    
    async def autonomous_tick(self, guild_id: int):
        """Main autonomous check (your current system)"""
        # Decision made by heuristics (no LLM)
        action_type = self.engine.should_take_action(guild_id)
        
        if not action_type:
            return
        
        # Get current mood
        mood, _ = server_manager.get_server_mood(guild_id)
        
        # Execute action based on type
        if action_type == "join_conversation":
            await self._join_conversation(guild_id, mood)
        elif action_type == "engage_user":
            await self._engage_user(guild_id, mood)
        # ... other action types
    
    async def _join_conversation(self, guild_id: int, mood: str):
        """Join conversation - optionally use MCP for context"""
        channel = get_autonomous_channel(guild_id)
        recent_msgs = await get_recent_messages(channel, limit=20)
        
        # Check if conversation involves factual questions
        needs_tools = await self._check_if_tools_needed(recent_msgs)
        
        if needs_tools:
            # Use MCP to enrich context
            tool_context = await self.mcp.get_relevant_context(
                recent_msgs, 
                mood
            )
            context = f"Recent conversation:\n{recent_msgs}\n\n"
            context += f"Additional context: {tool_context}"
        else:
            # Standard personality-driven response
            context = f"Recent conversation:\n{recent_msgs}"
        
        # Generate response with Miku's personality
        response = await generate_miku_message(
            context=context,
            mood=mood,
            response_type="join_conversation"
        )
        
        await channel.send(response)
    
    async def _check_if_tools_needed(self, messages: str) -> bool:
        """Quick heuristic check (no LLM needed for most cases)"""
        # Simple keyword matching
        tool_keywords = [
            "what is", "who is", "when is", "where is", "how to",
            "look up", "search for", "find", "weather", "news"
        ]
        
        msg_lower = messages.lower()
        return any(keyword in msg_lower for keyword in tool_keywords)
    
    async def handle_direct_question(self, message: discord.Message):
        """Handle direct questions to Miku (always check for tool usage)"""
        mood = get_current_mood(message.guild.id)
        
        # For direct questions, more likely to use tools
        if await self.mcp.should_use_tools(message.content):
            # Use MCP tool calling
            tool_results = await self.mcp.get_tool_results(
                message.content,
                mood
            )
            
            # Format response with personality
            response = await generate_miku_response(
                question=message.content,
                tool_results=tool_results,
                mood=mood,
                personality_mode="helpful_but_sassy"
            )
        else:
            # Standard response without tools
            response = await generate_miku_response(
                question=message.content,
                mood=mood,
                personality_mode="conversational"
            )
        
        await message.reply(response)

This hybrid approach gives you the best of both worlds:

  • Fast, personality-consistent autonomous behavior (your system)
  • Enhanced capability for factual queries (MCP when needed)
  • Cost-effective (tools only used when genuinely helpful)