Skip to content

Commit 342d949

Browse files
ivanvia7jirispilka
andauthored
fix(open-meteo-mcp-server): simplify billing to avoid the errors (#67)
Co-authored-by: Jiří Spilka <[email protected]>
1 parent 87ef17c commit 342d949

File tree

2 files changed

+83
-26
lines changed

2 files changed

+83
-26
lines changed

open-meteo-mcp-server/src/billing.ts

Lines changed: 77 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,81 @@
1-
21
import { Actor, log } from 'apify';
3-
import { readFile } from 'node:fs/promises';
4-
import path from 'node:path';
52

6-
// Load billable events from .actor/pay_per_event.json (sync at startup)
7-
let BILLABLE_EVENTS: Record<string, any> = {};
8-
const payPerEventPath = path.resolve(__dirname, '../.actor/pay_per_event.json');
9-
async function loadBillableEvents() {
10-
try {
11-
const data = await readFile(payPerEventPath, 'utf-8');
12-
BILLABLE_EVENTS = JSON.parse(data);
13-
log.info('Loaded billable events from pay_per_event.json');
14-
} catch (err) {
15-
log.error('Failed to load billable events:', { error: err });
3+
const TOOL_PRICING: Record<string, { eventPriceUsd: number; eventTitle: string }> = {
4+
"actor-start": {
5+
eventPriceUsd: 0.1,
6+
eventTitle: "Price for Actor start",
7+
},
8+
"weather_forecast": {
9+
eventPriceUsd: 0.0001,
10+
eventTitle: "Weather forecast tool",
11+
},
12+
"weather_archive": {
13+
eventPriceUsd: 0.0001,
14+
eventTitle: "Weather archive tool",
15+
},
16+
"air_quality": {
17+
eventPriceUsd: 0.0001,
18+
eventTitle: "Air quality tool",
19+
},
20+
"marine_weather": {
21+
eventPriceUsd: 0.0001,
22+
eventTitle: "Marine weather tool",
23+
},
24+
"elevation": {
25+
eventPriceUsd: 0.0001,
26+
eventTitle: "Elevation tool",
27+
},
28+
"geocoding": {
29+
eventPriceUsd: 0.0001,
30+
eventTitle: "Geocoding tool",
31+
},
32+
"dwd_icon_forecast": {
33+
eventPriceUsd: 0.0001,
34+
eventTitle: "DWD ICON forecast tool",
35+
},
36+
"gfs_forecast": {
37+
eventPriceUsd: 0.0001,
38+
eventTitle: "NOAA GFS forecast tool",
39+
},
40+
"meteofrance_forecast": {
41+
eventPriceUsd: 0.0001,
42+
eventTitle: "Météo-France forecast tool",
43+
},
44+
"ecmwf_forecast": {
45+
eventPriceUsd: 0.0001,
46+
eventTitle: "ECMWF forecast tool",
47+
},
48+
"jma_forecast": {
49+
eventPriceUsd: 0.0001,
50+
eventTitle: "JMA forecast tool",
51+
},
52+
"metno_forecast": {
53+
eventPriceUsd: 0.0001,
54+
eventTitle: "MET Norway forecast tool",
55+
},
56+
"gem_forecast": {
57+
eventPriceUsd: 0.0001,
58+
eventTitle: "Environment Canada GEM forecast tool",
59+
},
60+
"flood_forecast": {
61+
eventPriceUsd: 0.0001,
62+
eventTitle: "Flood forecast tool",
63+
},
64+
"seasonal_forecast": {
65+
eventPriceUsd: 0.0001,
66+
eventTitle: "Seasonal forecast tool",
67+
},
68+
"climate_projection": {
69+
eventPriceUsd: 0.0001,
70+
eventTitle: "Climate projection tool",
71+
},
72+
"ensemble_forecast": {
73+
eventPriceUsd: 0.0001,
74+
eventTitle: "Ensemble forecast tool",
1675
}
17-
}
18-
// Immediately load on module import
19-
await loadBillableEvents();
76+
};
2077
/**
21-
* This module handles billing for different types of protocol requests in the MCP server.
22-
* It defines a function to charge users based on the type of protocol method invoked.
23-
*/
2478
25-
/**
2679
* Charges the user for a message request based on the method type.
2780
* Supported method types are mapped to specific billing events.
2881
*
@@ -34,17 +87,17 @@ export async function chargeMessageRequest(request: { method: string; params?: {
3487

3588
if (method === 'tools/call' && request?.params?.tool) {
3689
const toolName = request.params.tool;
37-
if (BILLABLE_EVENTS[toolName]) {
90+
if (TOOL_PRICING[toolName]) {
3891
await Actor.charge({ eventName: toolName });
39-
const event = BILLABLE_EVENTS[toolName];
92+
const event = TOOL_PRICING[toolName];
4093
log.info(`Charged for tool call: ${toolName} ($${event.eventPriceUsd}) - ${event.eventTitle}`);
4194
} else {
4295
await Actor.charge({ eventName: 'tool-call' });
4396
log.info(`Charged for tool call (unknown tool): ${toolName}`);
4497
}
45-
} else if (BILLABLE_EVENTS[method]) {
98+
} else if (TOOL_PRICING[method]) {
4699
await Actor.charge({ eventName: method });
47-
const event = BILLABLE_EVENTS[method];
100+
const event = TOOL_PRICING[method];
48101
log.info(`Charged for event: ${method} ($${event.eventPriceUsd}) - ${event.eventTitle}`);
49102
} else {
50103
log.info(`Not charging for method: ${method}`);

open-meteo-mcp-server/src/server.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,9 @@ async function mcpPostHandler(req: Request, res: Response) {
9595
await server.connect(transport);
9696

9797
// Charge for the request
98-
await chargeMessageRequest(req.body);
98+
const { method, params } = req.body;
99+
const chargeParams = params && typeof params.tool === 'string' ? { tool: params.tool } : undefined;
100+
await chargeMessageRequest({ method, params: chargeParams });
99101

100102
await transport.handleRequest(req, res, req.body);
101103
return; // Already handled
@@ -113,7 +115,9 @@ async function mcpPostHandler(req: Request, res: Response) {
113115
}
114116

115117
// Charge for the request
116-
await chargeMessageRequest(req.body);
118+
const { method, params } = req.body;
119+
const chargeParams = params && typeof params.tool === 'string' ? { tool: params.tool } : undefined;
120+
await chargeMessageRequest({ method, params: chargeParams });
117121
// Handle the request with existing transport - no need to reconnect
118122
// The existing transport is already connected to the server
119123
await transport.handleRequest(req, res, req.body);

0 commit comments

Comments
 (0)