Skip to content

fix: Drop redundant store-search call in fetchActorDetails - #1377

Closed
MQ37 wants to merge 1 commit into
masterfrom
fix/drop-redundant-actor-details-store-search
Closed

MQ37 wants to merge 1 commit into
masterfrom
fix/drop-redundant-actor-details-store-search

Conversation

@MQ37

@MQ37 MQ37 commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

What

fetchActorDetails drops the extra searchActorsByKeywords call it made solely to recover pictureUrl; reads it straight off actor.get() instead, same untyped-cast pattern already used in actor_definition.ts.

Why

Closes #804. pictureUrl is already returned by GET /v2/acts/:actorId (apify-core's API_PUBLISHED_ACT2_FIELDS includes it) — the store-search result was only ever a fallback source for the same field, never the sole source. The extra call was pure overhead.

Testing

Unit: pnpm run type-check, lint, test:unit (1683 passed), format, format:check, check:agents — all pass. Added a unit test asserting pictureUrl comes through from the direct Actor response.
E2E: built and ran the stdio server for real via mcpc against production Apify with a real token — fetch-actor-details on apify/web-scraper returned pictureUrl correctly with the store-search call removed. fetch-actor-details-widget shares this exact function (registry.ts), so the same path covers it.

pictureUrl is already returned directly on actor.get() (apify-core's API_PUBLISHED_ACT2_FIELDS includes it; actor_definition.ts already reads it this way). The searchActorsByKeywords call here was only ever a fallback source for the same field, never the sole source.
@MQ37

MQ37 commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #1467. Dropping the Store search without a replacement would break the widget icons (the raw S3 URL fails CORS, #459), so #1467 lets the hosted server provide a proxied URL instead and keeps the search as the fallback.

@MQ37 MQ37 closed this Sep 30, 2026
MQ37 added a commit that referenced this pull request Oct 19, 2026
## Why
Part of #804. `fetch-actor-details` gets the Actor picture from the
Store search (resized imgproxy URL) because the raw S3 URL from the
Apify API has no CORS headers and breaks the widget avatar (#459). That
costs an extra request per call and does not work for private or
unlisted Actors. The hosted server can sign the same URL itself.

## What changed
- Before: `fetchActorDetails` always searched the Store for the picture
URL.
- Now: `ActorStore` has an optional `getProxiedPictureUrl()`. If the
host provides it, the search is skipped and its URL is used. Without it
(stdio) nothing changes.
- `fetchActorDetails` takes `{ cardOptions, actorStore }` to stay at 3
positional params (not exported from `./internals`).

## Notes for reviewers (human-written)
- Internal impact: apify-mcp-server-internal#807 implements the method;
it needs this released first.
- Deliberate: one request less per call on hosted, and private Actors
get a working URL.
- Alternative considered: a new server option, about 8 files of
threading; `actorStore` already reaches every tool.
- Out of scope: tool-list icons (`image/png` hard-coded). Supersedes
#1377.
- AI assistance: Claude Code helped write and test this change.

## Proof it works
Internal server with this build, container, real api.apify.com:
```
$ mcpc @pr tools-call fetch-actor-details actor:=apify/instagram-scraper
  pictureUrl = https://images.apifyusercontent.com/…/rs:fill:76:76/cb:1/….webp  (== Store API URL)
$ curl -sI -H 'Origin: https://claude.ai' <pictureUrl>
  200 image/webp, access-control-allow-origin: *, 1.4 KB  (raw S3 PNG: ~200 KB)
```
Same for web-scraper and rag-web-browser. No `/v2/store` call on the
hosted path, one in the stdio fallback.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

perf: Drop redundant store-search call in fetchActorDetails (use Actor.pictureUrl directly)

2 participants