prospectapis-mcp 0.2.2 → 0.2.4

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/CHANGELOG.md CHANGED
@@ -6,6 +6,28 @@ All notable changes to `prospectapis-mcp` are documented here. The format follow
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.2.4] - unreleased
10
+
11
+ ### Fixed
12
+
13
+ - Every tool has a human title ("Search Funding Rounds", "Delete Watchlist"), sent as both the tool's `title` and `annotations.title`; before, the title was the raw tool name.
14
+ - `watchlist_delete` now says `destructiveHint: true` (it removes the watchlist and its delivery history), so a client asks before running it; it said `false`, like every other tool. The other writes stay non-destructive: they only add a research job, a watchlist, a test event or a report.
15
+ - `idempotentHint` is set where it is true: the free reads and `watchlist_delete`. `funding_search` and `funding_get` stay `false`, because every call that returns records is billed again. `openWorldHint` stays `true` on every tool.
16
+ - One factory, `annotationsFor()` in `src/tools.js`, builds these annotations for the npm server and the hosted MCP door alike. `test/annotations.test.js` checks every served tool (a title that is not the raw name and has no underscore, every `*_delete` tool destructive and not read-only) and plants each regression to prove the check fails on it.
17
+
18
+ - README opening rewritten for the listings that copy it word for word (Glama, mcpservers.org, the MCP Registry, npm): one paragraph on what the server does and costs, then the install lines and the website, plus a three-question FAQ. No tool or behaviour change; 14 tools.
19
+ - `package-lock.json` carries the package version again (it still said 0.2.2).
20
+ - `test/readme-opening.test.js` checks the opening against the package name, its Website line against `server.json` `websiteUrl`, every tool count the README states against `src/tools.js`, the stated Node floor against `engines`, and one version across `package.json`, `server.json` and `package-lock.json`.
21
+ - The README no longer says every funding record carries its announcement URL: some records come back without one, so the opening and the FAQ now say records carry the public announcement URL when there is one, and `test/readme-opening.test.js` fails on any sentence that promises a URL on every record.
22
+ - `test/package-scripts.test.js` checks that every file an npm script runs exists in the checkout.
23
+
24
+ ## [0.2.3] - 2026-10-11
25
+
26
+ ### Added
27
+
28
+ - `server.json` (the Official MCP Registry manifest) and the matching `mcpName` field in `package.json`, both `io.github.ProspectAPIs/prospectapis-mcp`, so the server can be listed on registry.modelcontextprotocol.io (which PulseMCP ingests). No tool or behaviour change.
29
+ - `scripts/registry-drift.mjs` with `npm run check:registry-drift` and a `postpublish` hook, so every npm release also updates the registry entry and a drift between npm, `server.json` and the registry fails the check.
30
+
9
31
  ## [0.2.2] - 2026-10-03
10
32
 
11
33
  ### Changed
package/README.md CHANGED
@@ -1,10 +1,12 @@
1
1
  # prospectapis-mcp
2
2
 
3
- MCP server for the ProspectAPIs funding data and research API. It gives an MCP client (Claude Desktop, Claude
4
- Code, Cursor and others) fourteen tools over `https://api.prospectapis.com`, one per customer endpoint (the
5
- liveness probe `GET /health` has none; `api_version` answers the same question). Five tools change state:
6
- `research_submit` (starts a paid research job), `watchlist_create`, `watchlist_test`, `watchlist_delete` and
7
- `feedback_send`; every other tool only reads.
3
+ prospectapis-mcp is the MCP server for ProspectAPIs, built for sales teams and their AI agents in Claude Code, Claude Desktop, Cursor and other MCP clients. It gives your agent fourteen tools over the ProspectAPIs API: search funding rounds by date, round, amount, company, investor and country, get new matching rounds pushed to your webhook, and order a cited research brief on any company or person. Funding records carry the public announcement URL when there is one. Records cost $0.02 each after 100 free a month, a completed brief costs $0.15, and there are no seats, no subscription and no card to sign up. It needs Node.js 22 or later.
4
+
5
+ Install (Claude Code): `claude mcp add prospectapis -e PROSPECTAPIS_API_KEY=pa_live_... -- npx -y prospectapis-mcp`
6
+
7
+ Other clients: run `npx -y prospectapis-mcp` with `PROSPECTAPIS_API_KEY` from https://prospectapis.com
8
+
9
+ Website: https://prospectapis.com/mcp
8
10
 
9
11
  | Tool | Endpoint | Cost |
10
12
  |---|---|---|
@@ -50,6 +52,14 @@ Client config (for example `claude_desktop_config.json`):
50
52
 
51
53
  Claude Code: `claude mcp add prospectapis -e PROSPECTAPIS_API_KEY=pa_live_... -- npx -y prospectapis-mcp`.
52
54
 
