Skip to content

MCP Tools - Model Context Protocol#

lit-mux implements the Model Context Protocol for extending AI capabilities with external tools. MCP provides a standardized way for LLMs to discover, describe, and execute tools.

MCP Architecture#

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   LLM Backend   │────▶│    lit-mux      │────▶│   MCP Server    │
│  (Claude, etc)  │◀────│   MCP Client    │◀────│  (Jira, Git...)  │
└─────────────────┘     └─────────────────┘     └─────────────────┘

lit-mux acts as an MCP client, connecting to multiple MCP servers that provide tools. The LLM sees all available tools and can invoke them during conversations.

Built-in MCP Servers#

lit-mux includes several built-in MCP servers:

Server Tools Use Case
jira Search, create, update issues Project management
agent-messaging Send messages between agents Multi-agent coordination
heartbeat-actions Control agent behavior Autonomous operations

Jira Server#

Full Jira integration for issue tracking:

jira_search          - Search issues with JQL
jira_get_issue       - Get issue details
jira_create_issue    - Create new issues
jira_update_issue    - Update issue fields
jira_add_comment     - Add comments
jira_transition_issue - Change issue status
jira_assign_issue    - Assign to users
jira_link_issues     - Link related issues
jira_get_epic_issues - Get epic children

Configuration:

mcp_servers:
  jira:
    command: "python"
    args: ["-m", "lit_mux.mcp_servers.jira_server"]
    env:
      JIRA_URL: "https://your-company.atlassian.net"
      JIRA_EMAIL: "${JIRA_EMAIL}"
      JIRA_API_TOKEN: "${JIRA_API_TOKEN}"

Agent Messaging Server#

Enables agent-to-agent communication:

send_agent_message   - Send message to another agent
get_my_agent_config  - Get own configuration
list_connected_agents - List available agents
get_agent_info       - Get agent details
get_message_status   - Check message delivery
get_queue_status     - Check queue status
send_message_to_user - Send message to human user

Heartbeat Actions Server#

Control autonomous agent behavior:

set_sleep_duration   - Adjust sleep interval
wake_immediately     - Force wake from sleep
pause_heartbeat      - Pause autonomous operation
resume_heartbeat     - Resume autonomous operation

External MCP Servers#

lit-mux can connect to any MCP-compatible server. Common external servers:

Server Description
filesystem Read/write files
git Git operations
postgres Database queries
sqlite Local database
puppeteer Web automation
brave-search Web search

Configuring External Servers#

Add servers to your agent configuration:

{
    "id": "dev-assistant",
    "mcp_servers": ["jira", "git", "filesystem"],
    "mcp_server_overrides": {
        "filesystem": {
            "args": ["--allowed-directories", "/home/projects"]
        }
    }
}

Or configure globally in config.yaml:

mcp_servers:
  git:
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-git"]
  filesystem:
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/projects"]

Per-Agent MCP Configuration#

Different agents can have different toolsets:

// project-manager.json
{
    "id": "project-manager",
    "mcp_servers": ["jira", "agent-messaging"],
    "mcp_server_overrides": {
        "jira": {
            "env": { "JIRA_PROJECT": "PM" }
        }
    }
}

// developer.json
{
    "id": "developer",
    "mcp_servers": ["git", "filesystem", "jira"],
    "mcp_server_overrides": {
        "filesystem": {
            "args": ["--allowed-directories", "/home/dev/projects"]
        }
    }
}

API Endpoints#

List Available Tools#

GET /tools

# Response
[
    {
        "name": "jira_search",
        "description": "Search for Jira issues using JQL",
        "inputSchema": {
            "type": "object",
            "properties": {
                "jql": { "type": "string", "description": "JQL query" },
                "max_results": { "type": "integer", "default": 50 }
            },
            "required": ["jql"]
        }
    },
    ...
]

List MCP Servers#

GET /mcp/servers

# Response
[
    { "name": "jira", "status": "connected", "tools": 12 },
    { "name": "git", "status": "connected", "tools": 8 },
    { "name": "filesystem", "status": "disconnected" }
]

MCP Health Check#

GET /mcp/health

