From 080bc26f9fa337c468ea95cf29f0d443fb3904ba Mon Sep 17 00:00:00 2001 From: Maksim Redzkin Date: Mon, 6 Jul 2026 13:47:36 +0300 Subject: [PATCH 1/2] Add sync & poll inbox --- package.json | 2 +- src/linked-api-tools.ts | 6 ++++ src/tools/get-inbox.ts | 58 ++++++++++++++++++++++++++++++++++++ src/tools/nv-send-message.ts | 17 +++++++---- src/tools/nv-sync-inbox.ts | 24 +++++++++++++++ src/tools/send-message.ts | 14 ++++++--- src/tools/sync-inbox.ts | 24 +++++++++++++++ 7 files changed, 135 insertions(+), 10 deletions(-) create mode 100644 src/tools/get-inbox.ts create mode 100644 src/tools/nv-sync-inbox.ts create mode 100644 src/tools/sync-inbox.ts diff --git a/package.json b/package.json index 6ba572d..1f70add 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@linkedapi/mcp", - "version": "2.1.2", + "version": "2.1.3", "description": "MCP server that lets AI assistants control LinkedIn accounts and retrieve real-time data.", "main": "dist/index.js", "bin": { diff --git a/src/linked-api-tools.ts b/src/linked-api-tools.ts index 89123e0..ef4d5df 100644 --- a/src/linked-api-tools.ts +++ b/src/linked-api-tools.ts @@ -28,6 +28,7 @@ import { FetchPersonTool } from './tools/fetch-person.js'; import { FetchPostTool } from './tools/fetch-post.js'; import { GetApiUsageTool } from './tools/get-api-usage-stats.js'; import { GetConversationTool } from './tools/get-conversation.js'; +import { GetInboxTool } from './tools/get-inbox.js'; import { GetWorkflowResultTool } from './tools/get-workflow-result.js'; import { NvFetchCompanyTool } from './tools/nv-fetch-company.js'; import { NvFetchPersonTool } from './tools/nv-fetch-person.js'; @@ -35,6 +36,7 @@ import { NvGetConversationTool } from './tools/nv-get-conversation.js'; import { NvSearchCompaniesTool } from './tools/nv-search-companies.js'; import { NvSearchPeopleTool } from './tools/nv-search-people.js'; import { NvSendMessageTool } from './tools/nv-send-message.js'; +import { NvSyncInboxTool } from './tools/nv-sync-inbox.js'; import { ReactToPostTool } from './tools/react-to-post.js'; import { RemoveConnectionTool } from './tools/remove-connection.js'; import { RetrieveConnectionsTool } from './tools/retrieve-connections.js'; @@ -46,6 +48,7 @@ import { SearchJobsTool } from './tools/search-jobs.js'; import { SearchPeopleTool } from './tools/search-people.js'; import { SendConnectionRequestTool } from './tools/send-connection-request.js'; import { SendMessageTool } from './tools/send-message.js'; +import { SyncInboxTool } from './tools/sync-inbox.js'; import { WithdrawConnectionRequestTool } from './tools/withdraw-connection-request.js'; import type { TLinkedApiToolResult } from './types/linked-api-tool-result.type.js'; import { AdminTool } from './utils/admin-tool.js'; @@ -70,6 +73,8 @@ export class LinkedApiTools { // Standard tools new SendMessageTool(), new GetConversationTool(), + new SyncInboxTool(), + new GetInboxTool(), new CheckConnectionStatusTool(), new RetrieveConnectionsTool(), new SendConnectionRequestTool(), @@ -91,6 +96,7 @@ export class LinkedApiTools { // Sales Navigator tools new NvSendMessageTool(), new NvGetConversationTool(), + new NvSyncInboxTool(), new NvSearchCompaniesTool(), new NvSearchPeopleTool(), new NvFetchCompanyTool(), diff --git a/src/tools/get-inbox.ts b/src/tools/get-inbox.ts new file mode 100644 index 0000000..9ea6a9d --- /dev/null +++ b/src/tools/get-inbox.ts @@ -0,0 +1,58 @@ +import LinkedApi, { TInboxPollRequest, TInboxPollResult, TMappedResponse } from '@linkedapi/node'; +import { Tool } from '@modelcontextprotocol/sdk/types.js'; +import z from 'zod'; + +import { LinkedApiTool } from '../utils/linked-api-tool.js'; + +export class GetInboxTool extends LinkedApiTool { + public readonly name = 'get_inbox'; + protected readonly schema = z.object({ + since: z.string().optional(), + type: z.enum(['st', 'nv']).optional(), + threadId: z.string().optional(), + }); + + public override async execute({ + linkedapi, + args: { since, type, threadId }, + }: { + linkedapi: LinkedApi; + args: TInboxPollRequest; + }): Promise> { + return linkedapi.pollInbox({ + since, + type, + threadId, + }); + } + + public override getTool(): Tool { + return { + name: this.name, + description: + 'Get messages from the monitored inbox across all conversations (standard and Sales Navigator), newest first. Requires inbox monitoring to be enabled once with sync_inbox (or nv_sync_inbox for Sales Navigator).', + inputSchema: { + type: 'object', + properties: { + since: { + type: 'string', + description: + "Optional ISO 8601 timestamp to only retrieve messages after this date (e.g., '2024-01-15T10:30:00Z'). If not provided, all captured messages are returned.", + }, + type: { + type: 'string', + enum: ['st', 'nv'], + description: + 'Optional inbox type filter: "st" for standard messages, "nv" for Sales Navigator messages. If omitted, both are returned.', + }, + threadId: { + type: 'string', + description: + 'Optional conversation thread identifier to restrict the result to a single thread.', + }, + }, + required: [], + }, + }; + } +} diff --git a/src/tools/nv-send-message.ts b/src/tools/nv-send-message.ts index 9c1e0c8..fd59a77 100644 --- a/src/tools/nv-send-message.ts +++ b/src/tools/nv-send-message.ts @@ -8,23 +8,24 @@ export class NvSendMessageTool extends OperationTool { + public override readonly name = 'nv_sync_inbox'; + public override readonly operationName = OPERATION_NAME.nvSyncInbox; + protected override readonly schema = z.object({}); + + public override getTool(): Tool { + return { + name: this.name, + description: + 'Enable whole-inbox monitoring in Sales Navigator so every incoming conversation can be polled with get_inbox (nv.syncInbox action). Run once per account; only messages that arrive after it is enabled are captured.', + inputSchema: { + type: 'object', + properties: {}, + required: [], + }, + }; + } +} diff --git a/src/tools/send-message.ts b/src/tools/send-message.ts index 716495f..852a4e1 100644 --- a/src/tools/send-message.ts +++ b/src/tools/send-message.ts @@ -8,29 +8,35 @@ export class SendMessageTool extends OperationTool public override readonly name = 'send_message'; public override readonly operationName = OPERATION_NAME.sendMessage; protected override readonly schema = z.object({ - personUrl: z.string(), + personUrl: z.string().optional(), text: z.string().min(1), + threadId: z.string().optional(), }); public override getTool(): Tool { return { name: this.name, description: - 'Allows you to send a message to a person (st.sendMessage action). If this workflow is still running, do not retry this tool; retrying can send duplicate messages to the same person.', + 'Allows you to send a message to a person (st.sendMessage action). Provide either personUrl or threadId (threadId replies into an existing conversation thread and takes precedence). If this workflow is still running, do not retry this tool; retrying can send duplicate messages to the same person.', inputSchema: { type: 'object', properties: { personUrl: { type: 'string', description: - "LinkedIn URL of the person you want to send a message to (e.g., 'https://www.linkedin.com/in/john-doe')", + "LinkedIn URL of the person you want to send a message to (e.g., 'https://www.linkedin.com/in/john-doe'). Optional if threadId is provided.", }, text: { type: 'string', description: 'The message text, must be up to 1900 characters.', }, + threadId: { + type: 'string', + description: + 'Optional conversation thread identifier to reply into, as returned by get_inbox. Provide this instead of personUrl to reply directly into a known thread.', + }, }, - required: ['personUrl', 'text'], + required: ['text'], }, }; } diff --git a/src/tools/sync-inbox.ts b/src/tools/sync-inbox.ts new file mode 100644 index 0000000..d45ae0d --- /dev/null +++ b/src/tools/sync-inbox.ts @@ -0,0 +1,24 @@ +import { OPERATION_NAME, TSyncInboxParams } from '@linkedapi/node'; +import { Tool } from '@modelcontextprotocol/sdk/types.js'; +import { z } from 'zod'; + +import { OperationTool } from '../utils/linked-api-tool.js'; + +export class SyncInboxTool extends OperationTool { + public override readonly name = 'sync_inbox'; + public override readonly operationName = OPERATION_NAME.syncInbox; + protected override readonly schema = z.object({}); + + public override getTool(): Tool { + return { + name: this.name, + description: + 'Enable whole-inbox monitoring so every incoming conversation can be polled with get_inbox (st.syncInbox action). Run once per account; only messages that arrive after it is enabled are captured.', + inputSchema: { + type: 'object', + properties: {}, + required: [], + }, + }; + } +} From 592d6f0e3d16528905a538b620478e3b71846344 Mon Sep 17 00:00:00 2001 From: Maksim Redzkin Date: Mon, 6 Jul 2026 14:16:05 +0300 Subject: [PATCH 2/2] Sync lock file with @linkedapi/node --- package-lock.json | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index b316501..b8d019e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@linkedapi/mcp", - "version": "2.1.2", + "version": "2.1.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@linkedapi/mcp", - "version": "2.1.2", + "version": "2.1.3", "license": "MIT", "dependencies": { - "@linkedapi/node": "^2.0.4", + "@linkedapi/node": "^2.1.1", "@modelcontextprotocol/sdk": "^1.17.4", "zod": "^4.1.1" }, @@ -921,9 +921,9 @@ } }, "node_modules/@linkedapi/node": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@linkedapi/node/-/node-2.0.4.tgz", - "integrity": "sha512-x/Xvkt3/mcJJoW1eZhkSqTvB7XFZVcXNZcAwQBEZfd2AvYhBiZWxKV2OkORetogfRxXHGsIw49ZPKJHadzJvSQ==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@linkedapi/node/-/node-2.1.1.tgz", + "integrity": "sha512-5CUuzuWOUvlJ9bBM+M0tua+ezA7mDjUbur87w5h3bqLE5rnHiFT3abspy6HmYxwpXjHErzUs7EfXTJrgejanLQ==" }, "node_modules/@modelcontextprotocol/sdk": { "version": "1.26.0", diff --git a/package.json b/package.json index 1f70add..1cd6b1c 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "author": "Linked API", "license": "MIT", "dependencies": { - "@linkedapi/node": "^2.0.4", + "@linkedapi/node": "^2.1.1", "@modelcontextprotocol/sdk": "^1.17.4", "zod": "^4.1.1" },