diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 4e9d6c7e..32ac6588 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "7.1.1" + ".": "8.0.0" } diff --git a/.stats.yml b/.stats.yml index f035d349..e75a1bc7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 42 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-c7ad6f552b38f2145781847f8b390fa1ec43068d64e45a33012a97a9299edc10.yml -openapi_spec_hash: 50f281e91210ad5018ac7e4eee216f56 -config_hash: 74a8263b80c732a2b016177e7d56bb9c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-9d184cb502ab32a85db2889c796cdfebe812f2a55a604df79c85dd4b5e7e2add.yml +openapi_spec_hash: a9aa620376fce66532c84f9364209b0b +config_hash: 71cab8223bb5610c6c7ca6e9c4cc1f89 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0617e7cc..4280b20e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,71 @@ # Changelog +## 8.0.0 (2026-01-08) + +Full Changelog: [v7.1.1...v8.0.0](https://github.com/imagekit-developer/imagekit-nodejs/compare/v7.1.1...v8.0.0) + +### ⚠ BREAKING CHANGES + +* **mcp:** remove deprecated tool schemes +* **mcp:** **Migration:** To migrate, simply modify the command used to invoke the MCP server. Currently, the only supported tool scheme is code mode. Now, starting the server with just `node /path/to/mcp/server` or `npx package-name` will invoke code tools: changing your command to one of these is likely all you will need to do. + +### Features + +* **api:** add GetImageAttributesOptions and ResponsiveImageAttributes schemas; update resource references in main.yaml; remove dummy endpoint ([9ea439a](https://github.com/imagekit-developer/imagekit-nodejs/commit/9ea439a2d0a4c8300d14d4424dc72ab40a67c4d4)) +* **mcp:** add detail field to docs search tool ([f36d795](https://github.com/imagekit-developer/imagekit-nodejs/commit/f36d79523b0613a27afd45d56f4e1e906e6fdfe9)) +* **mcp:** add typescript check to code execution tool ([63ab735](https://github.com/imagekit-developer/imagekit-nodejs/commit/63ab735bf6c8458a53bd66c8c437b45a7aef60fe)) +* **mcp:** enable optional code execution tool on http mcp servers ([cc68e38](https://github.com/imagekit-developer/imagekit-nodejs/commit/cc68e38fa61078db6a5c961e7ed75dad342dc7e8)) +* **mcp:** handle code mode calls in the Stainless API ([eb22f08](https://github.com/imagekit-developer/imagekit-nodejs/commit/eb22f0883fc74c94959fdd97e50d41d940e1aed6)) +* **mcp:** return logs on code tool errors ([6118fe4](https://github.com/imagekit-developer/imagekit-nodejs/commit/6118fe4804be492482268ff25e0afc714bea7613)) + + +### Bug Fixes + +* **docs:** remove extraneous example object fields ([a043056](https://github.com/imagekit-developer/imagekit-nodejs/commit/a043056abd2f86bcb5a691ac8f5c7ccf8a17663c)) +* **mcp:** add client instantiation options to code tool ([967c8d9](https://github.com/imagekit-developer/imagekit-nodejs/commit/967c8d90503b2e0ed0576b919be09f3b924ec890)) +* **mcpb:** pin @anthropic-ai/mcpb version ([d81e225](https://github.com/imagekit-developer/imagekit-nodejs/commit/d81e22560aab772ee9b241fb44a50561b8837034)) +* **mcp:** correct code tool API endpoint ([f4d2b6c](https://github.com/imagekit-developer/imagekit-nodejs/commit/f4d2b6c9989e8cc6c69badba7de0abb57e6de398)) +* **mcp:** correct code tool api output types ([0371082](https://github.com/imagekit-developer/imagekit-nodejs/commit/03710823b0d477506a6a321c8aa68cba1a95e452)) +* **mcp:** fix env parsing ([b33b4e9](https://github.com/imagekit-developer/imagekit-nodejs/commit/b33b4e9c4f595d850403d292057e5d0810303e62)) +* **mcp:** fix options parsing ([de44ed6](https://github.com/imagekit-developer/imagekit-nodejs/commit/de44ed62ad53d22aa4b196ca2416d33d784242ee)) +* **mcp:** pass base url to code tool ([908fa87](https://github.com/imagekit-developer/imagekit-nodejs/commit/908fa874d20613761caa76cd4b2151524ef87606)) +* **mcp:** return correct lines on typescript errors ([aa7ae07](https://github.com/imagekit-developer/imagekit-nodejs/commit/aa7ae07286cf492a7b1fecce34697006837beeef)) +* **mcp:** return tool execution error on api error ([1e866f8](https://github.com/imagekit-developer/imagekit-nodejs/commit/1e866f8e5254ecc305b3dfee53ec232455143cc4)) +* **mcp:** return tool execution error on jq failure ([d1949db](https://github.com/imagekit-developer/imagekit-nodejs/commit/d1949dbef79859b446ee9ee2c8a2d562568c1cca)) +* **mcp:** update cloudflare worker host page ([664a668](https://github.com/imagekit-developer/imagekit-nodejs/commit/664a6686e0b268c2b3d3985508c744358b937cf3)) +* **mcp:** update code tool prompt ([e3a5c5e](https://github.com/imagekit-developer/imagekit-nodejs/commit/e3a5c5ed81f7f05cdd00a1703a8e3f8aa24a0eb6)) + + +### Chores + +* break long lines in snippets into multiline ([011013e](https://github.com/imagekit-developer/imagekit-nodejs/commit/011013e6bac4c2ca8c6253d3ef482641bb089560)) +* **client:** fix logger property type ([6269318](https://github.com/imagekit-developer/imagekit-nodejs/commit/6269318024cd320f3038def32c3d5bf1f1da77a1)) +* extract some types in mcp docs ([de606ba](https://github.com/imagekit-developer/imagekit-nodejs/commit/de606ba3b734389e1c52a9929dbf8487828822e0)) +* **internal:** codegen related update ([4b79947](https://github.com/imagekit-developer/imagekit-nodejs/commit/4b79947c8eb22cf9c609da4efd9ea703caea0c41)) +* **internal:** codegen related update ([b6b0d1a](https://github.com/imagekit-developer/imagekit-nodejs/commit/b6b0d1a7d2f00d9ecaa9e0e630a012c25f6a00f4)) +* **internal:** codegen related update ([26acc3a](https://github.com/imagekit-developer/imagekit-nodejs/commit/26acc3a9fe08c7c478eed956dd553333bd8cf210)) +* **internal:** codegen related update ([662aa87](https://github.com/imagekit-developer/imagekit-nodejs/commit/662aa87091dc519bb811554438eaf978660d035e)) +* **internal:** codegen related update ([8c9026a](https://github.com/imagekit-developer/imagekit-nodejs/commit/8c9026ace5d217264e5753c01309a02a2c09095e)) +* **internal:** grammar fix (it's -> its) ([71e22a3](https://github.com/imagekit-developer/imagekit-nodejs/commit/71e22a30017324842fed5ab08ee1efbb1eecb6d2)) +* **internal:** upgrade eslint ([310bf0d](https://github.com/imagekit-developer/imagekit-nodejs/commit/310bf0d0cc1d5b15d08a2cbb483a9969ebf4f11d)) +* **internal:** use npm pack for build uploads ([bdfd369](https://github.com/imagekit-developer/imagekit-nodejs/commit/bdfd369118542dad02cf8a0fae8713d0d8bea4eb)) +* mcp code tool explicit error message when missing a run function ([6678ee1](https://github.com/imagekit-developer/imagekit-nodejs/commit/6678ee13cc1eee5ce1ac51b672144be77c38e9ea)) +* **mcp:** add friendlier MCP code tool errors on incorrect method invocations ([636829d](https://github.com/imagekit-developer/imagekit-nodejs/commit/636829d18a7dda730b65c0549298258afcea6341)) +* **mcp:** add line numbers to code tool errors ([25e4e59](https://github.com/imagekit-developer/imagekit-nodejs/commit/25e4e59f434c07c2d9afeef3f548dd99e250a7ab)) +* **mcp:** clarify http auth error ([00789ac](https://github.com/imagekit-developer/imagekit-nodejs/commit/00789acfb9ceb07af0cd03b1951090f430691592)) +* **mcp:** remove deprecated tool schemes ([b1a0e60](https://github.com/imagekit-developer/imagekit-nodejs/commit/b1a0e607e55f27ffed93b2862e8f4466bc609809)) +* **mcp:** update lockfile ([0703827](https://github.com/imagekit-developer/imagekit-nodejs/commit/07038271d5ec459516a8a936eb49f31490ccf6b0)) +* **mcp:** upgrade jq-web ([0750770](https://github.com/imagekit-developer/imagekit-nodejs/commit/075077081fc5826a4502a76a2abc40788f7915a3)) +* use latest @modelcontextprotocol/sdk ([f7b9b4e](https://github.com/imagekit-developer/imagekit-nodejs/commit/f7b9b4e55919b644d9445730c03c8972ecdfe0b7)) +* use structured error when code execution tool errors ([451f306](https://github.com/imagekit-developer/imagekit-nodejs/commit/451f306f6328e6c48374d0525dad9a0ddc6511d6)) + + +### Documentation + +* **mcp:** add a README button for one-click add to Cursor ([a7575d3](https://github.com/imagekit-developer/imagekit-nodejs/commit/a7575d308e3038715964f7416284bb012e27b240)) +* **mcp:** add a README link to add server to VS Code or Claude Code ([2a90d28](https://github.com/imagekit-developer/imagekit-nodejs/commit/2a90d2802e4814d97ec5bba77097eec2f0a5a718)) +* prominently feature MCP server setup in root SDK readmes ([80ce57e](https://github.com/imagekit-developer/imagekit-nodejs/commit/80ce57e3dee9eb822c8251ee8ed1c66afcfc156a)) + ## 7.1.1 (2025-10-06) Full Changelog: [v7.1.0...v7.1.1](https://github.com/imagekit-developer/imagekit-nodejs/compare/v7.1.0...v7.1.1) diff --git a/LICENSE b/LICENSE index e7a4d160..20278610 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2025 Image Kit + Copyright 2026 Image Kit Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 7747aaf8..c1f828aa 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,15 @@ If you are looking to integrate file uploads in browsers, use one of our [fronte - [Requirements](#requirements) - [Contributing](#contributing) +## MCP Server + +Use the Image Kit MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application. + +[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40imagekit%2Fapi-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBpbWFnZWtpdC9hcGktbWNwIl19) +[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40imagekit%2Fapi-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40imagekit%2Fapi-mcp%22%5D%7D) + +> Note: You may need to set environment variables in your MCP client. + ## Installation ```sh @@ -112,8 +121,14 @@ await client.files.upload({ file: new File(['my bytes'], 'file'), fileName: 'fil await client.files.upload({ file: await fetch('https://somesite/file'), fileName: 'fileName' }); // Finally, if none of the above are convenient, you can use our `toFile` helper: -await client.files.upload({ file: await toFile(Buffer.from('my bytes'), 'file'), fileName: 'fileName' }); -await client.files.upload({ file: await toFile(new Uint8Array([0, 1, 2]), 'file'), fileName: 'fileName' }); +await client.files.upload({ + file: await toFile(Buffer.from('my bytes'), 'file'), + fileName: 'fileName', +}); +await client.files.upload({ + file: await toFile(new Uint8Array([0, 1, 2]), 'file'), + fileName: 'fileName', +}); ``` ## URL generation diff --git a/api.md b/api.md index 86719ecf..fc87a76f 100644 --- a/api.md +++ b/api.md @@ -4,10 +4,12 @@ Types: - BaseOverlay - Extensions +- GetImageAttributesOptions - ImageOverlay - Overlay - OverlayPosition - OverlayTiming +- ResponsiveImageAttributes - SolidColorOverlay - SolidColorOverlayTransformation - SrcOptions diff --git a/package.json b/package.json index efd98c94..9fd98223 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@imagekit/nodejs", - "version": "7.1.1", + "version": "8.0.0", "description": "Offical NodeJS SDK for ImageKit.io integration", "author": "Image Kit ", "types": "dist/index.d.ts", @@ -37,7 +37,7 @@ "@types/node": "^20.17.6", "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", - "eslint": "^9.20.1", + "eslint": "^9.39.1", "eslint-plugin-prettier": "^5.4.1", "eslint-plugin-unused-imports": "^4.1.4", "iconv-lite": "^0.6.3", diff --git a/packages/mcp-server/README.md b/packages/mcp-server/README.md index 38260a76..ddac00d6 100644 --- a/packages/mcp-server/README.md +++ b/packages/mcp-server/README.md @@ -25,7 +25,7 @@ For clients with a configuration JSON, it might look something like this: "mcpServers": { "imagekit_nodejs_api": { "command": "npx", - "args": ["-y", "@imagekit/api-mcp", "--client=claude", "--tools=dynamic"], + "args": ["-y", "@imagekit/api-mcp"], "env": { "IMAGEKIT_PRIVATE_KEY": "My Private Key", "OPTIONAL_IMAGEKIT_IGNORES_THIS": "My Password", @@ -36,97 +36,45 @@ For clients with a configuration JSON, it might look something like this: } ``` -## Exposing endpoints to your MCP Client +### Cursor -There are two ways to expose endpoints as tools in the MCP server: +If you use Cursor, you can install the MCP server by using the button below. You will need to set your environment variables +in Cursor's `mcp.json`, which can be found in Cursor Settings > Tools & MCP > New MCP Server. -1. Exposing one tool per endpoint, and filtering as necessary -2. Exposing a set of tools to dynamically discover and invoke endpoints from the API +[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40imagekit%2Fapi-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBpbWFnZWtpdC9hcGktbWNwIl0sImVudiI6eyJJTUFHRUtJVF9QUklWQVRFX0tFWSI6IlNldCB5b3VyIElNQUdFS0lUX1BSSVZBVEVfS0VZIGhlcmUuIiwiT1BUSU9OQUxfSU1BR0VLSVRfSUdOT1JFU19USElTIjoiU2V0IHlvdXIgT1BUSU9OQUxfSU1BR0VLSVRfSUdOT1JFU19USElTIGhlcmUuIiwiSU1BR0VLSVRfV0VCSE9PS19TRUNSRVQiOiJTZXQgeW91ciBJTUFHRUtJVF9XRUJIT09LX1NFQ1JFVCBoZXJlLiJ9fQ) -### Filtering endpoints and tools +### VS Code -You can run the package on the command line to discover and filter the set of tools that are exposed by the -MCP Server. This can be helpful for large APIs where including all endpoints at once is too much for your AI's -context window. +If you use MCP, you can install the MCP server by clicking the link below. You will need to set your environment variables +in VS Code's `mcp.json`, which can be found via Command Palette > MCP: Open User Configuration. -You can filter by multiple aspects: +[Open VS Code](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40imagekit%2Fapi-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40imagekit%2Fapi-mcp%22%5D%2C%22env%22%3A%7B%22IMAGEKIT_PRIVATE_KEY%22%3A%22Set%20your%20IMAGEKIT_PRIVATE_KEY%20here.%22%2C%22OPTIONAL_IMAGEKIT_IGNORES_THIS%22%3A%22Set%20your%20OPTIONAL_IMAGEKIT_IGNORES_THIS%20here.%22%2C%22IMAGEKIT_WEBHOOK_SECRET%22%3A%22Set%20your%20IMAGEKIT_WEBHOOK_SECRET%20here.%22%7D%7D) -- `--tool` includes a specific tool by name -- `--resource` includes all tools under a specific resource, and can have wildcards, e.g. `my.resource*` -- `--operation` includes just read (get/list) or just write operations +### Claude Code -### Dynamic tools +If you use Claude Code, you can install the MCP server by running the command below in your terminal. You will need to set your +environment variables in Claude Code's `.claude.json`, which can be found in your home directory. -If you specify `--tools=dynamic` to the MCP server, instead of exposing one tool per endpoint in the API, it will -expose the following tools: - -1. `list_api_endpoints` - Discovers available endpoints, with optional filtering by search query -2. `get_api_endpoint_schema` - Gets detailed schema information for a specific endpoint -3. `invoke_api_endpoint` - Executes any endpoint with the appropriate parameters - -This allows you to have the full set of API endpoints available to your MCP Client, while not requiring that all -of their schemas be loaded into context at once. Instead, the LLM will automatically use these tools together to -search for, look up, and invoke endpoints dynamically. However, due to the indirect nature of the schemas, it -can struggle to provide the correct properties a bit more than when tools are imported explicitly. Therefore, -you can opt-in to explicit tools, the dynamic tools, or both. - -See more information with `--help`. - -All of these command-line options can be repeated, combined together, and have corresponding exclusion versions (e.g. `--no-tool`). - -Use `--list` to see the list of available tools, or see below. - -### Specifying the MCP Client - -Different clients have varying abilities to handle arbitrary tools and schemas. - -You can specify the client you are using with the `--client` argument, and the MCP server will automatically -serve tools and schemas that are more compatible with that client. - -- `--client=`: Set all capabilities based on a known MCP client - - - Valid values: `openai-agents`, `claude`, `claude-code`, `cursor` - - Example: `--client=cursor` - -Additionally, if you have a client not on the above list, or the client has gotten better -over time, you can manually enable or disable certain capabilities: - -- `--capability=`: Specify individual client capabilities - - Available capabilities: - - `top-level-unions`: Enable support for top-level unions in tool schemas - - `valid-json`: Enable JSON string parsing for arguments - - `refs`: Enable support for $ref pointers in schemas - - `unions`: Enable support for union types (anyOf) in schemas - - `formats`: Enable support for format validations in schemas (e.g. date-time, email) - - `tool-name-length=N`: Set maximum tool name length to N characters - - Example: `--capability=top-level-unions --capability=tool-name-length=40` - - Example: `--capability=top-level-unions,tool-name-length=40` - -### Examples - -1. Filter for read operations on cards: - -```bash ---resource=cards --operation=read ``` - -2. Exclude specific tools while including others: - -```bash ---resource=cards --no-tool=create_cards +claude mcp add imagekit_api_mcp_api --env IMAGEKIT_PRIVATE_KEY="Your IMAGEKIT_PRIVATE_KEY here." OPTIONAL_IMAGEKIT_IGNORES_THIS="Your OPTIONAL_IMAGEKIT_IGNORES_THIS here." IMAGEKIT_WEBHOOK_SECRET="Your IMAGEKIT_WEBHOOK_SECRET here." -- npx -y @imagekit/api-mcp ``` -3. Configure for Cursor client with custom max tool name length: +## Code Mode -```bash ---client=cursor --capability=tool-name-length=40 -``` +This MCP server is built on the "Code Mode" tool scheme. In this MCP Server, +your agent will write code against the TypeScript SDK, which will then be executed in an +isolated sandbox. To accomplish this, the server will expose two tools to your agent: -4. Complex filtering with multiple criteria: +- The first tool is a docs search tool, which can be used to generically query for + documentation about your API/SDK. -```bash ---resource=cards,accounts --operation=read --tag=kyc --no-tool=create_cards -``` +- The second tool is a code tool, where the agent can write code against the TypeScript SDK. + The code will be executed in a sandbox environment without web or filesystem access. Then, + anything the code returns or prints will be returned to the agent as the result of the + tool call. + +Using this scheme, agents are capable of performing very complex tasks deterministically +and repeatably. ## Running remotely @@ -154,198 +102,3 @@ A configuration JSON for this server might look like this, assuming the server i } } ``` - -The command-line arguments for filtering tools and specifying clients can also be used as query parameters in the URL. -For example, to exclude specific tools while including others, use the URL: - -``` -http://localhost:3000?resource=cards&resource=accounts&no_tool=create_cards -``` - -Or, to configure for the Cursor client, with a custom max tool name length, use the URL: - -``` -http://localhost:3000?client=cursor&capability=tool-name-length%3D40 -``` - -## Importing the tools and server individually - -```js -// Import the server, generated endpoints, or the init function -import { server, endpoints, init } from "@imagekit/api-mcp/server"; - -// import a specific tool -import createCustomMetadataFields from "@imagekit/api-mcp/tools/custom-metadata-fields/create-custom-metadata-fields"; - -// initialize the server and all endpoints -init({ server, endpoints }); - -// manually start server -const transport = new StdioServerTransport(); -await server.connect(transport); - -// or initialize your own server with specific tools -const myServer = new McpServer(...); - -// define your own endpoint -const myCustomEndpoint = { - tool: { - name: 'my_custom_tool', - description: 'My custom tool', - inputSchema: zodToJsonSchema(z.object({ a_property: z.string() })), - }, - handler: async (client: client, args: any) => { - return { myResponse: 'Hello world!' }; - }) -}; - -// initialize the server with your custom endpoints -init({ server: myServer, endpoints: [createCustomMetadataFields, myCustomEndpoint] }); -``` - -## Available Tools - -The following tools are available in this MCP server. - -### Resource `customMetadataFields`: - -- `create_custom_metadata_fields` (`write`): This API creates a new custom metadata field. Once a custom metadata field is created either through this API or using the dashboard UI, its value can be set on the assets. The value of a field for an asset can be set using the media library UI or programmatically through upload or update assets API. -- `update_custom_metadata_fields` (`write`): This API updates the label or schema of an existing custom metadata field. -- `list_custom_metadata_fields` (`read`): This API returns the array of created custom metadata field objects. By default the API returns only non deleted field objects, but you can include deleted fields in the API response. - - You can also filter results by a specific folder path to retrieve custom metadata fields applicable at that location. This path-specific filtering is useful when using the **Path policy** feature to determine which custom metadata fields are selected for a given path. - -- `delete_custom_metadata_fields` (`write`): This API deletes a custom metadata field. Even after deleting a custom metadata field, you cannot create any new custom metadata field with the same name. - -### Resource `files`: - -- `update_files` (`write`): This API updates the details or attributes of the current version of the file. You can update `tags`, `customCoordinates`, `customMetadata`, publication status, remove existing `AITags` and apply extensions using this API. -- `delete_files` (`write`): This API deletes the file and all its file versions permanently. - - Note: If a file or specific transformation has been requested in the past, then the response is cached. Deleting a file does not purge the cache. You can purge the cache using purge cache API. - -- `copy_files` (`write`): This will copy a file from one folder to another. - - Note: If any file at the destination has the same name as the source file, then the source file and its versions (if `includeFileVersions` is set to true) will be appended to the destination file version history. - -- `get_files` (`read`): This API returns an object with details or attributes about the current version of the file. -- `move_files` (`write`): This will move a file and all its versions from one folder to another. - - Note: If any file at the destination has the same name as the source file, then the source file and its versions will be appended to the destination file. - -- `rename_files` (`write`): You can rename an already existing file in the media library using rename file API. This operation would rename all file versions of the file. - - Note: The old URLs will stop working. The file/file version URLs cached on CDN will continue to work unless a purge is requested. - -- `upload_files` (`write`): ImageKit.io allows you to upload files directly from both the server and client sides. For server-side uploads, private API key authentication is used. For client-side uploads, generate a one-time `token`, `signature`, and `expire` from your secure backend using private API. [Learn more](/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload) about how to implement client-side file upload. - - The [V2 API](/docs/api-reference/upload-file/upload-file-v2) enhances security by verifying the entire payload using JWT. - - **File size limit** \ - On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw files and 100MB for videos. On the paid plan, these limits increase to 40MB for images, audio, and raw files and 2GB for videos. These limits can be further increased with higher-tier plans. - - **Version limit** \ - A file can have a maximum of 100 versions. - - **Demo applications** - - - A full-fledged [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), supporting file selections from local storage, URL, Dropbox, Google Drive, Instagram, and more. - - [Quick start guides](/docs/quick-start-guides) for various frameworks and technologies. - -### Resource `files.bulk`: - -- `delete_files_bulk` (`write`): This API deletes multiple files and all their file versions permanently. - - Note: If a file or specific transformation has been requested in the past, then the response is cached. Deleting a file does not purge the cache. You can purge the cache using purge cache API. - - A maximum of 100 files can be deleted at a time. - -- `add_tags_files_bulk` (`write`): This API adds tags to multiple files in bulk. A maximum of 50 files can be specified at a time. -- `remove_ai_tags_files_bulk` (`write`): This API removes AITags from multiple files in bulk. A maximum of 50 files can be specified at a time. -- `remove_tags_files_bulk` (`write`): This API removes tags from multiple files in bulk. A maximum of 50 files can be specified at a time. - -### Resource `files.versions`: - -- `list_files_versions` (`read`): This API returns details of all versions of a file. -- `delete_files_versions` (`write`): This API deletes a non-current file version permanently. The API returns an empty response. - - Note: If you want to delete all versions of a file, use the delete file API. - -- `get_files_versions` (`read`): This API returns an object with details or attributes of a file version. -- `restore_files_versions` (`write`): This API restores a file version as the current file version. - -### Resource `files.metadata`: - -- `get_files_metadata` (`read`): You can programmatically get image EXIF, pHash, and other metadata for uploaded files in the ImageKit.io media library using this API. - - You can also get the metadata in upload API response by passing `metadata` in `responseFields` parameter. - -- `get_from_url_files_metadata` (`read`): Get image EXIF, pHash, and other metadata from ImageKit.io powered remote URL using this API. - -### Resource `assets`: - -- `list_assets` (`read`): This API can list all the uploaded files and folders in your ImageKit.io media library. In addition, you can fine-tune your query by specifying various filters by generating a query string in a Lucene-like syntax and provide this generated string as the value of the `searchQuery`. - -### Resource `cache.invalidation`: - -- `create_cache_invalidation` (`write`): This API will purge CDN cache and ImageKit.io's internal cache for a file. Note: Purge cache is an asynchronous process and it may take some time to reflect the changes. -- `get_cache_invalidation` (`read`): This API returns the status of a purge cache request. - -### Resource `folders`: - -- `create_folders` (`write`): This will create a new folder. You can specify the folder name and location of the parent folder where this new folder should be created. -- `delete_folders` (`write`): This will delete a folder and all its contents permanently. The API returns an empty response. -- `copy_folders` (`write`): This will copy one folder into another. The selected folder, its nested folders, files, and their versions (in `includeVersions` is set to true) are copied in this operation. Note: If any file at the destination has the same name as the source file, then the source file and its versions will be appended to the destination file version history. -- `move_folders` (`write`): This will move one folder into another. The selected folder, its nested folders, files, and their versions are moved in this operation. Note: If any file at the destination has the same name as the source file, then the source file and its versions will be appended to the destination file version history. -- `rename_folders` (`write`): This API allows you to rename an existing folder. The folder and all its nested assets and sub-folders will remain unchanged, but their paths will be updated to reflect the new folder name. - -### Resource `folders.job`: - -- `get_folders_job` (`read`): This API returns the status of a bulk job like copy and move folder operations. - -### Resource `accounts.usage`: - -- `get_accounts_usage` (`read`): Get the account usage information between two dates. Note that the API response includes data from the start date while excluding data from the end date. In other words, the data covers the period starting from the specified start date up to, but not including, the end date. - -### Resource `accounts.origins`: - -- `create_accounts_origins` (`write`): **Note:** This API is currently in beta. - Creates a new origin and returns the origin object. -- `update_accounts_origins` (`write`): **Note:** This API is currently in beta. - Updates the origin identified by `id` and returns the updated origin object. -- `list_accounts_origins` (`read`): **Note:** This API is currently in beta. - Returns an array of all configured origins for the current account. -- `delete_accounts_origins` (`write`): **Note:** This API is currently in beta. - Permanently removes the origin identified by `id`. If the origin is in use by any URL‑endpoints, the API will return an error. -- `get_accounts_origins` (`read`): **Note:** This API is currently in beta. - Retrieves the origin identified by `id`. - -### Resource `accounts.urlEndpoints`: - -- `create_accounts_url_endpoints` (`write`): **Note:** This API is currently in beta. - Creates a new URL‑endpoint and returns the resulting object. -- `update_accounts_url_endpoints` (`write`): **Note:** This API is currently in beta. - Updates the URL‑endpoint identified by `id` and returns the updated object. -- `list_accounts_url_endpoints` (`read`): **Note:** This API is currently in beta. - Returns an array of all URL‑endpoints configured including the default URL-endpoint generated by ImageKit during account creation. -- `delete_accounts_url_endpoints` (`write`): **Note:** This API is currently in beta. - Deletes the URL‑endpoint identified by `id`. You cannot delete the default URL‑endpoint created by ImageKit during account creation. -- `get_accounts_url_endpoints` (`read`): **Note:** This API is currently in beta. - Retrieves the URL‑endpoint identified by `id`. - -### Resource `beta.v2.files`: - -- `upload_v2_beta_files` (`write`): The V2 API enhances security by verifying the entire payload using JWT. This API is in beta. - - ImageKit.io allows you to upload files directly from both the server and client sides. For server-side uploads, private API key authentication is used. For client-side uploads, generate a one-time `token` from your secure backend using private API. [Learn more](/docs/api-reference/upload-file/upload-file-v2#how-to-implement-secure-client-side-file-upload) about how to implement secure client-side file upload. - - **File size limit** \ - On the free plan, the maximum upload file sizes are 20MB for images, audio, and raw files, and 100MB for videos. On the paid plan, these limits increase to 40MB for images, audio, and raw files, and 2GB for videos. These limits can be further increased with higher-tier plans. - - **Version limit** \ - A file can have a maximum of 100 versions. - - **Demo applications** - - - A full-fledged [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), supporting file selections from local storage, URL, Dropbox, Google Drive, Instagram, and more. - - [Quick start guides](/docs/quick-start-guides) for various frameworks and technologies. diff --git a/packages/mcp-server/cloudflare-worker/package.json b/packages/mcp-server/cloudflare-worker/package.json index 85f7956d..1067db1d 100644 --- a/packages/mcp-server/cloudflare-worker/package.json +++ b/packages/mcp-server/cloudflare-worker/package.json @@ -18,7 +18,7 @@ }, "dependencies": { "@cloudflare/workers-oauth-provider": "^0.0.5", - "@modelcontextprotocol/sdk": "^1.11.4", + "@modelcontextprotocol/sdk": "^1.24.0", "agents": "^0.0.88", "hono": "^4.7.9", "@imagekit/api-mcp": "latest", diff --git a/packages/mcp-server/cloudflare-worker/src/app.ts b/packages/mcp-server/cloudflare-worker/src/app.ts index 3ed46ca8..5e3a8ec4 100644 --- a/packages/mcp-server/cloudflare-worker/src/app.ts +++ b/packages/mcp-server/cloudflare-worker/src/app.ts @@ -8,14 +8,13 @@ import { renderAuthorizationRejectedContent, } from './utils'; import type { OAuthHelpers } from '@cloudflare/workers-oauth-provider'; -import { McpOptions } from '@imagekit/api-mcp/server'; import { ServerConfig } from '.'; export type Bindings = Env & { OAUTH_PROVIDER: OAuthHelpers; }; -export function makeOAuthConsent(config: ServerConfig, defaultOptions?: Partial) { +export function makeOAuthConsent(config: ServerConfig) { const app = new Hono<{ Bindings: Bindings; }>(); @@ -30,17 +29,14 @@ export function makeOAuthConsent(config: ServerConfig, defaultOptions?: Partial< app.get('/authorize', async (c) => { const oauthReqInfo = await c.env.OAUTH_PROVIDER.parseAuthRequest(c.req.raw); - const content = await renderLoggedOutAuthorizeScreen(config, oauthReqInfo, defaultOptions); + const content = await renderLoggedOutAuthorizeScreen(config, oauthReqInfo); return c.html(layout(content, 'Authorization', config)); }); // This endpoint is responsible for validating any login information and // then completing the authorization request with the OAUTH_PROVIDER app.post('/approve', async (c) => { - const { action, oauthReqInfo, clientProps, clientConfig } = await parseApproveFormBody( - await c.req.parseBody(), - config, - ); + const { action, oauthReqInfo, clientProps } = await parseApproveFormBody(await c.req.parseBody(), config); if (action !== 'login_approve') { return c.html( @@ -52,7 +48,7 @@ export function makeOAuthConsent(config: ServerConfig, defaultOptions?: Partial< ); } - if (!oauthReqInfo || !clientProps || !clientConfig) { + if (!oauthReqInfo || !clientProps) { return c.html('INVALID LOGIN', 401); } @@ -67,7 +63,6 @@ export function makeOAuthConsent(config: ServerConfig, defaultOptions?: Partial< scope: oauthReqInfo.scope, props: { clientProps, - clientConfig, }, }); @@ -78,7 +73,7 @@ export function makeOAuthConsent(config: ServerConfig, defaultOptions?: Partial< // Render the authorize screen for demoing the OAuth flow (it won't actually log in) app.get('/demo', async (c) => { - const content = await renderLoggedOutAuthorizeScreen(config, {} as any, defaultOptions); + const content = await renderLoggedOutAuthorizeScreen(config, {} as any); return c.html(layout(content, 'Authorization', config)); }); diff --git a/packages/mcp-server/cloudflare-worker/src/index.ts b/packages/mcp-server/cloudflare-worker/src/index.ts index 35eecb01..18cc7802 100644 --- a/packages/mcp-server/cloudflare-worker/src/index.ts +++ b/packages/mcp-server/cloudflare-worker/src/index.ts @@ -2,6 +2,7 @@ import { makeOAuthConsent } from './app'; import { McpAgent } from 'agents/mcp'; import OAuthProvider from '@cloudflare/workers-oauth-provider'; import { McpOptions, initMcpServer, server, ClientOptions } from '@imagekit/api-mcp/server'; +import type { ExportedHandler } from '@cloudflare/workers-types'; type MCPProps = { clientProps: ClientOptions; @@ -102,7 +103,9 @@ export default new OAuthProvider({ // @ts-expect-error '/mcp': MyMCP.serve('/mcp'), // Streaming HTTP }, - defaultHandler: makeOAuthConsent(serverConfig), + // Type assertion needed due to Headers type mismatch between Hono and @cloudflare/workers-types + // At runtime, Hono's fetch handler is fully compatible with ExportedHandler + defaultHandler: makeOAuthConsent(serverConfig) as unknown as ExportedHandler, authorizeEndpoint: '/authorize', tokenEndpoint: '/token', clientRegistrationEndpoint: '/register', diff --git a/packages/mcp-server/cloudflare-worker/src/utils.ts b/packages/mcp-server/cloudflare-worker/src/utils.ts index 4f089916..4c00c592 100644 --- a/packages/mcp-server/cloudflare-worker/src/utils.ts +++ b/packages/mcp-server/cloudflare-worker/src/utils.ts @@ -4,7 +4,7 @@ import type { HtmlEscapedString } from 'hono/utils/html'; import { marked } from 'marked'; import type { AuthRequest } from '@cloudflare/workers-oauth-provider'; import { env } from 'cloudflare:workers'; -import { ServerConfig, McpOptions, ClientType, Filter, ClientProperty } from '@imagekit/api-mcp/server'; +import { ServerConfig, ClientProperty } from '.'; export const layout = (content: HtmlEscapedString | string, title: string, config: ServerConfig) => html` @@ -161,46 +161,10 @@ export const homeContent = async (req: Request): Promise => { return html`
${raw(content)}
`; }; -export const renderLoggedOutAuthorizeScreen = async ( - config: ServerConfig, - oauthReqInfo: AuthRequest, - defaultOptions?: Partial, -) => { +export const renderLoggedOutAuthorizeScreen = async (config: ServerConfig, oauthReqInfo: AuthRequest) => { const checked = (condition: boolean) => (condition ? 'checked' : ''); const selected = (condition: boolean) => (condition ? 'selected' : ''); - // Helper to check if a capability is enabled by default - const hasCapability = (capability: string) => { - if (!defaultOptions?.capabilities) { - // Default capabilities when none specified - return ['refs', 'unions', 'formats'].includes(capability); - } - switch (capability) { - case 'top-level-unions': - return defaultOptions.capabilities.topLevelUnions || false; - case 'valid-json': - return defaultOptions.capabilities.validJson || false; - case 'refs': - return defaultOptions.capabilities.refs || false; - case 'unions': - return defaultOptions.capabilities.unions || false; - case 'formats': - return defaultOptions.capabilities.formats || false; - default: - return false; - } - }; - - // Helper to check if an operation is enabled by default - const hasOperation = (operation: string) => { - if (!defaultOptions?.filters) { - // Default operations when none specified - return ['read', 'write'].includes(operation); - } - return defaultOptions.filters.some( - (f) => f.type === 'operation' && f.op === 'include' && f.value === operation, - ); - }; const renderField = (field: ClientProperty) => { if (field.type === 'select' && field.options) { return html` @@ -268,112 +232,6 @@ export const renderLoggedOutAuthorizeScreen = async (
${config.clientProperties.map(renderField)}
-
-
- - Configuration Options - -
-
- - -
- -
- - -
- - ? - -
- Have the LLM dynamically discover the endpoints, instead of directly exposing one tool per - endpoint. -
-
-
- -
-
- - -
- - ? - -
- Restrict the available tools to only be able to read data. -
-
-
-
-
-
-
-