- 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
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:
-
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
-
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
-
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:
-
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
-
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) -
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:
-
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) -
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) -
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:
-
✅ Keep your current autonomous engine
- It's perfectly designed for social autonomous behavior
- Fast, cost-effective, personality-consistent
- Already handles mood-driven decisions beautifully
-
✅ 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
-
❌ 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):
- Extract MCP components from jaison-core
- Create a lightweight wrapper for Miku's use cases
- Add configuration for specific MCP servers (search, memory, etc.)
- Integrate at the response generation stage, not decision stage
- 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)