55
+ ## FAQ
56
+
57
+ **Where does the funding data come from?** Records carry the public announcement URL when there is one.
58
+
59
+ **What is free?** 100 funding records a month, any search that matches nothing, watchlist management, and the balance, pricing and version tools.
60
+
61
+ **Which clients work?** Claude Code, Claude Desktop, Cursor and any client that reads an mcpServers config, through `npx -y prospectapis-mcp`.
62
+
53
63
  ## Develop
54
64
 
55
65
  ```bash
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "prospectapis-mcp",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
+ "mcpName": "io.github.ProspectAPIs/prospectapis-mcp",
4
5
  "description": "MCP server for ProspectAPIs: search funding rounds, run paid prospect research briefs, manage funding watchlists, read your balance and the live price list.",
5
6
  "type": "module",
6
7
  "bin": {
@@ -25,7 +26,9 @@
25
26
  "start": "node src/index.js",
26
27
  "check": "node --check src/index.js && node --check src/server.js && node --check src/tools.js",
27
28
  "test": "node --test \"test/**/*.test.js\"",
28
- "prepublishOnly": "npm test"
29
+ "prepublishOnly": "npm test && node scripts/prepublish-tenant-check.mjs",
30
+ "check:registry-drift": "node scripts/registry-drift.mjs",
31
+ "postpublish": "node scripts/registry-drift.mjs --publish"
29
32
  },
30
33
  "dependencies": {
31
34
  "@modelcontextprotocol/sdk": "^1.29.0",
package/src/server.js CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { createRequire } from "node:module";
7
7
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
- import { TOOLS, buildUrl, buildPath, buildBody } from "./tools.js";
8
+ import { TOOLS, buildUrl, buildPath, buildBody, annotationsFor } from "./tools.js";
9
9
 
10
10
  export const { version: VERSION } = createRequire(import.meta.url)("../package.json");
11
11
 
@@ -95,9 +95,10 @@ export function createServer({
95
95
  server.registerTool(
96
96
  tool.name,
97
97
  {
98
+ title: tool.title,
98
99
  description: tool.description,
99
100
  inputSchema: tool.shape,
100
- annotations: { title: tool.name, readOnlyHint: !tool.write, destructiveHint: false, openWorldHint: true },
101
+ annotations: annotationsFor(tool),
101
102
  },
102
103
  (args) => callEndpoint(tool, args),
103
104
  );
package/src/tools.js CHANGED
@@ -10,7 +10,13 @@
10
10
  // - `write: true` marks a tool that changes state or spends credits
11
11
  // (research_submit starts a paid job); the server turns `write` into MCP's
12
12
  // readOnlyHint, so every other tool is read-only;
13
- // - `auth: false` marks the tools the API serves without a key (pricing_get, api_version).
13
+ // - `auth: false` marks the tools the API serves without a key (pricing_get, api_version);
14
+ // - `title` is the human name a client shows instead of the raw tool name;
15
+ // - `idempotent: true` marks a tool whose repeat call with the same arguments changes nothing more: the free
16
+ // reads, and watchlist_delete (a second delete finds nothing to delete). funding_search and funding_get are
17
+ // read-only but NOT idempotent, because every call that returns records is billed again.
18
+ // annotationsFor() below turns these fields into MCP tool annotations; the npm server and the hosted door
19
+ // (apps/api/src/lib/mcp-door.js, through createServer) both register every tool with it, so they cannot drift.
14
20
 
15
21
  import { z } from "zod";
16
22
 
@@ -38,6 +44,7 @@ export const TOOLS = [
38
44
  name: "funding_search",
39
45
  method: "GET",
40
46
  path: "/v1/funding",
47
+ title: "Search Funding Rounds",
41
48
  write: false,
42
49
  format: { min_amount_usd: formatAmount, max_amount_usd: formatAmount },
43
50
  description:
@@ -64,6 +71,7 @@ export const TOOLS = [
64
71
  name: "funding_get",
65
72
  method: "GET",
66
73
  path: "/v1/funding/{id}",
74
+ title: "Get Funding Round",
67
75
  write: false,
68
76
  description: "Read one funding record by id. Costs $0.02 when found (free records are used first); a missing id is free.",
69
77
  shape: {
@@ -74,6 +82,7 @@ export const TOOLS = [
74
82
  name: "research_submit",
75
83
  method: "POST",
76
84
  path: "/v1/research",
85
+ title: "Start Prospect Research",
77
86
  write: true,
78
87
  body: true,
79
88
  description:
@@ -103,6 +112,8 @@ export const TOOLS = [
103
112
  name: "research_get",
104
113
  method: "GET",
105
114
  path: "/v1/research/{id}",
115
+ title: "Get Research Brief",
116
+ idempotent: true,
106
117
  write: false,
107
118
  description:
108
119
  "Read a research job by the `research_id` research_submit returned: `status` (queued, running, completed, failed), `input`, " +
@@ -118,6 +129,7 @@ export const TOOLS = [
118
129
  name: "watchlist_create",
119
130
  method: "POST",
120
131
  path: "/v1/watchlists",
132
+ title: "Create Funding Watchlist",
121
133
  body: true,
122
134
  write: true,
123
135
  description:
@@ -145,6 +157,8 @@ export const TOOLS = [
145
157
  name: "watchlist_list",
146
158
  method: "GET",
147
159
  path: "/v1/watchlists",
160
+ title: "List Watchlists",
161
+ idempotent: true,
148
162
  write: false,
149
163
  description: "Your funding-signal alerts (without their secrets). Free.",
150
164
  shape: {},
@@ -153,6 +167,8 @@ export const TOOLS = [
153
167
  name: "watchlist_get",
154
168
  method: "GET",
155
169
  path: "/v1/watchlists/{id}",
170
+ title: "Get Watchlist",
171
+ idempotent: true,
156
172
  write: false,
157
173
  description: "One funding-signal alert: its name, filters, webhook URL, whether it is active and why it was paused (never its secret). Free.",
158
174
  shape: { id: z.string().uuid().describe("The watchlist id.") },
@@ -161,6 +177,8 @@ export const TOOLS = [
161
177
  name: "watchlist_deliveries",
162
178
  method: "GET",
163
179
  path: "/v1/watchlists/{id}/deliveries",
180
+ title: "List Watchlist Deliveries",
181
+ idempotent: true,
164
182
  write: false,
165
183
  description: "The last 50 deliveries of one alert and their outcome (delivered, retry, failed, no_credit). Free.",
166
184
  shape: { id: z.string().uuid().describe("The watchlist id.") },
@@ -169,6 +187,7 @@ export const TOOLS = [
169
187
  name: "watchlist_test",
170
188
  method: "POST",
171
189
  path: "/v1/watchlists/{id}/test",
190
+ title: "Send Watchlist Test Event",
172
191
  body: true,
173
192
  write: true,
174
193
  description: "Send a signed sample event to the alert's webhook now, to build and verify the receiver. Free; 5 a minute.",
@@ -178,6 +197,8 @@ export const TOOLS = [
178
197
  name: "watchlist_delete",
179
198
  method: "DELETE",
180
199
  path: "/v1/watchlists/{id}",
200
+ title: "Delete Watchlist",
201
+ idempotent: true,
181
202
  write: true,
182
203
  description: "Delete a funding-signal alert and its delivery history. Free.",
183
204
  shape: { id: z.string().uuid().describe("The watchlist id.") },
@@ -186,6 +207,8 @@ export const TOOLS = [
186
207
  name: "account_balance",
187
208
  method: "GET",
188
209
  path: "/v1/account",
210
+ title: "Get Account Balance",
211
+ idempotent: true,
189
212
  write: false,
190
213
  description: "Your credit balance and the free records left this month. Free. Check it before a large paged search.",
191
214
  shape: {},
@@ -194,6 +217,7 @@ export const TOOLS = [
194
217
  name: "feedback_send",
195
218
  method: "POST",
196
219
  path: "/v1/feedback",
220
+ title: "Send Feedback",
197
221
  body: true,
198
222
  write: true,
199
223
  description:
@@ -212,6 +236,8 @@ export const TOOLS = [
212
236
  name: "pricing_get",
213
237
  method: "GET",
214
238
  path: "/pricing",
239
+ title: "Get Pricing",
240
+ idempotent: true,
215
241
  write: false,
216
242
  auth: false,
217
243
  description:
@@ -223,6 +249,8 @@ export const TOOLS = [
223
249
  name: "api_version",
224
250
  method: "GET",
225
251
  path: "/v1/version",
252
+ title: "Get API Version",
253
+ idempotent: true,
226
254
  write: false,
227
255
  auth: false,
228
256
  description: "The API's version and deployed build. Free, needs no key.",
@@ -270,3 +298,17 @@ export function buildBody(tool, args) {
270
298
  }
271
299
  return JSON.stringify(out);
272
300
  }
301
+
302
+ // The one place a catalog entry becomes MCP tool annotations. A tool is destructive when it is a write whose
303
+ // method is DELETE (watchlist_delete removes the watchlist and its delivery history); every other write only adds
304
+ // (a research job, a watchlist, a test event, a report), so it is a write that is not destructive.
305
+ export function annotationsFor(tool) {
306
+ const write = !!tool.write;
307
+ return {
308
+ title: tool.title,
309
+ readOnlyHint: !write,
310
+ destructiveHint: write && tool.method === "DELETE",
311
+ idempotentHint: !!tool.idempotent,
312
+ openWorldHint: true,
313
+ };
314
+ }