# Response
{
    "status": "healthy",
    "servers": {
        "jira": { "connected": true, "last_ping": "2024-01-15T10:30:00Z" },
        "git": { "connected": true, "last_ping": "2024-01-15T10:30:00Z" }
    }
}

Security Model#

Execute as User#

Unlike typical AI platforms, lit-mux tools execute with the user's actual permissions:

  • Tools run as the authenticated user, not a service account
  • No privilege escalation—tools can only access what the user can access
  • Audit trails show real user identity
  • Existing RBAC and ACLs are respected

Per-Agent Isolation#

  • Each agent only sees tools from its configured mcp_servers
  • MCP server overrides are agent-specific
  • Working directories are isolated per agent

Tool Validation#

  • Input schemas are validated before execution
  • Output is sanitized before returning to LLM
  • Errors are caught and reported gracefully

Creating Custom MCP Servers#

Python Server#

from mcp.server import Server
from mcp.types import Tool, TextContent

server = Server("my-tools")

@server.tool()
async def my_custom_tool(query: str) -> list[TextContent]:
    """Search for something custom.

    Args:
        query: The search query
    """
    result = await do_search(query)
    return [TextContent(type="text", text=result)]

if __name__ == "__main__":
    import asyncio
    asyncio.run(server.run())

TypeScript Server#

import { Server } from "@modelcontextprotocol/sdk/server";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio";

const server = new Server({
    name: "my-tools",
    version: "1.0.0"
});

server.setRequestHandler("tools/list", async () => ({
    tools: [{
        name: "my_custom_tool",
        description: "Search for something custom",
        inputSchema: {
            type: "object",
            properties: {
                query: { type: "string", description: "Search query" }
            },
            required: ["query"]
        }
    }]
}));

server.setRequestHandler("tools/call", async (request) => {
    const { name, arguments: args } = request.params;
    if (name === "my_custom_tool") {
        const result = await doSearch(args.query);
        return { content: [{ type: "text", text: result }] };
    }
    throw new Error(`Unknown tool: ${name}`);
});

const transport = new StdioServerTransport();
server.connect(transport);

Registering Custom Servers#

Add to config.yaml:

mcp_servers:
  my-tools:
    command: "python"
    args: ["/path/to/my_server.py"]
    env:
      MY_API_KEY: "${MY_API_KEY}"

Or per-agent:

{
    "id": "my-agent",
    "mcp_servers": ["my-tools"],
    "mcp_server_overrides": {
        "my-tools": {
            "command": "python",
            "args": ["/path/to/my_server.py"]
        }
    }
}

Tool Execution Flow#

1. User sends message
2. LLM decides to use tool
3. lit-mux validates tool call
4. lit-mux routes to appropriate MCP server
5. MCP server executes tool
6. Result returned to LLM
7. LLM incorporates result into response

Streaming Tool Execution#

During streaming, tool execution is communicated via events:

{"type": "tool_start", "tool_name": "jira_search", "tool_id": "call_123"}
{"type": "tool_input", "tool_id": "call_123", "input": {"jql": "project=PROJ"}}
{"type": "tool_result", "tool_id": "call_123", "result": "Found 5 issues..."}

Best Practices#

Tool Design#

  1. Single Purpose: Each tool should do one thing well
  2. Clear Descriptions: Help the LLM understand when to use the tool
  3. Validated Inputs: Use JSON Schema for input validation
  4. Graceful Errors: Return helpful error messages

Performance#

  1. Connection Pooling: Reuse MCP server connections
  2. Timeout Configuration: Set appropriate timeouts for slow tools
  3. Caching: Cache tool results where appropriate

Security#

  1. Least Privilege: Only enable tools an agent needs
  2. Input Sanitization: Validate and sanitize all inputs
  3. Audit Logging: Log all tool invocations
  4. Secret Management: Use environment variables for credentials

Troubleshooting#

Server Not Connecting#

# Check server status
GET /mcp/servers

# Check server logs
journalctl -u lit-mux | grep "mcp"

Tool Not Appearing#

  • Verify server is listed in agent's mcp_servers
  • Check server is running and healthy
  • Ensure tool has valid schema

Execution Errors#

  • Check tool input matches schema
  • Verify credentials/environment variables
  • Look for timeout issues with slow tools

Resources#