Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@linkedapi/mcp",
"version": "2.3.17",
"version": "2.3.18",
"description": "MCP server that lets AI assistants control LinkedIn accounts and retrieve real-time data.",
"main": "dist/index.js",
"bin": {
Expand Down Expand Up @@ -30,7 +30,7 @@
"author": "Linked API",
"license": "MIT",
"dependencies": {
"@linkedapi/node": "^2.3.17",
"@linkedapi/node": "^2.3.19",
"@modelcontextprotocol/sdk": "^1.17.4",
"zod": "^4.1.1"
},
Expand Down
4 changes: 4 additions & 0 deletions src/linked-api-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import { CheckConnectionStatusTool } from './tools/check-connection-status.js';
import { CommentOnPostTool } from './tools/comment-on-post.js';
import { CreatePostTool } from './tools/create-post.js';
import { CreateRepostTool } from './tools/create-repost.js';
import { EndorsePersonSkillTool } from './tools/endorse-person-skill.js';
import { EndorsePersonSkillsTool } from './tools/endorse-person-skills.js';
import { ExecuteCustomWorkflowTool } from './tools/execute-custom-workflow.js';
import { FetchCompanyTool } from './tools/fetch-company.js';
import { FetchJobTool } from './tools/fetch-job.js';
Expand Down Expand Up @@ -114,6 +116,8 @@ export class LinkedApiTools {
new SearchPostsTool(),
new FetchCompanyTool(),
new FetchPersonTool(),
new EndorsePersonSkillTool(),
new EndorsePersonSkillsTool(),
new FetchPostTool(),
new FetchJobTool(),
new ReactToPostTool(),
Expand Down
4 changes: 2 additions & 2 deletions src/tools/admin-delete-limits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class AdminDeleteLimitsTool extends AdminTool<TDeleteLimitsParams, void>
return {
name: this.name,
description:
'Delete specific rate limits for an account. Deleted limits fall back to system defaults.',
'Delete specific rate limits for an account. Each removed category/period has no limit until set again. Use admin_reset_limits to restore all default limits for the account.',
inputSchema: {
type: 'object',
properties: {
Expand All @@ -46,7 +46,7 @@ export class AdminDeleteLimitsTool extends AdminTool<TDeleteLimitsParams, void>
properties: {
category: {
type: 'string',
description: 'Limit category',
description: 'Limit category, e.g. stEndorsements',
},
period: {
type: 'string',
Expand Down
2 changes: 1 addition & 1 deletion src/tools/admin-set-limits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class AdminSetLimitsTool extends AdminTool<TSetLimitsParams, void> {
return {
name: this.name,
description:
'Set rate limits for an account. Only specified limits are created or updated; other limits remain unchanged. Categories: stPersonProfileViews, stCompanyPageViews, stConnectionRequests, stMessages, stSearchQueries, stReactions, stComments, stPosts, nvPersonProfileViews, nvCompanyPageViews, nvMessages.',
'Set rate limits for an account. Only specified limits are created or updated; other limits remain unchanged. Categories: stPersonProfileViews, stCompanyPageViews, stConnectionRequests, stMessages, stSearchQueries, stReactions, stComments, stPosts, stEndorsements, nvPersonProfileViews, nvCompanyPageViews, nvMessages.',
inputSchema: {
type: 'object',
properties: {
Expand Down
39 changes: 39 additions & 0 deletions src/tools/endorse-person-skill.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { OPERATION_NAME, TEndorsePersonSkillParams } from '@linkedapi/node';
import { Tool } from '@modelcontextprotocol/sdk/types.js';
import { z } from 'zod';

import { OperationTool } from '../utils/linked-api-tool.js';

export class EndorsePersonSkillTool extends OperationTool<TEndorsePersonSkillParams, void> {
public override readonly name = 'endorse_person_skill';
public override readonly operationName = OPERATION_NAME.endorsePersonSkill;
protected override readonly schema = z.object({
personUrl: z.string(),
skillName: z.string().min(1).max(200),
});

public override getTool(): Tool {
return {
name: this.name,
description:
"Endorses one skill by name on a 1st-degree connection's profile. Skill names are in the profile owner's language, regardless of your LinkedIn language. An already-endorsed skill counts as success and is never removed. Every success, including an existing endorsement, counts toward the stEndorsements limit. Use endorse_person_skills to select skills with patterns or endorse all skills. If this workflow is still running, do not retry this tool; retrying can count the same skill toward the stEndorsements limit again.",
inputSchema: {
type: 'object',
properties: {
personUrl: {
type: 'string',
description: 'Public or hashed LinkedIn URL of your 1st-degree connection.',
},
skillName: {
type: 'string',
minLength: 1,
maxLength: 200,
description:
"Exact skill name in the profile owner's language, up to 200 characters. Letter case and extra spaces are ignored. This is not a pattern.",
},
},
required: ['personUrl', 'skillName'],
},
};
}
}
51 changes: 51 additions & 0 deletions src/tools/endorse-person-skills.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {
OPERATION_NAME,
TEndorsePersonSkillsParams,
TPersonSkillEndorsement,
} from '@linkedapi/node';
import { Tool } from '@modelcontextprotocol/sdk/types.js';
import { z } from 'zod';

import { OperationTool } from '../utils/linked-api-tool.js';

export class EndorsePersonSkillsTool extends OperationTool<
TEndorsePersonSkillsParams,
Array<TPersonSkillEndorsement>
> {
public override readonly name = 'endorse_person_skills';
public override readonly operationName = OPERATION_NAME.endorsePersonSkills;
protected override readonly schema = z.object({
personUrl: z.string(),
skillNamePatterns: z.array(z.string().min(1).max(200)).min(1).max(20).optional(),
});

public override getTool(): Tool {
return {
name: this.name,
description:
"Endorses selected skills of a 1st-degree connection, returning each selected skill's name, success and error if it failed. Skill names are in the profile owner's language. Patterns use RE2, are case-insensitive and match anywhere; anchor with ^…$ to match a whole name. Omit skillNamePatterns to endorse all skills; never pass []. An already-endorsed skill counts as success and is never removed. Each success counts toward the stEndorsements limit, including existing endorsements. The limit is checked for each skill; a failure does not stop the others, so check every item's success. If this workflow is still running, do not retry this tool; retrying can count the same skills toward the stEndorsements limit again.",
inputSchema: {
type: 'object',
properties: {
personUrl: {
type: 'string',
description: 'Public or hashed LinkedIn URL of your 1st-degree connection.',
},
skillNamePatterns: {
type: 'array',
minItems: 1,
maxItems: 20,
items: {
type: 'string',
minLength: 1,
maxLength: 200,
},
description:
"Optional. 1-20 RE2 patterns, each 1-200 characters, matching names in the profile owner's language. Any matching pattern selects the skill. Matching is case-insensitive and searches anywhere: manage matches Project Management; ^scrum$ matches only the whole name Scrum. Lookaround and backreferences are unsupported. Omit this parameter to endorse all skills; never pass an empty array.",
},
},
required: ['personUrl'],
},
};
}
}
Loading