Skip to main content
Glama
ubie-oss

Slack MCP Server

by ubie-oss

slack_search_users

Search for Slack users by partial match on username, display name, or real name. Specify a query to find matching users, with optional limit and bot inclusion.

Instructions

Search for users by partial name match across username, display name, and real name. Use this when you need to find users containing specific keywords in their names. Returns up to the specified limit of matching users.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesSearch users by name, display name, or real name (partial match, case-insensitive)
limitNoMaximum number of users to return (default 20)
include_botsNoInclude bot users in results (default false)

Implementation Reference

  • Input validation schema for slack_search_users tool. Defines 'query' (string, required), 'limit' (1-100, default 20), and 'include_bots' (boolean, default false).
    export const SearchUsersRequestSchema = z.object({
      query: z
        .string()
        .describe(
          'Search users by name, display name, or real name (partial match, case-insensitive)'
        ),
      limit: z
        .number()
        .int()
        .min(1)
        .max(100)
        .optional()
        .default(20)
        .describe('Maximum number of users to return (default 20)'),
      include_bots: z
        .boolean()
        .optional()
        .default(false)
        .describe('Include bot users in results (default false)'),
    });
  • src/index.ts:170-175 (registration)
    Registration of slack_search_users tool in the ListTools handler. Sets name, description, and inputSchema.
    {
      name: 'slack_search_users',
      description:
        'Search for users by partial name match across username, display name, and real name. Use this when you need to find users containing specific keywords in their names. Returns up to the specified limit of matching users.',
      inputSchema: zodToJsonSchema(SearchUsersRequestSchema),
    },
  • Handler implementation for slack_search_users. Fetches all users via Slack API (paginated), filters by case-insensitive partial match on name/display_name/real_name, excludes bots unless include_bots is true, limits results, and returns the response.
    case 'slack_search_users': {
      const args = SearchUsersRequestSchema.parse(request.params.arguments);
    
      // Fetch all users with a reasonable limit
      const allUsers: Array<{
        id?: string;
        name?: string;
        real_name?: string;
        is_bot?: boolean;
        profile?: {
          display_name?: string;
          display_name_normalized?: string;
          [key: string]: unknown;
        };
        [key: string]: unknown;
      }> = [];
      let cursor: string | undefined;
      const maxPages = 5; // Limit to prevent infinite loops
      let pageCount = 0;
    
      // Fetch multiple pages if needed
      while (pageCount < maxPages) {
        const response = await slackClient.users.list({
          limit: 1000, // Max allowed by Slack API
          cursor,
        });
    
        if (!response.ok) {
          throw new Error(`Failed to search users: ${response.error}`);
        }
    
        if (response.members) {
          allUsers.push(...(response.members as typeof allUsers));
        }
    
        cursor = response.response_metadata?.next_cursor;
        pageCount++;
    
        // Stop if no more pages
        if (!cursor) break;
      }
    
      // Filter users (case-insensitive partial match across multiple fields)
      const searchTerm = args.query.toLowerCase();
      const filteredUsers = allUsers.filter((user) => {
        // Skip bots if requested
        if (!args.include_bots && user.is_bot) {
          return false;
        }
    
        // Search across multiple name fields
        const name = user.name?.toLowerCase() || '';
        const realName = user.real_name?.toLowerCase() || '';
        const displayName = user.profile?.display_name?.toLowerCase() || '';
        const displayNameNormalized =
          user.profile?.display_name_normalized?.toLowerCase() || '';
    
        return (
          name.includes(searchTerm) ||
          realName.includes(searchTerm) ||
          displayName.includes(searchTerm) ||
          displayNameNormalized.includes(searchTerm)
        );
      });
    
      // Limit results
      const limitedUsers = filteredUsers.slice(0, args.limit);
    
      const response = {
        ok: true,
        members: limitedUsers,
      };
    
      const parsed = GetUsersResponseSchema.parse(response);
      return {
        content: [{ type: 'text', text: JSON.stringify(parsed) }],
      };
    }
Behavior3/5

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

With no annotations, the description carries the full burden. It discloses partial matching and the limit behavior, but does not mention that bots are excluded by default (include_bots defaults to false) or return format. Adequate but could be more detailed.

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 with no unnecessary words. Front-loaded with the action and immediate context. Highly efficient.

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

Completeness4/5

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

With 3 parameters, full schema coverage, and no output schema, the description explains the search behavior and limit. It does not mention return format or error handling, but is fairly complete for a simple search 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 coverage is 100%, so baseline 3 is appropriate. The description reinforces what the query parameter does but adds no additional details about limit or include_bots beyond the schema.

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 it searches for users by partial name match across username, display name, and real name. This distinguishes it from sibling tools like slack_get_users (which likely returns all users) and slack_search_channels (channels).

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?

It explicitly says 'Use this when you need to find users containing specific keywords in their names,' providing clear context. It does not explicitly state when not to use alternatives, but the purpose is sufficiently differentiated.

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/ubie-oss/slack-mcp-server'

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