@oneshot-agent/mcp-server 0.32.0 → 0.34.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 CHANGED
@@ -102,7 +102,7 @@ Read tools (inbox, SMS inbox, notifications, balance, browser profiles) return p
102
102
  ## Remote (hosted)
103
103
 
104
104
  Clients that run in someone else's cloud (Grok Bot, hosted runners) cannot spawn this
105
- server and must not hold a wallet key. For them, OneShot hosts the same 73 tools over
105
+ server and must not hold a wallet key. For them, OneShot hosts the same 81 tools over
106
106
  Streamable HTTP at **`https://win.oneshotagent.com/mcp`**, authenticated with an
107
107
  **agent access token** and billed to the agent's credit balance:
108
108
 
@@ -125,6 +125,18 @@ instead of the wallet variables for a credits-only session on your own machine.
125
125
 
126
126
  ## Available Tools
127
127
 
128
+ ### Soul Hunt
129
+
130
+ | Tool | Description |
131
+ |------|-------------|
132
+ | `oneshot_hunt_list` | List active or collected Soul Hunts. Free. |
133
+ | `oneshot_hunt_status` | Detailed status, rounds and timeline for a specific hunt. Free. |
134
+ | `oneshot_hunt_predict` | Submit a prediction for a hunt. Debits a stake from your balance. Paid, and requires a wallet session — Soul Hunt enforces a wallet-signed write proof that an access-token/OAuth session cannot produce. |
135
+ | `oneshot_hunt_collection` | View the souls you have captured. Free. |
136
+ | `oneshot_hunt_leaderboard` | Public predictor leaderboard. Free. |
137
+
138
+ Soul Hunt is a separate service (`api.soulhunt.ai`) from the main OneShot API; the wallet session's `X-Agent-ID`/`x-agent-proof` carry over, but the OneShot bearer token never does.
139
+
128
140
  ### Communication
129
141
 
130
142
  | Tool | Description |
