@oneshot-agent/mcp-server 0.22.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +1 -1
- package/dist/tools/index.js +19 -0
- package/dist/tools/linkedin.d.ts +20 -0
- package/dist/tools/linkedin.js +198 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -96,7 +96,7 @@ Read tools (inbox, SMS inbox, notifications, balance, browser profiles) return p
|
|
|
96
96
|
## Remote (hosted)
|
|
97
97
|
|
|
98
98
|
Clients that run in someone else's cloud — Grok Bot, hosted runners — cannot spawn this
|
|
99
|
-
server and must not hold a wallet key. For them OneShot hosts the same
|
|
99
|
+
server and must not hold a wallet key. For them OneShot hosts the same 61 tools over
|
|
100
100
|
Streamable HTTP at **`https://win.oneshotagent.com/mcp`**, authenticated with an
|
|
101
101
|
**agent access token** and billed to the agent's credit balance:
|
|
102
102
|
|
package/dist/index.js
CHANGED
|
@@ -52,7 +52,7 @@ async function main() {
|
|
|
52
52
|
// Create MCP server
|
|
53
53
|
const server = new Server({
|
|
54
54
|
name: "oneshot-mcp",
|
|
55
|
-
version: "0.
|
|
55
|
+
version: "0.23.0", // keep in sync with package.json; guarded by version.test.ts
|
|
56
56
|
}, {
|
|
57
57
|
capabilities: {
|
|
58
58
|
tools: {},
|
package/dist/tools/index.js
CHANGED
|
@@ -17,6 +17,7 @@ import { deepResearchPersonTool, socialProfilesTool, articleSearchTool, personNe
|
|
|
17
17
|
import { companySearchTool, enrichCompanyTool, handleCompanySearch, handleEnrichCompany } from "./company.js";
|
|
18
18
|
import { localSearchTool, localResolveTool, handleLocalSearch, handleLocalResolve } from "./local.js";
|
|
19
19
|
import { govSolicitationsTool, handleGovSolicitations } from "./gov.js";
|
|
20
|
+
import { linkedinConnectTool, linkedinAccountsTool, linkedinSyncTool, linkedinConversationsTool, linkedinMessagesTool, linkedinReplyTool, linkedinViewProfileTool, linkedinReactTool, handleLinkedinConnect, handleLinkedinAccounts, handleLinkedinSync, handleLinkedinConversations, handleLinkedinMessages, handleLinkedinReply, handleLinkedinViewProfile, handleLinkedinReact, } from "./linkedin.js";
|
|
20
21
|
import { computeTool, computeStatusTool, computeTasksTool, computeCancelTool, computeRespondTool, computePauseTool, computeResumeTool, computeFundTool, handleCompute, handleComputeStatus, handleComputeTasks, handleComputeCancel, handleComputeRespond, handleComputePause, handleComputeResume, handleComputeFund } from "./compute.js";
|
|
21
22
|
import { listDomainsTool, pauseDomainTool, resumeDomainTool, handleListDomains, handlePauseDomain, handleResumeDomain } from "./domains.js";
|
|
22
23
|
import { spendBreakdownTool, rocsTool, rocsByGoalTool, receiptsListTool, tagReceiptValueTool, handleSpendBreakdown, handleRocs, handleRocsByGoal, handleReceiptsList, handleTagReceiptValue } from "./analytics.js";
|
|
@@ -71,6 +72,15 @@ export const tools = [
|
|
|
71
72
|
browserDeleteProfileTool,
|
|
72
73
|
// Web Read
|
|
73
74
|
webReadTool,
|
|
75
|
+
// LinkedIn (human-connected account)
|
|
76
|
+
linkedinConnectTool,
|
|
77
|
+
linkedinAccountsTool,
|
|
78
|
+
linkedinSyncTool,
|
|
79
|
+
linkedinConversationsTool,
|
|
80
|
+
linkedinMessagesTool,
|
|
81
|
+
linkedinReplyTool,
|
|
82
|
+
linkedinViewProfileTool,
|
|
83
|
+
linkedinReactTool,
|
|
74
84
|
// Domains
|
|
75
85
|
listDomainsTool,
|
|
76
86
|
pauseDomainTool,
|
|
@@ -138,6 +148,15 @@ const handlers = {
|
|
|
138
148
|
"oneshot_browser_delete_profile": handleBrowserDeleteProfile,
|
|
139
149
|
// Web Read
|
|
140
150
|
"oneshot_web_read": handleWebRead,
|
|
151
|
+
// LinkedIn (human-connected account)
|
|
152
|
+
"oneshot_linkedin_connect": handleLinkedinConnect,
|
|
153
|
+
"oneshot_linkedin_accounts": handleLinkedinAccounts,
|
|
154
|
+
"oneshot_linkedin_sync": handleLinkedinSync,
|
|
155
|
+
"oneshot_linkedin_conversations": handleLinkedinConversations,
|
|
156
|
+
"oneshot_linkedin_messages": handleLinkedinMessages,
|
|
157
|
+
"oneshot_linkedin_reply": handleLinkedinReply,
|
|
158
|
+
"oneshot_linkedin_view_profile": handleLinkedinViewProfile,
|
|
159
|
+
"oneshot_linkedin_react": handleLinkedinReact,
|
|
141
160
|
// Domains
|
|
142
161
|
"oneshot_list_domains": handleListDomains,
|
|
143
162
|
"oneshot_pause_domain": handlePauseDomain,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import type { OneShot } from "@oneshot-agent/sdk";
|
|
3
|
+
export declare const linkedinConnectTool: Tool;
|
|
4
|
+
export declare const linkedinAccountsTool: Tool;
|
|
5
|
+
export declare const linkedinSyncTool: Tool;
|
|
6
|
+
export declare const linkedinConversationsTool: Tool;
|
|
7
|
+
export declare const linkedinMessagesTool: Tool;
|
|
8
|
+
export declare const linkedinReplyTool: Tool;
|
|
9
|
+
export declare const linkedinViewProfileTool: Tool;
|
|
10
|
+
export declare const linkedinReactTool: Tool;
|
|
11
|
+
export declare function handleLinkedinConnect(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").LinkedInConnectIntentIssued>;
|
|
12
|
+
export declare function handleLinkedinAccounts(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").LinkedInConnectIntent | import("@oneshot-agent/sdk").LinkedInSyncStatus | {
|
|
13
|
+
accounts: import("@oneshot-agent/sdk").LinkedInAccount[];
|
|
14
|
+
}>;
|
|
15
|
+
export declare function handleLinkedinSync(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").LinkedInSyncRunResult>;
|
|
16
|
+
export declare function handleLinkedinConversations(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").LinkedInConversationsPage>;
|
|
17
|
+
export declare function handleLinkedinMessages(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").LinkedInMessagesPage>;
|
|
18
|
+
export declare function handleLinkedinReply(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").LinkedInWriteResult>;
|
|
19
|
+
export declare function handleLinkedinViewProfile(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").LinkedInProfileViewResult>;
|
|
20
|
+
export declare function handleLinkedinReact(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").LinkedInWriteResult>;
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LinkedIn messaging through a human-connected account (issue #756).
|
|
3
|
+
*
|
|
4
|
+
* The human connects their own LinkedIn account via a hosted login link and
|
|
5
|
+
* grants specific actions (read, reply, view_profile, react). Reconnect and
|
|
6
|
+
* revoke are deliberately NOT exposed as MCP tools — a human decides those
|
|
7
|
+
* from the application that owns the account.
|
|
8
|
+
*/
|
|
9
|
+
const GRANT_ACTIONS = ["read", "reply", "view_profile", "react", "invite", "comment"];
|
|
10
|
+
export const linkedinConnectTool = {
|
|
11
|
+
name: "oneshot_linkedin_connect",
|
|
12
|
+
description: "Create a hosted LinkedIn login link for a human to connect THEIR OWN LinkedIn account to this agent, granting specific actions (read, reply, view_profile, react). Returns intent_id + url (show the url to the human; it expires in 30 minutes; never embed it in an iframe). Poll oneshot_linkedin_accounts with the intent_id afterwards. Free tool.",
|
|
13
|
+
inputSchema: {
|
|
14
|
+
type: "object",
|
|
15
|
+
properties: {
|
|
16
|
+
requested_actions: { type: "array", items: { type: "string", enum: GRANT_ACTIONS }, description: "Actions to ask the human to grant. 'read' is needed for sync + reads; 'reply' to send; 'view_profile' / 'react' for engagement." },
|
|
17
|
+
success_redirect_url: { type: "string", description: "https:// URL the human is sent to after connecting (optional)" },
|
|
18
|
+
failure_redirect_url: { type: "string", description: "https:// URL on failure (optional)" },
|
|
19
|
+
},
|
|
20
|
+
required: ["requested_actions"],
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
export const linkedinAccountsTool = {
|
|
24
|
+
name: "oneshot_linkedin_accounts",
|
|
25
|
+
description: "List the LinkedIn accounts connected to this agent (status, granted actions, sync coverage), or, with intent_id, check a pending connection from oneshot_linkedin_connect (pending → completed with the account, or failed with a reason). Free tool.",
|
|
26
|
+
inputSchema: {
|
|
27
|
+
type: "object",
|
|
28
|
+
properties: {
|
|
29
|
+
intent_id: { type: "string", description: "Connection intent to check instead of listing accounts" },
|
|
30
|
+
account_id: { type: "string", description: "Return one account (with coverage + recent sync runs) instead of the list" },
|
|
31
|
+
include_revoked: { type: "boolean", description: "Include revoked accounts in the list (default false)" },
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
export const linkedinSyncTool = {
|
|
36
|
+
name: "oneshot_linkedin_sync",
|
|
37
|
+
description: "Sync message history from a connected LinkedIn account. One paid call = one bounded run (up to max_pages × 250 messages, newest first); a run that hits the bound is paused with a cursor and the next call with mode 'continue' resumes it. Check coverage.complete / pending_cursor in the result before buying another run. Requires the 'read' grant. Paid tool (flat price per run).",
|
|
38
|
+
inputSchema: {
|
|
39
|
+
type: "object",
|
|
40
|
+
properties: {
|
|
41
|
+
account_id: { type: "string", description: "Connected LinkedIn account id (required)" },
|
|
42
|
+
mode: { type: "string", enum: ["continue", "restart", "history"], description: "continue = resume the paused cursor (default); restart = discard paused cursors; history = also re-request the provider's history back-fill" },
|
|
43
|
+
max_pages: { type: "number", description: "Pages of 250 messages this run may fetch (1-10, default 10)" },
|
|
44
|
+
memo: { type: "string", description: "Why this sync is running (audit trail)" },
|
|
45
|
+
},
|
|
46
|
+
required: ["account_id"],
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
export const linkedinConversationsTool = {
|
|
50
|
+
name: "oneshot_linkedin_conversations",
|
|
51
|
+
description: "List synced LinkedIn conversations for a connected account, newest activity first, with attendees and unread counts. Every response carries coverage + sync_state — an empty list with sync_state != 'complete' means not synced yet, not an empty inbox. Free tool.",
|
|
52
|
+
inputSchema: {
|
|
53
|
+
type: "object",
|
|
54
|
+
properties: {
|
|
55
|
+
account_id: { type: "string", description: "Connected LinkedIn account id (required)" },
|
|
56
|
+
cursor: { type: "string", description: "next_cursor from the previous page" },
|
|
57
|
+
limit: { type: "number", description: "1-100, default 50" },
|
|
58
|
+
since: { type: "string", description: "ISO time: only conversations changed after this" },
|
|
59
|
+
unread: { type: "boolean", description: "Only conversations with unread messages" },
|
|
60
|
+
archived: { type: "boolean", description: "List archived conversations instead of active ones (default false)" },
|
|
61
|
+
},
|
|
62
|
+
required: ["account_id"],
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
export const linkedinMessagesTool = {
|
|
66
|
+
name: "oneshot_linkedin_messages",
|
|
67
|
+
description: "List synced LinkedIn messages for a connected account, newest first. Filter by conversation_id, direction ('inbound' = the human received it; use since as a reply watermark), since (sent after), changed_since (edited/read/deleted after). Attachment metadata only. Free tool.",
|
|
68
|
+
inputSchema: {
|
|
69
|
+
type: "object",
|
|
70
|
+
properties: {
|
|
71
|
+
account_id: { type: "string", description: "Connected LinkedIn account id (required)" },
|
|
72
|
+
conversation_id: { type: "string", description: "Restrict to one conversation" },
|
|
73
|
+
direction: { type: "string", enum: ["inbound", "outbound"] },
|
|
74
|
+
since: { type: "string", description: "ISO time: only messages sent after this" },
|
|
75
|
+
changed_since: { type: "string", description: "ISO time: only messages updated after this" },
|
|
76
|
+
cursor: { type: "string", description: "next_cursor from the previous page" },
|
|
77
|
+
limit: { type: "number", description: "1-100, default 50" },
|
|
78
|
+
include_deleted: { type: "boolean", description: "Include messages deleted upstream (default false)" },
|
|
79
|
+
},
|
|
80
|
+
required: ["account_id"],
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
export const linkedinReplyTool = {
|
|
84
|
+
name: "oneshot_linkedin_reply",
|
|
85
|
+
description: "Send a reply in an existing LinkedIn conversation through a connected account that granted 'reply'. The human's account sends it; a message LinkedIn accepted cannot be recalled. Per-account daily cap (default 50) shared by every caller; sends are paced. An Idempotency-Key is generated automatically so a retry never double-sends. Outcome (sent / failed / ambiguous-under-reconciliation) is in the returned job result. Paid tool (flat price per message).",
|
|
86
|
+
inputSchema: {
|
|
87
|
+
type: "object",
|
|
88
|
+
properties: {
|
|
89
|
+
account_id: { type: "string", description: "Connected LinkedIn account id (required)" },
|
|
90
|
+
conversation_id: { type: "string", description: "Conversation id from oneshot_linkedin_conversations (required)" },
|
|
91
|
+
text: { type: "string", description: "Message text, 1-4000 characters (required)" },
|
|
92
|
+
memo: { type: "string", description: "Why this reply is being sent (audit trail)" },
|
|
93
|
+
idempotency_key: { type: "string", description: "Optional caller-supplied key; reuse it to safely retry the same send" },
|
|
94
|
+
},
|
|
95
|
+
required: ["account_id", "conversation_id", "text"],
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
export const linkedinViewProfileTool = {
|
|
99
|
+
name: "oneshot_linkedin_view_profile",
|
|
100
|
+
description: "View a LinkedIn profile through a connected account that granted 'view_profile' and return a public-safe summary (name, headline, location, network distance). notify=false (default) is a data read; notify=true makes the human appear in the target's 'who viewed your profile' and cannot be undone. Per-account daily cap (default 100). Paid tool (flat price per view).",
|
|
101
|
+
inputSchema: {
|
|
102
|
+
type: "object",
|
|
103
|
+
properties: {
|
|
104
|
+
account_id: { type: "string", description: "Connected LinkedIn account id (required)" },
|
|
105
|
+
identifier: { type: "string", description: "Public identifier, provider id, or a linkedin.com/in/<slug> URL (required)" },
|
|
106
|
+
notify: { type: "boolean", description: "Default false. true = the profile owner sees the view." },
|
|
107
|
+
memo: { type: "string", description: "Why (audit trail)" },
|
|
108
|
+
idempotency_key: { type: "string", description: "Optional caller-supplied key; reuse it to safely retry the same view without paying or notifying twice" },
|
|
109
|
+
},
|
|
110
|
+
required: ["account_id", "identifier"],
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
export const linkedinReactTool = {
|
|
114
|
+
name: "oneshot_linkedin_react",
|
|
115
|
+
description: "React to a LinkedIn post through a connected account that granted 'react' (like, celebrate, support, love, insightful, funny). Per-account daily cap (default 50). Reactions can be removed by the human on LinkedIn but not through this tool. Paid tool (flat price per reaction).",
|
|
116
|
+
inputSchema: {
|
|
117
|
+
type: "object",
|
|
118
|
+
properties: {
|
|
119
|
+
account_id: { type: "string", description: "Connected LinkedIn account id (required)" },
|
|
120
|
+
post_id: { type: "string", description: "LinkedIn post social id, e.g. urn:li:activity:… (required)" },
|
|
121
|
+
reaction_type: { type: "string", enum: ["like", "celebrate", "support", "love", "insightful", "funny"], description: "Default like" },
|
|
122
|
+
memo: { type: "string", description: "Why (audit trail)" },
|
|
123
|
+
idempotency_key: { type: "string", description: "Optional caller-supplied key; reuse it to safely retry the same reaction" },
|
|
124
|
+
},
|
|
125
|
+
required: ["account_id", "post_id"],
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
export async function handleLinkedinConnect(agent, args) {
|
|
129
|
+
return agent.linkedinConnect({
|
|
130
|
+
requestedActions: args.requested_actions,
|
|
131
|
+
successRedirectUrl: args.success_redirect_url,
|
|
132
|
+
failureRedirectUrl: args.failure_redirect_url,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
export async function handleLinkedinAccounts(agent, args) {
|
|
136
|
+
if (typeof args.intent_id === "string" && args.intent_id)
|
|
137
|
+
return agent.getLinkedInConnection(args.intent_id);
|
|
138
|
+
if (typeof args.account_id === "string" && args.account_id)
|
|
139
|
+
return agent.getLinkedInSync(args.account_id);
|
|
140
|
+
return agent.listLinkedInAccounts({ includeRevoked: args.include_revoked });
|
|
141
|
+
}
|
|
142
|
+
export async function handleLinkedinSync(agent, args) {
|
|
143
|
+
return agent.linkedinSync({
|
|
144
|
+
accountId: args.account_id,
|
|
145
|
+
mode: args.mode,
|
|
146
|
+
maxPages: args.max_pages,
|
|
147
|
+
memo: args.memo,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
export async function handleLinkedinConversations(agent, args) {
|
|
151
|
+
return agent.linkedinConversations({
|
|
152
|
+
accountId: args.account_id,
|
|
153
|
+
cursor: args.cursor,
|
|
154
|
+
limit: args.limit,
|
|
155
|
+
since: args.since,
|
|
156
|
+
unread: args.unread,
|
|
157
|
+
archived: args.archived,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
export async function handleLinkedinMessages(agent, args) {
|
|
161
|
+
return agent.linkedinMessages({
|
|
162
|
+
accountId: args.account_id,
|
|
163
|
+
conversationId: args.conversation_id,
|
|
164
|
+
direction: args.direction,
|
|
165
|
+
since: args.since,
|
|
166
|
+
changedSince: args.changed_since,
|
|
167
|
+
cursor: args.cursor,
|
|
168
|
+
limit: args.limit,
|
|
169
|
+
includeDeleted: args.include_deleted,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
export async function handleLinkedinReply(agent, args) {
|
|
173
|
+
return agent.linkedinReply({
|
|
174
|
+
accountId: args.account_id,
|
|
175
|
+
conversationId: args.conversation_id,
|
|
176
|
+
text: args.text,
|
|
177
|
+
memo: args.memo,
|
|
178
|
+
idempotencyKey: args.idempotency_key,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
export async function handleLinkedinViewProfile(agent, args) {
|
|
182
|
+
return agent.linkedinViewProfile({
|
|
183
|
+
accountId: args.account_id,
|
|
184
|
+
identifier: args.identifier,
|
|
185
|
+
notify: args.notify,
|
|
186
|
+
memo: args.memo,
|
|
187
|
+
idempotencyKey: args.idempotency_key,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
export async function handleLinkedinReact(agent, args) {
|
|
191
|
+
return agent.linkedinReact({
|
|
192
|
+
accountId: args.account_id,
|
|
193
|
+
postId: args.post_id,
|
|
194
|
+
reactionType: args.reaction_type,
|
|
195
|
+
memo: args.memo,
|
|
196
|
+
idempotencyKey: args.idempotency_key,
|
|
197
|
+
});
|
|
198
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oneshot-agent/mcp-server",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "MCP server for OneShot -
|
|
3
|
+
"version": "0.23.0",
|
|
4
|
+
"description": "MCP server for OneShot - 61 tools for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@coinbase/cdp-sdk": "1.45.0",
|
|
27
27
|
"@modelcontextprotocol/sdk": "1.27.1",
|
|
28
|
-
"@oneshot-agent/sdk": "^0.
|
|
28
|
+
"@oneshot-agent/sdk": "^0.35.0",
|
|
29
29
|
"zod": "3.25.76"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|