Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.cnap.tech/llms.txt

Use this file to discover all available pages before exploring further.

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.