Skip to main content
Glama
getmasv

masv

Official

list_files_on_integration

List files from cloud or storage gateway integrations with pagination support. Use a cursor to retrieve subsequent pages when more results are available.

Instructions

List files on any integration (cloud or MASV Storage Gateway). Supports pagination — if more results are available, a cursor is returned; pass it back in the next call to get the next page.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
integrationIdYesID of the cloud or storage gateway integration
pathNoDirectory path/prefix to list files from
cursorNoPagination cursor returned from a previous call. Pass this to retrieve the next page of results.

Implementation Reference

  • The main handler function that lists files on a cloud or Storage Gateway integration. It fetches integration details, determines if it's a Storage Gateway (offset-based pagination) or cloud integration (last_file_path cursor pagination), fetches files via MASV API, and formats the response with file names, sizes, and pagination cursors.
    async function listFilesOnIntegration({
      integrationId,
      path,
      cursor,
    }: ListFilesOnIntegrationParams) {
      const integration = await getIntegration(integrationId);
      const STORAGE_GATEWAY_PROVIDERS = new Set([
        "storage_gateway",
        "jellyfish_sg",
        "synology_sg",
        "qnap_sg",
        "amazon_efs_sg",
        "opendrives_sg",
        "desktop_sg",
      ]);
      const isStorageGateway = STORAGE_GATEWAY_PROVIDERS.has(integration.provider);
    
      const headers = {
        "content-type": "application/json",
        "x-api-key": MASV_API_KEY,
      };
    
      let files: any[];
      let hasMore = false;
      let nextCursor: string | undefined;
    
      if (isStorageGateway) {
        // Storage gateway uses offset-based pagination
        let offset = 0;
        if (cursor) {
          const decoded = decodeCursor(cursor);
          if (decoded.type !== "storage_gateway") throw new Error("Invalid cursor for this integration type");
          offset = decoded.offset;
        }
    
        const url = new URL(
          `${MASV_BASE_URL}/v1/cloud_connections/providers/storage_gateway/${integrationId}/files`,
        );
        if (path) url.searchParams.append("path", path);
        url.searchParams.append("offset", String(offset));
        // Request 1 more file to check if there are more files than we return
        url.searchParams.append("count", String(PAGE_SIZE + 1));
    
        const r = await fetch(url.toString(), { headers });
        const data = await r.json();
    
        const allFiles = data.files || [];
        hasMore = allFiles.length > PAGE_SIZE || data.more_data === true;
        files = allFiles.slice(0, PAGE_SIZE);
    
        if (hasMore) {
          nextCursor = encodeCursor({ type: "storage_gateway", offset: offset + PAGE_SIZE });
        }
      } else {
        // Cloud integrations use last_file_path cursor pagination
        let last_file_path: string | undefined;
        if (cursor) {
          const decoded = decodeCursor(cursor);
          if (decoded.type !== "cloud") throw new Error("Invalid cursor for this integration type");
          last_file_path = decoded.last_file_path;
        }
    
        const url = new URL(
          `${MASV_BASE_URL}/v1/cloud_connections/${integrationId}/files`,
        );
        if (path) url.searchParams.append("prefix", path);
        if (last_file_path) url.searchParams.append("prev_key", last_file_path);
    
        // Request 1 more file to check if there are more files than we return
        url.searchParams.append("count", String(PAGE_SIZE + 1));
    
        const r = await fetch(url.toString(), { headers });
        const data = await r.json();
    
        const allFiles = Array.isArray(data) ? data : [];
        hasMore = allFiles.length > PAGE_SIZE;
        files = allFiles.slice(0, PAGE_SIZE);
    
        if (hasMore) {
          const lastFile = files[files.length - 1];
          const lastPath = lastFile?.id || "";
          nextCursor = encodeCursor({ type: "cloud", last_file_path: lastPath });
        }
      }
    
      // Format response
      const formattedLines: string[] = [];
    
      for (const file of files) {
        const isDirectory = file.kind === "directory";
        const name = file.name || "";
        const size = file.size;
        const id = file.id || "";
    
        if (isDirectory) {
          formattedLines.push(`[DIR] ${name}/${id ? ` (ID: ${id})` : ""}`);
        } else {
          const sizeStr = size !== undefined && size !== null ? formatFileSize(size) : "unknown";
          formattedLines.push(`[FILE] ${name} (${sizeStr})${id ? ` (ID: ${id})` : ""}`);
        }
      }
    
      if (hasMore && nextCursor) {
        formattedLines.push(
          `\nMore results available. Call this tool again with cursor: ${nextCursor}`,
        );
      }
    
      return formattedLines.join("\n");
    }
  • Zod schema for the list_files_on_integration tool: defines integrationId (required), path (optional directory prefix), and cursor (optional pagination cursor).
    const ListFilesOnIntegrationSchema = z.object({
      integrationId: z.string().describe("ID of the cloud or storage gateway integration"),
      path: z.string().optional().describe("Directory path/prefix to list files from"),
      cursor: z.string().optional().describe("Pagination cursor returned from a previous call. Pass this to retrieve the next page of results."),
    });
  • src/index.ts:280-296 (registration)
    Registers the 'list_files_on_integration' tool with the MCP server, linking the schema (ListFilesOnIntegrationSchema.shape) and the handler (listFilesOnIntegration function).
    server.registerTool(
      "list_files_on_integration",
      {
        description:
          "List files on any integration (cloud or MASV Storage Gateway). Supports pagination — if more results are available, a cursor is returned; pass it back in the next call to get the next page.",
        inputSchema: ListFilesOnIntegrationSchema.shape,
      },
      async (args) => {
        try {
          const data = await listFilesOnIntegration(args);
    
          return mcpOk(data);
        } catch (error) {
          return mcpError(error);
        }
      },
    );
  • Helper function formatFileSize converts bytes to human-readable sizes (B, KiB, MiB, GiB, TiB). Used by listFilesOnIntegration to display file sizes in the formatted output.
    function formatFileSize(bytes: number): string {
      if (bytes === 0) return "0 B";
    
      const units = ["B", "KiB", "MiB", "GiB", "TiB"];
      const bytesPerUnit = 1024;
      const maxUnitIndex = units.length - 1;
    
      let unitIndex = 0;
      let size = bytes;
    
      while (size >= bytesPerUnit && unitIndex !== maxUnitIndex) {
        unitIndex++;
        size = size / bytesPerUnit;
      }
    
      return `${size.toFixed(2)} ${units[unitIndex]}`;
    }
  • Helper types and functions for cursor-based pagination: CloudCursor (type + last_file_path), StorageGatewayCursor (type + offset), encodeCursor, decodeCursor, and PAGE_SIZE constant (50).
    // Cursor encodes pagination state for both integration types
    type CloudCursor = { type: "cloud"; last_file_path: string };
    type StorageGatewayCursor = { type: "storage_gateway"; offset: number };
    type PaginationCursor = CloudCursor | StorageGatewayCursor;
    
    function encodeCursor(cursor: PaginationCursor): string {
      return Buffer.from(JSON.stringify(cursor)).toString("base64");
    }
    
    function decodeCursor(cursor: string): PaginationCursor {
      return JSON.parse(Buffer.from(cursor, "base64").toString("utf8"));
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must convey behavioral traits. It mentions pagination (cursor usage) but omits other traits like read-only nature or rate limits. Adequate but not comprehensive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences: first states purpose, second explains pagination. No wasted words, front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so description should specify return format. It explains pagination but does not describe the list contents (e.g., file names, metadata). Adequate for a simple pagination tool but could be more complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds minimal extra meaning beyond the schema: it confirms integration types but repeats schema descriptions for integrationId and cursor.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action 'list files' on a specific resource 'any integration (cloud or MASV Storage Gateway)', distinguishing it from sibling tools like get_package_files that list files in a package.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use the tool (to list files on integrations) and provides pagination guidance, but does not explicitly exclude cases or compare with alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/getmasv/masv-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server