@oneshot-agent/mcp-server 0.30.0 → 0.32.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/dist/index.js CHANGED
@@ -46,23 +46,19 @@ async function initAgent() {
46
46
  " ONESHOT_WALLET_PRIVATE_KEY, or ONESHOT_ACCESS_TOKEN (credits-only session)");
47
47
  process.exit(1);
48
48
  }
49
- // Start server
50
49
  async function main() {
51
50
  const agent = await initAgent();
52
- // Create MCP server
53
51
  const server = new Server({
54
52
  name: "oneshot-mcp",
55
- version: "0.30.0", // keep in sync with package.json; guarded by version.test.ts
53
+ version: "0.32.0", // keep in sync with package.json; guarded by version.test.ts
56
54
  }, {
57
55
  capabilities: {
58
56
  tools: {},
59
57
  },
60
58
  });
61
- // List available tools
62
59
  server.setRequestHandler(ListToolsRequestSchema, async () => {
63
60
  return { tools };
64
61
  });
65
- // Handle tool calls
66
62
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
67
63
  const { name, arguments: args } = request.params;
68
64
  return handleToolCall(agent, name, args || {});
@@ -6,22 +6,18 @@ const OPEN = true;
6
6
  const OWN = false;
7
7
  const DESTRUCTIVE = true;
8
8
  export const TOOL_ANNOTATIONS = {
9
- // Communication
10
9
  oneshot_email: write("Send email", OPEN),
11
10
  oneshot_voice: write("Place a phone call", OPEN),
12
11
  oneshot_sms: write("Send a text message", OPEN),
13
- // Inbox
14
12
  oneshot_inbox_list: read("List received emails", OWN),
15
13
  oneshot_inbox_get: read("Read a received email", OWN),
16
14
  oneshot_sms_inbox_list: read("List received texts", OWN),
17
15
  oneshot_sms_inbox_get: read("Read a received text", OWN),
18
- // Inbound voice
19
16
  oneshot_voice_number_provision: write("Get a phone number", OPEN),
20
17
  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),
18
+ oneshot_voice_inbound_set: write("Set up call answering", OPEN, DESTRUCTIVE), // replaces the number's answering settings; outside callers reach it via the carrier
19
+ oneshot_voice_inbound_disable: write("Stop answering calls", OPEN),
23
20
  oneshot_voice_inbound_calls: read("List answered calls", OWN),
24
- // Research & enrichment
25
21
  oneshot_research: read("Deep research", OPEN),
26
22
  oneshot_people_search: read("Find people", OPEN),
27
23
  oneshot_enrich_profile: read("Look up a person's profile", OPEN),
@@ -39,10 +35,8 @@ export const TOOL_ANNOTATIONS = {
39
35
  oneshot_local_search: read("Find local businesses", OPEN),
40
36
  oneshot_local_resolve: read("Look up a local business", OPEN),
41
37
  oneshot_gov_solicitations: read("Find government contracts", OPEN),
42
- // Commerce
43
38
  oneshot_commerce_search: read("Search products", OPEN),
44
39
  oneshot_commerce_buy: write("Buy a product", OPEN),
45
- // Compute orchestration
46
40
  oneshot_compute: write("Start a goal", OPEN),
47
41
  oneshot_compute_status: read("Check a goal", OWN),
48
42
  oneshot_compute_tasks: read("List a goal's tasks", OWN),
@@ -51,17 +45,13 @@ export const TOOL_ANNOTATIONS = {
51
45
  oneshot_compute_pause: write("Pause a goal", OWN),
52
46
  oneshot_compute_resume: write("Resume a goal", OWN),
53
47
  oneshot_compute_fund: write("Add budget to a goal", OWN),
54
- // Build
55
48
  oneshot_build: write("Build a website", OPEN),
56
49
  oneshot_update_build: write("Update a website", OPEN, DESTRUCTIVE), // overwrites the live site
57
- // Browser
58
50
  oneshot_browser: write("Browse and act on a website", OPEN),
59
51
  oneshot_browser_create_profile: write("Create a browser profile", OWN),
60
52
  oneshot_browser_list_profiles: read("List browser profiles", OWN),
61
53
  oneshot_browser_delete_profile: write("Delete a browser profile", OWN, DESTRUCTIVE),
62
- // Web read
63
54
  oneshot_web_read: read("Read a web page", OPEN),
64
- // LinkedIn
65
55
  oneshot_linkedin_connect: write("Connect LinkedIn", OPEN),
66
56
  oneshot_linkedin_accounts: read("List LinkedIn accounts", OWN),
67
57
  oneshot_linkedin_sync: write("Sync LinkedIn messages", OPEN), // paid; imports history into the account
@@ -72,22 +62,18 @@ export const TOOL_ANNOTATIONS = {
72
62
  oneshot_linkedin_withdraw_invitation: write("Withdraw a LinkedIn invitation", OPEN, DESTRUCTIVE),
73
63
  oneshot_linkedin_view_profile: write("View a LinkedIn profile", OPEN), // notify=true is visible to the person
74
64
  oneshot_linkedin_react: write("React to a LinkedIn post", OPEN),
75
- // Domains
76
65
  oneshot_list_domains: read("List sending domains", OWN),
77
66
  oneshot_pause_domain: write("Pause a sending domain", OWN),
78
67
  oneshot_resume_domain: write("Resume a sending domain", OWN),
79
- // Analytics
80
68
  oneshot_spend_breakdown: read("Show spending", OWN),
81
69
  oneshot_return_on_spend: read("Show return on spend", OWN),
82
70
  oneshot_return_on_spend_by_goal: read("Show return on spend by goal", OWN),
83
71
  oneshot_receipts_list: read("List receipts", OWN),
84
72
  oneshot_tag_receipt_value: write("Tag a receipt's value", OWN),
85
- // Account
86
73
  oneshot_notifications: read("List notifications", OWN),
87
74
  oneshot_mark_notification_read: write("Mark a notification read", OWN),
88
75
  oneshot_get_balance: read("Check balance", OWN),
89
76
  oneshot_budget_status: read("Check budget", OWN),
90
- // Approvals
91
77
  oneshot_approval_create: write("Ask a person to approve", OPEN),
92
78
  oneshot_approval_get: read("Check an approval", OWN),
93
79
  oneshot_approval_list: read("List approvals", OWN),
@@ -1,6 +1,5 @@
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.
1
+ // Setting the action policy is deliberately not exposed here — an agent that
2
+ // could loosen its own policy would make the policy meaningless.
4
3
  export const approvalCreateTool = {
5
4
  name: "oneshot_approval_create",
6
5
  description: "Ask a named human to approve or deny something before you do it. They get a one-tap link by email or SMS. " +
@@ -1,12 +1,12 @@
1
1
  export const buildTool = {
2
2
  name: "oneshot_build",
3
- description: "Build and deploy production websites - SaaS landing pages, portfolios, agency sites, restaurant pages, event sites, and more. Creates fully-functional sites with real hosting. Paid tool — quote provided before payment.",
3
+ description: "Build and deploy production websites - SaaS landing pages, portfolios, agency sites, restaurant pages, event sites, and more, single-page or multi-page (pages). Creates fully-functional sites with real hosting. Paid tool — quote provided before payment.",
4
4
  inputSchema: {
5
5
  type: "object",
6
6
  properties: {
7
7
  type: {
8
8
  type: "string",
9
- enum: ["saas", "portfolio", "agency", "personal", "product", "funnel", "restaurant", "event", "app", "social"],
9
+ enum: ["saas", "portfolio", "agency", "personal", "product", "funnel", "restaurant", "event"],
10
10
  description: "Build type (default: saas)",
11
11
  },
12
12
  product: {
@@ -40,6 +40,21 @@ export const buildTool = {
40
40
  items: { type: "string" },
41
41
  description: "Specific sections to include (e.g., ['hero', 'features', 'pricing', 'testimonials'])",
42
42
  },
43
+ pages: {
44
+ type: "array",
45
+ maxItems: 8,
46
+ description: "Extra pages beyond the home page, each priced separately (e.g., [{ path: '/pricing', name: 'Pricing' }, { path: '/about', name: 'About', purpose: 'Team and story' }])",
47
+ items: {
48
+ type: "object",
49
+ properties: {
50
+ path: { type: "string", description: "Route: lowercase words and hyphens, e.g. /pricing or /blog/launch" },
51
+ name: { type: "string", description: "Nav label" },
52
+ purpose: { type: "string", description: "What the page is for" },
53
+ sections: { type: "array", items: { type: "string" }, description: "Sections for this page" },
54
+ },
55
+ required: ["path", "name"],
56
+ },
57
+ },
43
58
  lead_capture: {
44
59
  type: "object",
45
60
  properties: {
@@ -98,7 +113,7 @@ export const buildTool = {
98
113
  };
99
114
  export const updateBuildTool = {
100
115
  name: "oneshot_update_build",
101
- description: "Update an existing website with new content or configuration. Requires the build_id from a previous build. Updates reuse existing hosting infrastructure at a discounted rate.",
116
+ description: "Change an existing website. With `changes` (plain-language edits, e.g. 'make the hero darker and add an FAQ page'), the site's existing code is edited and redeployed to the same URL at a flat price. With `product` and no `changes`, the site is regenerated from scratch at a discounted rate. Requires the build_id from a previous build.",
102
117
  inputSchema: {
103
118
  type: "object",
104
119
  properties: {
@@ -106,6 +121,10 @@ export const updateBuildTool = {
106
121
  type: "string",
107
122
  description: "Existing build ID to update (from previous build result)",
108
123
  },
124
+ changes: {
125
+ type: "string",
126
+ description: "Plain-language edits to apply to the existing site (keeps everything else). Max 5000 chars.",
127
+ },
109
128
  product: {
110
129
  type: "object",
111
130
  properties: {
@@ -130,7 +149,7 @@ export const updateBuildTool = {
130
149
  },
131
150
  type: {
132
151
  type: "string",
133
- enum: ["saas", "portfolio", "agency", "personal", "product", "funnel", "restaurant", "event", "app", "social"],
152
+ enum: ["saas", "portfolio", "agency", "personal", "product", "funnel", "restaurant", "event"],
134
153
  description: "Build type (optional, keeps existing if not specified)",
135
154
  },
136
155
  source_url: {
@@ -142,6 +161,21 @@ export const updateBuildTool = {
142
161
  items: { type: "string" },
143
162
  description: "Specific sections to include",
144
163
  },
164
+ pages: {
165
+ type: "array",
166
+ maxItems: 8,
167
+ description: "Extra pages beyond the home page, each priced separately (e.g., [{ path: '/pricing', name: 'Pricing' }, { path: '/about', name: 'About', purpose: 'Team and story' }])",
168
+ items: {
169
+ type: "object",
170
+ properties: {
171
+ path: { type: "string", description: "Route: lowercase words and hyphens, e.g. /pricing or /blog/launch" },
172
+ name: { type: "string", description: "Nav label" },
173
+ purpose: { type: "string", description: "What the page is for" },
174
+ sections: { type: "array", items: { type: "string" }, description: "Sections for this page" },
175
+ },
176
+ required: ["path", "name"],
177
+ },
178
+ },
145
179
  lead_capture: {
146
180
  type: "object",
147
181
  properties: {
@@ -169,7 +203,7 @@ export const updateBuildTool = {
169
203
  description: "Custom domain",
170
204
  },
171
205
  },
172
- required: ["build_id", "product"],
206
+ required: ["build_id"],
173
207
  },
174
208
  };
175
209
  export async function handleBuild(agent, args) {
@@ -184,6 +218,7 @@ export async function handleBuild(agent, args) {
184
218
  },
185
219
  source_url: args.source_url,
186
220
  sections: args.sections,
221
+ pages: args.pages,
187
222
  lead_capture: args.lead_capture,
188
223
  brand: args.brand,
189
224
  images: args.images,
@@ -192,7 +227,13 @@ export async function handleBuild(agent, args) {
192
227
  });
193
228
  }
194
229
  export async function handleUpdateBuild(agent, args) {
230
+ if (typeof args.changes === "string" && args.changes.trim()) {
231
+ return agent.refineBuild({ build_id: args.build_id, changes: args.changes });
232
+ }
195
233
  const product = args.product;
234
+ if (!product) {
235
+ throw new Error("oneshot_update_build needs either changes (to edit the site) or product (to regenerate it)");
236
+ }
196
237
  return agent.updateBuild({
197
238
  build_id: args.build_id,
198
239
  product: {
@@ -204,6 +245,7 @@ export async function handleUpdateBuild(agent, args) {
204
245
  type: args.type,
205
246
  source_url: args.source_url,
206
247
  sections: args.sections,
248
+ pages: args.pages,
207
249
  lead_capture: args.lead_capture,
208
250
  brand: args.brand,
209
251
  images: args.images,
@@ -24,24 +24,19 @@ import { computeTool, computeStatusTool, computeTasksTool, computeCancelTool, co
24
24
  import { listDomainsTool, pauseDomainTool, resumeDomainTool, handleListDomains, handlePauseDomain, handleResumeDomain } from "./domains.js";
25
25
  import { TOOL_ANNOTATIONS } from "./annotations.js";
26
26
  import { spendBreakdownTool, rocsTool, rocsByGoalTool, receiptsListTool, tagReceiptValueTool, handleSpendBreakdown, handleRocs, handleRocsByGoal, handleReceiptsList, handleTagReceiptValue } from "./analytics.js";
27
- // All available tools, before annotations
28
27
  const toolDefinitions = [
29
- // Communication
30
28
  emailTool,
31
29
  voiceTool,
32
30
  smsTool,
33
- // Inbox
34
31
  inboxListTool,
35
32
  inboxGetTool,
36
33
  smsInboxListTool,
37
34
  smsInboxGetTool,
38
- // Inbound voice
39
35
  voiceNumberProvisionTool,
40
36
  voiceNumbersTool,
41
37
  voiceInboundSetTool,
42
38
  voiceInboundDisableTool,
43
39
  voiceInboundCallsTool,
44
- // Research & Enrichment
45
40
  researchTool,
46
41
  peopleSearchTool,
47
42
  enrichProfileTool,
@@ -59,10 +54,8 @@ const toolDefinitions = [
59
54
  localSearchTool,
60
55
  localResolveTool,
61
56
  govSolicitationsTool,
62
- // Commerce
63
57
  commerceSearchTool,
64
58
  commerceBuyTool,
65
- // Compute orchestration
66
59
  computeTool,
67
60
  computeStatusTool,
68
61
  computeTasksTool,
@@ -71,17 +64,13 @@ const toolDefinitions = [
71
64
  computePauseTool,
72
65
  computeResumeTool,
73
66
  computeFundTool,
74
- // Build
75
67
  buildTool,
76
68
  updateBuildTool,
77
- // Browser
78
69
  browserTool,
79
70
  browserCreateProfileTool,
80
71
  browserListProfilesTool,
81
72
  browserDeleteProfileTool,
82
- // Web Read
83
73
  webReadTool,
84
- // LinkedIn (human-connected account)
85
74
  linkedinConnectTool,
86
75
  linkedinAccountsTool,
87
76
  linkedinSyncTool,
@@ -91,22 +80,18 @@ const toolDefinitions = [
91
80
  linkedinInviteTool, linkedinWithdrawInvitationTool,
92
81
  linkedinViewProfileTool,
93
82
  linkedinReactTool,
94
- // Domains
95
83
  listDomainsTool,
96
84
  pauseDomainTool,
97
85
  resumeDomainTool,
98
- // Analytics
99
86
  spendBreakdownTool,
100
87
  rocsTool,
101
88
  rocsByGoalTool,
102
89
  receiptsListTool,
103
90
  tagReceiptValueTool,
104
- // Account
105
91
  notificationsTool,
106
92
  markReadTool,
107
93
  getBalanceTool,
108
94
  budgetStatusTool,
109
- // Approvals
110
95
  approvalCreateTool,
111
96
  approvalGetTool,
112
97
  approvalListTool,
@@ -121,24 +106,19 @@ export const tools = toolDefinitions.map((tool) => {
121
106
  throw new Error(`Tool ${tool.name} has no annotations — add it to tools/annotations.ts`);
122
107
  return { ...tool, title: hints.title, annotations: { ...hints } };
123
108
  });
124
- // Tool handlers map
125
109
  const handlers = {
126
- // Communication
127
110
  "oneshot_email": handleEmail,
128
111
  "oneshot_voice": handleVoice,
129
112
  "oneshot_sms": handleSms,
130
- // Inbox
131
113
  "oneshot_inbox_list": handleInboxList,
132
114
  "oneshot_inbox_get": handleInboxGet,
133
115
  "oneshot_sms_inbox_list": handleSmsInboxList,
134
116
  "oneshot_sms_inbox_get": handleSmsInboxGet,
135
- // Inbound voice
136
117
  "oneshot_voice_number_provision": handleVoiceNumberProvision,
137
118
  "oneshot_voice_numbers": handleVoiceNumbers,
138
119
  "oneshot_voice_inbound_set": handleVoiceInboundSet,
139
120
  "oneshot_voice_inbound_disable": handleVoiceInboundDisable,
140
121
  "oneshot_voice_inbound_calls": handleVoiceInboundCalls,
141
- // Research & Enrichment
142
122
  "oneshot_research": handleResearch,
143
123
  "oneshot_people_search": handlePeopleSearch,
144
124
  "oneshot_enrich_profile": handleEnrichProfile,
@@ -156,10 +136,8 @@ const handlers = {
156
136
  "oneshot_local_search": handleLocalSearch,
157
137
  "oneshot_local_resolve": handleLocalResolve,
158
138
  "oneshot_gov_solicitations": handleGovSolicitations,
159
- // Commerce
160
139
  "oneshot_commerce_search": handleCommerceSearch,
161
140
  "oneshot_commerce_buy": handleCommerceBuy,
162
- // Compute orchestration
163
141
  "oneshot_compute": handleCompute,
164
142
  "oneshot_compute_status": handleComputeStatus,
165
143
  "oneshot_compute_tasks": handleComputeTasks,
@@ -168,17 +146,13 @@ const handlers = {
168
146
  "oneshot_compute_pause": handleComputePause,
169
147
  "oneshot_compute_resume": handleComputeResume,
170
148
  "oneshot_compute_fund": handleComputeFund,
171
- // Build
172
149
  "oneshot_build": handleBuild,
173
150
  "oneshot_update_build": handleUpdateBuild,
174
- // Browser
175
151
  "oneshot_browser": handleBrowser,
176
152
  "oneshot_browser_create_profile": handleBrowserCreateProfile,
177
153
  "oneshot_browser_list_profiles": handleBrowserListProfiles,
178
154
  "oneshot_browser_delete_profile": handleBrowserDeleteProfile,
179
- // Web Read
180
155
  "oneshot_web_read": handleWebRead,
181
- // LinkedIn (human-connected account)
182
156
  "oneshot_linkedin_connect": handleLinkedinConnect,
183
157
  "oneshot_linkedin_accounts": handleLinkedinAccounts,
184
158
  "oneshot_linkedin_sync": handleLinkedinSync,
@@ -189,22 +163,18 @@ const handlers = {
189
163
  "oneshot_linkedin_withdraw_invitation": handleLinkedinWithdrawInvitation,
190
164
  "oneshot_linkedin_view_profile": handleLinkedinViewProfile,
191
165
  "oneshot_linkedin_react": handleLinkedinReact,
192
- // Domains
193
166
  "oneshot_list_domains": handleListDomains,
194
167
  "oneshot_pause_domain": handlePauseDomain,
195
168
  "oneshot_resume_domain": handleResumeDomain,
196
- // Analytics
197
169
  "oneshot_spend_breakdown": handleSpendBreakdown,
198
170
  "oneshot_return_on_spend": handleRocs,
199
171
  "oneshot_return_on_spend_by_goal": handleRocsByGoal,
200
172
  "oneshot_receipts_list": handleReceiptsList,
201
173
  "oneshot_tag_receipt_value": handleTagReceiptValue,
202
- // Account
203
174
  "oneshot_notifications": handleNotifications,
204
175
  "oneshot_mark_notification_read": handleMarkRead,
205
176
  "oneshot_get_balance": handleGetBalance,
206
177
  "oneshot_budget_status": handleBudgetStatus,
207
- // Approvals
208
178
  "oneshot_approval_create": handleApprovalCreate,
209
179
  "oneshot_approval_get": handleApprovalGet,
210
180
  "oneshot_approval_list": handleApprovalList,
@@ -1,10 +1,8 @@
1
1
  /**
2
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, invite). Reconnect and
6
- * revoke are deliberately NOT exposed as MCP tools — a human decides those
7
- * from the application that owns the account.
3
+ * The human grants specific actions (read, reply, view_profile, react, invite)
4
+ * via a hosted login link; reconnect/revoke are deliberately NOT exposed here —
5
+ * a human decides those from the application that owns the account.
8
6
  */
9
7
  const GRANT_ACTIONS = ["read", "reply", "view_profile", "react", "invite", "comment"];
10
8
  export const linkedinConnectTool = {
@@ -72,7 +72,6 @@ export const personInteractionsTool = {
72
72
  required: ["social_media_url"],
73
73
  },
74
74
  };
75
- // Handlers
76
75
  /** Deep person research fans out across several providers; the SDK's 120s default was too short. */
77
76
  export const DEEP_RESEARCH_PERSON_TIMEOUT_SEC = 300;
78
77
  export async function handleDeepResearchPerson(agent, args) {
@@ -2,10 +2,9 @@ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
2
  import type { OneShot } from "@oneshot-agent/sdk";
3
3
  export declare const researchTool: Tool;
4
4
  /**
5
- * Wait budget per depth. The SDK's default is 120s, but deep research runs
6
- * 2–5 minutes (as the tool description says), so every deep call used to end
7
- * in JobTimeoutError while the job kept running. Results are pushed the
8
- * moment they exist, so a generous ceiling costs nothing on fast jobs.
5
+ * The SDK's 120s default is too short for deep research (runs 2-5min);
6
+ * results are pushed the moment they exist, so a generous ceiling costs
7
+ * nothing on fast jobs.
9
8
  */
10
9
  export declare const RESEARCH_TIMEOUT_SEC: Record<"quick" | "deep", number>;
11
10
  export declare function handleResearch(agent: OneShot, args: Record<string, unknown>): Promise<import("@oneshot-agent/sdk").ResearchResult>;
@@ -27,10 +27,9 @@ export const researchTool = {
27
27
  },
28
28
  };
29
29
  /**
30
- * Wait budget per depth. The SDK's default is 120s, but deep research runs
31
- * 2–5 minutes (as the tool description says), so every deep call used to end
32
- * in JobTimeoutError while the job kept running. Results are pushed the
33
- * moment they exist, so a generous ceiling costs nothing on fast jobs.
30
+ * The SDK's 120s default is too short for deep research (runs 2-5min);
31
+ * results are pushed the moment they exist, so a generous ceiling costs
32
+ * nothing on fast jobs.
34
33
  */
35
34
  export const RESEARCH_TIMEOUT_SEC = { quick: 180, deep: 600 };
36
35
  export async function handleResearch(agent, args) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oneshot-agent/mcp-server",
3
- "version": "0.30.0",
3
+ "version": "0.32.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.44.0",
28
+ "@oneshot-agent/sdk": "^0.46.0",
29
29
  "zod": "3.25.76"
30
30
  },
31
31
  "devDependencies": {