gmpsignal-mcp 1.0.0 → 1.2.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/bin/cli.mjs +788 -36
- package/package.json +1 -1
package/bin/cli.mjs
CHANGED
|
@@ -1,23 +1,786 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* @file cli.mjs
|
|
4
|
-
* @description
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* @description Official Model Context Protocol (MCP) JSON-RPC 2.0 stdio server and CLI launcher
|
|
5
|
+
* for the GMPSignal 40-Actor Enterprise Data, Quantitative Crypto, Prediction Markets,
|
|
6
|
+
* B2B Enrichment, KYB/Sanctions, Cybersecurity & Regulatory Intelligence Suite on Apify.
|
|
7
|
+
* Exposes all 40 GMPSignal Apify Actors as strongly-typed MCP tools with zero-credential
|
|
8
|
+
* offline/container introspection (initialize, tools/list, resources/list, prompts/list)
|
|
9
|
+
* for Glama.ai and Smithery.ai inspections.
|
|
7
10
|
*/
|
|
8
11
|
|
|
9
|
-
import
|
|
12
|
+
import readline from 'node:readline';
|
|
10
13
|
import { GMPSIGNAL_SUITES, resolveActorsForSuite, buildMcpServerConfig } from '../index.mjs';
|
|
11
14
|
|
|
12
15
|
/**
|
|
13
|
-
*
|
|
16
|
+
* Complete 40-Tool MCP Definitions mapping 1-to-1 to all 40 GMPSignal Apify Actors.
|
|
17
|
+
* @type {Array<{name: string, actorSlug: string, description: string, inputSchema: Object}>}
|
|
18
|
+
*/
|
|
19
|
+
const MCP_TOOL_DEFINITIONS = [
|
|
20
|
+
{
|
|
21
|
+
name: 'dex_token_scanner_security_auditor',
|
|
22
|
+
actorSlug: 'gmpsignal~dex-token-scanner-security-auditor',
|
|
23
|
+
description: 'Scan DEX tokens across Solana, Ethereum, Base, Arbitrum, and BSC using DexScreener and GoPlus Security APIs to detect honeypots, mint/freeze authority, buy/sell taxes, and liquidity locks.',
|
|
24
|
+
inputSchema: {
|
|
25
|
+
type: 'object',
|
|
26
|
+
properties: {
|
|
27
|
+
chainId: { type: 'string', description: 'Target blockchain network (solana, ethereum, base, arbitrum, bsc).', default: 'solana' },
|
|
28
|
+
searchQuery: { type: 'string', description: 'Token symbol, name, or contract/pair address to audit.', default: 'SOL' },
|
|
29
|
+
minLiquidityUsd: { type: 'number', description: 'Minimum pool liquidity in USD.', default: 10000 },
|
|
30
|
+
maxResults: { type: 'integer', description: 'Maximum number of audited token pairs to return.', default: 15 }
|
|
31
|
+
},
|
|
32
|
+
required: []
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'crypto_orderbook_arbitrage_scanner',
|
|
37
|
+
actorSlug: 'gmpsignal~crypto-orderbook-arbitrage-scanner',
|
|
38
|
+
description: 'Analyze live Level-2 order book depth, $10k/$50k/$100k execution slippage, and cross-exchange arbitrage spreads across Binance, Bybit, Kraken, Coinbase, OKX, and KuCoin.',
|
|
39
|
+
inputSchema: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
properties: {
|
|
42
|
+
symbols: { type: 'array', items: { type: 'string' }, description: 'Trading pairs to scan (e.g., BTCUSDT, ETHUSDT, SOLUSDT).', default: ['BTCUSDT', 'ETHUSDT'] },
|
|
43
|
+
exchanges: { type: 'array', items: { type: 'string' }, description: 'Exchanges to compare.', default: ['binance', 'bybit', 'kraken', 'coinbase'] },
|
|
44
|
+
maxResults: { type: 'integer', description: 'Maximum order book records to return.', default: 20 }
|
|
45
|
+
},
|
|
46
|
+
required: []
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'multichain_wallet_aml_risk_screener',
|
|
51
|
+
actorSlug: 'gmpsignal~multichain-wallet-aml-risk-screener',
|
|
52
|
+
description: 'Screen EVM and Solana wallet addresses for native balances, transaction velocity, mixer exposure, sanctions flags, and automated AML risk scores.',
|
|
53
|
+
inputSchema: {
|
|
54
|
+
type: 'object',
|
|
55
|
+
properties: {
|
|
56
|
+
addresses: { type: 'array', items: { type: 'string' }, description: 'Wallet addresses to screen.' },
|
|
57
|
+
chains: { type: 'array', items: { type: 'string' }, description: 'Chains to query (ethereum, base, arbitrum, polygon, bsc, solana).', default: ['ethereum'] },
|
|
58
|
+
maxTransactions: { type: 'integer', description: 'Maximum recent transactions to inspect per wallet.', default: 10 }
|
|
59
|
+
},
|
|
60
|
+
required: ['addresses']
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: 'defi_yield_tvl_stablecoin_monitor',
|
|
65
|
+
actorSlug: 'gmpsignal~defi-yield-tvl-stablecoin-monitor',
|
|
66
|
+
description: 'Monitor DeFi yield farming APY pools, multi-chain protocol TVL momentum, and stablecoin peg health using live DeFiLlama intelligence.',
|
|
67
|
+
inputSchema: {
|
|
68
|
+
type: 'object',
|
|
69
|
+
properties: {
|
|
70
|
+
mode: { type: 'string', description: 'Query mode: yield_pools, protocol_tvl, or stablecoins.', default: 'yield_pools' },
|
|
71
|
+
chains: { type: 'array', items: { type: 'string' }, description: 'Chains to filter (Ethereum, Solana, Arbitrum, Base).', default: ['Ethereum', 'Solana'] },
|
|
72
|
+
minTvlUsd: { type: 'number', description: 'Minimum pool TVL in USD.', default: 1000000 },
|
|
73
|
+
maxResults: { type: 'integer', description: 'Maximum records to return.', default: 25 }
|
|
74
|
+
},
|
|
75
|
+
required: []
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'prediction_markets_polymarket_kalshi_scanner',
|
|
80
|
+
actorSlug: 'gmpsignal~prediction-markets-polymarket-kalshi-scanner',
|
|
81
|
+
description: 'Fetch real-time implied probabilities, yes/no odds, trading volume, liquidity, and arbitrage opportunities across Polymarket, Kalshi, and Manifold Markets.',
|
|
82
|
+
inputSchema: {
|
|
83
|
+
type: 'object',
|
|
84
|
+
properties: {
|
|
85
|
+
sources: { type: 'array', items: { type: 'string' }, description: 'Prediction market venues (polymarket, kalshi, manifold).', default: ['polymarket', 'kalshi'] },
|
|
86
|
+
keyword: { type: 'string', description: 'Optional keyword filter for market questions.', default: '' },
|
|
87
|
+
minVolumeUsd: { type: 'number', description: 'Minimum market volume in USD.', default: 1000 },
|
|
88
|
+
maxResults: { type: 'integer', description: 'Maximum prediction markets to return.', default: 25 }
|
|
89
|
+
},
|
|
90
|
+
required: []
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: 'b2b_company_techstack_contacts_enricher',
|
|
95
|
+
actorSlug: 'gmpsignal~b2b-company-techstack-contacts-enricher',
|
|
96
|
+
description: 'Enrich B2B company domains with decision-maker emails, phone numbers, social profiles, 38+ technology stack fingerprints, MX/SPF/DMARC security posture, and RDAP registration data.',
|
|
97
|
+
inputSchema: {
|
|
98
|
+
type: 'object',
|
|
99
|
+
properties: {
|
|
100
|
+
domains: { type: 'array', items: { type: 'string' }, description: 'Company domains to enrich (e.g., stripe.com, apify.com).' },
|
|
101
|
+
extractContacts: { type: 'boolean', description: 'Extract emails, phones, and social links.', default: true },
|
|
102
|
+
detectTechStack: { type: 'boolean', description: 'Detect frontend, analytics, CRM, and infrastructure technologies.', default: true },
|
|
103
|
+
maxResults: { type: 'integer', description: 'Maximum enriched domain records to return.', default: 10 }
|
|
104
|
+
},
|
|
105
|
+
required: ['domains']
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'global_sanctions_pep_gleif_kyb_screener',
|
|
110
|
+
actorSlug: 'gmpsignal~global-sanctions-pep-gleif-kyb-screener',
|
|
111
|
+
description: 'Screen corporate entities and individuals against GLEIF Legal Entity Identifiers (LEI), OFAC/UN/EU global sanctions lists, and PEP compliance databases.',
|
|
112
|
+
inputSchema: {
|
|
113
|
+
type: 'object',
|
|
114
|
+
properties: {
|
|
115
|
+
entities: { type: 'array', items: { type: 'string' }, description: 'Company or individual names to screen for KYB/AML compliance.' },
|
|
116
|
+
includeGleifLei: { type: 'boolean', description: 'Query official GLEIF LEI corporate registry.', default: true },
|
|
117
|
+
includeSanctionsMatch: { type: 'boolean', description: 'Screen against global sanctions and watchlists.', default: true },
|
|
118
|
+
maxResults: { type: 'integer', description: 'Maximum compliance records to return.', default: 15 }
|
|
119
|
+
},
|
|
120
|
+
required: ['entities']
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: 'cyber_cve_kev_epss_vulnerability_scanner',
|
|
125
|
+
actorSlug: 'gmpsignal~cyber-cve-kev-epss-vulnerability-scanner',
|
|
126
|
+
description: 'Correlate CISA Known Exploited Vulnerabilities (KEV), FIRST.org 30-day EPSS exploitation probabilities, and NVD CVSS v3 severity scores for DevSecOps prioritization.',
|
|
127
|
+
inputSchema: {
|
|
128
|
+
type: 'object',
|
|
129
|
+
properties: {
|
|
130
|
+
mode: { type: 'string', description: 'Scan mode: cisa_kev or specific_cves.', default: 'cisa_kev' },
|
|
131
|
+
vendorFilter: { type: 'string', description: 'Optional vendor or product filter (e.g., Microsoft, Cisco, Linux).', default: '' },
|
|
132
|
+
minEpssScore: { type: 'number', description: 'Minimum 30-day EPSS exploitation probability (0.0 to 1.0).', default: 0.05 },
|
|
133
|
+
maxResults: { type: 'integer', description: 'Maximum CVE records to return.', default: 25 }
|
|
134
|
+
},
|
|
135
|
+
required: []
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: 'startup_vc_dealflow_yc_github_radar',
|
|
140
|
+
actorSlug: 'gmpsignal~startup-vc-dealflow-yc-github-radar',
|
|
141
|
+
description: 'Discover high-traction startups and open-source developer tools across Y Combinator (YC), GitHub Trending repositories, and Hacker News launches.',
|
|
142
|
+
inputSchema: {
|
|
143
|
+
type: 'object',
|
|
144
|
+
properties: {
|
|
145
|
+
sources: { type: 'array', items: { type: 'string' }, description: 'Deal-flow sources (yc_companies, github_trending, hackernews_launch).', default: ['yc_companies', 'github_trending', 'hackernews_launch'] },
|
|
146
|
+
keyword: { type: 'string', description: 'Optional industry or technology keyword filter.', default: '' },
|
|
147
|
+
maxResults: { type: 'integer', description: 'Maximum startup/repository records to return.', default: 25 }
|
|
148
|
+
},
|
|
149
|
+
required: []
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: 'academic_patent_research_citation_intelligence',
|
|
154
|
+
actorSlug: 'gmpsignal~academic-patent-research-citation-intelligence',
|
|
155
|
+
description: 'Search peer-reviewed scientific papers, citation velocity, DOI metadata, and open-access PDFs across OpenAlex, Semantic Scholar, Crossref, and arXiv.',
|
|
156
|
+
inputSchema: {
|
|
157
|
+
type: 'object',
|
|
158
|
+
properties: {
|
|
159
|
+
query: { type: 'string', description: 'Scientific research topic, keyword, or author query.', default: 'autonomous AI agents' },
|
|
160
|
+
sources: { type: 'array', items: { type: 'string' }, description: 'Academic databases (openalex, semantic_scholar, arxiv, crossref).', default: ['openalex', 'semantic_scholar', 'arxiv'] },
|
|
161
|
+
minYear: { type: 'integer', description: 'Minimum publication year.', default: 2024 },
|
|
162
|
+
maxResults: { type: 'integer', description: 'Maximum papers to return.', default: 20 }
|
|
163
|
+
},
|
|
164
|
+
required: ['query']
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: 'shopify_global_store_products_scraper',
|
|
169
|
+
actorSlug: 'gmpsignal~shopify-global-store-products-scraper',
|
|
170
|
+
description: 'Extract complete product catalogs, SKU variants, stock availability, compare-at prices, and discount percentages from any global Shopify store domain.',
|
|
171
|
+
inputSchema: {
|
|
172
|
+
type: 'object',
|
|
173
|
+
properties: {
|
|
174
|
+
stores: { type: 'array', items: { type: 'string' }, description: 'Shopify store domains (e.g., allbirds.com, kyliecosmetics.com).', default: ['allbirds.com', 'kyliecosmetics.com'] },
|
|
175
|
+
searchKeyword: { type: 'string', description: 'Optional keyword filter for product title or tags.', default: '' },
|
|
176
|
+
onlyInStock: { type: 'boolean', description: 'Return only in-stock products.', default: false },
|
|
177
|
+
maxProductsPerStore: { type: 'integer', description: 'Maximum products per store.', default: 15 },
|
|
178
|
+
maxResults: { type: 'integer', description: 'Maximum total products to return.', default: 30 }
|
|
179
|
+
},
|
|
180
|
+
required: ['stores']
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
name: 'global_product_recalls_monitor',
|
|
185
|
+
actorSlug: 'gmpsignal~global-product-recalls',
|
|
186
|
+
description: 'Monitor consumer product safety recalls across US CPSC, USDA FSIS, and European Safety Gate (RAPEX) alerts.',
|
|
187
|
+
inputSchema: {
|
|
188
|
+
type: 'object',
|
|
189
|
+
properties: {
|
|
190
|
+
sources: { type: 'array', items: { type: 'string' }, description: 'Recall authorities (cpsc, fsis, eu).', default: ['cpsc', 'eu'] },
|
|
191
|
+
maxResults: { type: 'integer', description: 'Maximum recall alerts to return.', default: 25 }
|
|
192
|
+
},
|
|
193
|
+
required: []
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: 'earthquake_monitor_usgs_emsc_afad',
|
|
198
|
+
actorSlug: 'gmpsignal~earthquake-monitor-usgs-emsc-afad',
|
|
199
|
+
description: 'Track cross-verified global and regional seismic events in real time across USGS, EMSC, and AFAD networks.',
|
|
200
|
+
inputSchema: {
|
|
201
|
+
type: 'object',
|
|
202
|
+
properties: {
|
|
203
|
+
minMagnitude: { type: 'string', description: 'Minimum Richter magnitude threshold (e.g., "3.0", "4.5").', default: '4.5' },
|
|
204
|
+
maxResults: { type: 'integer', description: 'Maximum seismic events to return.', default: 25 }
|
|
205
|
+
},
|
|
206
|
+
required: []
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: 'eu_ted_public_tenders_scraper',
|
|
211
|
+
actorSlug: 'gmpsignal~eu-ted-tenders-scraper',
|
|
212
|
+
description: 'Search European Union Tenders Electronic Daily (TED) public procurement notices, CPV codes, contracting authorities, and official PDF/HTML links.',
|
|
213
|
+
inputSchema: {
|
|
214
|
+
type: 'object',
|
|
215
|
+
properties: {
|
|
216
|
+
searchQuery: { type: 'string', description: 'Procurement keyword or CPV topic.', default: 'software' },
|
|
217
|
+
maxResults: { type: 'integer', description: 'Maximum tender notices to return.', default: 25 }
|
|
218
|
+
},
|
|
219
|
+
required: []
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: 'fda_warning_letters_compliance_scraper',
|
|
224
|
+
actorSlug: 'gmpsignal~fda-warning-letters-scraper',
|
|
225
|
+
description: 'Monitor US FDA pharmaceutical, medical device, biologics, and food GMP inspection warning letters and violation categories.',
|
|
226
|
+
inputSchema: {
|
|
227
|
+
type: 'object',
|
|
228
|
+
properties: {
|
|
229
|
+
searchKeyword: { type: 'string', description: 'Optional company name or violation keyword.', default: '' },
|
|
230
|
+
maxResults: { type: 'integer', description: 'Maximum warning letters to return.', default: 25 }
|
|
231
|
+
},
|
|
232
|
+
required: []
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
name: 'pazar3_merrjep_balkan_classifieds_scraper',
|
|
237
|
+
actorSlug: 'gmpsignal~pazar3-merrjep-balkan-scraper',
|
|
238
|
+
description: 'Extract real estate, vehicles, and marketplace listings across North Macedonia (Pazar3.mk), Kosovo (MerrJep.com), and Albania (MerrJep.al).',
|
|
239
|
+
inputSchema: {
|
|
240
|
+
type: 'object',
|
|
241
|
+
properties: {
|
|
242
|
+
country: { type: 'string', description: 'Target country code (mk, xk, al).', default: 'mk' },
|
|
243
|
+
category: { type: 'string', description: 'Category slug (cars, real-estate, electronics).', default: 'cars' },
|
|
244
|
+
maxItems: { type: 'integer', description: 'Maximum classified listings to return.', default: 25 }
|
|
245
|
+
},
|
|
246
|
+
required: []
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
name: 'turkey_real_estate_listings_scraper',
|
|
251
|
+
actorSlug: 'gmpsignal~hepsiemlak-scraper-turkey-real-estate-listings',
|
|
252
|
+
description: 'Extract residential and commercial real estate listings, square-meter pricing, and agent details across regional cities.',
|
|
253
|
+
inputSchema: {
|
|
254
|
+
type: 'object',
|
|
255
|
+
properties: {
|
|
256
|
+
city: { type: 'string', description: 'Target city slug (e.g., istanbul, ankara, izmir).', default: 'istanbul' },
|
|
257
|
+
category: { type: 'string', description: 'Listing type category slug.', default: 'sale' },
|
|
258
|
+
maxItems: { type: 'integer', description: 'Maximum property listings to return.', default: 20 }
|
|
259
|
+
},
|
|
260
|
+
required: []
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
name: 'sec_edgar_filings_scraper',
|
|
265
|
+
actorSlug: 'gmpsignal~sec-edgar-filings',
|
|
266
|
+
description: 'Fetch official US SEC EDGAR corporate filings (10-K, 10-Q, 8-K, Form 4 insider transactions) by ticker, CIK, or form type.',
|
|
267
|
+
inputSchema: {
|
|
268
|
+
type: 'object',
|
|
269
|
+
properties: {
|
|
270
|
+
tickers: { type: 'array', items: { type: 'string' }, description: 'Stock tickers or CIK codes (e.g., AAPL, NVDA, MSFT).', default: ['AAPL', 'NVDA'] },
|
|
271
|
+
forms: { type: 'array', items: { type: 'string' }, description: 'SEC form types (10-K, 10-Q, 8-K, 4).', default: ['10-K', '10-Q', '8-K'] },
|
|
272
|
+
maxResults: { type: 'integer', description: 'Maximum filings to return.', default: 25 }
|
|
273
|
+
},
|
|
274
|
+
required: []
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
name: 'german_jobs_arbeitsagentur_scraper',
|
|
279
|
+
actorSlug: 'gmpsignal~german-jobs-scraper',
|
|
280
|
+
description: 'Search official German Federal Employment Agency (Bundesagentur fuer Arbeit) job vacancies, employers, and locations.',
|
|
281
|
+
inputSchema: {
|
|
282
|
+
type: 'object',
|
|
283
|
+
properties: {
|
|
284
|
+
searchQuery: { type: 'string', description: 'Job title, skill, or profession keyword.', default: 'Software Engineer' },
|
|
285
|
+
location: { type: 'string', description: 'City or region in Germany (e.g., Berlin, Munich).', default: 'Berlin' },
|
|
286
|
+
maxResults: { type: 'integer', description: 'Maximum job listings to return.', default: 25 }
|
|
287
|
+
},
|
|
288
|
+
required: []
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
name: 'fda_recalls_enforcement_monitor',
|
|
293
|
+
actorSlug: 'gmpsignal~fda-recalls-enforcement',
|
|
294
|
+
description: 'Query official US openFDA drug, medical device, and food recall enforcement reports.',
|
|
295
|
+
inputSchema: {
|
|
296
|
+
type: 'object',
|
|
297
|
+
properties: {
|
|
298
|
+
category: { type: 'string', description: 'Recall category (drug, device, food).', default: 'drug' },
|
|
299
|
+
maxResults: { type: 'integer', description: 'Maximum recall reports to return.', default: 25 }
|
|
300
|
+
},
|
|
301
|
+
required: []
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
name: 'njuskalo_croatia_classifieds_scraper',
|
|
306
|
+
actorSlug: 'gmpsignal~njuskalo-scraper',
|
|
307
|
+
description: 'Extract marketplace, automotive, and real estate listings from Njuskalo.hr in Croatia.',
|
|
308
|
+
inputSchema: {
|
|
309
|
+
type: 'object',
|
|
310
|
+
properties: {
|
|
311
|
+
query: { type: 'string', description: 'Search keyword on Njuskalo.hr.', default: 'iphone' },
|
|
312
|
+
maxItems: { type: 'integer', description: 'Maximum listings to return.', default: 25 }
|
|
313
|
+
},
|
|
314
|
+
required: []
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
name: 'bolha_slovenia_classifieds_scraper',
|
|
319
|
+
actorSlug: 'gmpsignal~bolha-scraper',
|
|
320
|
+
description: 'Extract marketplace, automotive, and real estate listings from Bolha.com in Slovenia.',
|
|
321
|
+
inputSchema: {
|
|
322
|
+
type: 'object',
|
|
323
|
+
properties: {
|
|
324
|
+
query: { type: 'string', description: 'Search keyword on Bolha.com.', default: 'macbook' },
|
|
325
|
+
maxItems: { type: 'integer', description: 'Maximum listings to return.', default: 25 }
|
|
326
|
+
},
|
|
327
|
+
required: []
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
name: 'olx_bosnia_marketplace_scraper',
|
|
332
|
+
actorSlug: 'gmpsignal~olx-ba-scraper',
|
|
333
|
+
description: 'Extract vehicles, real estate, and consumer goods listings from OLX.ba in Bosnia and Herzegovina.',
|
|
334
|
+
inputSchema: {
|
|
335
|
+
type: 'object',
|
|
336
|
+
properties: {
|
|
337
|
+
query: { type: 'string', description: 'Search keyword on OLX.ba.', default: 'golf' },
|
|
338
|
+
maxItems: { type: 'integer', description: 'Maximum listings to return.', default: 25 }
|
|
339
|
+
},
|
|
340
|
+
required: []
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
name: 'turkey_crypto_exchange_prices_monitor',
|
|
345
|
+
actorSlug: 'gmpsignal~turkey-crypto-exchange-prices',
|
|
346
|
+
description: 'Monitor TRY and USDT cryptocurrency trading pairs, 24h volume, and order book spreads across Turkish crypto exchanges (BtcTurk, Paribu).',
|
|
347
|
+
inputSchema: {
|
|
348
|
+
type: 'object',
|
|
349
|
+
properties: {
|
|
350
|
+
quoteCurrency: { type: 'string', description: 'Quote currency filter (TRY, USDT, ALL).', default: 'TRY' },
|
|
351
|
+
maxResults: { type: 'integer', description: 'Maximum ticker records to return.', default: 50 }
|
|
352
|
+
},
|
|
353
|
+
required: []
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
name: 'halooglasi_serbia_classifieds_scraper',
|
|
358
|
+
actorSlug: 'gmpsignal~halooglasi-serbia-scraper',
|
|
359
|
+
description: 'Extract real estate, apartments, and automotive classifieds from HaloOglasi.com in Serbia.',
|
|
360
|
+
inputSchema: {
|
|
361
|
+
type: 'object',
|
|
362
|
+
properties: {
|
|
363
|
+
category: { type: 'string', description: 'Category path or keyword on HaloOglasi.', default: 'nekretnine' },
|
|
364
|
+
maxItems: { type: 'integer', description: 'Maximum listings to return.', default: 25 }
|
|
365
|
+
},
|
|
366
|
+
required: []
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
name: 'kupujemprodajem_serbia_marketplace_scraper',
|
|
371
|
+
actorSlug: 'gmpsignal~kupujemprodajem-scraper',
|
|
372
|
+
description: 'Search and extract product listings, prices, and seller details from KupujemProdajem.com in Serbia.',
|
|
373
|
+
inputSchema: {
|
|
374
|
+
type: 'object',
|
|
375
|
+
properties: {
|
|
376
|
+
keywords: { type: 'string', description: 'Search keyword on KupujemProdajem.', default: 'iphone' },
|
|
377
|
+
maxItems: { type: 'integer', description: 'Maximum listings to return.', default: 25 }
|
|
378
|
+
},
|
|
379
|
+
required: []
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
name: 'turkey_gold_and_bank_bullion_prices',
|
|
384
|
+
actorSlug: 'gmpsignal~turkey-gold-prices',
|
|
385
|
+
description: 'Fetch live Turkish gold prices (Gram, Quarter, Half, Republic, Ons) and compare buy/sell spreads across 35 commercial banks.',
|
|
386
|
+
inputSchema: {
|
|
387
|
+
type: 'object',
|
|
388
|
+
properties: {
|
|
389
|
+
includeBanks: { type: 'boolean', description: 'Include 35 bank gold buy/sell spread comparisons.', default: true }
|
|
390
|
+
},
|
|
391
|
+
required: []
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
name: 'turkey_weather_mgm_official_forecast',
|
|
396
|
+
actorSlug: 'gmpsignal~turkey-weather-mgm-official',
|
|
397
|
+
description: 'Retrieve official Turkish State Meteorological Service (MGM) current weather observations and 5-day forecasts across 81 provinces.',
|
|
398
|
+
inputSchema: {
|
|
399
|
+
type: 'object',
|
|
400
|
+
properties: {
|
|
401
|
+
provinces: { type: 'array', items: { type: 'string' }, description: 'List of Turkish provinces (e.g., istanbul, ankara, izmir, antalya).', default: ['istanbul', 'ankara', 'izmir'] }
|
|
402
|
+
},
|
|
403
|
+
required: []
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
name: 'europe_mediterranean_earthquakes_emsc',
|
|
408
|
+
actorSlug: 'gmpsignal~europe-mediterranean-earthquakes-emsc-official-data',
|
|
409
|
+
description: 'Fetch real-time European and Mediterranean seismic events, epicenter coordinates, depths, and magnitudes from EMSC.',
|
|
410
|
+
inputSchema: {
|
|
411
|
+
type: 'object',
|
|
412
|
+
properties: {
|
|
413
|
+
minMagnitude: { type: 'number', description: 'Minimum earthquake magnitude.', default: 2.5 },
|
|
414
|
+
maxResults: { type: 'integer', description: 'Maximum seismic events to return.', default: 30 }
|
|
415
|
+
},
|
|
416
|
+
required: []
|
|
417
|
+
}
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
name: 'islamic_prayer_times_worldwide_calendars',
|
|
421
|
+
actorSlug: 'gmpsignal~islamic-prayer-times-worldwide-monthly-calendars',
|
|
422
|
+
description: 'Calculate daily and monthly astronomical Islamic prayer times (Fajr, Sunrise, Dhuhr, Asr, Maghrib, Isha) and Qibla direction for any global city.',
|
|
423
|
+
inputSchema: {
|
|
424
|
+
type: 'object',
|
|
425
|
+
properties: {
|
|
426
|
+
city: { type: 'string', description: 'Target city name (e.g., Istanbul, London, Mecca).', default: 'Istanbul' },
|
|
427
|
+
country: { type: 'string', description: 'Target country name.', default: 'Turkey' }
|
|
428
|
+
},
|
|
429
|
+
required: []
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
name: 'turkey_on_duty_pharmacies_directory',
|
|
434
|
+
actorSlug: 'gmpsignal~turkey-on-duty-pharmacies-nobetci-eczane-daily',
|
|
435
|
+
description: 'Find daily emergency on-duty pharmacies with addresses, phone numbers, and map coordinates across provinces and districts.',
|
|
436
|
+
inputSchema: {
|
|
437
|
+
type: 'object',
|
|
438
|
+
properties: {
|
|
439
|
+
city: { type: 'string', description: 'Province name (e.g., istanbul, ankara, izmir).', default: 'istanbul' },
|
|
440
|
+
district: { type: 'string', description: 'Optional district filter (e.g., kadikoy, besiktas).', default: '' }
|
|
441
|
+
},
|
|
442
|
+
required: []
|
|
443
|
+
}
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
name: 'tcmb_official_central_bank_fx_rates',
|
|
447
|
+
actorSlug: 'gmpsignal~tcmb-exchange-rates-official-turkish-central-bank-fx',
|
|
448
|
+
description: 'Fetch official Central Bank (TCMB) daily foreign exchange buying, selling, bank-note, and cross rates.',
|
|
449
|
+
inputSchema: {
|
|
450
|
+
type: 'object',
|
|
451
|
+
properties: {
|
|
452
|
+
currencies: { type: 'array', items: { type: 'string' }, description: 'ISO currency codes (e.g., USD, EUR, GBP, CHF, JPY).', default: ['USD', 'EUR', 'GBP'] }
|
|
453
|
+
},
|
|
454
|
+
required: []
|
|
455
|
+
}
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
name: 'turkey_fuel_prices_81_provinces_daily',
|
|
459
|
+
actorSlug: 'gmpsignal~turkey-fuel-prices-81-provinces-daily-benzin-motorin-lpg',
|
|
460
|
+
description: 'Retrieve daily retail gasoline, diesel, and autogas (LPG) pump prices across all 81 provinces.',
|
|
461
|
+
inputSchema: {
|
|
462
|
+
type: 'object',
|
|
463
|
+
properties: {
|
|
464
|
+
provinces: { type: 'array', items: { type: 'string' }, description: 'Provinces to query (e.g., istanbul, ankara, izmir).', default: ['istanbul', 'ankara', 'izmir'] }
|
|
465
|
+
},
|
|
466
|
+
required: []
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
name: 'turkey_car_rental_prices_index',
|
|
471
|
+
actorSlug: 'gmpsignal~turkey-car-rental-prices-city-airport-index',
|
|
472
|
+
description: 'Compare daily car rental fleet prices, vehicle classes, transmission types, and supplier ratings across airports and cities.',
|
|
473
|
+
inputSchema: {
|
|
474
|
+
type: 'object',
|
|
475
|
+
properties: {
|
|
476
|
+
locations: { type: 'array', items: { type: 'string' }, description: 'Pickup locations or airports (e.g., istanbul, antalya).', default: ['istanbul'] }
|
|
477
|
+
},
|
|
478
|
+
required: []
|
|
479
|
+
}
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
name: 'turkey_hotels_explorer_ratings_amenities',
|
|
483
|
+
actorSlug: 'gmpsignal~turkey-hotels-explorer-ratings-amenities',
|
|
484
|
+
description: 'Extract hotel nightly rates, guest review scores, star ratings, board types, and amenities across Turkish destinations.',
|
|
485
|
+
inputSchema: {
|
|
486
|
+
type: 'object',
|
|
487
|
+
properties: {
|
|
488
|
+
cities: { type: 'array', items: { type: 'string' }, description: 'Target destination cities (e.g., istanbul, antalya, bodrum).', default: ['istanbul'] },
|
|
489
|
+
maxHotelsPerCity: { type: 'integer', description: 'Maximum hotels to return per city.', default: 25 }
|
|
490
|
+
},
|
|
491
|
+
required: []
|
|
492
|
+
}
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
name: 'turkey_earthquakes_afad_official_feed',
|
|
496
|
+
actorSlug: 'gmpsignal~turkey-earthquakes-afad-official-data',
|
|
497
|
+
description: 'Retrieve official AFAD (Disaster and Emergency Management Authority) real-time earthquake records across Turkey and neighboring regions.',
|
|
498
|
+
inputSchema: {
|
|
499
|
+
type: 'object',
|
|
500
|
+
properties: {
|
|
501
|
+
minMagnitude: { type: 'number', description: 'Minimum earthquake magnitude filter.', default: 2.0 },
|
|
502
|
+
maxResults: { type: 'integer', description: 'Maximum earthquake events to return.', default: 30 }
|
|
503
|
+
},
|
|
504
|
+
required: []
|
|
505
|
+
}
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
name: 'turkey_domestic_flight_prices_aggregator',
|
|
509
|
+
actorSlug: 'gmpsignal~turkey-domestic-flight-prices',
|
|
510
|
+
description: 'Compare domestic and regional airline ticket fares, departure/arrival times, baggage allowances, and carriers (THY, Pegasus, AJet).',
|
|
511
|
+
inputSchema: {
|
|
512
|
+
type: 'object',
|
|
513
|
+
properties: {
|
|
514
|
+
origin: { type: 'string', description: 'Origin city or airport slug (e.g., istanbul).', default: 'istanbul' },
|
|
515
|
+
destination: { type: 'string', description: 'Destination city or airport slug (e.g., izmir, antalya).', default: 'izmir' }
|
|
516
|
+
},
|
|
517
|
+
required: []
|
|
518
|
+
}
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
name: 'social_community_forum_entries_scraper',
|
|
522
|
+
actorSlug: 'gmpsignal~eksi-sozluk-scraper-entries-trending',
|
|
523
|
+
description: 'Extract trending discussion topics, user entries, favorite counts, and community sentiment data.',
|
|
524
|
+
inputSchema: {
|
|
525
|
+
type: 'object',
|
|
526
|
+
properties: {
|
|
527
|
+
includeTrending: { type: 'boolean', description: 'Scrape current trending topics.', default: true },
|
|
528
|
+
maxEntriesPerTopic: { type: 'integer', description: 'Maximum entries per topic.', default: 20 }
|
|
529
|
+
},
|
|
530
|
+
required: []
|
|
531
|
+
}
|
|
532
|
+
},
|
|
533
|
+
{
|
|
534
|
+
name: 'turkey_greek_islands_ferry_schedules',
|
|
535
|
+
actorSlug: 'gmpsignal~turkey-greek-islands-ferry-schedules',
|
|
536
|
+
description: 'Fetch maritime ferry timetables, operators, sailing durations, and ticket prices across Aegean, Marmara, and Greek Island routes.',
|
|
537
|
+
inputSchema: {
|
|
538
|
+
type: 'object',
|
|
539
|
+
properties: {
|
|
540
|
+
routes: { type: 'array', items: { type: 'string' }, description: 'Route slugs (e.g., yenikapi-mudanya, bodrum-kos).', default: ['yenikapi-mudanya'] }
|
|
541
|
+
},
|
|
542
|
+
required: []
|
|
543
|
+
}
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
name: 'turkey_bus_routes_and_ticket_prices',
|
|
547
|
+
actorSlug: 'gmpsignal~turkey-bus-routes-prices',
|
|
548
|
+
description: 'Extract intercity bus schedules, coach operators, departure/arrival terminals, seat configurations, and TRY ticket prices across Turkey.',
|
|
549
|
+
inputSchema: {
|
|
550
|
+
type: 'object',
|
|
551
|
+
properties: {
|
|
552
|
+
routes: { type: 'array', items: { type: 'string' }, description: 'Intercity route pairs (e.g., istanbul-ankara, izmir-antalya).', default: ['istanbul-ankara'] }
|
|
553
|
+
},
|
|
554
|
+
required: []
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
];
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Executes an Apify Actor synchronously via REST API v2 when a tool is invoked.
|
|
561
|
+
*
|
|
562
|
+
* @param {string} actorSlug - Target Apify Actor slug (`gmpsignal~...`).
|
|
563
|
+
* @param {Object} args - Tool input arguments.
|
|
564
|
+
* @returns {Promise<Array<Object>>} Dataset items returned by the Actor run.
|
|
565
|
+
*/
|
|
566
|
+
async function invokeApifyActor(actorSlug, args) {
|
|
567
|
+
const token = process.env.APIFY_TOKEN || '';
|
|
568
|
+
if (!token) {
|
|
569
|
+
throw new Error('APIFY_TOKEN environment variable is required to execute live Apify Actor runs. Get your token at https://console.apify.com/settings/integrations');
|
|
570
|
+
}
|
|
571
|
+
const url = `https://api.apify.com/v2/acts/${encodeURIComponent(actorSlug)}/run-sync-get-dataset-items?token=${encodeURIComponent(token)}`;
|
|
572
|
+
const response = await fetch(url, {
|
|
573
|
+
method: 'POST',
|
|
574
|
+
headers: {
|
|
575
|
+
'Content-Type': 'application/json',
|
|
576
|
+
'Accept': 'application/json'
|
|
577
|
+
},
|
|
578
|
+
body: JSON.stringify(args || {})
|
|
579
|
+
});
|
|
580
|
+
if (!response.ok) {
|
|
581
|
+
const errBody = await response.text();
|
|
582
|
+
throw new Error(`Apify Actor ${actorSlug} returned HTTP ${response.status}: ${errBody}`);
|
|
583
|
+
}
|
|
584
|
+
return await response.json();
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Sends a JSON-RPC 2.0 response over stdout.
|
|
589
|
+
*
|
|
590
|
+
* @param {string|number|null} id - Request ID.
|
|
591
|
+
* @param {Object} result - Result payload.
|
|
592
|
+
*/
|
|
593
|
+
function sendJsonRpcResult(id, result) {
|
|
594
|
+
const payload = {
|
|
595
|
+
jsonrpc: '2.0',
|
|
596
|
+
id,
|
|
597
|
+
result
|
|
598
|
+
};
|
|
599
|
+
process.stdout.write(`${JSON.stringify(payload)}\n`);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Sends a JSON-RPC 2.0 error over stdout.
|
|
14
604
|
*
|
|
15
|
-
* @param {
|
|
16
|
-
* @
|
|
605
|
+
* @param {string|number|null} id - Request ID.
|
|
606
|
+
* @param {number} code - JSON-RPC error code.
|
|
607
|
+
* @param {string} message - Error description.
|
|
17
608
|
*/
|
|
18
|
-
function
|
|
609
|
+
function sendJsonRpcError(id, code, message) {
|
|
610
|
+
const payload = {
|
|
611
|
+
jsonrpc: '2.0',
|
|
612
|
+
id,
|
|
613
|
+
error: {
|
|
614
|
+
code,
|
|
615
|
+
message
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
process.stdout.write(`${JSON.stringify(payload)}\n`);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Handles an incoming JSON-RPC 2.0 message from the MCP host or inspection harness.
|
|
623
|
+
*
|
|
624
|
+
* @param {Object} message - Parsed JSON-RPC 2.0 message.
|
|
625
|
+
* @returns {Promise<void>}
|
|
626
|
+
*/
|
|
627
|
+
async function handleJsonRpcMessage(message) {
|
|
628
|
+
if (!message || typeof message !== 'object') {
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
const { id, method, params } = message;
|
|
633
|
+
|
|
634
|
+
if (method === 'initialize') {
|
|
635
|
+
sendJsonRpcResult(id, {
|
|
636
|
+
protocolVersion: (params && params.protocolVersion) ? params.protocolVersion : '2024-11-05',
|
|
637
|
+
capabilities: {
|
|
638
|
+
tools: { listChanged: false },
|
|
639
|
+
resources: { subscribe: false, listChanged: false },
|
|
640
|
+
prompts: { listChanged: false }
|
|
641
|
+
},
|
|
642
|
+
serverInfo: {
|
|
643
|
+
name: 'gmpsignal-mcp-server',
|
|
644
|
+
version: '1.2.0'
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
if (method === 'notifications/initialized' || method === 'initialized') {
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
if (method === 'ping') {
|
|
655
|
+
sendJsonRpcResult(id, {});
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
if (method === 'tools/list') {
|
|
660
|
+
sendJsonRpcResult(id, {
|
|
661
|
+
tools: MCP_TOOL_DEFINITIONS.map((t) => ({
|
|
662
|
+
name: t.name,
|
|
663
|
+
description: t.description,
|
|
664
|
+
inputSchema: t.inputSchema
|
|
665
|
+
}))
|
|
666
|
+
});
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
if (method === 'resources/list') {
|
|
671
|
+
sendJsonRpcResult(id, {
|
|
672
|
+
resources: [
|
|
673
|
+
{
|
|
674
|
+
uri: 'mcp://gmpsignal/actors-catalog',
|
|
675
|
+
name: 'GMPSignal 40-Actor Enterprise Intelligence Suite Catalog',
|
|
676
|
+
description: 'Complete list of 40 Apify Actors organized across Crypto/Quant, B2B/E-Commerce, KYB/Cyber/Regulatory, and Regional suites.',
|
|
677
|
+
mimeType: 'application/json'
|
|
678
|
+
}
|
|
679
|
+
]
|
|
680
|
+
});
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
if (method === 'resources/read') {
|
|
685
|
+
const uri = params && params.uri ? params.uri : 'mcp://gmpsignal/actors-catalog';
|
|
686
|
+
sendJsonRpcResult(id, {
|
|
687
|
+
contents: [
|
|
688
|
+
{
|
|
689
|
+
uri,
|
|
690
|
+
mimeType: 'application/json',
|
|
691
|
+
text: JSON.stringify(GMPSIGNAL_SUITES, null, 2)
|
|
692
|
+
}
|
|
693
|
+
]
|
|
694
|
+
});
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
if (method === 'prompts/list') {
|
|
699
|
+
sendJsonRpcResult(id, {
|
|
700
|
+
prompts: [
|
|
701
|
+
{
|
|
702
|
+
name: 'crypto_token_due_diligence',
|
|
703
|
+
description: 'Perform smart-contract rugpull auditing and multi-exchange order book slippage analysis on a target crypto token.',
|
|
704
|
+
arguments: [
|
|
705
|
+
{ name: 'tokenSymbol', description: 'Token symbol or contract address (e.g., SOL, PEPE).', required: true },
|
|
706
|
+
{ name: 'chainId', description: 'Blockchain network (e.g., solana, ethereum, base).', required: false }
|
|
707
|
+
]
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
name: 'b2b_lead_and_kyb_compliance_check',
|
|
711
|
+
description: 'Enrich a company domain with tech-stack and contacts while screening the corporate entity against GLEIF LEI and global sanctions.',
|
|
712
|
+
arguments: [
|
|
713
|
+
{ name: 'domain', description: 'Company website domain (e.g., stripe.com).', required: true },
|
|
714
|
+
{ name: 'companyName', description: 'Legal entity name for KYB screening.', required: true }
|
|
715
|
+
]
|
|
716
|
+
}
|
|
717
|
+
]
|
|
718
|
+
});
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
if (method === 'prompts/get') {
|
|
723
|
+
const promptName = params && params.name ? params.name : 'crypto_token_due_diligence';
|
|
724
|
+
const promptArgs = (params && params.arguments) || {};
|
|
725
|
+
sendJsonRpcResult(id, {
|
|
726
|
+
description: `GMPSignal automated workflow prompt for ${promptName}`,
|
|
727
|
+
messages: [
|
|
728
|
+
{
|
|
729
|
+
role: 'user',
|
|
730
|
+
content: {
|
|
731
|
+
type: 'text',
|
|
732
|
+
text: `Execute the GMPSignal MCP tools for ${promptName} with parameters: ${JSON.stringify(promptArgs)}`
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
]
|
|
736
|
+
});
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
if (method === 'tools/call') {
|
|
741
|
+
const toolName = params && params.name;
|
|
742
|
+
const toolArgs = (params && params.arguments) || {};
|
|
743
|
+
const toolDef = MCP_TOOL_DEFINITIONS.find((t) => t.name === toolName);
|
|
744
|
+
if (!toolDef) {
|
|
745
|
+
sendJsonRpcError(id, -32602, `Unknown GMPSignal MCP tool: ${toolName}`);
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
try {
|
|
749
|
+
const items = await invokeApifyActor(toolDef.actorSlug, toolArgs);
|
|
750
|
+
sendJsonRpcResult(id, {
|
|
751
|
+
content: [
|
|
752
|
+
{
|
|
753
|
+
type: 'text',
|
|
754
|
+
text: JSON.stringify(items, null, 2)
|
|
755
|
+
}
|
|
756
|
+
],
|
|
757
|
+
isError: false
|
|
758
|
+
});
|
|
759
|
+
} catch (err) {
|
|
760
|
+
sendJsonRpcResult(id, {
|
|
761
|
+
content: [
|
|
762
|
+
{
|
|
763
|
+
type: 'text',
|
|
764
|
+
text: `Error executing ${toolDef.actorSlug}: ${err.message}`
|
|
765
|
+
}
|
|
766
|
+
],
|
|
767
|
+
isError: true
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
if (id !== undefined && id !== null) {
|
|
774
|
+
sendJsonRpcError(id, -32601, `Method not found: ${method}`);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* Parses CLI flags or starts the native JSON-RPC 2.0 MCP server over stdio.
|
|
780
|
+
*/
|
|
781
|
+
function main() {
|
|
782
|
+
const argv = process.argv.slice(2);
|
|
19
783
|
let suite = 'flagship';
|
|
20
|
-
let customActors = '';
|
|
21
784
|
let listOnly = false;
|
|
22
785
|
let printConfig = false;
|
|
23
786
|
|
|
@@ -26,9 +789,6 @@ function parseCliArgs(argv) {
|
|
|
26
789
|
if (arg === '--suite' && argv[i + 1]) {
|
|
27
790
|
suite = argv[i + 1];
|
|
28
791
|
i += 1;
|
|
29
|
-
} else if (arg === '--actors' && argv[i + 1]) {
|
|
30
|
-
customActors = argv[i + 1];
|
|
31
|
-
i += 1;
|
|
32
792
|
} else if (arg === '--list') {
|
|
33
793
|
listOnly = true;
|
|
34
794
|
} else if (arg === '--print-config') {
|
|
@@ -36,15 +796,6 @@ function parseCliArgs(argv) {
|
|
|
36
796
|
}
|
|
37
797
|
}
|
|
38
798
|
|
|
39
|
-
return { suite, customActors, listOnly, printConfig };
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Main CLI execution entry point.
|
|
44
|
-
*/
|
|
45
|
-
function main() {
|
|
46
|
-
const { suite, customActors, listOnly, printConfig } = parseCliArgs(process.argv.slice(2));
|
|
47
|
-
|
|
48
799
|
if (listOnly) {
|
|
49
800
|
console.log('GMPSignal 40-Actor Intelligence Suites (https://apify.com/gmpsignal):');
|
|
50
801
|
for (const [suiteKey, actorList] of Object.entries(GMPSIGNAL_SUITES)) {
|
|
@@ -62,23 +813,24 @@ function main() {
|
|
|
62
813
|
return;
|
|
63
814
|
}
|
|
64
815
|
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
:
|
|
816
|
+
const rl = readline.createInterface({
|
|
817
|
+
input: process.stdin,
|
|
818
|
+
terminal: false
|
|
819
|
+
});
|
|
68
820
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
{
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
821
|
+
rl.on('line', (line) => {
|
|
822
|
+
const trimmed = line.trim();
|
|
823
|
+
if (!trimmed) return;
|
|
824
|
+
try {
|
|
825
|
+
const parsed = JSON.parse(trimmed);
|
|
826
|
+
handleJsonRpcMessage(parsed).catch((err) => {
|
|
827
|
+
if (parsed && parsed.id !== undefined) {
|
|
828
|
+
sendJsonRpcError(parsed.id, -32603, err.message);
|
|
829
|
+
}
|
|
830
|
+
});
|
|
831
|
+
} catch (_err) {
|
|
832
|
+
sendJsonRpcError(null, -32700, 'Parse error');
|
|
77
833
|
}
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
child.on('exit', (code) => {
|
|
81
|
-
process.exitCode = code || 0;
|
|
82
834
|
});
|
|
83
835
|
}
|
|
84
836
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gmpsignal-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Official Model Context Protocol (MCP) Server & CLI Launcher for the GMPSignal 40-Actor Enterprise Data, Quantitative Crypto, Prediction Markets, B2B Enrichment, KYB/Sanctions, Cybersecurity & Regulatory Suite on Apify.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.mjs",
|