search_jobs
Search LinkedIn job listings with filters for location, salary, experience level, and employment type to find relevant opportunities.
Instructions
Search LinkedIn jobs. Returns cleaned data in TOON format.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| search | No | Search jobs by title | |
| companyId | No | Filter by company ID | |
| location | No | Filter by location | |
| geoId | No | Filter by LinkedIn Geo ID | |
| sortBy | No | Sort by: relevance or date | |
| workplaceType | No | Filter: office, hybrid, remote | |
| employmentType | No | Filter: full-time, part-time, contract, temporary, volunteer, internship | |
| salary | No | Filter by salary: 40k+, 60k+, 80k+, 100k+, 120k+, 140k+, 160k+, 180k+, 200k+ | |
| postedLimit | No | Filter by post date: 24h, week, month | |
| experienceLevel | No | Filter: internship, entry, associate, mid-senior, director, executive | |
| industryId | No | Filter by industry ID (comma-separated) | |
| functionId | No | Filter by job function ID (comma-separated) | |
| under10Applicants | No | Filter jobs with under 10 applicants | |
| easyApply | No | Filter Easy Apply jobs | |
| page | No | Page number | |
| save_dir | No | Directory to save cleaned JSON data | |
| max_items | No | Maximum results (default: 10) |
Implementation Reference
- src/index.ts:842-870 (handler)The main handler function that implements the search_jobs tool. Builds query parameters from input args, calls the HarvestAPI /job-search endpoint, cleans the job search results using DataCleaners.cleanJobSearchResult, limits results, and returns a formatted TOON-encoded response with optional saving and pagination info.private async searchJobs(args: Record<string, any>): Promise<CallToolResult> { const params: Record<string, any> = {}; if (args.search) params.search = args.search; if (args.companyId) params.companyId = args.companyId; if (args.location) params.location = args.location; if (args.geoId) params.geoId = args.geoId; if (args.sortBy) params.sortBy = args.sortBy; if (args.workplaceType) params.workplaceType = args.workplaceType; if (args.employmentType) params.employmentType = args.employmentType; if (args.salary) params.salary = args.salary; if (args.postedLimit) params.postedLimit = args.postedLimit; if (args.experienceLevel) params.experienceLevel = args.experienceLevel; if (args.industryId) params.industryId = args.industryId; if (args.functionId) params.functionId = args.functionId; if (args.under10Applicants) params.under10Applicants = args.under10Applicants; if (args.easyApply !== undefined) params.easyApply = args.easyApply; if (args.page) params.page = args.page; const data = await this.makeRequest('/job-search', params); const maxItems = args.max_items || 10; const cleaned = (data.elements || []).slice(0, maxItems).map(DataCleaners.cleanJobSearchResult); return this.formatResponse(cleaned, { saveDir: args.save_dir, toolName: 'search_jobs', pagination: data.pagination, }); }
- src/index.ts:394-416 (schema)Input schema definition for the search_jobs tool, specifying all available parameters, their types, descriptions, enums, and defaults for MCP validation.inputSchema: { type: 'object', properties: { search: { type: 'string', description: 'Search jobs by title' }, companyId: { type: 'string', description: 'Filter by company ID' }, location: { type: 'string', description: 'Filter by location' }, geoId: { type: 'string', description: 'Filter by LinkedIn Geo ID' }, sortBy: { type: 'string', description: 'Sort by: relevance or date', enum: ['relevance', 'date'] }, workplaceType: { type: 'string', description: 'Filter: office, hybrid, remote', enum: ['office', 'hybrid', 'remote'] }, employmentType: { type: 'string', description: 'Filter: full-time, part-time, contract, temporary, volunteer, internship', enum: ['full-time', 'part-time', 'contract', 'temporary', 'volunteer', 'internship'] }, salary: { type: 'string', description: 'Filter by salary: 40k+, 60k+, 80k+, 100k+, 120k+, 140k+, 160k+, 180k+, 200k+' }, postedLimit: { type: 'string', description: 'Filter by post date: 24h, week, month', enum: ['24h', 'week', 'month'] }, experienceLevel: { type: 'string', description: 'Filter: internship, entry, associate, mid-senior, director, executive', enum: ['internship', 'entry', 'associate', 'mid-senior', 'director', 'executive'] }, industryId: { type: 'string', description: 'Filter by industry ID (comma-separated)' }, functionId: { type: 'string', description: 'Filter by job function ID (comma-separated)' }, under10Applicants: { type: 'boolean', description: 'Filter jobs with under 10 applicants' }, easyApply: { type: 'boolean', description: 'Filter Easy Apply jobs' }, page: { type: 'integer', description: 'Page number', default: 1 }, save_dir: { type: 'string', description: 'Directory to save cleaned JSON data' }, max_items: { type: 'integer', description: 'Maximum results (default: 10)', default: 10 }, }, required: [], },
- src/index.ts:391-417 (registration)Tool registration in the MCP server's listTools response, defining name, description, and inputSchema for search_jobs.{ name: 'search_jobs', description: 'Search LinkedIn jobs. Returns cleaned data in TOON format.', inputSchema: { type: 'object', properties: { search: { type: 'string', description: 'Search jobs by title' }, companyId: { type: 'string', description: 'Filter by company ID' }, location: { type: 'string', description: 'Filter by location' }, geoId: { type: 'string', description: 'Filter by LinkedIn Geo ID' }, sortBy: { type: 'string', description: 'Sort by: relevance or date', enum: ['relevance', 'date'] }, workplaceType: { type: 'string', description: 'Filter: office, hybrid, remote', enum: ['office', 'hybrid', 'remote'] }, employmentType: { type: 'string', description: 'Filter: full-time, part-time, contract, temporary, volunteer, internship', enum: ['full-time', 'part-time', 'contract', 'temporary', 'volunteer', 'internship'] }, salary: { type: 'string', description: 'Filter by salary: 40k+, 60k+, 80k+, 100k+, 120k+, 140k+, 160k+, 180k+, 200k+' }, postedLimit: { type: 'string', description: 'Filter by post date: 24h, week, month', enum: ['24h', 'week', 'month'] }, experienceLevel: { type: 'string', description: 'Filter: internship, entry, associate, mid-senior, director, executive', enum: ['internship', 'entry', 'associate', 'mid-senior', 'director', 'executive'] }, industryId: { type: 'string', description: 'Filter by industry ID (comma-separated)' }, functionId: { type: 'string', description: 'Filter by job function ID (comma-separated)' }, under10Applicants: { type: 'boolean', description: 'Filter jobs with under 10 applicants' }, easyApply: { type: 'boolean', description: 'Filter Easy Apply jobs' }, page: { type: 'integer', description: 'Page number', default: 1 }, save_dir: { type: 'string', description: 'Directory to save cleaned JSON data' }, max_items: { type: 'integer', description: 'Maximum results (default: 10)', default: 10 }, }, required: [], }, } as Tool,
- src/index.ts:543-543 (registration)Dispatch case in the callTool request handler that routes search_jobs calls to the searchJobs method.case 'search_jobs': return await this.searchJobs(args as Record<string, any>);
- src/index.ts:119-130 (helper)Helper function in DataCleaners that cleans raw job search results, extracting key fields like id, title, url, company, location for agent-friendly output.cleanJobSearchResult(raw: any): any { if (!raw) return null; return { id: raw.id, title: raw.title, url: raw.url, postedDate: raw.postedDate, company: raw.company?.name, location: raw.location?.linkedinText, easyApply: raw.easyApply, }; },