Skip to main content
The exec endpoint isn’t just for running echo hello. Agents use it to interact with databases, caches, and any CLI tool running inside a container — turning natural language into actual application-level operations.

PostgreSQL — Table Size Report

An agent asked “what’s the largest table in my Postgres?” runs psql inside the container:
async () => {
  const clusterId = "cls_abc123"; // resolved by the agent from conversation

  const res = await cnap.request({
    method: "POST",
    path: `/v1/clusters/${clusterId}/exec`,
    body: {
      namespace: "default",
      pod: "postgres-0",
      container: "postgresql",
      command: ["psql", "-U", "postgres", "-c", `
        SELECT schemaname, tablename,
               pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) AS total_size,
               pg_size_pretty(pg_relation_size(schemaname || '.' || tablename)) AS data_size,
               pg_size_pretty(pg_indexes_size(schemaname || '.' || quote_ident(tablename))) AS index_size,
               n_live_tup AS row_count
        FROM pg_stat_user_tables
        ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC
        LIMIT 15;
      `]
    }
  });
  return res.body;
}
The agent gets back formatted SQL output with table sizes, index sizes, and row counts. It can then reason about which tables need vacuuming, which indexes are bloated, or whether a migration is needed.

Redis — Memory Analysis

async () => {
  const clusterId = "cls_abc123"; // resolved by the agent from conversation

  const info = await cnap.request({
    method: "POST",
    path: `/v1/clusters/${clusterId}/exec`,
    body: {
      namespace: "default",
      pod: "redis-0",
      container: "redis",
      command: ["redis-cli", "INFO", "memory"]
    }
  });

  const stats = await cnap.request({
    method: "POST",
    path: `/v1/clusters/${clusterId}/exec`,
    body: {
      namespace: "default",
      pod: "redis-0",
      container: "redis",
      command: ["redis-cli", "INFO", "keyspace"]
    }
  });

  return { memory: info.body.stdout, keyspace: stats.body.stdout };
}

Chaining Queries

The agent can chain multiple queries in a single execution — check replication lag, then inspect the slowest queries:
async () => {
  const clusterId = "cls_abc123"; // resolved by the agent from conversation

  const exec = (command) => cnap.request({
    method: "POST",
    path: `/v1/clusters/${clusterId}/exec`,
    body: {
      namespace: "default",
      pod: "postgres-0",
      container: "postgresql",
      command: ["psql", "-U", "postgres", "-t", "-A", "-c", command]
    }
  }).then(r => r.body.stdout.trim());

  const [replLag, slowQueries, connCount, dbSize] = await Promise.all([
    exec("SELECT CASE WHEN pg_is_in_recovery() THEN extract(epoch FROM now() - pg_last_xact_replay_timestamp())::int || 's' ELSE 'primary' END"),
    exec("SELECT query, calls, mean_exec_time::int || 'ms' FROM pg_stat_statements ORDER BY mean_exec_time DESC LIMIT 5"),
    exec("SELECT count(*) FROM pg_stat_activity WHERE state = 'active'"),
    exec("SELECT pg_size_pretty(pg_database_size(current_database()))"),
  ]);

  return { replication_lag: replLag, slow_queries: slowQueries, active_connections: connCount, database_size: dbSize };
}
Four psql queries in parallel — replication lag, slowest queries, active connections, database size. All from one execute call.

Why This Matters

Database operations through traditional MCP tools would need a dedicated tool per database type — postgres-query, redis-info, mongo-stats — each with their own schema, parameters, and maintenance burden. With exec + Code Mode, the agent writes the exact command it needs. It knows psql flags, redis-cli subcommands, and mongosh syntax from its training data. No pre-built tools required — the agent composes the right command for any database, any query.
Exec is non-interactive with a 30-second timeout. It’s ideal for read queries and diagnostics. For long-running operations or interactive sessions, use the dashboard terminal.