wiki/appdoc/mcp_value_analysis.md
2025-12-03 23:02:58 +01:00

8.3 KiB

MCP Value Analysis: When Does MCP Actually Add Value?

Critical Question

Does MCP enable AI calls to automatically call MCP servers, or is MCP independent of AI calls?

Answer: MCP is independent of AI calls, but its primary value is when AI models can discover and call tools directly.


How MCP Actually Works

MCP's Design Purpose

MCP is designed for direct AI-to-tool communication:

AI Model (Claude Desktop, GPT-4, etc.)
  ↓ (discovers tools via MCP)
MCP Server (provides tools)
  ↓ (executes tool)
External System (database, API, file system)

Key Point: The AI model itself discovers and calls tools directly, not a separate planning system.

Example: Claude Desktop with MCP

# User asks Claude Desktop: "Read file X and summarize it"

# Claude Desktop (AI model):
# 1. Discovers available MCP tools via MCP protocol
tools = mcpClient.listTools()
# Returns: ["file.read", "file.write", "slack.sendMessage", ...]

# 2. AI decides to call file.read tool
result = await mcpClient.callTool("file.read", {"path": "file.txt"})

# 3. AI uses result to generate response
response = await aiModel.generate(f"Summarize: {result['content']}")

The AI model directly calls tools - no separate planning phase.


Your Current Architecture vs MCP

Your Architecture: Two-Phase Planning + Execution

User Request
  ↓
Planning Phase (AI decides what to do)
  ├─> Stage 1: Select action ("ai.process")
  └─> Stage 2: Generate parameters
  ↓
Execution Phase (System executes, not AI)
  ├─> ActionExecutor.executeAction()
  └─> Method.action() executes

Key Difference:

  • Your system: AI plans, then system executes
  • MCP design: AI plans AND executes directly

The Disconnect

MCP's value is when AI directly calls tools, but your architecture separates planning from execution:

  1. Planning: AI selects actions (via _planSelect())
  2. Execution: System executes actions (via ActionExecutor)

MCP doesn't fit this pattern because:

  • MCP assumes AI calls tools directly
  • Your system has AI plan, then system executes
  • Adding MCP would just add overhead without changing the flow

When MCP Actually Adds Value

Scenario 1: External AI Systems Call Your Tools

Use Case: External AI systems (Claude Desktop, GPT-4, etc.) want to use your actions as tools.

Value: High - Enables external AI systems to use your capabilities

Example:

# External Claude Desktop connects to your MCP server
# User asks Claude: "Process document X using PowerOn AI"

# Claude Desktop discovers your tools via MCP
tools = await yourMcpServer.listTools()
# Returns: ["poweron.ai.process", "poweron.outlook.readEmails", ...]

# Claude directly calls your tool
result = await yourMcpServer.callTool("poweron.ai.process", {
    "aiPrompt": "Summarize document",
    "documentList": ["doc_123"]
})

# Claude uses result in its response

This is valuable if you want to expose your actions to external AI systems.


Scenario 2: Your AI Directly Calls Tools (No Planning Phase)

Use Case: Change your architecture so AI directly calls tools instead of planning first.

Value: ⚠️ Medium - Requires architectural change, but enables direct tool calling

Example:

# Instead of planning phase, AI directly calls tools
userRequest = "Summarize document X"

# AI discovers tools
tools = mcpClient.listTools()

# AI decides and calls tool directly
result = await mcpClient.callTool("ai.process", {
    "aiPrompt": "Summarize the document",
    "documentList": ["doc_123"]
})

# No separate planning phase - AI does it all

This would require:

  • Removing planning phase (_planSelect, _actExecute)
  • Making AI directly call tools
  • Significant architectural change

Not recommended - your planning phase provides value (two-stage parameter generation, etc.)


Scenario 3: Use External MCP Servers as Tools

Use Case: Use external MCP servers (Slack, GitHub, Postgres) as tools in your system.

Value: High - Easy integration of external tools

Example:

# Connect to external Slack MCP server
slackMcpClient = ExternalMcpClient("http://slack-mcp-server:8080")

# Use Slack as a tool in your actions
@action
async def sendSlackNotification(self, parameters: Dict) -> ActionResult:
    # Call external MCP tool
    result = await slackMcpClient.callTool("slack.sendMessage", {
        "channel": parameters["channel"],
        "text": parameters["text"]
    })
    return ActionResult(success=True, ...)

This is valuable - easy integration of external services without custom connectors.


Scenario 4: Wrap Internal Actions as MCP Tools (Current Proposal)

Use Case: Wrap your existing actions as MCP tools, but keep same architecture.

Value: Low - Adds overhead without changing functionality

Why it doesn't add value:

  • Your actions already work fine
  • MCP adds JSON-RPC overhead
  • No external systems benefit (they're internal)
  • Your AI doesn't call tools directly (it plans, then system executes)

This is what the current proposal does - and it doesn't add real value.


Honest Assessment: When to Use MCP

Use MCP When:

  1. Exposing tools to external AI systems

    • Claude Desktop wants to use your actions
    • GPT-4 wants to call your tools
    • Any external AI system needs your capabilities
  2. Using external MCP servers as tools

    • Slack MCP server for notifications
    • GitHub MCP server for code operations
    • Postgres MCP server for database access
  3. Changing architecture to direct AI tool calling

    • Remove planning phase
    • AI directly discovers and calls tools
    • (But this loses your two-stage planning benefits)

Don't Use MCP When:

  1. Just wrapping internal actions

    • Actions already work fine
    • No external systems need them
    • Adds overhead without benefit
  2. Keeping current planning + execution architecture

    • MCP assumes direct AI tool calling
    • Your architecture separates planning from execution
    • MCP doesn't fit this pattern

Revised Recommendation

Use MCP only for external tools, not for wrapping internal actions:

# Use external MCP servers as tools
class MethodSlack(MethodBase):
    def __init__(self, services):
        super().__init__(services)
        self.mcpClient = ExternalMcpClient("http://slack-mcp-server:8080")
    
    @action
    async def sendMessage(self, parameters: Dict) -> ActionResult:
        # Call external MCP tool
        result = await self.mcpClient.callTool("slack.sendMessage", parameters)
        return self._mcpResultToActionResult(result)

Value: Easy integration of external services


Option B: Expose Actions to External AI (If Needed)

Only if you want external AI systems to use your actions:

# Create MCP server that external AI can connect to
mcpServer = MethodMcpServer(methodInstance)

# External AI (Claude Desktop) connects and discovers tools
tools = await mcpServer.listTools()
result = await mcpServer.callTool("poweron.ai.process", {...})

Value: Enables external AI systems to use your capabilities


Option C: Skip MCP for Internal Actions (Current Recommendation)

Don't wrap internal actions as MCP tools - they already work fine:

# Keep existing architecture
methodInstance = methods["ai"]['instance']
actionMethod = methodInstance.actions["process"]['method']
result = await actionMethod(parameters=parameters)

Value: No overhead, works perfectly


Conclusion

MCP is independent of AI calls, but its primary value is when AI models can discover and call tools directly.

For your architecture:

  • Don't wrap internal actions as MCP tools (adds overhead, no benefit)
  • Do use external MCP servers as tools (easy integration)
  • Do expose actions via MCP if external AI systems need them

The current proposal adds overhead without real value because:

  1. Your actions already work fine
  2. Your AI doesn't call tools directly (it plans, then system executes)
  3. No external systems benefit from wrapping internal actions

Better approach: Use MCP only for external tool integration, not for wrapping internal actions.