Skip to main content
Glama
jginorio

Sprout Social MCP Server

by jginorio

get_cases

Fetch customer inquiries and issues from Sprout Social to manage social care cases, with filters for date range, priority, and pagination.

Instructions

Retrieve cases (customer inquiries/issues) from Sprout Social. Cases represent customer interactions that may require action by a social care agent.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
updated_time_startNoFilter by updated time start (YYYY-MM-DD format).
updated_time_endNoFilter by updated time end (YYYY-MM-DD format).
priorityNoFilter by priority. Valid values: 'HIGH', 'MEDIUM', 'LOW', 'UNDEFINED'.
limitNoMaximum cases to return per page.
sortNoSort order, e.g. ['created_time:asc'].
timezoneNoTimezone for date filters (e.g. 'America/Chicago'). Defaults to UTC.
page_cursorNoCursor for pagination (from previous response).

Implementation Reference

  • src/index.ts:516-574 (registration)
    The tool 'get_cases' is registered using server.tool() with the MCP SDK. It registers the tool name, description, Zod schema for input validation, and the handler callback.
    server.tool(
      "get_cases",
      "Retrieve cases (customer inquiries/issues) from Sprout Social. " +
        "Cases represent customer interactions that may require action by a social care agent.",
      {
        updated_time_start: z
          .string()
          .optional()
          .describe("Filter by updated time start (YYYY-MM-DD format)."),
        updated_time_end: z
          .string()
          .optional()
          .describe("Filter by updated time end (YYYY-MM-DD format)."),
        priority: z
          .array(z.string())
          .optional()
          .describe(
            "Filter by priority. Valid values: 'HIGH', 'MEDIUM', 'LOW', 'UNDEFINED'."
          ),
        limit: z.number().optional().describe("Maximum cases to return per page."),
        sort: z
          .array(z.string())
          .optional()
          .describe("Sort order, e.g. ['created_time:asc']."),
        timezone: z
          .string()
          .optional()
          .describe(
            "Timezone for date filters (e.g. 'America/Chicago'). Defaults to UTC."
          ),
        page_cursor: z
          .string()
          .optional()
          .describe("Cursor for pagination (from previous response)."),
      },
      async ({ updated_time_start, updated_time_end, priority, limit, sort, timezone, page_cursor }) => {
        const filters: string[] = [];
    
        if (updated_time_start && updated_time_end) {
          filters.push(
            `updated_time.in(${updated_time_start}...${updated_time_end})`
          );
        }
    
        if (priority && priority.length > 0) {
          filters.push(`priority.eq(${priority.join(", ")})`);
        }
    
        const body: Record<string, unknown> = {};
        if (filters.length > 0) body.filters = filters;
        if (limit) body.limit = limit;
        if (sort) body.sort = sort;
        if (timezone) body.timezone = timezone;
        if (page_cursor) body.page_cursor = page_cursor;
    
        const data = await sproutRequest("POST", "/cases/filter", body);
        return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
      }
    );
  • Input validation schema using Zod: optional updated_time_start/updated_time_end (strings, YYYY-MM-DD format), priority (array of 'HIGH'/'MEDIUM'/'LOW'/'UNDEFINED'), limit (number), sort (array of strings like 'created_time:asc'), timezone (string), and page_cursor (string for pagination).
    {
      updated_time_start: z
        .string()
        .optional()
        .describe("Filter by updated time start (YYYY-MM-DD format)."),
      updated_time_end: z
        .string()
        .optional()
        .describe("Filter by updated time end (YYYY-MM-DD format)."),
      priority: z
        .array(z.string())
        .optional()
        .describe(
          "Filter by priority. Valid values: 'HIGH', 'MEDIUM', 'LOW', 'UNDEFINED'."
        ),
      limit: z.number().optional().describe("Maximum cases to return per page."),
      sort: z
        .array(z.string())
        .optional()
        .describe("Sort order, e.g. ['created_time:asc']."),
      timezone: z
        .string()
        .optional()
        .describe(
          "Timezone for date filters (e.g. 'America/Chicago'). Defaults to UTC."
        ),
      page_cursor: z
        .string()
        .optional()
        .describe("Cursor for pagination (from previous response)."),
  • The handler function that executes the tool logic: builds filters from optional parameters, constructs a request body, calls sproutRequest('POST', '/cases/filter', body), and returns the JSON response.
    async ({ updated_time_start, updated_time_end, priority, limit, sort, timezone, page_cursor }) => {
      const filters: string[] = [];
    
      if (updated_time_start && updated_time_end) {
        filters.push(
          `updated_time.in(${updated_time_start}...${updated_time_end})`
        );
      }
    
      if (priority && priority.length > 0) {
        filters.push(`priority.eq(${priority.join(", ")})`);
      }
    
      const body: Record<string, unknown> = {};
      if (filters.length > 0) body.filters = filters;
      if (limit) body.limit = limit;
      if (sort) body.sort = sort;
      if (timezone) body.timezone = timezone;
      if (page_cursor) body.page_cursor = page_cursor;
    
      const data = await sproutRequest("POST", "/cases/filter", body);
      return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
    }
  • The sproutRequest helper function used by the handler. It constructs the API URL, attaches Authorization header, sends the HTTP request, and returns parsed JSON. For the 'get_cases' tool, it's called with method 'POST' and path '/cases/filter'.
    async function sproutRequest(
      method: "GET" | "POST",
      path: string,
      body?: Record<string, unknown>
    ): Promise<unknown> {
      const { apiKey, customerId } = getConfig();
      const url = `${SPROUT_API_BASE}/v1/${customerId}${path}`;
    
      const headers: Record<string, string> = {
        Authorization: `Bearer ${apiKey}`,
        Accept: "application/json",
      };
    
      const options: RequestInit = { method, headers };
    
      if (body) {
        headers["Content-Type"] = "application/json";
        options.body = JSON.stringify(body);
      }
    
      const response = await fetch(url, options);
    
      if (!response.ok) {
        const errorText = await response.text();
        throw new Error(
          `Sprout Social API error (${response.status}): ${errorText}`
        );
      }
    
      return response.json();
    }
Behavior2/5

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

No annotations provided, so description carries full burden. Fails to disclose pagination behavior (page_cursor in schema but not explained), rate limits, or authentication needs. Only describes resource purpose.

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 concise sentences, front-loaded with verb and resource. No extraneous information.

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

Completeness2/5

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

Given 7 parameters with extensive filtering and pagination, description lacks details on expected output, pagination behavior, and error handling. Incomplete for a complex tool.

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 description coverage is 100%, so baseline 3 applies. Description adds no additional meaning beyond the schema's parameter descriptions.

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?

Description clearly states verb 'Retrieve' and resource 'cases' with a definition distinguishing from general messages. Distinguishes from sibling tools like get_messages.

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

Usage Guidelines2/5

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

No guidance on when to use this tool vs alternatives like get_messages or search. No when-not-to-use or prerequisite information.

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/jginorio/sprout-social-mcp'

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