anyapi-mcp-server 1.1.2 → 1.1.3
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/build/api-client.js +14 -9
- package/build/index.js +3 -3
- package/build/response-cache.js +10 -0
- package/package.json +1 -1
package/build/api-client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { withRetry, RetryableError, isRetryableStatus } from "./retry.js";
|
|
2
|
-
import { buildCacheKey,
|
|
2
|
+
import { buildCacheKey, consumeCached, setCache } from "./response-cache.js";
|
|
3
3
|
import { logEntry, isLoggingEnabled } from "./logger.js";
|
|
4
4
|
import { parseResponse } from "./response-parser.js";
|
|
5
5
|
const TIMEOUT_MS = 30_000;
|
|
@@ -15,14 +15,19 @@ function interpolatePath(pathTemplate, params) {
|
|
|
15
15
|
});
|
|
16
16
|
return { url, remainingParams: remaining };
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
/**
|
|
19
|
+
* @param cacheMode
|
|
20
|
+
* - "populate" — skip cache read, always fetch, store result (used by call_api)
|
|
21
|
+
* - "consume" — read-and-evict cache, fetch on miss, do NOT re-store (used by query_api)
|
|
22
|
+
* - "none" — no caching at all (default)
|
|
23
|
+
*/
|
|
24
|
+
export async function callApi(config, method, pathTemplate, params, body, extraHeaders, cacheMode = "none") {
|
|
25
|
+
// --- Cache check (consume mode only) ---
|
|
26
|
+
const cacheKey = cacheMode !== "none"
|
|
22
27
|
? buildCacheKey(method, pathTemplate, params, body, extraHeaders)
|
|
23
28
|
: "";
|
|
24
|
-
if (
|
|
25
|
-
const cached =
|
|
29
|
+
if (cacheMode === "consume") {
|
|
30
|
+
const cached = consumeCached(cacheKey);
|
|
26
31
|
if (cached !== undefined)
|
|
27
32
|
return cached;
|
|
28
33
|
}
|
|
@@ -104,8 +109,8 @@ export async function callApi(config, method, pathTemplate, params, body, extraH
|
|
|
104
109
|
clearTimeout(timeout);
|
|
105
110
|
}
|
|
106
111
|
});
|
|
107
|
-
// --- Cache store (
|
|
108
|
-
if (
|
|
112
|
+
// --- Cache store (populate mode only) ---
|
|
113
|
+
if (cacheMode === "populate") {
|
|
109
114
|
setCache(cacheKey, result);
|
|
110
115
|
}
|
|
111
116
|
return result;
|
package/build/index.js
CHANGED
|
@@ -13,7 +13,7 @@ initLogger(config.logPath ?? null);
|
|
|
13
13
|
const apiIndex = new ApiIndex(config.spec);
|
|
14
14
|
const server = new McpServer({
|
|
15
15
|
name: config.name,
|
|
16
|
-
version: "1.1.
|
|
16
|
+
version: "1.1.3",
|
|
17
17
|
});
|
|
18
18
|
// --- Tool 1: list_api ---
|
|
19
19
|
server.tool("list_api", `List available ${config.name} API endpoints. ` +
|
|
@@ -125,7 +125,7 @@ server.tool("call_api", `Inspect a ${config.name} API endpoint. Makes a real req
|
|
|
125
125
|
"Overrides default --header values."),
|
|
126
126
|
}, async ({ method, path, params, body, headers }) => {
|
|
127
127
|
try {
|
|
128
|
-
const data = await callApi(config, method, path, params, body, headers);
|
|
128
|
+
const data = await callApi(config, method, path, params, body, headers, "populate");
|
|
129
129
|
const endpoint = apiIndex.getEndpoint(method, path);
|
|
130
130
|
const schema = getOrBuildSchema(data, method, path, endpoint?.requestBodySchema);
|
|
131
131
|
const sdl = schemaToSDL(schema);
|
|
@@ -223,7 +223,7 @@ server.tool("query_api", `Fetch data from a ${config.name} API endpoint, returni
|
|
|
223
223
|
.describe("Client-side slice: items to skip in already-fetched response (default: 0). For API pagination, use params instead."),
|
|
224
224
|
}, async ({ method, path, params, body, query, headers, limit, offset }) => {
|
|
225
225
|
try {
|
|
226
|
-
const rawData = await callApi(config, method, path, params, body, headers);
|
|
226
|
+
const rawData = await callApi(config, method, path, params, body, headers, "consume");
|
|
227
227
|
const endpoint = apiIndex.getEndpoint(method, path);
|
|
228
228
|
const schema = getOrBuildSchema(rawData, method, path, endpoint?.requestBodySchema);
|
|
229
229
|
const { data, truncated, total } = truncateIfArray(rawData, limit, offset);
|
package/build/response-cache.js
CHANGED
|
@@ -23,6 +23,16 @@ export function getCached(key) {
|
|
|
23
23
|
}
|
|
24
24
|
return entry.data;
|
|
25
25
|
}
|
|
26
|
+
/** Read and immediately evict a cache entry (one-shot consumption). */
|
|
27
|
+
export function consumeCached(key) {
|
|
28
|
+
const entry = cache.get(key);
|
|
29
|
+
if (!entry)
|
|
30
|
+
return undefined;
|
|
31
|
+
cache.delete(key);
|
|
32
|
+
if (Date.now() > entry.expiresAt)
|
|
33
|
+
return undefined;
|
|
34
|
+
return entry.data;
|
|
35
|
+
}
|
|
26
36
|
export function setCache(key, data, ttlMs = DEFAULT_TTL_MS) {
|
|
27
37
|
cache.set(key, { data, expiresAt: Date.now() + ttlMs });
|
|
28
38
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anyapi-mcp-server",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "A universal MCP server that connects any REST API (via OpenAPI spec) to AI assistants, with GraphQL-style field selection and automatic schema inference.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|