← Back to Home

OpenClaw Integration Guide

Build AI agents that automatically select the most reliable MCP servers using MCPulse.

What is OpenClaw?

OpenClaw is an open-source framework for building autonomous AI agents with MCP tool access. It handles agent orchestration, tool calling, memory, and execution loops.

This guide shows how to integrate MCPulse reliability scoring so your agents automatically choose the best MCP servers.

Prerequisites

Step 1: Install Required Packages

Install both MCPulse monitor and the API client:

Node.js/TypeScript:

npm install mcpulse-monitor axios

Python:

pip install mcpulse httpx

Step 2: Monitor Your MCP Servers

First, wrap your MCP servers with monitoring (same as other platforms):

// weather-server.js
import { McpServer } from '@modelcontextprotocol/sdk';
import { wrapMcpServer } from 'mcpulse-monitor';

const server = new McpServer({
  name: 'weather-api',
  version: '1.0.0'
});

server.tool('get_weather', async ({ location }) => {
  // Weather API logic
  return { temperature: 72, conditions: 'sunny' };
});

const monitored = wrapMcpServer(server, {
  serverId: 'weather-server-id',
  reportInterval: 60000,
  batchSize: 50
});

monitored.start();

Repeat this for all MCP servers your OpenClaw agents might use.

Step 3: Build a Server Selection Module

Create a module that queries MCPulse and selects the best server:

reliability-selector.js

import axios from 'axios';

export class ReliabilitySelector {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://stacks.polsia.app/api';
  }

  async selectBestServer(serverIds, options = {}) {
    const {
      minReliability = 95.0,
      maxLatency = 500,
      window = '24h'
    } = options;

    try {
      // Query MCPulse API for reliability scores
      const response = await axios.get(`${this.baseUrl}/reliability`, {
        headers: {
          'Authorization': `Bearer ${this.apiKey}`
        },
        params: {
          server_ids: serverIds.join(','),
          window
        }
      });

      // Filter by requirements
      const eligible = response.data.servers.filter(s =>
        s.reliability_score >= minReliability &&
        s.avg_response_time <= maxLatency &&
        s.status === 'healthy'
      );

      if (eligible.length === 0) {
        throw new Error('No servers meet reliability requirements');
      }

      // Sort by composite score: reliability (70%) + speed (30%)
      eligible.sort((a, b) => {
        const scoreA = (a.reliability_score * 0.7) +
                      ((1000 - a.avg_response_time) / 1000 * 100 * 0.3);
        const scoreB = (b.reliability_score * 0.7) +
                      ((1000 - b.avg_response_time) / 1000 * 100 * 0.3);
        return scoreB - scoreA;
      });

      return eligible[0];
    } catch (error) {
      console.error('Reliability check failed:', error.message);
      // Fallback: return first server
      return { server_id: serverIds[0] };
    }
  }

  async getServerHealth(serverId) {
    const response = await axios.get(
      `${this.baseUrl}/reliability/${serverId}`,
      {
        headers: { 'Authorization': `Bearer ${this.apiKey}` }
      }
    );
    return response.data;
  }
}

Step 4: Use in Your OpenClaw Agent

Integrate the selector into your agent's server selection logic:

agent.js

import { Agent } from 'openclaw';
import { ReliabilitySelector } from './reliability-selector.js';

const selector = new ReliabilitySelector(process.env.MCPULSE_API_KEY);

const agent = new Agent({
  name: 'WeatherAssistant',
  description: 'Provides weather information using reliable MCP servers',

  // Define available servers
  mcpServers: {
    weatherApi1: 'weather-server-id-1',
    weatherApi2: 'weather-server-id-2',
    weatherApi3: 'weather-server-id-3'
  },

  // Custom server selection before each task
  async selectServer(task) {
    const serverIds = Object.values(this.mcpServers);

    // Let MCPulse choose the most reliable server
    const best = await selector.selectBestServer(serverIds, {
      minReliability: 95.0,
      maxLatency: 500,
      window: '24h'
    });

    console.log(
      `Selected ${best.name} (${best.reliability_score}% reliable, ` +
      `${best.avg_response_time}ms avg latency)`
    );

    return best.server_id;
  },

  async execute(task) {
    // Select best server for this execution
    const serverId = await this.selectServer(task);

    // Call the selected server's tool
    const result = await this.callTool(serverId, 'get_weather', {
      location: task.location
    });

    return result;
  }
});

// Run the agent
agent.start();

Advanced: Failover & Retry Logic

Build resilient agents with automatic failover to backup servers:

export class ResilientAgent extends Agent {
  constructor(config) {
    super(config);
    this.selector = new ReliabilitySelector(config.apiKey);
  }

