-
Notifications
You must be signed in to change notification settings - Fork 78
feat: implement the new internal MCP configuration spec #226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
MQ37
merged 23 commits into
feat/tools-actors-input-allow-empty
from
feat/vibe-mcp-spec
Aug 26, 2025
Merged
Changes from 17 commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
0bb8397
feat: refactor and unify input handling, remove unnecessary logic
MQ37 abc22ca
feat: vibe new mcp input spec
MQ37 f06d72e
fix: remove unnecessary addTool in mcp/server.ts
MQ37 2e41b61
fix: fix stdio.only add-actor tool related circular dependency cause …
MQ37 f326b73
fix test suite, clean up
MQ37 662aba1
fix tests and logic to adhere to the new spec
MQ37 48301cd
refactor code
MQ37 fd1436f
lint
MQ37 4944f34
rename to fetch-actor-details
MQ37 4763f51
improve readme
MQ37 92c1244
update stdio help
MQ37 f969ac2
improve test case names
MQ37 3869388
fix and improve the call-actor generic tool
MQ37 47e93f2
more spec new spec complience tests
MQ37 8419e13
lint
MQ37 7bebb9c
one more test, just in case
MQ37 5799ebe
address pr comment and refactor the process input func
MQ37 ac81747
fix: Delete example clients, update Readme (#239)
jirispilka ceafe8b
Update tests/unit/input.test.ts
MQ37 495c465
Update tests/unit/input.test.ts
MQ37 3e7d9e8
Update README.md
MQ37 240793a
address review comments
MQ37 3947d1e
clean up imports and update comments for clarity, export functions fo…
MQ37 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,49 +1,78 @@ | ||
| /* | ||
| * Actor input processing. | ||
| * | ||
| * Normalizes raw inputs (CLI/env/HTTP) into a consistent `Input` shape. | ||
| * No tool-loading is done here; we only canonicalize values and preserve | ||
| * intent via `undefined` (use defaults later) vs empty (explicitly none). | ||
| */ | ||
| import log from '@apify/log'; | ||
|
|
||
| import type { Input, ToolCategory } from './types.js'; | ||
| import type { Input, ToolSelector } from './types.js'; | ||
|
|
||
| // Helpers | ||
| // Normalize booleans that may arrive as strings or be undefined. | ||
| function toBoolean(value: unknown, defaultValue: boolean): boolean { | ||
MQ37 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if (value === undefined) return defaultValue; | ||
| if (typeof value === 'boolean') return value; | ||
| if (typeof value === 'string') return value.toLowerCase() === 'true'; | ||
| return defaultValue; | ||
| } | ||
|
|
||
| // Normalize lists from comma-separated strings or arrays. | ||
| function normalizeList(value: string | string[] | undefined): string[] | undefined { | ||
MQ37 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if (value === undefined) return undefined; | ||
| if (Array.isArray(value)) return value.map((s) => String(s).trim()).filter((s) => s !== ''); | ||
| const trimmed = String(value).trim(); | ||
| if (trimmed === '') return []; | ||
| return trimmed.split(',').map((s) => s.trim()).filter((s) => s !== ''); | ||
| } | ||
|
|
||
| /** | ||
| * Process input parameters, split Actors string into an array | ||
| * @param originalInput | ||
| * @returns input | ||
| * Normalize user-provided input into a canonical `Input`. | ||
| * | ||
| * Responsibilities: | ||
| * - Coerce `actors`, `tools` from string/array into trimmed arrays ('' → []). | ||
| * - Normalize booleans (including legacy `enableActorAutoLoading`). | ||
| * - Merge `actors` into `tools` so selection lives in one place. | ||
| * | ||
| * Semantics passed to the loader: | ||
| * - `undefined` → use defaults; `[]` → explicitly none. | ||
| */ | ||
| export function processInput(originalInput: Partial<Input>): Input { | ||
| const input = originalInput as Input; | ||
|
|
||
| // actors can be a string or an array of strings | ||
| if (input.actors && typeof input.actors === 'string') { | ||
| /** | ||
| * Filter out empty strings to prevent invalid Actor API error. | ||
| */ | ||
| input.actors = input.actors.split(',').map((format: string) => format.trim()).filter((actor) => actor !== '') as string[]; | ||
| } | ||
| /** | ||
| * Replace empty string with empty array to prevent invalid Actor API error. | ||
| */ | ||
| if (input.actors === '') { | ||
| input.actors = []; | ||
| // Normalize actors (strings and arrays) to a clean array or undefined | ||
| const actors = normalizeList(originalInput.actors) as unknown as string[] | undefined; | ||
|
|
||
| // Map deprecated flag to the new one and normalize both to boolean. | ||
| let enableAddingActors: boolean; | ||
| if (originalInput.enableAddingActors === undefined && originalInput.enableActorAutoLoading !== undefined) { | ||
| log.warning('enableActorAutoLoading is deprecated, use enableAddingActors instead'); | ||
| enableAddingActors = toBoolean(originalInput.enableActorAutoLoading, false); | ||
| } else { | ||
| enableAddingActors = toBoolean(originalInput.enableAddingActors, false); | ||
| } | ||
|
|
||
| // enableAddingActors is deprecated, use enableActorAutoLoading instead | ||
| if (input.enableAddingActors === undefined) { | ||
| if (input.enableActorAutoLoading !== undefined) { | ||
| log.warning('enableActorAutoLoading is deprecated, use enableAddingActors instead'); | ||
| input.enableAddingActors = input.enableActorAutoLoading === true || input.enableActorAutoLoading === 'true'; | ||
| // Normalize tools (strings/arrays) to a clean array or undefined | ||
| let tools = normalizeList(originalInput.tools as string | string[] | undefined) as unknown as ToolSelector[] | undefined; | ||
|
|
||
| // Merge actors into tools. If tools undefined → tools = actors, then remove actors; | ||
| // otherwise append actors to tools. | ||
| // NOTE (future): Actor names contain '/', unlike internal tool names or categories. We could use that to differentiate between the two. | ||
| if (Array.isArray(actors) && actors.length > 0) { | ||
| if (tools === undefined) { | ||
| tools = [...actors] as ToolSelector[]; | ||
| } else { | ||
| input.enableAddingActors = true; | ||
| const currentTools: ToolSelector[] = Array.isArray(tools) | ||
| ? tools | ||
| : [tools as ToolSelector]; | ||
| tools = [...currentTools, ...actors] as ToolSelector[]; | ||
| } | ||
| } else { | ||
| input.enableAddingActors = input.enableAddingActors === true || input.enableAddingActors === 'true'; | ||
| } | ||
|
|
||
| if (input.tools && typeof input.tools === 'string') { | ||
| /** | ||
| * Filter out empty strings just in case. | ||
| */ | ||
| input.tools = input.tools.split(',').map((tool: string) => tool.trim()).filter((tool) => tool !== '') as ToolCategory[]; | ||
| } | ||
| return input; | ||
| // Return a new object with all properties explicitly defined | ||
| return { | ||
| ...originalInput, | ||
| actors: Array.isArray(actors) && actors.length > 0 && tools !== undefined ? undefined : actors, | ||
| enableAddingActors, | ||
| tools, | ||
| }; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.