@oneshot-agent/mcp-server 0.27.0 → 0.29.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 API enforces this proof by default — a request with no proof (or a mismatched one) and no valid access token is rejected.
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 73 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
 
@@ -178,7 +184,7 @@ instead of the wallet variables for a credits-only session on your own machine.
178
184
  |------|-------------|
179
185
  | `oneshot_web_search` | Search the web |
180
186
  | `oneshot_web_read` | Read any URL as markdown + screenshot |
181
- | `oneshot_browser` | Autonomous browser — navigate, click, extract |
187
+ | `oneshot_browser` | Autonomous browser: navigate, click, extract |
182
188
 
183
189
  ### Commerce
184
190
 
@@ -198,12 +204,12 @@ instead of the wallet variables for a credits-only session on your own machine.
198
204
 
199
205
  | Tool | Description |
200
206
  |------|-------------|
201
- | `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 |
202
208
  | `oneshot_compute_status` | Get a compute goal's status and budget |
203
209
  | `oneshot_compute_tasks` | List tasks planned/executed under a goal |
204
210
  | `oneshot_compute_cancel` | Cancel a goal and refund remaining budget |
205
211
  | `oneshot_compute_respond` | Respond to a human-in-the-loop task |
206
- | `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 |
207
213
  | `oneshot_compute_resume` | Resume a paused recurring goal |
208
214
  | `oneshot_compute_fund` | Top up a recurring goal's USDC budget |
209
215
 
@@ -233,7 +239,7 @@ instead of the wallet variables for a credits-only session on your own machine.
233
239
  | `oneshot_get_balance` | Get USDC wallet balance |
234
240
  | `oneshot_budget_status` | Today's spend vs the configured budget (read-only) |
235
241
 
236
- 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.
237
243
 
238
244
  ## Tool Examples
239
245
 
@@ -328,7 +334,16 @@ Use oneshot_inbox_list:
328
334
 
329
335
  ## Funding Your Agent
330
336
 
331
- 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.
332
347
 
333
348
  ## Links
334
349
 
