@tickerbot/mcp-server 0.1.5 → 0.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/dist/handler.js +55 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +1569 -313
- package/package.json +1 -1
package/dist/handler.js
CHANGED
|
@@ -48,11 +48,65 @@ export async function runTool(name, args, apiKey, options = {}) {
|
|
|
48
48
|
catch {
|
|
49
49
|
// non-JSON response — fall through with text body
|
|
50
50
|
}
|
|
51
|
+
// Surface advisory headers instead of discarding them (TB-188): the agent
|
|
52
|
+
// should learn when a route is deprecated/sunsetting, when it is being
|
|
53
|
+
// throttled, or when the Free monthly quota is nearly gone. Mirrors
|
|
54
|
+
// main_service/mcp/handler.js — keep the two in step.
|
|
55
|
+
const advisories = collectAdvisories(res.headers);
|
|
51
56
|
if (!res.ok) {
|
|
52
|
-
|
|
57
|
+
const err = new ToolError(`Tickerbot ${tool.endpoint.method} ${tool.endpoint.path} failed: ${res.status} ${res.statusText}`, res.status, parsed);
|
|
58
|
+
if (advisories)
|
|
59
|
+
err.advisories = advisories;
|
|
60
|
+
throw err;
|
|
61
|
+
}
|
|
62
|
+
if (advisories && parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
63
|
+
;
|
|
64
|
+
parsed._advisories = advisories;
|
|
53
65
|
}
|
|
54
66
|
return parsed;
|
|
55
67
|
}
|
|
68
|
+
// The advisory subset of the response-header contract. Deliberately
|
|
69
|
+
// selective: always-on X-RateLimit-*/X-Quota-* counters would add noise to
|
|
70
|
+
// every call, so rate/quota numbers ride along only when the server is
|
|
71
|
+
// actually warning (throttled, near-limit, or low quota).
|
|
72
|
+
function collectAdvisories(headers) {
|
|
73
|
+
const out = {};
|
|
74
|
+
const dep = headers.get('deprecation');
|
|
75
|
+
const sunset = headers.get('sunset');
|
|
76
|
+
if (dep || sunset) {
|
|
77
|
+
const link = headers.get('link') ?? '';
|
|
78
|
+
const succ = link.match(/<([^>]+)>\s*;\s*rel="successor-version"/);
|
|
79
|
+
out.deprecated = {
|
|
80
|
+
...(dep ? { since: dep } : {}),
|
|
81
|
+
...(sunset ? { sunset_on: sunset, warning: `This route stops serving on ${sunset}.` } : {}),
|
|
82
|
+
...(succ ? { successor: succ[1] } : {}),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const retryAfter = headers.get('retry-after');
|
|
86
|
+
const rlWarning = headers.get('x-ratelimit-warning');
|
|
87
|
+
if (retryAfter || rlWarning) {
|
|
88
|
+
const remaining = headers.get('x-ratelimit-remaining');
|
|
89
|
+
out.rate_limit = {
|
|
90
|
+
...(rlWarning ? { warning: rlWarning } : {}),
|
|
91
|
+
...(retryAfter ? { retry_after_seconds: Number(retryAfter) || retryAfter } : {}),
|
|
92
|
+
...(headers.get('x-ratelimit-limit') ? { limit: Number(headers.get('x-ratelimit-limit')) } : {}),
|
|
93
|
+
...(remaining != null && remaining !== '' ? { remaining: Number(remaining) } : {}),
|
|
94
|
+
...(headers.get('x-ratelimit-reset') ? { reset_epoch_s: Number(headers.get('x-ratelimit-reset')) } : {}),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const quotaLimit = Number(headers.get('x-quota-limit'));
|
|
98
|
+
const quotaRemaining = Number(headers.get('x-quota-remaining'));
|
|
99
|
+
if (headers.get('x-quota-limit') && Number.isFinite(quotaLimit) && Number.isFinite(quotaRemaining)
|
|
100
|
+
&& quotaLimit > 0 && quotaRemaining <= quotaLimit * 0.1) {
|
|
101
|
+
out.monthly_quota = {
|
|
102
|
+
warning: `Free-plan monthly quota nearly exhausted: ${quotaRemaining} of ${quotaLimit} calls left this month.`,
|
|
103
|
+
limit: quotaLimit,
|
|
104
|
+
remaining: quotaRemaining,
|
|
105
|
+
...(headers.get('x-quota-reset') ? { reset_epoch_s: Number(headers.get('x-quota-reset')) } : {}),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return Object.keys(out).length ? out : null;
|
|
109
|
+
}
|
|
56
110
|
function buildRequest(tool, args, baseUrl) {
|
|
57
111
|
let path = tool.endpoint.path;
|
|
58
112
|
const query = new URLSearchParams();
|