package/dist/index.js CHANGED
@@ -50,7 +50,7 @@ async function main() {
50
50
  const agent = await initAgent();
51
51
  const server = new Server({
52
52
  name: "oneshot-mcp",
53
- version: "0.32.0", // keep in sync with package.json; guarded by version.test.ts
53
+ version: "0.34.0", // keep in sync with package.json; guarded by version.test.ts
54
54
  }, {
55
55
  capabilities: {
56
56
  tools: {},
@@ -25,7 +25,7 @@ export const receiptsListTool = {
25
25
  type: "object",
26
26
  properties: {
27
27
  period: { type: "number", description: "Lookback window in days" },
28
- category: { type: "string", description: "Filter by tool category" },
28
+ category: { type: "string", enum: ["data", "verification", "communication", "commerce", "infrastructure", "agent_to_agent"], description: "Filter by receipt category" },
29
29
  limit: { type: "number", description: "Max receipts to return (1-100, default 50)" },
30
30
  offset: { type: "number", description: "Pagination offset" },
31
31
  since: { type: "string", description: "Lower bound on created_at (ISO 8601). Page back to older receipts." },
@@ -72,6 +72,10 @@ export async function handleRocs(agent, args) {
72
72
  return agent.rocs({ period: args.period });
73
73
  }
74
74
  export async function handleReceiptsList(agent, args) {
75
+ // Pass `category` through as received — an unrecognized value must still
76
+ // reach the API and get its 400 invalid_category response (#1078), not be
77
+ // silently dropped here into an unfiltered list. The cast only satisfies
78
+ // the SDK's compile-time enum narrowing; the API validates at runtime.
75
79
  return agent.receiptsList({
76
80
  period: args.period,
77
81
  category: args.category,
@@ -6,6 +6,11 @@ const OPEN = true;
6
6
  const OWN = false;
7
7
  const DESTRUCTIVE = true;
8
8
  export const TOOL_ANNOTATIONS = {
9
+ oneshot_hunt_list: read("List Soul Hunts", OPEN),
10
+ oneshot_hunt_status: read("Get Soul Hunt Status", OPEN),
11
+ oneshot_hunt_predict: write("Predict Soul Hunt", OPEN),
12
+ oneshot_hunt_collection: read("List Collected Souls", OWN),
13
+ oneshot_hunt_leaderboard: read("Soul Hunt Leaderboard", OPEN),
9
14
  oneshot_email: write("Send email", OPEN),
10
15
  oneshot_voice: write("Place a phone call", OPEN),
11
16
  oneshot_sms: write("Send a text message", OPEN),
@@ -57,7 +62,10 @@ export const TOOL_ANNOTATIONS = {
57
62
  oneshot_linkedin_sync: write("Sync LinkedIn messages", OPEN), // paid; imports history into the account
58
63
  oneshot_linkedin_conversations: read("List LinkedIn conversations", OWN),
59
64
  oneshot_linkedin_messages: read("Read LinkedIn messages", OWN),
60
- oneshot_linkedin_reply: write("Send a LinkedIn message", OPEN),
65
+ oneshot_linkedin_reply: write("Reply in a LinkedIn conversation", OPEN),
66
+ oneshot_linkedin_message: write("Message a LinkedIn connection", OPEN),
67
+ oneshot_linkedin_invitation: read("Check a LinkedIn invitation", OWN),
68
+ oneshot_linkedin_invitations: read("List LinkedIn invitations", OWN),
61
69
  oneshot_linkedin_invite: write("Send a LinkedIn invitation", OPEN),
62
70
  oneshot_linkedin_withdraw_invitation: write("Withdraw a LinkedIn invitation", OPEN, DESTRUCTIVE),
63
71
  oneshot_linkedin_view_profile: write("View a LinkedIn profile", OPEN), // notify=true is visible to the person
@@ -71,7 +71,7 @@ export async function handleApprovalCancel(agent, args) {
71
71
  }
72
72
  export const actionPolicyGetTool = {
73
73
  name: "oneshot_action_policy",
74
- description: "Read-only: this agent's action policy — which email/SMS/voice/commerce calls run, are denied, or need a human approval " +
74
+ description: "Read-only: this agent's action policy — which side-effect calls (email, SMS, voice, commerce, physical mail, LinkedIn actions, builds, browser tasks) run, are denied, or need a human approval " +
75
75
  "(rules, approver channel, timeout). The policy is set by the operator from a wallet session and cannot be changed from here. Free.",
76
76
  inputSchema: { type: "object", properties: {} },
77
77
  };
@@ -1,6 +1,7 @@
1
1
  export const emailTool = {
2
2
  name: "oneshot_email",
3
- description: "Send an email. Supports HTML body, attachments, and threaded replies (set reply_to_email_id to an inbound email id from oneshot_inbox_list/oneshot_inbox_get). Paid tool — quote provided before payment.",
3
+ description: "Send an email. Supports HTML body, attachments, and threaded replies (set reply_to_email_id to an inbound email id from oneshot_inbox_list/oneshot_inbox_get). Paid tool — quote provided before payment.\n\n" +
4
+ "Sending requires a domain the agent owns. A fresh account has none — call oneshot_list_domains first to see what's already owned. If there is no usable domain, pass from_domain with a new domain to register it. A call with a new from_domain only quotes — nothing is charged — and returns status 'confirmation_required' with the exact cost (registrar price + a service fee, plus a mailbox fee if mailbox_mode is 'mailbox') and a quote_id. Tell the user that exact computed number, never a guessed or approximate one, and only once they say to proceed, call this again with the same arguments and confirm_new_domain set to that quote_id: that registers the domain, charges exactly the quoted total (the stored quote is used, there is no re-quote), and sends the email in one call. The workspace balance must cover it, or the call fails with insufficient_credits.",
4
5
  inputSchema: {
5
6
  type: "object",
6
7
  properties: {
@@ -22,7 +23,7 @@ export const emailTool = {
22
23
  },
23
24
  from_domain: {
24
25
  type: "string",
25
- description: "Domain to send from (must be one you own). Omit both from_domain and from_mailbox to rotate across your warmed domains — the chosen address comes back on the quote.",
26
+ description: "Domain to send from. If you already own it, pass it to pin that domain. If you don't, pass a new domain here to register it — a call with a new from_domain only quotes (status 'confirmation_required' with a quote_id, nothing charged); repeat the call with confirm_new_domain set to that quote_id to register it, charge exactly the quoted registration + service fee (and a mailbox fee if mailbox_mode is 'mailbox'), and send. Only confirm once the user has seen that amount and asked to proceed. Omit both from_domain and from_mailbox to rotate across your warmed domains — the chosen address comes back on the result. Call oneshot_list_domains first to see what you already own.",
26
27
  },
27
28
  from_mailbox: {
28
29
  type: "string",
@@ -54,6 +55,10 @@ export const emailTool = {
54
55
  type: "string",
55
56
  description: "Only when retrying a call the action policy held: the approval_id from the approval_required error, once a human approved it. The call then runs once.",
56
57
  },
58
+ confirm_new_domain: {
59
+ type: "string",
60
+ description: "The quote_id from a 'confirmation_required' result, and nothing else. A call with a from_domain you don't own yet always stops before charging and returns that result with the exact total. Only after showing that total to the user and getting their go-ahead, call this again with the same arguments and confirm_new_domain set to the quote_id: the domain is registered, exactly that quote's total is charged, and the email is sent in that one call. Passing true never charges; it only quotes again. A wrong, expired or already-used quote id is rejected by the server without charge: drop it and call again without confirm_new_domain for a fresh quote.",
61
+ },
57
62
  },
58
63
  required: ["body"],
59
64
  },
@@ -70,5 +75,7 @@ export async function handleEmail(agent, args) {
70
75
  mailbox_mode: args.mailbox_mode,
71
76
  attachments: args.attachments,
72
77
  approvalId: args.approval_id,
78
+ // Only the quote id confirms; `true` or anything else is not a confirmation.
79
+ confirmNewDomain: typeof args.confirm_new_domain === "string" ? args.confirm_new_domain : undefined,
73
80
  });
74
81
  }
@@ -0,0 +1,12 @@
1
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
+ import type { OneShot } from "@oneshot-agent/sdk";
3
+ export declare const huntListTool: Tool;
4
+ export declare const huntStatusTool: Tool;
5
+ export declare const huntPredictTool: Tool;
6
+ export declare const huntCollectionTool: Tool;
7
+ export declare const huntLeaderboardTool: Tool;
8
+ export declare function handleHuntList(agent: OneShot, args: Record<string, unknown>): Promise<any>;
9
+ export declare function handleHuntStatus(agent: OneShot, args: Record<string, unknown>): Promise<any>;
10
+ export declare function handleHuntPredict(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").HuntQuote>;
11
+ export declare function handleHuntCollection(agent: OneShot, args: Record<string, unknown>): Promise<any[]>;
12
+ export declare function handleHuntLeaderboard(agent: OneShot, args: Record<string, unknown>): Promise<any>;
@@ -0,0 +1,76 @@
1
+ export const huntListTool = {
2
+ name: "oneshot_hunt_list",
3
+ description: "List active or collected Soul Hunts. Free.",
4
+ inputSchema: {
5
+ type: "object",
6
+ properties: {
7
+ status: { type: "string", description: "Hunt status ('active', 'captured', 'expired', etc.)", default: "active" },
8
+ limit: { type: "number", default: 20 },
9
+ offset: { type: "number", default: 0 },
10
+ },
11
+ },
12
+ };
13
+ export const huntStatusTool = {
14
+ name: "oneshot_hunt_status",
15
+ description: "Get detailed status, rounds, and timeline for a specific Soul Hunt. Free.",
16
+ inputSchema: {
17
+ type: "object",
18
+ properties: {
19
+ hunt_id: { type: "string", description: "Hunt ID or Soul Slug" },
20
+ },
21
+ required: ["hunt_id"],
22
+ },
23
+ };
24
+ export const huntPredictTool = {
25
+ name: "oneshot_hunt_predict",
26
+ description: "Submit a prediction for a Soul Hunt. Debits a stake (USDC) from your balance based on the round tier. Paid.",
27
+ inputSchema: {
28
+ type: "object",
29
+ properties: {
30
+ hunt_id: { type: "string", description: "Hunt ID or Soul Slug" },
31
+ predicted_tool: { type: "string", description: "The exact tool the soul will use next (e.g., 'research', 'email_send')" },
32
+ predicted_action: { type: "string", description: "What the soul will do with the tool (max 500 chars)" },
33
+ predicted_motivation: { type: "string", description: "Why the soul will do this, based on its objective (max 500 chars)" },
34
+ },
35
+ required: ["hunt_id", "predicted_tool", "predicted_action", "predicted_motivation"],
36
+ },
37
+ };
38
+ export const huntCollectionTool = {
39
+ name: "oneshot_hunt_collection",
40
+ description: "View the souls you have successfully captured. Free.",
41
+ inputSchema: {
42
+ type: "object",
43
+ properties: {},
44
+ },
45
+ };
46
+ export const huntLeaderboardTool = {
47
+ name: "oneshot_hunt_leaderboard",
48
+ description: "Get the public predictor leaderboard. Free.",
49
+ inputSchema: {
50
+ type: "object",
51
+ properties: {
52
+ period: { type: "string", description: "Time period ('all', 'month', 'week')", default: "all" },
53
+ sort: { type: "string", description: "Sort column ('captures', 'score', 'earned')", default: "captures" },
54
+ limit: { type: "number", default: 25 },
55
+ offset: { type: "number", default: 0 },
56
+ },
57
+ },
58
+ };
59
+ // MCP clients may send explicit nulls for optional fields; map null to
60
+ // undefined so the SDK's defaults apply instead of serializing "null".
61
+ const opt = (v) => (v === null ? undefined : v);
62
+ export async function handleHuntList(agent, args) {
63
+ return agent.hunts.list(opt(args.status), opt(args.limit), opt(args.offset));
64
+ }
65
+ export async function handleHuntStatus(agent, args) {
66
+ return agent.hunts.status(args.hunt_id);
67
+ }
68
+ export async function handleHuntPredict(agent, args) {
69
+ return agent.hunts.predict(args.hunt_id, args.predicted_tool, args.predicted_action, args.predicted_motivation);
70
+ }
71
+ export async function handleHuntCollection(agent, args) {
72
+ return agent.hunts.collection();
73
+ }
74
+ export async function handleHuntLeaderboard(agent, args) {
75
+ return agent.hunts.leaderboard(opt(args.period), opt(args.sort), opt(args.limit), opt(args.offset));
76
+ }
@@ -19,9 +19,10 @@ import { deepResearchPersonTool, socialProfilesTool, articleSearchTool, personNe
19
19
  import { companySearchTool, enrichCompanyTool, handleCompanySearch, handleEnrichCompany } from "./company.js";
20
20
  import { localSearchTool, localResolveTool, handleLocalSearch, handleLocalResolve } from "./local.js";
21
21
  import { govSolicitationsTool, handleGovSolicitations } from "./gov.js";
22
- import { linkedinConnectTool, linkedinAccountsTool, linkedinSyncTool, linkedinConversationsTool, linkedinMessagesTool, linkedinReplyTool, linkedinViewProfileTool, linkedinReactTool, linkedinInviteTool, linkedinWithdrawInvitationTool, handleLinkedinConnect, handleLinkedinAccounts, handleLinkedinSync, handleLinkedinConversations, handleLinkedinMessages, handleLinkedinReply, handleLinkedinViewProfile, handleLinkedinReact, handleLinkedinInvite, handleLinkedinWithdrawInvitation, } from "./linkedin.js";
22
+ import { linkedinConnectTool, linkedinAccountsTool, linkedinSyncTool, linkedinConversationsTool, linkedinMessagesTool, linkedinReplyTool, linkedinViewProfileTool, linkedinReactTool, linkedinInviteTool, linkedinWithdrawInvitationTool, linkedinMessageTool, linkedinInvitationTool, linkedinInvitationsTool, handleLinkedinConnect, handleLinkedinAccounts, handleLinkedinSync, handleLinkedinConversations, handleLinkedinMessages, handleLinkedinReply, handleLinkedinViewProfile, handleLinkedinReact, handleLinkedinInvite, handleLinkedinWithdrawInvitation, handleLinkedinMessage, handleLinkedinInvitation, handleLinkedinInvitations, } from "./linkedin.js";
23
23
  import { computeTool, computeStatusTool, computeTasksTool, computeCancelTool, computeRespondTool, computePauseTool, computeResumeTool, computeFundTool, handleCompute, handleComputeStatus, handleComputeTasks, handleComputeCancel, handleComputeRespond, handleComputePause, handleComputeResume, handleComputeFund } from "./compute.js";
24
24
  import { listDomainsTool, pauseDomainTool, resumeDomainTool, handleListDomains, handlePauseDomain, handleResumeDomain } from "./domains.js";
25
+ import { huntListTool, huntStatusTool, huntPredictTool, huntCollectionTool, huntLeaderboardTool, handleHuntList, handleHuntStatus, handleHuntPredict, handleHuntCollection, handleHuntLeaderboard } from "./hunt.js";
25
26
  import { TOOL_ANNOTATIONS } from "./annotations.js";
26
27
  import { spendBreakdownTool, rocsTool, rocsByGoalTool, receiptsListTool, tagReceiptValueTool, handleSpendBreakdown, handleRocs, handleRocsByGoal, handleReceiptsList, handleTagReceiptValue } from "./analytics.js";
27
28
  const toolDefinitions = [
@@ -78,11 +79,17 @@ const toolDefinitions = [
78
79
  linkedinMessagesTool,
79
80
  linkedinReplyTool,
80
81
  linkedinInviteTool, linkedinWithdrawInvitationTool,
82
+ linkedinMessageTool, linkedinInvitationTool, linkedinInvitationsTool,
81
83
  linkedinViewProfileTool,
82
84
  linkedinReactTool,
83
85
  listDomainsTool,
84
86
  pauseDomainTool,
85
87
  resumeDomainTool,
88
+ huntListTool,
89
+ huntStatusTool,
90
+ huntPredictTool,
91
+ huntCollectionTool,
92
+ huntLeaderboardTool,
86
93
  spendBreakdownTool,
87
94
  rocsTool,
88
95
  rocsByGoalTool,
@@ -161,11 +168,19 @@ const handlers = {
161
168
  "oneshot_linkedin_reply": handleLinkedinReply,
162
169
  "oneshot_linkedin_invite": handleLinkedinInvite,
163
170
  "oneshot_linkedin_withdraw_invitation": handleLinkedinWithdrawInvitation,
171
+ "oneshot_linkedin_message": handleLinkedinMessage,
172
+ "oneshot_linkedin_invitation": handleLinkedinInvitation,
173
+ "oneshot_linkedin_invitations": handleLinkedinInvitations,
164
174
  "oneshot_linkedin_view_profile": handleLinkedinViewProfile,
165
175
  "oneshot_linkedin_react": handleLinkedinReact,
166
176
  "oneshot_list_domains": handleListDomains,
167
177
  "oneshot_pause_domain": handlePauseDomain,
168
178
  "oneshot_resume_domain": handleResumeDomain,
179
+ "oneshot_hunt_list": handleHuntList,
180
+ "oneshot_hunt_status": handleHuntStatus,
181
+ "oneshot_hunt_predict": handleHuntPredict,
182
+ "oneshot_hunt_collection": handleHuntCollection,
183
+ "oneshot_hunt_leaderboard": handleHuntLeaderboard,
169
184
  "oneshot_spend_breakdown": handleSpendBreakdown,
170
185
  "oneshot_return_on_spend": handleRocs,
171
186
  "oneshot_return_on_spend_by_goal": handleRocsByGoal,
@@ -235,6 +250,36 @@ export function structuredToolError(error) {
235
250
  };
236
251
  case "PaymentError":
237
252
  return { error: "payment_failed", message: e.message, reason: e.reason };
253
+ case "ToolError": {
254
+ // Every 4xx the SDK doesn't recognize as one of the typed errors above
255
+ // (budget/credits/payment) lands here as a plain ToolError, and its
256
+ // `message` is the generic "Tool request failed" — the API's actual
257
+ // `error`/`reason`/`message` body only survives in `responseBody`
258
+ // (issue #1070). Parse it so the model sees e.g. `no_sending_domain`
259
+ // instead of a dead end. Only these four bounded, validated fields are
260
+ // ever surfaced — never the raw body, which could carry anything.
261
+ const bodyText = typeof e.responseBody === "string" ? e.responseBody : undefined;
262
+ let body;
263
+ if (bodyText) {
264
+ try {
265
+ const parsed = JSON.parse(bodyText);
266
+ if (parsed && typeof parsed === "object" && typeof parsed.error === "string")
267
+ body = parsed;
268
+ }
269
+ catch {
270
+ // Malformed/non-JSON body: fall through to the generic prose fallback.
271
+ }
272
+ }
273
+ if (!body)
274
+ return undefined;
275
+ const status = typeof e.statusCode === "number" ? e.statusCode : undefined;
276
+ return {
277
+ error: body.error,
278
+ ...(typeof body.reason === "string" ? { reason: body.reason } : {}),
279
+ message: typeof body.message === "string" ? body.message : e.message,
280
+ ...(status !== undefined ? { status } : {}),
281
+ };
282
+ }
238
283
  default:
239
284
  return undefined;
240
285
  }
@@ -30,3 +30,11 @@ export declare const linkedinInviteTool: Tool;
30
30
  export declare function handleLinkedinInvite(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").LinkedInInviteResult>;
31
31
  export declare const linkedinWithdrawInvitationTool: Tool;
32
32
  export declare function handleLinkedinWithdrawInvitation(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").LinkedInWithdrawInvitationResult>;
33
+ export declare const linkedinMessageTool: Tool;
34
+ export declare function handleLinkedinMessage(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").LinkedInMessageResult>;
35
+ export declare const linkedinInvitationTool: Tool;
36
+ export declare function handleLinkedinInvitation(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").LinkedInInvitation>;
37
+ export declare const linkedinInvitationsTool: Tool;
38
+ export declare function handleLinkedinInvitations(agent: OneShot, args: Record<string, unknown>): Promise<{
39
+ invitations: import("@oneshot-agent/sdk").LinkedInInvitation[];
40
+ }>;
@@ -215,3 +215,64 @@ export async function handleLinkedinWithdrawInvitation(agent, args) {
215
215
  return agent.linkedinWithdrawInvitation({ accountId: args.account_id, invitationId: args.invitation_id,
216
216
  memo: args.memo, idempotencyKey: args.idempotency_key });
217
217
  }
218
+ export const linkedinMessageTool = {
219
+ name: "oneshot_linkedin_message",
220
+ description: "Message a first-degree LinkedIn connection through a connected account that granted 'reply': into the 1:1 conversation the account already has with them, or a new one. Use it once an invitation is accepted, or for a connection the account has never messaged. Returns conversation_id. The human's account sends it; a message LinkedIn accepted cannot be recalled. Shares the reply daily cap (default 50); sends are paced. A failed send with not_connected (invite them first) or rate_limited means defer, not give up. An Idempotency-Key is generated automatically so a retry never double-sends. Paid tool.",
221
+ inputSchema: {
222
+ type: "object",
223
+ properties: {
224
+ account_id: { type: "string", description: "Connected LinkedIn account id (required)" },
225
+ profile: { type: "string", description: "The connection: a linkedin.com/in/<slug> URL, a slug or a profile id, as oneshot_linkedin_invite takes (required)" },
226
+ text: { type: "string", description: "Message text, 1-4000 characters (required)" },
227
+ memo: { type: "string", description: "Why this message is being sent (audit trail)" },
228
+ idempotency_key: { type: "string", description: "Optional caller-supplied key; reuse it to safely retry the same send" },
229
+ },
230
+ required: ["account_id", "profile", "text"],
231
+ },
232
+ };
233
+ export async function handleLinkedinMessage(agent, args) {
234
+ return agent.linkedinMessage({
235
+ accountId: args.account_id,
236
+ profile: args.profile,
237
+ text: args.text,
238
+ memo: args.memo,
239
+ idempotencyKey: args.idempotency_key,
240
+ });
241
+ }
242
+ export const linkedinInvitationTool = {
243
+ name: "oneshot_linkedin_invitation",
244
+ description: "Status of one invitation sent with oneshot_linkedin_invite: pending, accepted (with accepted_at), withdrawn, declined_or_unknown or not_sent. Reads accepted as soon as the person is a connection, without a message being exchanged. Free tool.",
245
+ inputSchema: {
246
+ type: "object",
247
+ properties: {
248
+ account_id: { type: "string", description: "Connected LinkedIn account id (required)" },
249
+ invitation_id: { type: "string", description: "invitation_id returned by oneshot_linkedin_invite (required)" },
250
+ },
251
+ required: ["account_id", "invitation_id"],
252
+ },
253
+ };
254
+ export async function handleLinkedinInvitation(agent, args) {
255
+ return agent.linkedinInvitation({ accountId: args.account_id, invitationId: args.invitation_id });
256
+ }
257
+ export const linkedinInvitationsTool = {
258
+ name: "oneshot_linkedin_invitations",
259
+ description: "List invitations sent with oneshot_linkedin_invite for a connected account, most recently changed first. Filter by status; poll with changed_since to learn which were accepted. Free tool.",
260
+ inputSchema: {
261
+ type: "object",
262
+ properties: {
263
+ account_id: { type: "string", description: "Connected LinkedIn account id (required)" },
264
+ status: { type: "string", enum: ["pending", "accepted", "withdrawn", "declined_or_unknown", "not_sent"] },
265
+ changed_since: { type: "string", description: "ISO time: only invitations whose status changed after this" },
266
+ limit: { type: "number", description: "1-100, default 50" },
267
+ },
268
+ required: ["account_id"],
269
+ },
270
+ };
271
+ export async function handleLinkedinInvitations(agent, args) {
272
+ return agent.linkedinInvitations({
273
+ accountId: args.account_id,
274
+ status: args.status,
275
+ changedSince: args.changed_since,
276
+ limit: args.limit,
277
+ });
278
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oneshot-agent/mcp-server",
3
- "version": "0.32.0",
4
- "description": "MCP server for OneShot - 73 tools for AI agents",
3
+ "version": "0.34.0",
4
+ "description": "MCP server for OneShot - 81 tools for AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -11,7 +11,8 @@
11
11
  "scripts": {
12
12
  "build": "tsc",
13
13
  "dev": "tsc --watch",
14
- "prepublishOnly": "npm run build"
14
+ "prepublishOnly": "npm run build",
15
+ "typecheck": "tsc --noEmit --incremental false"
15
16
  },
16
17
  "keywords": [
17
18
  "mcp",
@@ -25,7 +26,7 @@
25
26
  "dependencies": {
26
27
  "@coinbase/cdp-sdk": "1.45.0",
27
28
  "@modelcontextprotocol/sdk": "1.27.1",
28
- "@oneshot-agent/sdk": "^0.46.0",
29
+ "@oneshot-agent/sdk": "^0.48.0",
29
30
  "zod": "3.25.76"
30
31
  },
31
32
  "devDependencies": {
@@ -39,5 +40,19 @@
39
40
  "dist",
40
41
  "bin",
41
42
  "README.md"
42
- ]
43
+ ],
44
+ "nx": {
45
+ "targets": {
46
+ "build": {
47
+ "cache": true,
48
+ "inputs": [
49
+ "default",
50
+ "^default"
51
+ ],
52
+ "outputs": [
53
+ "{projectRoot}/dist"
54
+ ]
55
+ }
56
+ }
57
+ }
43
58
  }