vat-validator-mcp 2.0.23 → 2.0.25

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vat-validator-mcp",
3
3
  "mcpName": "io.github.OjasKord/vat-validator-mcp",
4
- "version": "2.0.23",
4
+ "version": "2.0.25",
5
5
  "description": "VAT number validator for AI agents. EU VIES, UK HMRC, AU ABR. Fraud risk scoring and name cross-check. PROCEED/HOLD verdict before any invoice payment.",
6
6
  "main": "src/server.js",
7
7
  "scripts": {
package/server.json CHANGED
@@ -1,26 +1,48 @@
1
- {
2
- "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
- "name": "io.github.OjasKord/vat-validator-mcp",
4
- "title": "VAT Validator MCP",
5
- "description": "Validate EU, UK, AU VAT numbers for AI agents. EU ViDA e-invoicing compliance.",
6
- "version": "2.0.4",
7
- "websiteUrl": "https://kordagencies.com",
8
- "repository": {
9
- "url": "https://github.com/OjasKord/vat-validator-mcp",
10
- "source": "github"
11
- },
12
- "packages": [
13
- {
14
- "registryType": "npm",
15
- "identifier": "vat-validator-mcp",
16
- "version": "2.0.4",
17
- "transport": { "type": "stdio" },
18
- "environmentVariables": [
19
- { "name": "ANTHROPIC_API_KEY", "description": "Anthropic API key for AI-powered fraud risk analysis", "isRequired": true, "isSecret": true },
20
- { "name": "HMRC_CLIENT_ID", "description": "HMRC Developer Hub client ID for UK VAT validation", "isRequired": false, "isSecret": true },
21
- { "name": "HMRC_CLIENT_SECRET", "description": "HMRC Developer Hub client secret for UK VAT validation", "isRequired": false, "isSecret": true }
22
- ]
23
- }
24
- ],
25
- "remotes": [{ "type": "streamable-http", "url": "https://vat-validator-mcp-production.up.railway.app" }]
26
- }
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.OjasKord/vat-validator-mcp",
4
+ "title": "VAT Validator MCP",
5
+ "description": "Validate EU, UK, AU VAT numbers for AI agents. EU ViDA e-invoicing compliance.",
6
+ "version": "2.0.23",
7
+ "websiteUrl": "https://kordagencies.com",
8
+ "repository": {
9
+ "url": "https://github.com/OjasKord/vat-validator-mcp",
10
+ "source": "github"
11
+ },
12
+ "packages": [
13
+ {
14
+ "registryType": "npm",
15
+ "identifier": "vat-validator-mcp",
16
+ "version": "2.0.23",
17
+ "transport": {
18
+ "type": "stdio"
19
+ },
20
+ "environmentVariables": [
21
+ {
22
+ "name": "ANTHROPIC_API_KEY",
23
+ "description": "Anthropic API key for AI-powered fraud risk analysis",
24
+ "isRequired": true,
25
+ "isSecret": true
26
+ },
27
+ {
28
+ "name": "HMRC_CLIENT_ID",
29
+ "description": "HMRC Developer Hub client ID for UK VAT validation",
30
+ "isRequired": false,
31
+ "isSecret": true
32
+ },
33
+ {
34
+ "name": "HMRC_CLIENT_SECRET",
35
+ "description": "HMRC Developer Hub client secret for UK VAT validation",
36
+ "isRequired": false,
37
+ "isSecret": true
38
+ }
39
+ ]
40
+ }
41
+ ],
42
+ "remotes": [
43
+ {
44
+ "type": "streamable-http",
45
+ "url": "https://vat-validator-mcp-production.up.railway.app"
46
+ }
47
+ ]
48
+ }
package/src/server.js CHANGED
@@ -7,7 +7,7 @@ const Stripe = require('stripe');
7
7
  const stripe = Stripe(process.env.STRIPE_SECRET_KEY);
8
8
 
9
9
  const PERSIST_FILE = '/tmp/vat_stats.json';
10
- const VERSION = '2.0.23';
10
+ const VERSION = '2.0.25';
11
11
 
12
12
  // Persistent device ID for HMRC fraud prevention headers (BATCH_PROCESS_DIRECT)
13
13
  const DEVICE_ID_FILE = path.join(__dirname, '..', 'device-id.txt');
@@ -28,6 +28,7 @@ const FREE_TIER_LIMIT = 50;
28
28
  const METERED_SUBSCRIBE_URL = 'https://vat-validator-mcp-production.up.railway.app/subscribe';
29
29
  const BUNDLE_500_URL = 'https://buy.stripe.com/28EeVceUB06N1ty3teebu0l';
30
30
  const BUNDLE_2000_URL = 'https://buy.stripe.com/00w14m7s96vb1ty5Bmebu0m';
31
+ const ALLOWED_PAYMENT_LINK_IDS = ['plink_1TQz5UD6WvRe6sn3I1GPShmC', 'plink_1TQz6rD6WvRe6sn3mqxD0Gy8'];
31
32
 
32
33
  const freeTierUsage = new Map();
33
34
  const usageLog = [];
@@ -226,8 +227,11 @@ async function sendEmail(to, subject, html) {
226
227
  const req = https.request({
227
228
  hostname: 'api.resend.com', path: '/emails', method: 'POST',
228
229
  headers: { 'Authorization': 'Bearer ' + RESEND_API_KEY, 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) }
229
- }, res => { let d = ''; res.on('data', c => d += c); res.on('end', () => resolve({ status: res.statusCode, body: d })); });
230
- req.on('error', e => resolve({ error: e.message }));
230
+ }, res => { let d = ''; res.on('data', c => d += c); res.on('end', () => {
231
+ if (res.statusCode < 200 || res.statusCode >= 300) console.error('[Resend] Email failed: HTTP ' + res.statusCode + ' ' + d);
232
+ resolve({ status: res.statusCode, body: d });
233
+ }); });
234
+ req.on('error', e => { console.error('[Resend] Email network error:', e.message); resolve({ error: e.message }); });
231
235
  req.write(body); req.end();
232
236
  });
233
237
  }
@@ -713,6 +717,11 @@ async function handleStripeWebhook(body, sig) {
713
717
  const event = JSON.parse(body);
714
718
  if (event.type === 'checkout.session.completed') {
715
719
  const session = event.data.object;
720
+ const paymentLinkId = session.payment_link;
721
+ if (paymentLinkId && !ALLOWED_PAYMENT_LINK_IDS.includes(paymentLinkId)) {
722
+ console.log('[vat] Webhook received but payment link ' + paymentLinkId + ' not for this server — ignoring.');
723
+ return { received: true, ignored: true };
724
+ }
716
725
  const plan = getPlanFromProduct(session.metadata?.product_name);
717
726
  const apiKey = generateApiKey();
718
727
  const limit = plan === 'metered' ? null : plan === 'bundle_2000' ? 2000 : 500;
@@ -727,7 +736,11 @@ async function handleStripeWebhook(body, sig) {
727
736
  };
728
737
  apiKeys.set(apiKey, record);
729
738
  await saveKeyToRedis(apiKey, record, REDIS_PREFIX);
730
- await sendApiKeyEmail(record.email, apiKey, plan);
739
+ if (record.email && record.email !== 'unknown') {
740
+ await sendApiKeyEmail(record.email, apiKey, plan);
741
+ } else {
742
+ console.error('[vat] No customer email in webhook — skipping email send');
743
+ }
731
744
  console.log('[vat] API key created for ' + record.email + ' (' + plan + ')');
732
745
  return { success: true, email: record.email, plan };
733
746
  }