Docs / Design
Edit on GitHub

MCP Integration

OpenViber integrates with Model Context Protocol (MCP) servers to extend task capabilities with standardized tools and resources.

1. Overview

MCP provides a standard way for AI tasks to interact with external systems. OpenViber acts as an MCP client that connects to one or more MCP servers. Each MCP server provides tools that the task can discover and use during execution.

graph TD subgraph Viber["Viber (Machine)"] Runtime["Viber Runtime (MCP Client)"] Runtime --> MCPS1(MCP Server GitHub) Runtime --> MCPS2(MCP Server Postgres) Runtime --> MCPS3(MCP Server Slack) end

2. Configuration

Basic Setup

# ~/.openviber/config.yaml

mcp_servers:
  - name: "github"
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-github"]
    env:
      GITHUB_TOKEN: "${GITHUB_TOKEN}"

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

  - name: "postgres"
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-postgres"]
    env:
      DATABASE_URL: "${DATABASE_URL}"

Full Configuration Options

mcp_servers:
  - name: "github"                    # Unique identifier
    description: "GitHub API access"  # Human-readable description
    
    # Process configuration
    command: "npx"                    # Executable
    args: ["-y", "@modelcontextprotocol/server-github"]
    cwd: "/home/user"                 # Working directory (optional)
    env:                              # Environment variables
      GITHUB_TOKEN: "${GITHUB_TOKEN}"
    
    # Connection settings
    startup_timeout_ms: 10000         # Max time to wait for server start
    request_timeout_ms: 30000         # Per-request timeout
    require_approval:                 # Tools requiring human approval
      - "create_issue"
      - "create_pull_request"
    
    # Resource access
    expose_resources: true            # Allow task to read MCP resources
    
    # Lifecycle
    auto_start: true                  # Start with Viber
    restart_on_failure: true          # Auto-restart if process dies
    max_restarts: 3                   # Max restart attempts

3. MCP Concepts

Tools vs Resources

ConceptDescriptionExample
ToolsActions the task can takecreate_issue, run_query
ResourcesData the task can readgithub://repo/issues, postgres://table/schema

Tool Discovery

When the Viber starts, it connects to all configured MCP servers and discovers available tools:

// MCP server advertises tools
{
  "tools": [
    {
      "name": "github_create_issue",
      "description": "Create a new GitHub issue",
      "inputSchema": {
        "type": "object",
        "properties": {
          "repo": { "type": "string" },
          "title": { "type": "string" },
          "body": { "type": "string" }
        },
        "required": ["repo", "title"]
      }
    }
  ]
}

// OpenViber registers these as task tools
// Task sees: github_create_issue(repo, title, body?)

Resource Access

Resources are read-only data sources:

// Task requests a resource
const issues = await mcp.readResource("github://dustland/openviber/issues");

// Returns structured data
{
  "uri": "github://dustland/openviber/issues",
  "contents": [
    { "number": 42, "title": "Bug in auth", "state": "open" },
    // ...
  ]
}

4. Security Model

Principle of Least Privilege

MCP servers run with minimal permissions:

mcp_servers:
  - name: "filesystem"
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-filesystem"]
    
    # Restrict to specific directories
    args_append:
      - "/home/user/projects"        # Only this directory
      - "--read-only"                # No writes

Approval Gates

Sensitive MCP tools can require human approval:

mcp_servers:
  - name: "postgres"
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-postgres"]
    
    require_approval:
      - "execute_query"              # All queries need approval
    
    # Or more granular:
    approval_rules:
      - pattern: "INSERT|UPDATE|DELETE"
        require: true
      - pattern: "SELECT"
        require: false

Credential Isolation

MCP servers are configured per task in ~/.openviber/vibers/{id}.yaml:

mcp_servers:
  - name: "github"
    env:
      GITHUB_TOKEN: "${GITHUB_TOKEN}"  # Only GitHub token
      # Does NOT receive DATABASE_URL or other secrets

Sandboxing (Optional)

MCP servers can run in isolated containers:

mcp_servers:
  - name: "untrusted-server"
    command: "docker"
    args: ["run", "--rm", "-i", "mcp-server-image"]
    
    sandbox:
      enabled: true
      network: "none"                # No network access
      memory_limit: "256m"
      cpu_limit: "0.5"

5. Lifecycle Management

Startup Sequence

sequenceDiagram participant V as Viber participant M as MCP Manager participant S as MCP Server V->>M: Initialize M->>S: Spawn process S->>M: Ready signal M->>S: List tools S->>M: Tool definitions M->>V: Server ready with N tools

Health Monitoring

// MCP Manager monitors server health
interface McpServerHealth {
  name: string;
  status: "starting" | "ready" | "unhealthy" | "stopped";
  pid?: number;
  uptime_ms?: number;
  last_request_at?: string;
  error?: string;
}

Graceful Shutdown

