@apify/actors-mcp-server 0.11.3-beta.0 → 0.11.3-beta.1

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.
@@ -9,10 +9,9 @@ import type { ActorDefinitionStorage, ActorDefinitionWithInfo, DatasetItem } fro
9
9
  */
10
10
  export declare function getActorDefinitionCached(actorIdOrName: string, apifyClient: ApifyClient): Promise<ActorDefinitionWithInfo | null>;
11
11
  /**
12
- * Resolve and cache the MCP server URL for the given Actor.
13
- * - Returns a string URL when the Actor exposes an MCP server
14
- * - Returns false when the Actor is not an MCP server
15
- * Uses a TTL LRU cache to avoid repeated API calls.
12
+ * Resolve the Actor's MCP server URL, or `false` if it isn't an MCP server. The URL is a pure function of
13
+ * the definition (`getActorMCPServerURL` does no I/O), so this rides the authorization-gated
14
+ * `getActorDefinitionCached` instead of a separate cache that would leak a private Actor's URL across tenants.
16
15
  */
17
16
  export declare function getActorMcpUrlCached(actorIdOrName: string, apifyClient: ApifyClient): Promise<string | false>;
18
17
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"actor.d.ts","sourceRoot":"","sources":["../../src/utils/actor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAItD,OAAO,KAAK,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGhG;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC1C,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,WAAW,GACzB,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAMzC;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC,CAkCnH;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,GAAG,MAAM,EAAE,CAiBtG;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACvC,KAAK,EAAE,WAAW,EAAE,EACpB,eAAe,EAAE,MAAM,EAAE,EACzB,SAAS,EAAE,MAAM,GAClB,WAAW,EAAE,CA+Bf"}
1
+ {"version":3,"file":"actor.d.ts","sourceRoot":"","sources":["../../src/utils/actor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAItD,OAAO,KAAK,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAwBhG;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC1C,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,WAAW,GACzB,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAMzC;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC,CAKnH;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,GAAG,MAAM,EAAE,CAiBtG;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACvC,KAAK,EAAE,WAAW,EAAE,EACpB,eAAe,EAAE,MAAM,EAAE,EACzB,SAAS,EAAE,MAAM,GAClB,WAAW,EAAE,CA+Bf"}
@@ -1,7 +1,28 @@
1
1
  import { getActorMCPServerPath, getActorMCPServerURL } from '../mcp/actors.js';
2
- import { actorDefinitionCache, mcpServerCache } from '../state.js';
2
+ import { actorDefinitionCache } from '../state.js';
3
3
  import { getActorDefinition } from '../tools/build.js';
4
4
  import { getValuesByDotKeys } from './generic.js';
5
+ import { getUserInfoCached } from './userid_cache.js';
6
+ /**
7
+ * `actorDefinitionCache` is process-wide, so a private Actor's definition must never be served from it to
8
+ * anyone but its owner — else another token on the same process reads it with no auth check. Two invariants
9
+ * keep this gate from inverting into a leak:
10
+ * 1. `info.userId` is the platform-set OWNER, not the fetching token — so a non-owner's re-fetch can't
11
+ * overwrite the cached ownership.
12
+ * 2. The caller is identified by `user('me')` under their own token (the same identity the platform
13
+ * authorizes with) and `null` is the sole non-identity sentinel — so a hit grants no more than a bare
14
+ * re-fetch would. Don't drop the `!== null` guard or swap in a cheaper identity source.
15
+ * Trade-off: an org-owned private Actor is cached under the org's userId, so an org member
16
+ * calling with a personal token never matches and re-fetches every time.
17
+ * Fail-safe (no leak), just uncached for members - accepted over an org-membership lookup
18
+ * that would put a per-call API round trip back on * this path.
19
+ */
20
+ async function callerMaySeeCachedActor(cached, apifyClient) {
21
+ if (cached.info.isPublic)
22
+ return true;
23
+ const { userId } = await getUserInfoCached(apifyClient.token, apifyClient);
24
+ return userId !== null && userId === cached.info.userId;
25
+ }
5
26
  /**
6
27
  * Returns the cached Actor definition + info, fetching from the platform on miss
7
28
  * and populating the cache on the way back.
@@ -11,7 +32,7 @@ import { getValuesByDotKeys } from './generic.js';
11
32
  */
12
33
  export async function getActorDefinitionCached(actorIdOrName, apifyClient) {
13
34
  const cached = actorDefinitionCache.get(actorIdOrName);
14
- if (cached)
35
+ if (cached && (await callerMaySeeCachedActor(cached, apifyClient)))
15
36
  return cached;
16
37
  const fetched = await getActorDefinition(actorIdOrName, apifyClient);
17
38
  if (fetched)
@@ -19,42 +40,17 @@ export async function getActorDefinitionCached(actorIdOrName, apifyClient) {
19
40
  return fetched;
20
41
  }
21
42
  /**
22
- * Resolve and cache the MCP server URL for the given Actor.
23
- * - Returns a string URL when the Actor exposes an MCP server
24
- * - Returns false when the Actor is not an MCP server
25
- * Uses a TTL LRU cache to avoid repeated API calls.
43
+ * Resolve the Actor's MCP server URL, or `false` if it isn't an MCP server. The URL is a pure function of
44
+ * the definition (`getActorMCPServerURL` does no I/O), so this rides the authorization-gated
45
+ * `getActorDefinitionCached` instead of a separate cache that would leak a private Actor's URL across tenants.
26
46
  */
27
47
  export async function getActorMcpUrlCached(actorIdOrName, apifyClient) {
28
- const cached = mcpServerCache.get(actorIdOrName);
29
- if (cached !== null && cached !== undefined) {
30
- return cached;
31
- }
32
- try {
33
- const actorDefinitionWithInfo = await getActorDefinitionCached(actorIdOrName, apifyClient);
34
- const definition = actorDefinitionWithInfo === null || actorDefinitionWithInfo === void 0 ? void 0 : actorDefinitionWithInfo.definition;
35
- const mcpPath = definition && getActorMCPServerPath(definition);
36
- if (mcpPath) {
37
- const url = await getActorMCPServerURL(definition.id, mcpPath);
38
- mcpServerCache.set(actorIdOrName, url);
39
- return url;
40
- }
41
- mcpServerCache.set(actorIdOrName, false);
48
+ var _a;
49
+ const definition = (_a = (await getActorDefinitionCached(actorIdOrName, apifyClient))) === null || _a === void 0 ? void 0 : _a.definition;
50
+ const mcpPath = definition && getActorMCPServerPath(definition);
51
+ if (!mcpPath)
42
52
  return false;
43
- }
44
- catch (error) {
45
- // Check if it's a "not found" error (404 or 400 status codes)
46
- const isNotFound = typeof error === 'object' &&
47
- error !== null &&
48
- 'statusCode' in error &&
49
- (error.statusCode === 404 || error.statusCode === 400);
50
- if (isNotFound) {
51
- // Actor doesn't exist - cache false and return false
52
- mcpServerCache.set(actorIdOrName, false);
53
- return false;
54
- }
55
- // Real server error - don't cache, let it propagate
56
- throw error;
57
- }
53
+ return getActorMCPServerURL(definition.id, mcpPath);
58
54
  }
59
55
  /**
60
56
  * Returns an array of all field names mentioned in the display.properties
@@ -1 +1 @@
1
- {"version":3,"file":"actor.js","sourceRoot":"","sources":["../../src/utils/actor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"actor.js","sourceRoot":"","sources":["../../src/utils/actor.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apify/actors-mcp-server",
3
- "version": "0.11.3-beta.0",
3
+ "version": "0.11.3-beta.1",
4
4
  "type": "module",
5
5
  "description": "Apify MCP Server",
6
6
  "mcpName": "com.apify/apify-mcp-server",