Skip to main content
Glama

search_jobs

Find job postings by filtering titles, locations, companies, skills, salary, remote options, experience levels, and posting dates.

Instructions

Search for jobs with filters like titles, locations, companies, skills, salary, and remote options. Returns a list of matching job postings.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
titlesNoJob titles to search for (e.g., ["Software Engineer", "Senior Developer"])
locationsNoLocations to search in (e.g., ["San Francisco", "New York", "Remote"])
countriesNoCountry codes to filter (e.g., ["US", "CA", "UK"])
companiesNoSpecific companies to search (e.g., ["Google", "Meta", "Apple"])
excludedCompaniesNoCompanies to exclude from results
skillsNoRequired skills (e.g., ["Python", "React", "AWS"])
remoteNoFilter for remote jobs only
baseSalaryMinNoMinimum base salary (USD)
baseSalaryMaxNoMaximum base salary (USD)
expLevelsNoExperience levels (e.g., ["SE" for Senior, "MI" for Mid-level, "EN" for Entry])
dateOffsetNoOnly show jobs posted within this time period (e.g., "2D" for last 2 days)
industriesNoFilter by company industries (use get_industries to see valid values)
companySizeNoFilter by company size (e.g., ["xs" for 1-50, "s" for 50-200, "m" for 200-1K, "l" for 1K-5K, "xl" for 5K+])
h1bSponsorshipNoFilter for jobs offering H1B sponsorship
limitNoMaximum number of results (default: 5, max: 50). Keep low to avoid large responses.
pageNoPage number for pagination (default: 1)