  async executeWithFailover(task, maxRetries = 3) {
    const serverIds = Object.values(this.mcpServers);

    // Get ranked list of servers
    const ranked = await this.selector.selectBestServer(serverIds);

    for (let i = 0; i < Math.min(maxRetries, serverIds.length); i++) {
      const serverId = serverIds[i];

      try {
        const result = await this.callTool(
          serverId,
          task.tool,
          task.params
        );

        // Success! Log and return
        console.log(`✓ ${serverId} succeeded on attempt ${i + 1}`);
        return result;
      } catch (error) {
        console.warn(
          `✗ ${serverId} failed (attempt ${i + 1}): ${error.message}`
        );

        // Try next server if available
        if (i < serverIds.length - 1) {
          console.log(`→ Failing over to ${serverIds[i + 1]}...`);
          await new Promise(r => setTimeout(r, 1000)); // Brief delay
        }
      }
    }

    throw new Error('All servers failed after retries');
  }
}

Step 6: Monitor Agent-Level Metrics

Track which servers your agents prefer over time:

export class MetricsCollector {
  constructor() {
    this.selections = {};
    this.successes = {};
    this.failures = {};
  }

  recordSelection(serverId) {
    this.selections[serverId] = (this.selections[serverId] || 0) + 1;
  }

  recordSuccess(serverId) {
    this.successes[serverId] = (this.successes[serverId] || 0) + 1;
  }

  recordFailure(serverId) {
    this.failures[serverId] = (this.failures[serverId] || 0) + 1;
  }

  getReport() {
    const report = [];

    for (const serverId in this.selections) {
      const total = this.selections[serverId];
      const success = this.successes[serverId] || 0;
      const failure = this.failures[serverId] || 0;

      report.push({
        serverId,
        selections: total,
        successRate: (success / total * 100).toFixed(1) + '%',
        failures: failure
      });
    }

    return report.sort((a, b) => b.selections - a.selections);
  }
}

// Usage in agent:
const metrics = new MetricsCollector();

async function executeTask(task) {
  const serverId = await selector.selectBestServer(serverIds);
  metrics.recordSelection(serverId);

  try {
    const result = await callTool(serverId, task);
    metrics.recordSuccess(serverId);
    return result;
  } catch (error) {
    metrics.recordFailure(serverId);
    throw error;
  }
}

// Periodic reporting
setInterval(() => {
  console.table(metrics.getReport());
}, 3600000); // Every hour

Expected Results

After integration, you should see:

Automatic Server Selection

Your agents will prefer servers with higher reliability scores, automatically routing away from degraded servers.

Lower Failure Rates

By avoiding unreliable servers, your agent success rate should improve by 5-15%.

Faster Response Times

The selector balances reliability and speed, preferring faster servers when reliability is equal.

Visibility in Dashboard

See which servers are chosen most often, and compare their performance side-by-side.

Troubleshooting

❌ API authentication errors

  • Verify your API key is correct (generate one at /dashboard)
  • Check that Authorization: Bearer YOUR_KEY header is set
  • API keys must be from a paid plan (Free tier has limited API access)
  • Test authentication manually: curl -H "Authorization: Bearer KEY" https://stacks.polsia.app/api/reliability

⚠️ No servers meet reliability threshold

  • Lower minReliability threshold (try 90.0 instead of 95.0)
  • Increase maxLatency if all servers are slightly slow
  • Check MCPulse dashboard to see actual server health
  • Implement fallback logic to select any available server if none are "good enough"

🔍 Selector always picks same server

  • Expected if one server is significantly more reliable than others
  • Add randomization for servers within 2% reliability: if (Math.abs(a.score - b.score) < 2) return Math.random() - 0.5
  • Consider load balancing across top 2-3 servers instead of always using #1
  • Check if other servers are actually online and monitored

🐢 Server selection is slow

  • Cache reliability scores for 1-5 minutes (they don't change that fast)
  • Query MCPulse API in parallel with agent startup, not per-request
  • Use window: '1h' instead of '7d' for faster queries
  • Consider pre-selecting servers at agent initialization instead of per-task

Best Practices for OpenClaw + MCPulse

Example Use Cases

🔍 Research Agent

Use 3-5 web search MCP servers. MCPulse selects the one with best uptime and speed for each query.

💬 Customer Support Bot

Multiple knowledge base MCP servers. Failover ensures users never see "server unavailable" errors.

📊 Data Pipeline Agent

ETL tasks across redundant database MCP servers. MCPulse routes to least-loaded server automatically.

🤖 Multi-Cloud Deployment

Same MCP server deployed to AWS, GCP, and Azure. Agent picks the region with best performance for user's location.

Full API Reference

For complete API documentation including all endpoints, authentication, rate limits, and response schemas:

View Full API Docs →

Other Integration Guides