@oneshot-agent/mcp-server 0.24.1 → 0.28.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
@@ -1,6 +1,12 @@
1
1
  # @oneshot-agent/mcp-server
2
2
 
3
- MCP (Model Context Protocol) server for [OneShot](https://oneshotagent.com) - enabling AI agents to execute commercial actions.
3
+ MCP (Model Context Protocol) server for [OneShot](https://oneshotagent.com). It gives any MCP client (Claude Desktop, Cursor, Claude Code) OneShot's tools: email, calls, SMS, research, enrichment, commerce, website builds. Paid calls are charged one at a time and show up in your receipts. An optional daily budget caps the spend.
4
+
5
+ Quick start:
6
+
7
+ 1. Install the server (below).
8
+ 2. Add it to your client's MCP config with CDP credentials ([Configuration](#configuration)).
9
+ 3. Send USDC on Base to the agent's wallet ([Funding Your Agent](#funding-your-agent)).
4
10
 
5
11
  ## Installation
6
12
 
@@ -10,7 +16,7 @@ npm install -g @oneshot-agent/mcp-server
10
16
 
11
17
  ## Configuration
12
18
 
13
- The server supports three auth methods: **CDP Wallet** (recommended, no private keys in config), a raw private key, or an **access token** (credits-only session, no key at all — see Remote below).
19
+ Pick one of three auth methods: **CDP Wallet** (recommended, no private keys in config), a raw private key, or an **access token** (credits-only session with no key; see Remote below).
14
20
 
15
21
  ### Environment Variables
16
22
 
@@ -87,16 +93,16 @@ Add to `~/.claude/settings.json`:
87
93
  }
88
94
  ```
89
95
 
90
- Get CDP credentials at [Coinbase Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/welcome). Or use `ONESHOT_WALLET_PRIVATE_KEY` instead of CDP env vars for raw key auth.
96
+ Get CDP credentials at [Coinbase Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/welcome), or use `ONESHOT_WALLET_PRIVATE_KEY` instead of the CDP env vars for raw key auth.
91
97
 
92
98
  ### Read authentication
93
99
 
94
- Read tools (inbox, SMS inbox, notifications, balance, browser profiles) return private, per-agent data. The server wraps the OneShot TypeScript SDK, which automatically signs a short-lived **EIP-712 read proof** (`x-agent-proof`) on each read so the API can verify you control the `X-Agent-ID` wallet. No configuration needed — this ships via `@oneshot-agent/sdk >= 0.25.0` (the bundled dependency). Read-proof verification is rolling out in log-only mode server-side, so older callers keep working until enforcement is enabled.
100
+ Read tools (inbox, SMS inbox, notifications, balance, browser profiles) return private, per-agent data. The server wraps the OneShot TypeScript SDK, which signs a short-lived **EIP-712 read proof** (`x-agent-proof`) on each read so the API can verify you control the `X-Agent-ID` wallet. This needs no configuration; it ships in `@oneshot-agent/sdk >= 0.25.0` (the bundled dependency). The server is rolling out read-proof verification in log-only mode, so older callers keep working until enforcement is enabled.
95
101
 
96
102
  ## Remote (hosted)
97
103
 
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 63 tools over
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
100
106
  Streamable HTTP at **`https://win.oneshotagent.com/mcp`**, authenticated with an
101
107
  **agent access token** and billed to the agent's credit balance:
102
108
 
@@ -136,6 +142,16 @@ instead of the wallet variables for a credits-only session on your own machine.
136
142
  | `oneshot_sms_inbox_list` | List received SMS messages |
137
143
  | `oneshot_sms_inbox_get` | Get a specific SMS message |
138
144
 
145
+ ### Inbound voice
146
+
147
+ | Tool | Description |
148
+ |------|-------------|
149
+ | `oneshot_voice_number_provision` | Get the agent a phone number (existing one free; new one charges the registration fee from credits) |
150
+ | `oneshot_voice_numbers` | List the agent's phone numbers |
151
+ | `oneshot_voice_inbound_set` | Make a number answer its own calls (wallet session only) |
152
+ | `oneshot_voice_inbound_disable` | Stop answering calls to a number (wallet session only) |
153
+ | `oneshot_voice_inbound_calls` | List inbound calls, or one call with transcript |
154
+
139
155
  ### Research & Enrichment
140
156
 
141
157
  | Tool | Description |
@@ -168,7 +184,7 @@ instead of the wallet variables for a credits-only session on your own machine.
168
184
  |------|-------------|
169
185
  | `oneshot_web_search` | Search the web |
170
186
  | `oneshot_web_read` | Read any URL as markdown + screenshot |
171
- | `oneshot_browser` | Autonomous browser — navigate, click, extract |
187
+ | `oneshot_browser` | Autonomous browser: navigate, click, extract |
172
188
 
173
189
  ### Commerce
174
190
 
@@ -188,12 +204,12 @@ instead of the wallet variables for a credits-only session on your own machine.
188
204
 
189
205
  | Tool | Description |
190
206
  |------|-------------|
191
- | `oneshot_compute` | Create an autonomous goal — objective + budget, the orchestrator plans and executes |
207
+ | `oneshot_compute` | Create an autonomous goal (objective + budget); the orchestrator plans and executes |
192
208
  | `oneshot_compute_status` | Get a compute goal's status and budget |
193
209
  | `oneshot_compute_tasks` | List tasks planned/executed under a goal |
194
210
  | `oneshot_compute_cancel` | Cancel a goal and refund remaining budget |
195
211
  | `oneshot_compute_respond` | Respond to a human-in-the-loop task |
196
- | `oneshot_compute_pause` | Pause a recurring goal — plan and progress are kept |
212
+ | `oneshot_compute_pause` | Pause a recurring goal; plan and progress are kept |
197
213
  | `oneshot_compute_resume` | Resume a paused recurring goal |
198
214
  | `oneshot_compute_fund` | Top up a recurring goal's USDC budget |
199
215
 
@@ -223,7 +239,7 @@ instead of the wallet variables for a credits-only session on your own machine.
223
239
  | `oneshot_get_balance` | Get USDC wallet balance |
224
240
  | `oneshot_budget_status` | Today's spend vs the configured budget (read-only) |
225
241
 
226
- All paid tools are priced in USDC via the x402 protocol. See [Pricing](https://docs.oneshotagent.com/pricing) for current rates.
242
+ Paid tools are priced in USDC via the x402 protocol. Current rates are on the [Pricing](https://docs.oneshotagent.com/pricing) page.
227
243
 
228
244
  ## Tool Examples
229
245
 
@@ -318,7 +334,16 @@ Use oneshot_inbox_list:
318
334
 
319
335
  ## Funding Your Agent
320
336
 
321
- Send USDC to your agent's wallet address on Base. The server operates on Base Mainnet (chain 8453).
337
+ Send USDC to your agent's wallet address on Base. The server runs on Base Mainnet (chain 8453).
338
+
339
+ ## LinkedIn connection recovery
340
+
341
+ If the active account list is empty or an account is `deleted_upstream` or
342
+ `revoked`, ask the human to use `oneshot_linkedin_connect` and authorize fresh
343
+ grants. An existing account with `reconnect_required` must be reconnected through
344
+ the owning application. Reconnect and revoke are deliberately not agent tools.
345
+ Do not create a new connection automatically after authentication failures or
346
+ timeouts.
322
347
 
323
348
  ## Links
324
349
 
@@ -328,12 +353,3 @@ Send USDC to your agent's wallet address on Base. The server operates on Base Ma
328
353
  - [Python SDK (LangChain)](https://pypi.org/project/langchain-oneshot/)
329
354
  - [Python SDK (Core)](https://pypi.org/project/oneshot-python/)
330
355
  - [GitHub](https://github.com/oneshot-agent/sdk)
331
-
332
- ### LinkedIn connection recovery
333
-
334
- If the active account list is empty or an account is `deleted_upstream` or
335
- `revoked`, ask the human to use `oneshot_linkedin_connect` and authorize fresh
336
- grants. An existing account with `reconnect_required` needs reconnect through
337
- the owning application. Reconnect and revoke are intentionally not agent tools.
338
- Do not automatically create a new connection in response to authentication
339
- failures or timeouts.
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.24.1", // keep in sync with package.json; guarded by version.test.ts
55
+ version: "0.28.0", // keep in sync with package.json; guarded by version.test.ts
56
56
  }, {
57
57
  capabilities: {
58
58
  tools: {},
@@ -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 approvalCreateTool: Tool;
4
+ export declare function handleApprovalCreate(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").Approval>;
5
+ export declare const approvalGetTool: Tool;
6
+ export declare function handleApprovalGet(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").Approval>;
7
+ export declare const approvalListTool: Tool;
8
+ export declare function handleApprovalList(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").Approval[]>;
9
+ export declare const approvalCancelTool: Tool;
10
+ export declare function handleApprovalCancel(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").Approval>;
11
+ export declare const actionPolicyGetTool: Tool;
12
+ export declare function handleActionPolicyGet(agent: OneShot, _args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").ActionPolicy | null>;
@@ -0,0 +1,81 @@
1
+ // Approvals: ask a named human, read decisions, and read (never loosen) the
2
+ // action policy. Setting the policy is deliberately not exposed here — an
3
+ // agent that could edit its own policy would make the policy meaningless.
4
+ export const approvalCreateTool = {
5
+ name: "oneshot_approval_create",
6
+ description: "Ask a named human to approve or deny something before you do it. They get a one-tap link by email or SMS. " +
7
+ "Returns an approval with status 'pending'; poll oneshot_approval_get for the decision. Unanswered = denied at expiry. Free.",
8
+ inputSchema: {
9
+ type: "object",
10
+ properties: {
11
+ action_summary: { type: "string", description: "What the human is deciding, in one line (max 2000 chars)" },
12
+ approver_email: { type: "string", description: "Approver's email address" },
13
+ approver_phone: { type: "string", description: "Approver's phone number, E.164 (e.g. +14155551234)" },
14
+ preview: { type: "object", description: "Details shown to the approver (optional, up to 4000 characters as JSON)" },
15
+ expires_in_seconds: { type: "number", description: "Seconds until it expires unanswered (default 3600, max 604800)" },
16
+ },
17
+ required: ["action_summary"],
18
+ },
19
+ };
20
+ export async function handleApprovalCreate(agent, args) {
21
+ return agent.approvals.create({
22
+ action_summary: args.action_summary,
23
+ approver: {
24
+ ...(args.approver_email ? { email: args.approver_email } : {}),
25
+ ...(args.approver_phone ? { phone: args.approver_phone } : {}),
26
+ },
27
+ ...(args.preview ? { preview: args.preview } : {}),
28
+ ...(args.expires_in_seconds ? { expires_in_seconds: args.expires_in_seconds } : {}),
29
+ });
30
+ }
31
+ export const approvalGetTool = {
32
+ name: "oneshot_approval_get",
33
+ description: "Read one approval: status is pending, approved, denied, expired, cancelled, or consumed (an approved held call already ran). " +
34
+ "When a paid call failed with approval_required, poll this with its approval_id; once approved, retry the same call with approval_id. Free.",
35
+ inputSchema: {
36
+ type: "object",
37
+ properties: { approval_id: { type: "string", description: "The approval id (appr_...)" } },
38
+ required: ["approval_id"],
39
+ },
40
+ };
41
+ export async function handleApprovalGet(agent, args) {
42
+ return agent.approvals.get(args.approval_id);
43
+ }
44
+ export const approvalListTool = {
45
+ name: "oneshot_approval_list",
46
+ description: "List this agent's approvals, newest first, optionally filtered by status. Free.",
47
+ inputSchema: {
48
+ type: "object",
49
+ properties: {
50
+ status: { type: "string", enum: ["pending", "approved", "denied", "expired", "cancelled", "consumed"] },
51
+ limit: { type: "number", description: "Max results (default 50, max 200)" },
52
+ },
53
+ },
54
+ };
55
+ export async function handleApprovalList(agent, args) {
56
+ return agent.approvals.list({
57
+ status: args.status,
58
+ limit: args.limit,
59
+ });
60
+ }
61
+ export const approvalCancelTool = {
62
+ name: "oneshot_approval_cancel",
63
+ description: "Withdraw a pending approval you no longer need. Free.",
64
+ inputSchema: {
65
+ type: "object",
66
+ properties: { approval_id: { type: "string", description: "The approval id (appr_...)" } },
67
+ required: ["approval_id"],
68
+ },
69
+ };
70
+ export async function handleApprovalCancel(agent, args) {
71
+ return agent.approvals.cancel(args.approval_id);
72
+ }
73
+ export const actionPolicyGetTool = {
74
+ name: "oneshot_action_policy",
75
+ description: "Read-only: this agent's action policy — which email/SMS/voice/commerce calls run, are denied, or need a human approval " +
76
+ "(rules, approver channel, timeout). The policy is set by the operator from a wallet session and cannot be changed from here. Free.",
77
+ inputSchema: { type: "object", properties: {} },
78
+ };
79
+ export async function handleActionPolicyGet(agent, _args) {
80
+ return agent.policy.get();
81
+ }
@@ -50,6 +50,10 @@ export const commerceBuyTool = {
50
50
  type: "string",
51
51
  description: "Product variant ID (optional)",
52
52
  },
53
+ approval_id: {
54
+ type: "string",
55
+ 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
+ },
53
57
  },
54
58
  required: ["product_url", "shipping_address"],
55
59
  },
@@ -77,6 +81,7 @@ export async function handleCommerceBuy(agent, args) {
77
81
  phone: shippingAddress.phone,
78
82
  },
79
83
  quantity: args.quantity,
84
+ approvalId: args.approval_id,
80
85
  variant_id: args.variant_id,
81
86
  });
82
87
  }
@@ -50,6 +50,10 @@ export const emailTool = {
50
50
  },
51
51
  description: "File attachments (optional)",
52
52
  },
53
+ approval_id: {
54
+ type: "string",
55
+ 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
+ },
53
57
  },
54
58
  required: ["body"],
55
59
  },
@@ -65,5 +69,6 @@ export async function handleEmail(agent, args) {
65
69
  from_name: args.from_name,
66
70
  mailbox_mode: args.mailbox_mode,
67
71
  attachments: args.attachments,
72
+ approvalId: args.approval_id,
68
73
  });
69
74
  }
@@ -1,5 +1,6 @@
1
1
  import { emailTool, handleEmail } from "./email.js";
2
2
  import { voiceTool, handleVoice } from "./voice.js";
3
+ import { voiceNumberProvisionTool, voiceNumbersTool, voiceInboundSetTool, voiceInboundDisableTool, voiceInboundCallsTool, handleVoiceNumberProvision, handleVoiceNumbers, handleVoiceInboundSet, handleVoiceInboundDisable, handleVoiceInboundCalls, } from "./voice-inbound.js";
3
4
  import { smsTool, handleSms } from "./sms.js";
4
5
  import { researchTool, handleResearch } from "./research.js";
5
6
  import { peopleSearchTool, handlePeopleSearch } from "./people.js";
@@ -9,6 +10,7 @@ import { inboxListTool, inboxGetTool, handleInboxList, handleInboxGet } from "./
9
10
  import { smsInboxListTool, smsInboxGetTool, handleSmsInboxList, handleSmsInboxGet } from "./sms-inbox.js";
10
11
  import { notificationsTool, markReadTool, handleNotifications, handleMarkRead } from "./notifications.js";
11
12
  import { getBalanceTool, budgetStatusTool, handleGetBalance, handleBudgetStatus } from "./wallet.js";
13
+ import { approvalCreateTool, approvalGetTool, approvalListTool, approvalCancelTool, actionPolicyGetTool, handleApprovalCreate, handleApprovalGet, handleApprovalList, handleApprovalCancel, handleActionPolicyGet, } from "./approvals.js";
12
14
  import { buildTool, updateBuildTool, handleBuild, handleUpdateBuild } from "./build.js";
13
15
  import { browserTool, browserCreateProfileTool, browserListProfilesTool, browserDeleteProfileTool, handleBrowser, handleBrowserCreateProfile, handleBrowserListProfiles, handleBrowserDeleteProfile } from "./browser.js";
14
16
  import { webSearchTool, handleWebSearch } from "./search.js";
@@ -32,6 +34,12 @@ export const tools = [
32
34
  inboxGetTool,
33
35
  smsInboxListTool,
34
36
  smsInboxGetTool,
37
+ // Inbound voice
38
+ voiceNumberProvisionTool,
39
+ voiceNumbersTool,
40
+ voiceInboundSetTool,
41
+ voiceInboundDisableTool,
42
+ voiceInboundCallsTool,
35
43
  // Research & Enrichment
36
44
  researchTool,
37
45
  peopleSearchTool,
@@ -97,6 +105,12 @@ export const tools = [
97
105
  markReadTool,
98
106
  getBalanceTool,
99
107
  budgetStatusTool,
108
+ // Approvals
109
+ approvalCreateTool,
110
+ approvalGetTool,
111
+ approvalListTool,
112
+ approvalCancelTool,
113
+ actionPolicyGetTool,
100
114
  ];
101
115
  // Tool handlers map
102
116
  const handlers = {
@@ -109,6 +123,12 @@ const handlers = {
109
123
  "oneshot_inbox_get": handleInboxGet,
110
124
  "oneshot_sms_inbox_list": handleSmsInboxList,
111
125
  "oneshot_sms_inbox_get": handleSmsInboxGet,
126
+ // Inbound voice
127
+ "oneshot_voice_number_provision": handleVoiceNumberProvision,
128
+ "oneshot_voice_numbers": handleVoiceNumbers,
129
+ "oneshot_voice_inbound_set": handleVoiceInboundSet,
130
+ "oneshot_voice_inbound_disable": handleVoiceInboundDisable,
131
+ "oneshot_voice_inbound_calls": handleVoiceInboundCalls,
112
132
  // Research & Enrichment
113
133
  "oneshot_research": handleResearch,
114
134
  "oneshot_people_search": handlePeopleSearch,
@@ -175,6 +195,12 @@ const handlers = {
175
195
  "oneshot_mark_notification_read": handleMarkRead,
176
196
  "oneshot_get_balance": handleGetBalance,
177
197
  "oneshot_budget_status": handleBudgetStatus,
198
+ // Approvals
199
+ "oneshot_approval_create": handleApprovalCreate,
200
+ "oneshot_approval_get": handleApprovalGet,
201
+ "oneshot_approval_list": handleApprovalList,
202
+ "oneshot_approval_cancel": handleApprovalCancel,
203
+ "oneshot_action_policy": handleActionPolicyGet,
178
204
  };
179
205
  export async function handleToolCall(agent, toolName, args) {
180
206
  const handler = handlers[toolName];
package/dist/tools/sms.js CHANGED
@@ -12,6 +12,10 @@ export const smsTool = {
12
12
  type: "string",
13
13
  description: "SMS message content (max 1600 chars, 160 chars per segment)",
14
14
  },
15
+ approval_id: {
16
+ type: "string",
17
+ 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.",
18
+ },
15
19
  },
16
20
  required: ["to_number", "message"],
17
21
  },
@@ -20,5 +24,6 @@ export async function handleSms(agent, args) {
20
24
  return agent.sms({
21
25
  to_number: args.to_number,
22
26
  message: args.message,
27
+ approvalId: args.approval_id,
23
28
  });
24
29
  }
@@ -0,0 +1,16 @@
1
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
+ import type { OneShot } from "@oneshot-agent/sdk";
3
+ export declare const voiceNumberProvisionTool: Tool;
4
+ export declare const voiceNumbersTool: Tool;
5
+ export declare const voiceInboundSetTool: Tool;
6
+ export declare const voiceInboundDisableTool: Tool;
7
+ export declare const voiceInboundCallsTool: Tool;
8
+ export declare function handleVoiceNumberProvision(agent: OneShot): Promise<import("@oneshot-agent/sdk").ProvisionedVoiceNumber>;
9
+ export declare function handleVoiceNumbers(agent: OneShot): Promise<{
10
+ numbers: import("@oneshot-agent/sdk").VoiceNumber[];
11
+ }>;
12
+ export declare function handleVoiceInboundSet(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").InboundVoiceConfigResult>;
13
+ export declare function handleVoiceInboundDisable(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").InboundVoiceConfigResult>;
14
+ export declare function handleVoiceInboundCalls(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").InboundCall | {
15
+ calls: import("@oneshot-agent/sdk").InboundCall[];
16
+ }>;
@@ -0,0 +1,102 @@
1
+ export const voiceNumberProvisionTool = {
2
+ name: "oneshot_voice_number_provision",
3
+ description: "Get this agent a phone number without placing a call, so it can answer calls (then use oneshot_voice_inbound_set). " +
4
+ "Returns the existing number for free; otherwise buys one and charges the one-time phone registration fee from prepaid credits. " +
5
+ "Fails with 402 and buys nothing when credits are too low. Requires a wallet session (not available with an agent access token).",
6
+ inputSchema: { type: "object", properties: {} },
7
+ };
8
+ export const voiceNumbersTool = {
9
+ name: "oneshot_voice_numbers",
10
+ description: "List this agent's phone numbers and whether each answers inbound calls. Free. A number comes from oneshot_voice_number_provision or the agent's first outbound voice call.",
11
+ inputSchema: { type: "object", properties: {} },
12
+ };
13
+ export const voiceInboundSetTool = {
14
+ name: "oneshot_voice_inbound_set",
15
+ description: "Make one of the agent's numbers answer its own calls. Replaces the whole inbound config. " +
16
+ "During business hours the assistant follows `prompt`; after hours it takes a message, transfers, or declines. " +
17
+ "Calls are paid from prepaid credits per started minute and are declined when credits cannot cover the minimum fee. " +
18
+ "Requires a wallet session (not available with an agent access token).",
19
+ inputSchema: {
20
+ type: "object",
21
+ properties: {
22
+ phone_number_id: { type: "string", description: "Number id from oneshot_voice_numbers" },
23
+ prompt: { type: "string", description: "How the assistant answers this number (max 8000 chars)" },
24
+ first_message: { type: "string", description: "Greeting spoken when the call connects (optional)" },
25
+ voice_id: { type: "string", description: "Voice id (optional)" },
26
+ language: { type: "string", enum: ["en", "es", "fr", "de", "pt", "it", "nl", "multi"] },
27
+ allowed_tools: { type: "array", items: { type: "string", enum: ["transfer_call", "end_call"] }, description: "Default: [\"end_call\"]" },
28
+ transfer_number: { type: "string", description: "E.164. Required with transfer_call or after_hours=transfer" },
29
+ business_hours: {
30
+ type: "object",
31
+ description: "Omit for always open. { timezone: 'America/New_York', windows: [{ days: ['mon',...], start: '09:00', end: '17:00' }] }",
32
+ properties: {
33
+ timezone: { type: "string" },
34
+ windows: {
35
+ type: "array",
36
+ items: {
37
+ type: "object",
38
+ properties: {
39
+ days: { type: "array", items: { type: "string", enum: ["mon", "tue", "wed", "thu", "fri", "sat", "sun"] } },
40
+ start: { type: "string" },
41
+ end: { type: "string" },
42
+ },
43
+ required: ["days", "start", "end"],
44
+ },
45
+ },
46
+ },
47
+ required: ["timezone", "windows"],
48
+ },
49
+ after_hours: { type: "string", enum: ["take_message", "transfer", "decline"], description: "Default: take_message" },
50
+ after_hours_message: { type: "string", description: "What callers hear after hours (optional)" },
51
+ max_minutes: { type: "number", description: "1-60, default 10" },
52
+ webhook_url: { type: "string", description: "HTTPS URL for a signed voice.inbound.completed event after each call (optional)" },
53
+ },
54
+ required: ["phone_number_id", "prompt"],
55
+ },
56
+ };
57
+ export const voiceInboundDisableTool = {
58
+ name: "oneshot_voice_inbound_disable",
59
+ description: "Stop answering calls to one of the agent's numbers. The settings are kept, disabled. Free. Requires a wallet session.",
60
+ inputSchema: {
61
+ type: "object",
62
+ properties: { phone_number_id: { type: "string", description: "Number id from oneshot_voice_numbers" } },
63
+ required: ["phone_number_id"],
64
+ },
65
+ };
66
+ export const voiceInboundCallsTool = {
67
+ name: "oneshot_voice_inbound_calls",
68
+ description: "List inbound calls to the agent's numbers, newest first, with caller, summary and charge. Free. Pass call_id for one call with its transcript.",
69
+ inputSchema: {
70
+ type: "object",
71
+ properties: {
72
+ call_id: { type: "string", description: "Return this one call, with transcript" },
73
+ limit: { type: "number", description: "Max calls (default 50, max 100)" },
74
+ before: { type: "string", description: "ISO timestamp; calls created before it" },
75
+ phone_number_id: { type: "string", description: "Only calls to this number" },
76
+ include_transcript: { type: "boolean", description: "Include transcripts in the list" },
77
+ },
78
+ },
79
+ };
80
+ export async function handleVoiceNumberProvision(agent) {
81
+ return agent.provisionVoiceNumber();
82
+ }
83
+ export async function handleVoiceNumbers(agent) {
84
+ return agent.voiceNumbers();
85
+ }
86
+ export async function handleVoiceInboundSet(agent, args) {
87
+ const { phone_number_id, ...config } = args;
88
+ return agent.setInboundVoice(phone_number_id, config);
89
+ }
90
+ export async function handleVoiceInboundDisable(agent, args) {
91
+ return agent.disableInboundVoice(args.phone_number_id);
92
+ }
93
+ export async function handleVoiceInboundCalls(agent, args) {
94
+ if (typeof args.call_id === "string" && args.call_id)
95
+ return agent.inboundCall(args.call_id);
96
+ return agent.inboundCalls({
97
+ limit: args.limit,
98
+ before: args.before,
99
+ phone_number_id: args.phone_number_id,
100
+ include_transcript: args.include_transcript === true,
101
+ });
102
+ }
@@ -24,6 +24,10 @@ export const voiceTool = {
24
24
  type: "number",
25
25
  description: "Maximum call duration in minutes (1-30, optional)",
26
26
  },
27
+ approval_id: {
28
+ type: "string",
29
+ 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.",
30
+ },
27
31
  },
28
32
  required: ["target_number", "objective"],
29
33
  },
@@ -35,5 +39,6 @@ export async function handleVoice(agent, args) {
35
39
  context: args.context,
36
40
  caller_persona: args.caller_persona,
37
41
  max_duration_minutes: args.max_duration_minutes,
42
+ approvalId: args.approval_id,
38
43
  });
39
44
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oneshot-agent/mcp-server",
3
- "version": "0.24.1",
4
- "description": "MCP server for OneShot - 63 tools for AI agents",
3
+ "version": "0.28.0",
4
+ "description": "MCP server for OneShot - 73 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.38.1",
28
+ "@oneshot-agent/sdk": "^0.42.0",
29
29
  "zod": "3.25.76"
30
30
  },
31
31
  "devDependencies": {