1const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js');
2const { SSEServerTransport } = require('@modelcontextprotocol/sdk/server/sse.js');
3const http = require('http');
4const { z } = require('zod');
5
6const API_BASE = 'https://israeli-business-api.vercel.app/api/v1/business';
7const API_KEY = process.env.API_SECRET_KEY || 'test-key-12345';
8
9async function callApi(path) {
10 const res = await fetch(`${API_BASE}${path}`, {
11 headers: { 'X-API-Key': API_KEY, 'Content-Type': 'application/json' },
12 });
13 return res.json();
14}
15
16async function callApiPost(path, body) {
17 const res = await fetch(`${API_BASE}${path}`, {
18 method: 'POST',
19 headers: { 'X-API-Key': API_KEY, 'Content-Type': 'application/json' },
20 body: JSON.stringify(body),
21 });
22 return res.json();
23}
24
25const server = new McpServer({
26 name: 'israeli-business-lookup',
27 version: '1.0.0',
28});
29
30
31server.tool(
32 'search_israeli_business',
33 'Search Israeli companies, nonprofits, partnerships, and cooperatives by name. 832K+ entities from 4 government registries.',
34 { name: z.string().describe('Company name (Hebrew or English)'), registry: z.enum(['companies', 'all']).default('all').describe('Search scope'), limit: z.number().default(10).describe('Max results') },
35 async ({ name, registry, limit }) => ({
36 content: [{ type: 'text', text: JSON.stringify(await callApi(`/search?name=${encodeURIComponent(name)}®istry=${registry}&limit=${limit}`), null, 2) }],
37 })
38);
39
40
41server.tool(
42 'lookup_israeli_company',
43 'Look up a specific Israeli company by registration number.',
44 { id: z.string().describe('Company registration number (e.g. 513695478)') },
45 async ({ id }) => ({
46 content: [{ type: 'text', text: JSON.stringify(await callApi(`/search?id=${id}`), null, 2) }],
47 })
48);
49
50
51server.tool(
52 'validate_israeli_id',
53 'Validate Israeli ID, company number, or nonprofit number using Luhn check digit.',
54 { id: z.string().describe('ID or company number to validate') },
55 async ({ id }) => ({
56 content: [{ type: 'text', text: JSON.stringify(await callApi(`/validate?id=${id}`), null, 2) }],
57 })
58);
59
60
61server.tool(
62 'israeli_company_risk_score',
63 'Risk score 0-100 for Israeli company. Checks: status, violator flag, reporting, age, government ownership.',
64 { id: z.string().describe('Company registration number') },
65 async ({ id }) => ({
66 content: [{ type: 'text', text: JSON.stringify(await callApi(`/risk?id=${id}`), null, 2) }],
67 })
68);
69
70
71server.tool(
72 'enrich_israeli_company',
73 'Full intelligence: registry data + validation + risk score + age + size + address. One call for KYB/due diligence.',
74 { id: z.string().describe('Company registration number') },
75 async ({ id }) => ({
76 content: [{ type: 'text', text: JSON.stringify(await callApi(`/enrich?id=${id}`), null, 2) }],
77 })
78);
79
80
81server.tool(
82 'israeli_company_phone',
83 'Get phone number, website, Google rating for an Israeli company.',
84 { id: z.string().describe('Company registration number') },
85 async ({ id }) => ({
86 content: [{ type: 'text', text: JSON.stringify(await callApi(`/phone?id=${id}`), null, 2) }],
87 })
88);
89
90
91server.tool(
92 'bulk_lookup_israeli_companies',
93 'Look up multiple companies by registration numbers. Max 100 IDs.',
94 { ids: z.array(z.number()).describe('Array of company registration numbers') },
95 async ({ ids }) => ({
96 content: [{ type: 'text', text: JSON.stringify(await callApiPost('/bulk', { ids }), null, 2) }],
97 })
98);
99
100
101server.tool(
102 'batch_validate_israeli_ids',
103 'Validate multiple IDs at once. Max 500.',
104 { ids: z.array(z.string()).describe('Array of IDs to validate') },
105 async ({ ids }) => ({
106 content: [{ type: 'text', text: JSON.stringify(await callApiPost('/validate', { ids }), null, 2) }],
107 })
108);
109
110
111const PORT = process.env.PORT || 3000;
112const transports = new Map();
113
114const httpServer = http.createServer(async (req, res) => {
115 const url = new URL(req.url, `http://localhost:${PORT}`);
116
117 if (url.pathname === '/' || url.pathname === '/health') {
118 res.writeHead(200, { 'Content-Type': 'application/json' });
119 res.end(JSON.stringify({ name: 'israeli-business-lookup', version: '1.0.0', status: 'ok', tools: 8 }));
120 return;
121 }
122
123 if (url.pathname === '/sse' || url.pathname === '/mcp') {
124 const transport = new SSEServerTransport('/messages', res);
125 transports.set(transport, true);
126 res.on('close', () => transports.delete(transport));
127 await server.connect(transport);
128 return;
129 }
130
131 if (url.pathname === '/messages') {
132 for (const [transport] of transports) {
133 await transport.handlePostMessage(req, res);
134 return;
135 }
136 res.writeHead(404);
137 res.end('Session not found');
138 return;
139 }
140
141 res.writeHead(404);
142 res.end('Not found');
143});
144
145httpServer.listen(PORT, () => {
146 console.log(`Israeli Business Lookup MCP Server on port ${PORT}`);
147 console.log(`MCP: http://localhost:${PORT}/mcp`);
148 console.log(`8 tools ready`);
149});