@@ -338,12 +353,3 @@ Send USDC to your agent's wallet address on Base. The server operates on Base Ma
338
353
  - [Python SDK (LangChain)](https://pypi.org/project/langchain-oneshot/)
339
354
  - [Python SDK (Core)](https://pypi.org/project/oneshot-python/)
340
355
  - [GitHub](https://github.com/oneshot-agent/sdk)
341
-
342
- ### LinkedIn connection recovery
343
-
344
- If the active account list is empty or an account is `deleted_upstream` or
345
- `revoked`, ask the human to use `oneshot_linkedin_connect` and authorize fresh
346
- grants. An existing account with `reconnect_required` needs reconnect through
347
- the owning application. Reconnect and revoke are intentionally not agent tools.
348
- Do not automatically create a new connection in response to authentication
349
- 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.27.0", // keep in sync with package.json; guarded by version.test.ts
55
+ version: "0.29.0", // keep in sync with package.json; guarded by version.test.ts
56
56
  }, {
57
57
  capabilities: {
58
58
  tools: {},
@@ -0,0 +1,16 @@
1
+ import type { ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
2
+ /**
3
+ * MCP tool annotations for every tool (#999). ChatGPT requires all three hints
4
+ * on every tool, and uses them: a tool that is not read-only asks the user to
5
+ * confirm before it runs.
6
+ *
7
+ * readOnlyHint true = retrieval only (paid lookups included — the only
8
+ * side effect is our own billing)
9
+ * destructiveHint true = deletes, overwrites or revokes something. Sends are
10
+ * additive writes, so false — like any mail app's send.
11
+ * openWorldHint true = reaches the public web or third parties;
12
+ * false = only the caller's own OneShot account data.
13
+ */
14
+ type Hints = Required<Pick<ToolAnnotations, "title" | "readOnlyHint" | "destructiveHint" | "openWorldHint">>;
15
+ export declare const TOOL_ANNOTATIONS: Record<string, Hints>;
16
+ export {};
@@ -0,0 +1,96 @@
1
+ /** Retrieval only. */
2
+ const read = (title, openWorld) => ({ title, readOnlyHint: true, destructiveHint: false, openWorldHint: openWorld });
3
+ /** Changes something. `destructive` only for delete / overwrite / revoke. */
4
+ const write = (title, openWorld, destructive = false) => ({ title, readOnlyHint: false, destructiveHint: destructive, openWorldHint: openWorld });
5
+ const OPEN = true;
6
+ const OWN = false;
7
+ const DESTRUCTIVE = true;
8
+ export const TOOL_ANNOTATIONS = {
9
+ // Communication
10
+ oneshot_email: write("Send email", OPEN),
11
+ oneshot_voice: write("Place a phone call", OPEN),
12
+ oneshot_sms: write("Send a text message", OPEN),
13
+ // Inbox
14
+ oneshot_inbox_list: read("List received emails", OWN),
15
+ oneshot_inbox_get: read("Read a received email", OWN),
16
+ oneshot_sms_inbox_list: read("List received texts", OWN),
17
+ oneshot_sms_inbox_get: read("Read a received text", OWN),
18
+ // Inbound voice
19
+ oneshot_voice_number_provision: write("Get a phone number", OPEN),
20
+ oneshot_voice_numbers: read("List phone numbers", OWN),
21
+ oneshot_voice_inbound_set: write("Set up call answering", OWN, DESTRUCTIVE), // replaces the number's answering settings
22
+ oneshot_voice_inbound_disable: write("Stop answering calls", OWN),
23
+ oneshot_voice_inbound_calls: read("List answered calls", OWN),
24
+ // Research & enrichment
25
+ oneshot_research: read("Deep research", OPEN),
26
+ oneshot_people_search: read("Find people", OPEN),
27
+ oneshot_enrich_profile: read("Look up a person's profile", OPEN),
28
+ oneshot_find_email: read("Find a work email", OPEN),
29
+ oneshot_verify_email: read("Verify an email address", OPEN),
30
+ oneshot_web_search: read("Web search", OPEN),
31
+ oneshot_deep_research_person: read("Research a person", OPEN),
32
+ oneshot_social_profiles: read("Find social profiles", OPEN),
33
+ oneshot_article_search: read("Find articles about a person", OPEN),
34
+ oneshot_person_newsfeed: read("Get a person's recent posts", OPEN),
35
+ oneshot_person_interests: read("Summarize a person's interests", OPEN),
36
+ oneshot_person_interactions: read("Find a person's interactions", OPEN),
37
+ oneshot_company_search: read("Find companies", OPEN),
38
+ oneshot_enrich_company: read("Look up a company", OPEN),
39
+ oneshot_local_search: read("Find local businesses", OPEN),
40
+ oneshot_local_resolve: read("Look up a local business", OPEN),
41
+ oneshot_gov_solicitations: read("Find government contracts", OPEN),
42
+ // Commerce
43
+ oneshot_commerce_search: read("Search products", OPEN),
44
+ oneshot_commerce_buy: write("Buy a product", OPEN),
45
+ // Compute orchestration
46
+ oneshot_compute: write("Start a goal", OPEN),
47
+ oneshot_compute_status: read("Check a goal", OWN),
48
+ oneshot_compute_tasks: read("List a goal's tasks", OWN),
49
+ oneshot_compute_cancel: write("Cancel a goal", OWN, DESTRUCTIVE),
50
+ oneshot_compute_respond: write("Answer a goal's question", OWN),
51
+ oneshot_compute_pause: write("Pause a goal", OWN),
52
+ oneshot_compute_resume: write("Resume a goal", OWN),
53
+ oneshot_compute_fund: write("Add budget to a goal", OWN),
54
+ // Build
55
+ oneshot_build: write("Build a website", OPEN),
56
+ oneshot_update_build: write("Update a website", OPEN, DESTRUCTIVE), // overwrites the live site
57
+ // Browser
58
+ oneshot_browser: write("Browse and act on a website", OPEN),
59
+ oneshot_browser_create_profile: write("Create a browser profile", OWN),
60
+ oneshot_browser_list_profiles: read("List browser profiles", OWN),
61
+ oneshot_browser_delete_profile: write("Delete a browser profile", OWN, DESTRUCTIVE),
62
+ // Web read
63
+ oneshot_web_read: read("Read a web page", OPEN),
64
+ // LinkedIn
65
+ oneshot_linkedin_connect: write("Connect LinkedIn", OPEN),
66
+ oneshot_linkedin_accounts: read("List LinkedIn accounts", OWN),
67
+ oneshot_linkedin_sync: read("Sync LinkedIn messages", OPEN),
68
+ oneshot_linkedin_conversations: read("List LinkedIn conversations", OWN),
69
+ oneshot_linkedin_messages: read("Read LinkedIn messages", OWN),
70
+ oneshot_linkedin_reply: write("Send a LinkedIn message", OPEN),
71
+ oneshot_linkedin_invite: write("Send a LinkedIn invitation", OPEN),
72
+ oneshot_linkedin_withdraw_invitation: write("Withdraw a LinkedIn invitation", OPEN, DESTRUCTIVE),
73
+ oneshot_linkedin_view_profile: write("View a LinkedIn profile", OPEN), // notify=true is visible to the person
74
+ oneshot_linkedin_react: write("React to a LinkedIn post", OPEN),
75
+ // Domains
76
+ oneshot_list_domains: read("List sending domains", OWN),
77
+ oneshot_pause_domain: write("Pause a sending domain", OWN),
78
+ oneshot_resume_domain: write("Resume a sending domain", OWN),
79
+ // Analytics
80
+ oneshot_spend_breakdown: read("Show spending", OWN),
81
+ oneshot_rocs: read("Show return on spend", OWN),
82
+ oneshot_rocs_by_goal: read("Show return on spend by goal", OWN),
83
+ oneshot_receipts_list: read("List receipts", OWN),
84
+ oneshot_tag_receipt_value: write("Tag a receipt's value", OWN),
85
+ // Account
86
+ oneshot_notifications: read("List notifications", OWN),
87
+ oneshot_mark_notification_read: write("Mark a notification read", OWN),
88
+ oneshot_get_balance: read("Check balance", OWN),
89
+ oneshot_budget_status: read("Check budget", OWN),
90
+ // Approvals
91
+ oneshot_approval_create: write("Ask a person to approve", OPEN),
92
+ oneshot_approval_get: read("Check an approval", OWN),
93
+ oneshot_approval_list: read("List approvals", OWN),
94
+ oneshot_approval_cancel: write("Cancel an approval", OWN, DESTRUCTIVE),
95
+ oneshot_action_policy: read("Show approval rules", OWN),
96
+ };
@@ -22,9 +22,10 @@ import { govSolicitationsTool, handleGovSolicitations } from "./gov.js";
22
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";
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 { TOOL_ANNOTATIONS } from "./annotations.js";
25
26
  import { spendBreakdownTool, rocsTool, rocsByGoalTool, receiptsListTool, tagReceiptValueTool, handleSpendBreakdown, handleRocs, handleRocsByGoal, handleReceiptsList, handleTagReceiptValue } from "./analytics.js";
26
- // All available tools
27
- export const tools = [
27
+ // All available tools, before annotations
28
+ const toolDefinitions = [
28
29
  // Communication
29
30
  emailTool,
30
31
  voiceTool,
@@ -112,6 +113,14 @@ export const tools = [
112
113
  approvalCancelTool,
113
114
  actionPolicyGetTool,
114
115
  ];
116
+ // Every tool carries a human title and the three MCP hints clients rely on
117
+ // (ChatGPT confirms any tool that is not read-only). See annotations.ts.
118
+ export const tools = toolDefinitions.map((tool) => {
119
+ const hints = TOOL_ANNOTATIONS[tool.name];
120
+ if (!hints)
121
+ throw new Error(`Tool ${tool.name} has no annotations — add it to tools/annotations.ts`);
122
+ return { ...tool, title: hints.title, annotations: { ...hints } };
123
+ });
115
124
  // Tool handlers map
116
125
  const handlers = {
117
126
  // Communication
@@ -2,7 +2,7 @@ export const voiceNumberProvisionTool = {
2
2
  name: "oneshot_voice_number_provision",
3
3
  description: "Get this agent a phone number without placing a call, so it can answer calls (then use oneshot_voice_inbound_set). " +
4
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).",
5
+ "Fails with 402 and buys nothing when credits are too low. Needs a wallet or OAuth session; a plain agent access token cannot buy numbers.",
6
6
  inputSchema: { type: "object", properties: {} },
7
7
  };
8
8
  export const voiceNumbersTool = {
@@ -15,7 +15,7 @@ export const voiceInboundSetTool = {
15
15
  description: "Make one of the agent's numbers answer its own calls. Replaces the whole inbound config. " +
16
16
  "During business hours the assistant follows `prompt`; after hours it takes a message, transfers, or declines. " +
17
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).",
18
+ "Needs a wallet or OAuth session; a plain agent access token can only read these settings.",
19
19
  inputSchema: {
20
20
  type: "object",
21
21
  properties: {
@@ -56,7 +56,7 @@ export const voiceInboundSetTool = {
56
56
  };
57
57
  export const voiceInboundDisableTool = {
58
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.",
59
+ description: "Stop answering calls to one of the agent's numbers. The settings are kept, disabled. Free. Needs a wallet or OAuth session.",
60
60
  inputSchema: {
61
61
  type: "object",
62
62
  properties: { phone_number_id: { type: "string", description: "Number id from oneshot_voice_numbers" } },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oneshot-agent/mcp-server",
3
- "version": "0.27.0",
3
+ "version": "0.29.0",
4
4
  "description": "MCP server for OneShot - 73 tools for AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -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.41.0",
28
+ "@oneshot-agent/sdk": "^0.43.0",
29
29
  "zod": "3.25.76"
30
30
  },
31
31
  "devDependencies": {