Implementation Reference

  • Handler for the 'search_jobs' MCP tool. It maps incoming arguments to filters, calls the client's searchJobs method, and returns formatted results.
    async (args) => {
      const filters: Record<string, unknown> = {};
      if (args.titles) { filters.titles = args.titles; }
      if (args.locations) { filters.locations = args.locations; }
      if (args.countries) { filters.countries = args.countries; }
      if (args.companies) { filters.companies = args.companies; }
      if (args.excludedCompanies) { filters.excludedCompanies = args.excludedCompanies; }
      if (args.skills) { filters.skills = args.skills; }
      if (args.remote !== undefined) { filters.remote = args.remote; }
      if (args.baseSalaryMin) { filters.baseSalaryMin = args.baseSalaryMin; }
      if (args.baseSalaryMax) { filters.baseSalaryMax = args.baseSalaryMax; }
      if (args.expLevels) { filters.expLevels = args.expLevels; }
      if (args.dateOffset) { filters.dateOffset = args.dateOffset; }
      if (args.industries) { filters.industries = args.industries; }
      if (args.companySize) { filters.companySize = args.companySize; }
      if (args.h1bSponsorship !== undefined) { filters.h1bSponsorship = args.h1bSponsorship; }
    
      const result = await client.searchJobs({
        filters,
        limit: args.limit || 5,
        page: args.page,
      });
    
      return { content: [{ type: 'text' as const, text: JSON.stringify({ count: result.count, jobs: result.jobs.map(formatJob) }, null, 2) }] };
    }
  • Zod input schema for 'search_jobs' tool, defining all filterable job parameters.
    {
      titles: z.array(z.string()).optional().describe('Job titles to search for (e.g., ["Software Engineer", "Senior Developer"])'),
      locations: z.array(z.string()).optional().describe('Locations to search in (e.g., ["San Francisco", "New York", "Remote"])'),
      countries: z.array(z.string()).optional().describe('Country codes to filter (e.g., ["US", "CA", "UK"])'),
      companies: z.array(z.string()).optional().describe('Specific companies to search (e.g., ["Google", "Meta", "Apple"])'),
      excludedCompanies: z.array(z.string()).optional().describe('Companies to exclude from results'),
      skills: z.array(z.string()).optional().describe('Required skills (e.g., ["Python", "React", "AWS"])'),
      remote: z.boolean().optional().describe('Filter for remote jobs only'),
      baseSalaryMin: z.number().optional().describe('Minimum base salary (USD)'),
      baseSalaryMax: z.number().optional().describe('Maximum base salary (USD)'),
      expLevels: z.array(z.string()).optional().describe('Experience levels (e.g., ["SE" for Senior, "MI" for Mid-level, "EN" for Entry])'),
      dateOffset: z.enum(['24H', '1D', '2D', '7D', '14D', '1M', '3M', '6M', '9M', '1Y']).optional().describe('Only show jobs posted within this time period (e.g., "2D" for last 2 days)'),
      industries: z.array(z.string()).optional().describe('Filter by company industries (use get_industries to see valid values)'),
      companySize: z.array(z.string()).optional().describe('Filter by company size (e.g., ["xs" for 1-50, "s" for 50-200, "m" for 200-1K, "l" for 1K-5K, "xl" for 5K+])'),
      h1bSponsorship: z.boolean().optional().describe('Filter for jobs offering H1B sponsorship'),
      limit: z.number().optional().describe('Maximum number of results (default: 5, max: 50). Keep low to avoid large responses.'),
      page: z.number().optional().describe('Page number for pagination (default: 1)'),
    },
  • src/tools/jobs.ts:6-52 (registration)
    Registration of 'search_jobs' tool within the McpServer.
    server.tool(
      'search_jobs',
      'Search for jobs with filters like titles, locations, companies, skills, salary, and remote options. Returns a list of matching job postings.',
      {
        titles: z.array(z.string()).optional().describe('Job titles to search for (e.g., ["Software Engineer", "Senior Developer"])'),
        locations: z.array(z.string()).optional().describe('Locations to search in (e.g., ["San Francisco", "New York", "Remote"])'),
        countries: z.array(z.string()).optional().describe('Country codes to filter (e.g., ["US", "CA", "UK"])'),
        companies: z.array(z.string()).optional().describe('Specific companies to search (e.g., ["Google", "Meta", "Apple"])'),
        excludedCompanies: z.array(z.string()).optional().describe('Companies to exclude from results'),
        skills: z.array(z.string()).optional().describe('Required skills (e.g., ["Python", "React", "AWS"])'),
        remote: z.boolean().optional().describe('Filter for remote jobs only'),
        baseSalaryMin: z.number().optional().describe('Minimum base salary (USD)'),
        baseSalaryMax: z.number().optional().describe('Maximum base salary (USD)'),
        expLevels: z.array(z.string()).optional().describe('Experience levels (e.g., ["SE" for Senior, "MI" for Mid-level, "EN" for Entry])'),
        dateOffset: z.enum(['24H', '1D', '2D', '7D', '14D', '1M', '3M', '6M', '9M', '1Y']).optional().describe('Only show jobs posted within this time period (e.g., "2D" for last 2 days)'),
        industries: z.array(z.string()).optional().describe('Filter by company industries (use get_industries to see valid values)'),
        companySize: z.array(z.string()).optional().describe('Filter by company size (e.g., ["xs" for 1-50, "s" for 50-200, "m" for 200-1K, "l" for 1K-5K, "xl" for 5K+])'),
        h1bSponsorship: z.boolean().optional().describe('Filter for jobs offering H1B sponsorship'),
        limit: z.number().optional().describe('Maximum number of results (default: 5, max: 50). Keep low to avoid large responses.'),
        page: z.number().optional().describe('Page number for pagination (default: 1)'),
      },
      async (args) => {
        const filters: Record<string, unknown> = {};
        if (args.titles) { filters.titles = args.titles; }
        if (args.locations) { filters.locations = args.locations; }
        if (args.countries) { filters.countries = args.countries; }
        if (args.companies) { filters.companies = args.companies; }
        if (args.excludedCompanies) { filters.excludedCompanies = args.excludedCompanies; }
        if (args.skills) { filters.skills = args.skills; }
        if (args.remote !== undefined) { filters.remote = args.remote; }
        if (args.baseSalaryMin) { filters.baseSalaryMin = args.baseSalaryMin; }
        if (args.baseSalaryMax) { filters.baseSalaryMax = args.baseSalaryMax; }
        if (args.expLevels) { filters.expLevels = args.expLevels; }
        if (args.dateOffset) { filters.dateOffset = args.dateOffset; }
        if (args.industries) { filters.industries = args.industries; }
        if (args.companySize) { filters.companySize = args.companySize; }
        if (args.h1bSponsorship !== undefined) { filters.h1bSponsorship = args.h1bSponsorship; }
    
        const result = await client.searchJobs({
          filters,
          limit: args.limit || 5,
          page: args.page,
        });
    
        return { content: [{ type: 'text' as const, text: JSON.stringify({ count: result.count, jobs: result.jobs.map(formatJob) }, null, 2) }] };
      }
    );
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions that the tool 'returns a list of matching job postings', which implies a read-only operation, but doesn't clarify if it's safe, whether it requires authentication, or if there are rate limits. For a search tool with 16 parameters and no annotations, this is insufficient to guide an agent on behavioral traits like performance or access requirements.

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

Conciseness4/5

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

The description is a single, efficient sentence that front-loads the core functionality (search with filters) and the output (list of job postings). It avoids unnecessary words, though it could be slightly more structured by explicitly mentioning key constraints or alternatives.

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?

Given the complexity (16 parameters, no output schema, no annotations), the description is minimally adequate. It covers what the tool does and the output type, but lacks details on behavioral aspects like authentication, rate limits, error handling, or pagination behavior. Without annotations or output schema, the description should do more to compensate, but it only partially meets the needs for such a parameter-rich 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?

The description lists example filter types (titles, locations, companies, skills, salary, remote options), which adds some context beyond the schema. However, with 100% schema description coverage, the schema already documents all 16 parameters thoroughly. The description doesn't provide additional syntax, format details, or usage tips that aren't already in the schema descriptions, so it meets the baseline for high schema coverage.

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

Purpose4/5

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

The description clearly states the tool's purpose: 'Search for jobs with filters... Returns a list of matching job postings.' It specifies the verb (search), resource (jobs), and output (list of job postings). However, it doesn't explicitly differentiate from sibling tools like 'match_jobs' or 'get_job', which could have overlapping functionality.

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?

The description provides no guidance on when to use this tool versus alternatives like 'match_jobs' or 'get_job'. It mentions filters but doesn't specify prerequisites, such as whether authentication is required or if there are rate limits. No explicit when-to-use or when-not-to-use context is provided.

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/6figr-com/job-gpt-mcp-server'

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