Skip to content

Refine MCP skills: align search-assets/sdk-reference with assets.list overload; drop webhooks#3

Open
imagekitio wants to merge 9 commits into
mainfrom
feat/refine-skills-mcp-overload
Open

Refine MCP skills: align search-assets/sdk-reference with assets.list overload; drop webhooks#3
imagekitio wants to merge 9 commits into
mainfrom
feat/refine-skills-mcp-overload

Conversation

@imagekitio

@imagekitio imagekitio commented Jun 26, 2026

Copy link
Copy Markdown

Summary

Builds on #2 and refines the two skills that interact most with TypeScript typing, so the agent gets correct results even when a skill isn't loaded. Pairs with companion SDK changes in imagekit-nodejs (an honest assets.list overload + an expanded execute tool prompt).

search-assets

  • Rewrote the TypeScript usage section to match the assets.list overload behavior:
    • Without searchQuery → pass { type: 'file' } / { type: 'folder' } for a typed File[] / Folder[] (no narrowing).
    • With searchQuery → the API ignores the type/tags/name params, so the result stays (File | Folder)[]; put type = "file" inside the query and narrow with for...of + if.
  • Added a "discover custom-metadata fields first" section: client.customMetadataFields.list() to get valid field names/types before building "customMetadata.<field>" queries (operators depend on the field type).
  • Added the key gotcha that searchQuery overrides the top-level type/tags/name params.

imagekit-sdk-reference

  • Updated the assets.list narrowing guidance to reflect the overload (narrowing only required for the union / searchQuery cases).
  • Reconciled the try/catch rule with the tool prompt: don't try/catch single calls in execute code; when branching on failure, duck-type the error instead of instanceof ImageKit.APIError (a value import of the SDK crashes at runtime in the Deno sandbox).
  • Removed the Webhooks section entirely — webhook unwrap verifies an incoming request and isn't usable inside the MCP execute sandbox.

Companion SDK changes (separate imagekit-nodejs PR)

Companion PR - imagekit-developer/imagekit-nodejs#163

  • assets.list overloads gated on searchQuery?: undefined so the typed File[]/Folder[] return is only produced when there's no searchQuery (no more type lie).
  • execute tool prompt expanded with list/search + pagination + nullable-field + custom-metadata-discovery guidance.

shivamik and others added 8 commits June 18, 2026 18:40
… and imagekit-plugin

chore(mcp): fix API URL in mcp configuration

docs(README): add imagekit-sdk-reference skill to documentation

chore(skills): include imagekit-sdk-reference in skills list
…e type gotchas

- Add search-assets skill: searchQuery filter syntax, operators, and field reference for client.assets.list()
- Add imagekit-integrations skill: index of ImageKit SDKs, plugins, and integrations
- Register both new skills under the General grouping in skills.sh.json
- imagekit-sdk-reference: add TypeScript Gotchas section explaining why .filter() with `item is File` fails in MCP/Deno (global File shadows SDK File); recommend for...of + if narrowing; document nullable props, .find() undefined, and webhook discrimination
- mcp-preflight: clarify execute tool description and upload routing wording
@shivamik

Copy link
Copy Markdown
Collaborator

One issue that i running with custom metadata is agent tries to use custom metadata tag as per user request. And because users dont exactly use custom meta data tag name correctly this usually search files to get the name. Correct path is to first get list of custom metadata tag and then proceed.

Below image shows using some cheaper model agent confuses metadata name. Also sometimes it uses list assets instead of first listing custom metadata. I am adding a section to guide llm to list metadata first

image

```

This returns the configured fields with their `name`, `type`, and any allowed values — use it to build a valid `searchQuery` (see the `search-assets` skill).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ye pura section search se related hai, why is it here in general preflight skill and not search-asset skill. Also pls avoid making direct changes here. just leave comment.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I will leave comment.
This is here because MCP sometimes skips search assets skills when using cheap models! Adding this section at least gives some context to the agent to make correct call in first attempt as this skill is always loaded.

@shivamik

shivamik commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Task: in my imagekit DAM, use AI task to add tag in these images
imagekit_api_mcp_trial
one of

  1. animal
  2. human
  3. other

Rest of things are working fine! One issue that I faced in terms of UX, is that when working with long running tasks, code written is sequential sometimes.

image

I had to prompt to write code in parallel.

image

We should tell agent to write code to use APIs in batches like we do for IK Agent now

```

---

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


Parallel Execution for Bulk File Operations

When you have a list of files to operate on, never await in a loop. Chunk into batches of 100 and run each batch concurrently with Promise.allSettled().

// ✅ files is any array of { fileId, name } — from assets.list(), a prior search, etc.
const CHUNK = 100;
const chunks = [];
for (let i = 0; i < files.length; i += CHUNK) chunks.push(files.slice(i, i + CHUNK));

for (const chunk of chunks) {
  await Promise.allSettled(
    chunk.map(({ fileId, name }) =>
      client.files.update(fileId, { tags: ['promo'] })
        .then(() => ({ fileId, name, status: 'ok' }))
        .catch((err: unknown) => ({ fileId, name, status: 'error', error: String(err) }))
    )
  );
}

Same pattern applies for files.delete(fileId), files.copy({...}), and files.move({...}).

For delete / addTags / removeTags, prefer the bulk endpoints (max 50 IDs each) — chunk IDs and run chunks in parallel:

const CHUNK = 50;
const chunks = [];
for (let i = 0; i < allFileIds.length; i += CHUNK) chunks.push(allFileIds.slice(i, i + CHUNK));
await Promise.allSettled(chunks.map(ids => client.files.bulk.delete({ fileIds: ids })));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can have a section for parallel execution

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.

3 participants