async function shutdownMcpServers() {
  // Shutdown all servers when Viber stops
  for (const server of mcpServers) {
    // 1. Stop accepting new requests
    server.pause();
    
    // 2. Wait for in-flight requests (max 5s)
    await server.drain(5000);
    
    // 3. Send SIGTERM
    server.process.kill('SIGTERM');
    
    // 4. Force kill after timeout
    setTimeout(() => server.process.kill('SIGKILL'), 3000);
  }
}

6. Error Handling

Server Failures

interface McpError {
  type: "connection" | "timeout" | "protocol" | "execution";
  server: string;
  tool?: string;
  message: string;
  recoverable: boolean;
}

// Error handling strategy
async function handleMcpError(error: McpError) {
  if (error.type === "connection" && error.recoverable) {
    // Attempt restart
    await restartServer(error.server);
  } else {
    // Report to task as tool failure
    return {
      success: false,
      error: `MCP server '${error.server}' error: ${error.message}`,
    };
  }
}

Timeout Handling

mcp_servers:
  - name: "slow-server"
    request_timeout_ms: 60000        # 60 seconds for slow operations
    
    # Per-tool timeouts
    tool_timeouts:
      quick_lookup: 5000
      long_analysis: 120000

7. Tool Namespacing

MCP tools are registered in the task’s tool registry alongside built-in tools:

Server: github
Tool: create_issue
→ Task sees: github_create_issue

Server: gitlab  
Tool: create_issue
→ Task sees: gitlab_create_issue

Custom Prefixes

mcp_servers:
  - name: "github"
    tool_prefix: "gh"               # gh_create_issue instead of github_create_issue

Tool Aliasing

mcp_servers:
  - name: "postgres"
    tool_aliases:
      execute_query: "db_query"     # Task sees db_query
      list_tables: "db_tables"

8. Resource Protocol

Resource URIs

MCP resources use URI schemes:

github://owner/repo/issues
postgres://database/table/schema
file:///path/to/file

Resource Discovery

// List available resources
const resources = await mcp.listResources("github");
// Returns:
// [
//   { uri: "github://dustland/openviber/issues", name: "Issues" },
//   { uri: "github://dustland/openviber/pulls", name: "Pull Requests" },
// ]

// Read a resource
const data = await mcp.readResource("github://dustland/openviber/issues");

Resource Caching

mcp_servers:
  - name: "github"
    resource_cache:
      enabled: true
      ttl_seconds: 300             # Cache for 5 minutes
      max_size_mb: 50

9. Integration with Tasks

Tool Registration

// During task initialization
async function registerMcpTools(task: Task, mcpManager: McpManager) {
  for (const server of mcpManager.servers) {
    // 3. Task discovers tools from all servers
    const tools = await server.listTools();
    
    for (const tool of tools) {
      task.registerTool({
        name: `${server.name}_${tool.name}`,
        description: tool.description,
        parameters: tool.inputSchema,
        execute: async (params) => {
          return await server.callTool(tool.name, params);
        },
      });
    }
  }
}

Context Injection

The Viber injects MCP context into the task’s system prompt:

// In task submission
{
  type: "task:submit",
  payload: {
    goal: "Fix the auth bug",
    messages: [...],
    mcp_context: [
      { uri: "github://dustland/openviber/issues/42" },
      { uri: "postgres://app/users/schema" }
    ]
  }
}

10. Popular MCP Servers

ServerPurposePackage
GitHubRepository operations@modelcontextprotocol/server-github
FilesystemFile operations@modelcontextprotocol/server-filesystem
PostgreSQLDatabase queries@modelcontextprotocol/server-postgres
Brave SearchWeb search@modelcontextprotocol/server-brave-search
PuppeteerBrowser automation@modelcontextprotocol/server-puppeteer
SlackTeam communication@modelcontextprotocol/server-slack

11. Creating Custom MCP Servers

For custom integrations, create an MCP server:

// my-mcp-server/index.ts
import { Server } from "@modelcontextprotocol/sdk/server";

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

server.setRequestHandler("tools/list", async () => ({
  tools: [
    {
      name: "my_tool",
      description: "Does something useful",
      inputSchema: {
        type: "object",
        properties: {
          input: { type: "string" },
        },
      },
    },
  ],
}));

server.setRequestHandler("tools/call", async (request) => {
  if (request.params.name === "my_tool") {
    const result = await doSomethingUseful(request.params.arguments.input);
    return { content: [{ type: "text", text: result }] };
  }
});

server.connect(process.stdin, process.stdout);

Then configure in OpenViber:

mcp_servers:
  - name: "my-custom"
    command: "node"
    args: ["./my-mcp-server/index.js"]

Summary

MCP integration in OpenViber:

  1. Configuration-driven — Add servers via YAML config
  2. Security-conscious — Approval gates, credential isolation, optional sandboxing
  3. Lifecycle-managed — Auto-start, health monitoring, graceful shutdown
  4. Namespaced tools — No collisions between servers
  5. Resource support — Read-only data access via URIs

This enables tasks to safely interact with external systems while maintaining the stateless Viber principle.