Skip to main content
Glama
Jing-yilin

LinkedIn MCP Server

by Jing-yilin
integration.test.ts12.7 kB
/** * MCP Server Integration Tests for LinkedIn MCP * * These tests verify the MCP server protocol compliance and tool schemas. * They spawn the actual MCP server and test via JSON-RPC. */ import { describe, test, expect } from 'bun:test'; import { spawn } from 'child_process'; import * as path from 'path'; const API_KEY = process.env.HARVESTAPI_API_KEY || process.env.LINKEDIN_API_KEY || ''; describe('LinkedIn MCP Server Integration Tests', () => { const sendRequest = (request: object): Promise<any> => { return new Promise((resolve, reject) => { const proc = spawn('node', [path.join(__dirname, '../build/index.js')], { env: { ...process.env, HARVESTAPI_API_KEY: API_KEY }, stdio: ['pipe', 'pipe', 'pipe'], }); let stdout = ''; let stderr = ''; proc.stdout?.on('data', (data) => { stdout += data.toString(); }); proc.stderr?.on('data', (data) => { stderr += data.toString(); }); proc.on('close', () => { try { const lines = stdout.trim().split('\n'); for (const line of lines) { if (line.startsWith('{')) { const response = JSON.parse(line); resolve(response); return; } } resolve({ stdout, stderr }); } catch (e) { resolve({ stdout, stderr, error: e }); } }); proc.on('error', reject); proc.stdin?.write(JSON.stringify(request) + '\n'); proc.stdin?.end(); setTimeout(() => { proc.kill(); reject(new Error('Request timeout')); }, 30000); }); }; describe('tools/list endpoint', () => { test('returns all 17 tools', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); expect(response.result).toBeDefined(); expect(response.result.tools).toBeInstanceOf(Array); expect(response.result.tools.length).toBe(17); }); test('includes get_profile tool with correct schema', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; const tool = tools.find((t: any) => t.name === 'get_profile'); expect(tool).toBeDefined(); expect(tool.inputSchema.properties).toHaveProperty('url'); expect(tool.inputSchema.properties).toHaveProperty('publicIdentifier'); expect(tool.inputSchema.properties).toHaveProperty('profileId'); expect(tool.inputSchema.properties).toHaveProperty('findEmail'); expect(tool.inputSchema.properties).toHaveProperty('includeAboutProfile'); }); test('includes search_profiles tool with correct schema', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; const tool = tools.find((t: any) => t.name === 'search_profiles'); expect(tool).toBeDefined(); expect(tool.inputSchema.required).toContain('search'); expect(tool.inputSchema.properties).toHaveProperty('currentCompany'); expect(tool.inputSchema.properties).toHaveProperty('pastCompany'); expect(tool.inputSchema.properties).toHaveProperty('school'); expect(tool.inputSchema.properties).toHaveProperty('firstName'); expect(tool.inputSchema.properties).toHaveProperty('lastName'); expect(tool.inputSchema.properties).toHaveProperty('title'); expect(tool.inputSchema.properties).toHaveProperty('location'); expect(tool.inputSchema.properties).toHaveProperty('geoId'); expect(tool.inputSchema.properties).toHaveProperty('industryId'); }); test('includes get_profile_posts tool', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; const tool = tools.find((t: any) => t.name === 'get_profile_posts'); expect(tool).toBeDefined(); expect(tool.inputSchema.properties).toHaveProperty('profile'); expect(tool.inputSchema.properties).toHaveProperty('profileId'); expect(tool.inputSchema.properties).toHaveProperty('profilePublicIdentifier'); expect(tool.inputSchema.properties).toHaveProperty('postedLimit'); }); test('includes get_company tool with correct schema', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; const tool = tools.find((t: any) => t.name === 'get_company'); expect(tool).toBeDefined(); expect(tool.inputSchema.properties).toHaveProperty('url'); expect(tool.inputSchema.properties).toHaveProperty('universalName'); expect(tool.inputSchema.properties).toHaveProperty('search'); }); test('includes search_companies tool', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; const tool = tools.find((t: any) => t.name === 'search_companies'); expect(tool).toBeDefined(); expect(tool.inputSchema.required).toContain('search'); expect(tool.inputSchema.properties).toHaveProperty('location'); expect(tool.inputSchema.properties).toHaveProperty('geoId'); expect(tool.inputSchema.properties).toHaveProperty('companySize'); }); test('includes get_job tool', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; const tool = tools.find((t: any) => t.name === 'get_job'); expect(tool).toBeDefined(); expect(tool.inputSchema.properties).toHaveProperty('jobId'); expect(tool.inputSchema.properties).toHaveProperty('url'); }); test('includes search_jobs tool with comprehensive filters', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; const tool = tools.find((t: any) => t.name === 'search_jobs'); expect(tool).toBeDefined(); expect(tool.inputSchema.properties).toHaveProperty('search'); expect(tool.inputSchema.properties).toHaveProperty('companyId'); expect(tool.inputSchema.properties).toHaveProperty('location'); expect(tool.inputSchema.properties).toHaveProperty('geoId'); expect(tool.inputSchema.properties).toHaveProperty('sortBy'); expect(tool.inputSchema.properties).toHaveProperty('workplaceType'); expect(tool.inputSchema.properties).toHaveProperty('employmentType'); expect(tool.inputSchema.properties).toHaveProperty('salary'); expect(tool.inputSchema.properties).toHaveProperty('postedLimit'); expect(tool.inputSchema.properties).toHaveProperty('experienceLevel'); expect(tool.inputSchema.properties).toHaveProperty('industryId'); expect(tool.inputSchema.properties).toHaveProperty('functionId'); expect(tool.inputSchema.properties).toHaveProperty('under10Applicants'); expect(tool.inputSchema.properties).toHaveProperty('easyApply'); }); test('includes get_post tool requiring URL', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; const tool = tools.find((t: any) => t.name === 'get_post'); expect(tool).toBeDefined(); expect(tool.inputSchema.required).toContain('url'); }); test('includes search_posts tool', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; const tool = tools.find((t: any) => t.name === 'search_posts'); expect(tool).toBeDefined(); expect(tool.inputSchema.properties).toHaveProperty('search'); expect(tool.inputSchema.properties).toHaveProperty('profile'); expect(tool.inputSchema.properties).toHaveProperty('company'); expect(tool.inputSchema.properties).toHaveProperty('authorsCompany'); expect(tool.inputSchema.properties).toHaveProperty('postedLimit'); expect(tool.inputSchema.properties).toHaveProperty('sortBy'); }); test('includes get_post_comments tool', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; const tool = tools.find((t: any) => t.name === 'get_post_comments'); expect(tool).toBeDefined(); expect(tool.inputSchema.required).toContain('post'); expect(tool.inputSchema.properties).toHaveProperty('sortBy'); expect(tool.inputSchema.properties).toHaveProperty('paginationToken'); }); test('includes get_post_reactions tool', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; const tool = tools.find((t: any) => t.name === 'get_post_reactions'); expect(tool).toBeDefined(); expect(tool.inputSchema.required).toContain('post'); }); test('includes get_group tool', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; const tool = tools.find((t: any) => t.name === 'get_group'); expect(tool).toBeDefined(); expect(tool.inputSchema.properties).toHaveProperty('url'); expect(tool.inputSchema.properties).toHaveProperty('groupId'); }); test('includes search_groups tool', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; const tool = tools.find((t: any) => t.name === 'search_groups'); expect(tool).toBeDefined(); expect(tool.inputSchema.required).toContain('search'); }); test('includes search_geo_id tool', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; const tool = tools.find((t: any) => t.name === 'search_geo_id'); expect(tool).toBeDefined(); expect(tool.inputSchema.required).toContain('search'); }); test('all tools have name and description', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; for (const tool of tools) { expect(tool).toHaveProperty('name'); expect(tool).toHaveProperty('description'); expect(tool).toHaveProperty('inputSchema'); expect(tool.name).toBeTruthy(); expect(tool.description).toBeTruthy(); } }); test('tool names follow snake_case convention', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {}, }); const tools = response.result.tools; const snakeCaseRegex = /^[a-z]+(_[a-z]+)*$/; for (const tool of tools) { expect(snakeCaseRegex.test(tool.name)).toBe(true); } }); }); describe('Error handling', () => { test('returns error for unknown tool', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 2, method: 'tools/call', params: { name: 'unknown_tool', arguments: {}, }, }); expect(response.error || response.result).toBeDefined(); }); test('returns error for missing arguments', async () => { const response = await sendRequest({ jsonrpc: '2.0', id: 3, method: 'tools/call', params: { name: 'get_profile', }, }); expect(response.error || response.result).toBeDefined(); }); }); });

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