Skip to main content
Glama
Jing-yilin

LinkedIn MCP Server

by Jing-yilin

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
NameRequiredDescriptionDefault
searchNoSearch jobs by title
companyIdNoFilter by company ID
locationNoFilter by location
geoIdNoFilter by LinkedIn Geo ID
sortByNoSort by: relevance or date
workplaceTypeNoFilter: office, hybrid, remote
employmentTypeNoFilter: full-time, part-time, contract, temporary, volunteer, internship
salaryNoFilter by salary: 40k+, 60k+, 80k+, 100k+, 120k+, 140k+, 160k+, 180k+, 200k+
postedLimitNoFilter by post date: 24h, week, month
experienceLevelNoFilter: internship, entry, associate, mid-senior, director, executive
industryIdNoFilter by industry ID (comma-separated)
functionIdNoFilter by job function ID (comma-separated)
under10ApplicantsNoFilter jobs with under 10 applicants
easyApplyNoFilter Easy Apply jobs
pageNoPage number
save_dirNoDirectory to save cleaned JSON data
max_itemsNoMaximum results (default: 10)

Implementation Reference

  • 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, }); }
  • 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>);
  • 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, }; },

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/Jing-yilin/linkedin-mcp-server'

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