@foldkit/devtools-mcp
Advanced tools
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAA8B,MAAM,QAAQ,CAAA;AAOlE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AA0L3D,KAAK,UAAU,GAAG,QAAQ,CAAC;IACzB,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;IAChE,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAC,CAAA;AAEF,8HAA8H;AAC9H,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;CACzD,CAAC,CAAA;AAsHF;;;;GAIG;AACH,eAAO,MAAM,UAAU,aACX,eAAe,KACxB,aAAa,CAAC,cAAc,CAsM9B,CAAA"} | ||
| {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAyB,MAAM,QAAQ,CAAA;AAO7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AA0L3D,KAAK,UAAU,GAAG,QAAQ,CAAC;IACzB,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;IAChE,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAC,CAAA;AAEF,8HAA8H;AAC9H,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;CACzD,CAAC,CAAA;AAsHF;;;;GAIG;AACH,eAAO,MAAM,UAAU,aACX,eAAe,KACxB,aAAa,CAAC,cAAc,CAsM9B,CAAA"} |
+38
-38
@@ -1,43 +0,43 @@ | ||
| import { Array, Effect, Match, Option, Schema as S } from 'effect'; | ||
| import { Array, Effect, Match, Option, Schema } from 'effect'; | ||
| import { MAX_DISPATCH_BATCH_SIZE, Request, } from 'foldkit/devtools-protocol'; | ||
| const RUNTIME_ID_DESCRIPTION = 'Optional connection id of a specific Foldkit runtime. Defaults to the most recently connected runtime.'; | ||
| const DEFAULT_LIST_MESSAGES_LIMIT = 50; | ||
| const RuntimeIdField = S.optional(S.String.annotate({ description: RUNTIME_ID_DESCRIPTION })); | ||
| const ListLimit = S.Int.check(S.isBetween({ minimum: 1, maximum: 500 })).annotate({ | ||
| const RuntimeIdField = Schema.optional(Schema.String.annotate({ description: RUNTIME_ID_DESCRIPTION })); | ||
| const ListLimit = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 500 })).annotate({ | ||
| description: `Maximum number of entries to return. Defaults to ${DEFAULT_LIST_MESSAGES_LIMIT}; max 500.`, | ||
| }); | ||
| const SinceIndex = S.Int.annotate({ | ||
| const SinceIndex = Schema.Int.annotate({ | ||
| description: 'Absolute history index to start from. Use the maybeNextIndex returned by a prior call to paginate.', | ||
| }); | ||
| const ChangedPathsMatchField = S.optional(S.Array(S.String).annotate({ | ||
| const ChangedPathsMatchField = Schema.optional(Schema.Array(Schema.String).annotate({ | ||
| description: "Dot-string path patterns matched against each entry's changedPaths, in the same 'root'-anchored alphabet foldkit_get_model uses. An entry matches when any pattern matches any changed path. Patterns compare segment-by-segment for the length of the shorter side, so 'root.grid' matches every change inside the grid subtree, and 'root.grid.5.3' also matches a wholesale replacement recorded at 'root.grid'. '*' matches exactly one segment: 'root.cards.*.title'. Entries that did not change the Model never match. An empty list applies no filter. Patterns not starting with 'root' or '*' are rejected.", | ||
| })); | ||
| const DiffChangedPathsMatchField = S.optional(S.Array(S.String).annotate({ | ||
| const DiffChangedPathsMatchField = Schema.optional(Schema.Array(Schema.String).annotate({ | ||
| description: "Dot-string path patterns narrowing the reported changes, in the same 'root'-anchored alphabet as changedPaths. A changed path is kept when any pattern matches it: patterns compare segment-by-segment for the length of the shorter side ('root.grid' keeps everything under the grid subtree) and '*' matches exactly one segment. An empty list applies no filter. Patterns not starting with 'root' or '*' are rejected.", | ||
| })); | ||
| const FromEndField = S.optional(S.Boolean.annotate({ | ||
| const FromEndField = Schema.optional(Schema.Boolean.annotate({ | ||
| description: "When true, return the final `limit` matching entries (the most recent) instead of the first, still in chronological order. The natural first call when live-debugging: 'what just happened'. Cannot be combined with since_index.", | ||
| })); | ||
| const DiffFromIndex = S.Int.annotate({ | ||
| const DiffFromIndex = Schema.Int.annotate({ | ||
| description: 'Absolute history index of the diff baseline: the Model state right after this entry was applied. Use -1 for the initial Model.', | ||
| }); | ||
| const DiffToIndex = S.Int.annotate({ | ||
| const DiffToIndex = Schema.Int.annotate({ | ||
| description: 'Absolute history index of the diff target: the Model state right after this entry was applied. -1 addresses the initial Model.', | ||
| }); | ||
| const MessageIndex = S.Int.annotate({ | ||
| const MessageIndex = Schema.Int.annotate({ | ||
| description: 'Absolute history index of the entry to read.', | ||
| }); | ||
| const KeyframeIndex = S.Int.annotate({ | ||
| const KeyframeIndex = Schema.Int.annotate({ | ||
| description: 'Index to replay to. Use -1 to jump to the initial Model (before any messages). Use a non-negative index to jump to the Model state right after that history index. Call foldkit_list_keyframes for the canonical replay points.', | ||
| }); | ||
| const ModelIndex = S.Int.annotate({ | ||
| const ModelIndex = Schema.Int.annotate({ | ||
| description: 'Absolute history index. Returns the Model state right after the entry at this index was applied. To inspect the Model immediately before message N, pass index N - 1. For the initial Model, use foldkit_get_init.', | ||
| }); | ||
| const PathField = S.optional(S.String.annotate({ | ||
| const PathField = Schema.optional(Schema.String.annotate({ | ||
| description: "Dot-string path into the Model anchored at 'root'. Examples: 'root', 'root.route', 'root.session.user', 'root.cards.0'. Matches the alphabet used by SerializedEntry.changedPaths so paths copied from one tool's output can be passed straight into the next. Defaults to 'root' (the whole Model).", | ||
| })); | ||
| const ExpandField = S.optional(S.Boolean.annotate({ | ||
| const ExpandField = Schema.optional(Schema.Boolean.annotate({ | ||
| description: "When false (the default), large arrays/records/strings collapse to '_summary' placeholders to keep payloads small. Set true to receive the literal value at the path. Pair with `path` to drill in: a narrow path with `expand: true` is the cheapest way to read a specific subtree at full fidelity.", | ||
| })); | ||
| const GetModelInput = S.Struct({ | ||
| const GetModelInput = Schema.Struct({ | ||
| runtime_id: RuntimeIdField, | ||
@@ -47,3 +47,3 @@ path: PathField, | ||
| }); | ||
| const GetModelAtInput = S.Struct({ | ||
| const GetModelAtInput = Schema.Struct({ | ||
| runtime_id: RuntimeIdField, | ||
@@ -54,15 +54,15 @@ index: ModelIndex, | ||
| }); | ||
| const ListMessagesInput = S.Struct({ | ||
| const ListMessagesInput = Schema.Struct({ | ||
| runtime_id: RuntimeIdField, | ||
| limit: S.optional(ListLimit), | ||
| since_index: S.optional(SinceIndex), | ||
| limit: Schema.optional(ListLimit), | ||
| since_index: Schema.optional(SinceIndex), | ||
| changed_paths_match: ChangedPathsMatchField, | ||
| from_end: FromEndField, | ||
| }); | ||
| const CountMessagesByTagInput = S.Struct({ | ||
| const CountMessagesByTagInput = Schema.Struct({ | ||
| runtime_id: RuntimeIdField, | ||
| since_index: S.optional(SinceIndex), | ||
| since_index: Schema.optional(SinceIndex), | ||
| changed_paths_match: ChangedPathsMatchField, | ||
| }); | ||
| const DiffModelsInput = S.Struct({ | ||
| const DiffModelsInput = Schema.Struct({ | ||
| runtime_id: RuntimeIdField, | ||
@@ -73,32 +73,32 @@ from_index: DiffFromIndex, | ||
| }); | ||
| const GetMessageInput = S.Struct({ | ||
| const GetMessageInput = Schema.Struct({ | ||
| runtime_id: RuntimeIdField, | ||
| index: MessageIndex, | ||
| }); | ||
| const ListKeyframesInput = S.Struct({ | ||
| const ListKeyframesInput = Schema.Struct({ | ||
| runtime_id: RuntimeIdField, | ||
| }); | ||
| const ReplayToKeyframeInput = S.Struct({ | ||
| const ReplayToKeyframeInput = Schema.Struct({ | ||
| runtime_id: RuntimeIdField, | ||
| keyframe_index: KeyframeIndex, | ||
| }); | ||
| const ResumeInput = S.Struct({ | ||
| const ResumeInput = Schema.Struct({ | ||
| runtime_id: RuntimeIdField, | ||
| }); | ||
| const GetInitInput = S.Struct({ | ||
| const GetInitInput = Schema.Struct({ | ||
| runtime_id: RuntimeIdField, | ||
| }); | ||
| const GetRuntimeStateInput = S.Struct({ | ||
| const GetRuntimeStateInput = Schema.Struct({ | ||
| runtime_id: RuntimeIdField, | ||
| }); | ||
| const DispatchMessageInput = S.Struct({ | ||
| const DispatchMessageInput = Schema.Struct({ | ||
| runtime_id: RuntimeIdField, | ||
| message: S.Record(S.String, S.Unknown).annotate({ | ||
| message: Schema.Record(Schema.String, Schema.Unknown).annotate({ | ||
| description: "A Foldkit Message object to dispatch into the runtime. Must match the runtime's Message Schema. Call `foldkit_get_message_schema` with no arguments to see the available variant tags, then `foldkit_get_message_schema { variant_tag: \"X\" }` to learn one variant's exact payload shape. At minimum it has a `_tag` field naming the variant. The runtime decodes the payload and returns a clean error if it doesn't match.", | ||
| }), | ||
| }); | ||
| const DispatchMessagesInput = S.Struct({ | ||
| const DispatchMessagesInput = Schema.Struct({ | ||
| runtime_id: RuntimeIdField, | ||
| messages: S.Array(S.Record(S.String, S.Unknown)) | ||
| .check(S.isNonEmpty(), S.isMaxLength(MAX_DISPATCH_BATCH_SIZE)) | ||
| messages: Schema.Array(Schema.Record(Schema.String, Schema.Unknown)) | ||
| .check(Schema.isNonEmpty(), Schema.isMaxLength(MAX_DISPATCH_BATCH_SIZE)) | ||
| .annotate({ | ||
@@ -108,6 +108,6 @@ description: `An ordered list of Foldkit Message objects to dispatch into the runtime, first to last. Must hold between 1 and ${MAX_DISPATCH_BATCH_SIZE} Messages. Each must match the runtime's Message Schema; call foldkit_get_message_schema to learn the shapes. The runtime decodes every entry before dispatching any of them, so one invalid entry rejects the whole batch with its zero-based position and nothing is dispatched.`, | ||
| }); | ||
| const VariantTagField = S.optional(S.String.annotate({ | ||
| const VariantTagField = Schema.optional(Schema.String.annotate({ | ||
| description: 'Optional dot-separated path of variant `_tag` values. When omitted, the tool returns a small variant index (tag names plus payload field names plus a tagged-union indicator) so agents can enumerate the top-level union cheaply. When provided, the tool walks the path through each variant\'s single tagged-union payload field, narrows the schema along the chain, and collapses any union deeper than the path to a `{ "_summary": "union", "variants": [...] }` placeholder. Extend the path to drill further. Examples: `"ScrolledSidebar"` (one top-level variant), `"GotMobileMenuDialogMessage.GotAnimationMessage"` (two levels of a Submodel chain).', | ||
| })); | ||
| const GetMessageSchemaInput = S.Struct({ | ||
| const GetMessageSchemaInput = Schema.Struct({ | ||
| runtime_id: RuntimeIdField, | ||
@@ -123,3 +123,3 @@ variant_tag: VariantTagField, | ||
| */ | ||
| const toInputSchema = (codec) => S.toJsonSchemaDocument(codec).schema; | ||
| const toInputSchema = (codec) => Schema.toJsonSchemaDocument(codec).schema; | ||
| const NO_INPUT_SCHEMA = { | ||
@@ -147,3 +147,3 @@ type: 'object', | ||
| */ | ||
| const decodeInput = (schema, rawInput) => S.decodeUnknownEffect(schema)(rawInput).pipe(Effect.mapError(error => new Error(`Invalid input: ${error.message}`))); | ||
| const decodeInput = (schema, rawInput) => Schema.decodeUnknownEffect(schema)(rawInput).pipe(Effect.mapError(error => new Error(`Invalid input: ${error.message}`))); | ||
| /** | ||
@@ -276,3 +276,3 @@ * Resolve a runtime id, defaulting to the most recently connected runtime when | ||
| name: 'foldkit_get_message_schema', | ||
| description: 'Describe the Message Schema for a Foldkit runtime so agents can construct valid payloads for `foldkit_dispatch_message`. Call with no arguments to receive a small variant index (every top-level variant\'s `_tag`, its payload field names, and which payload fields are themselves tagged-union shapes). Then call with `variant_tag: "ChosenVariant"` to drill in. The argument is a dot-separated path of variant `_tag` values: each segment names a variant, and the walker steps through the variant\'s single tagged-union payload field to reach the next. So `"GotMobileMenuDialogMessage"` narrows one level; `"GotMobileMenuDialogMessage.GotAnimationMessage"` narrows two levels of a Submodel chain. Discriminated unions deeper than the supplied path collapse to `{ "_summary": "union", "variants": [...] }` placeholders so the response stays compact even for deeply-nested apps; extend the path to drill further. `S.Option` fields render as `anyOf: [{_tag: "Some", value}, {_tag: "None"}]`. The full document follows the JSON Schema draft-2020-12 shape from `Schema.toJsonSchemaDocument`: `{ dialect, schema, definitions }`. Returns `maybeResult: None` when the runtime hasn\'t configured `DevToolsConfig.Message` (dispatch is also unavailable). Fields with no JSON representation, notably `S.instanceOf(File)` for user-uploaded files, render as `{type: "null"}`; those variants can\'t be dispatched via MCP because their values live in browser memory.', | ||
| description: 'Describe the Message Schema for a Foldkit runtime so agents can construct valid payloads for `foldkit_dispatch_message`. Call with no arguments to receive a small variant index (every top-level variant\'s `_tag`, its payload field names, and which payload fields are themselves tagged-union shapes). Then call with `variant_tag: "ChosenVariant"` to drill in. The argument is a dot-separated path of variant `_tag` values: each segment names a variant, and the walker steps through the variant\'s single tagged-union payload field to reach the next. So `"GotMobileMenuDialogMessage"` narrows one level; `"GotMobileMenuDialogMessage.GotAnimationMessage"` narrows two levels of a Submodel chain. Discriminated unions deeper than the supplied path collapse to `{ "_summary": "union", "variants": [...] }` placeholders so the response stays compact even for deeply-nested apps; extend the path to drill further. `Schema.Option` fields render as `anyOf: [{_tag: "Some", value}, {_tag: "None"}]`. The full document follows the JSON Schema draft-2020-12 shape from `Schema.toJsonSchemaDocument`: `{ dialect, schema, definitions }`. Returns `maybeResult: None` when the runtime hasn\'t configured `DevToolsConfig.Message` (dispatch is also unavailable). Fields with no JSON representation, notably `Schema.instanceOf(File)` for user-uploaded files, render as `{type: "null"}`; those variants can\'t be dispatched via MCP because their values live in browser memory.', | ||
| inputSchema: toInputSchema(GetMessageSchemaInput), | ||
@@ -279,0 +279,0 @@ handle: runRuntimeTool(GetMessageSchemaInput, ({ variant_tag }) => Request.RequestGetMessageSchema({ |
@@ -1,2 +0,2 @@ | ||
| import { Console, Deferred, Duration, Effect, Exit, Fiber, HashMap, Option, Ref, Schema as S, Schedule, pipe, } from 'effect'; | ||
| import { Console, Deferred, Duration, Effect, Exit, Fiber, HashMap, Option, Ref, Schedule, Schema, pipe, } from 'effect'; | ||
| import { RequestFrame, ResponseFrame, } from 'foldkit/devtools-protocol'; | ||
@@ -7,3 +7,3 @@ import { WebSocket } from 'ws'; | ||
| const MAX_RECONNECT_DELAY = Duration.seconds(30); | ||
| const encodeRequestFrameToJson = S.encodeUnknownSync(S.fromJsonString(RequestFrame)); | ||
| const encodeRequestFrameToJson = Schema.encodeUnknownSync(Schema.fromJsonString(RequestFrame)); | ||
| const generateRequestId = () => `req-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`; | ||
@@ -123,3 +123,3 @@ const reconnectSchedule = Schedule.exponential(INITIAL_RECONNECT_DELAY).pipe(Schedule.modifyDelay(({ duration }) => Effect.succeed(Duration.min(duration, MAX_RECONNECT_DELAY)))); | ||
| const handleIncomingMessage = (raw, pendingResponsesRef) => { | ||
| const decoded = S.decodeUnknownExit(S.fromJsonString(ResponseFrame))(raw.toString()); | ||
| const decoded = Schema.decodeUnknownExit(Schema.fromJsonString(ResponseFrame))(raw.toString()); | ||
| return Exit.match(decoded, { | ||
@@ -126,0 +126,0 @@ onFailure: error => Effect.sync(() => console.error('[foldkit-devtools-mcp] failed to decode frame', error)), |
+3
-3
| { | ||
| "name": "@foldkit/devtools-mcp", | ||
| "version": "0.19.2-canary.4aab52dcbe58", | ||
| "version": "0.19.2-canary.57e24366c899", | ||
| "description": "MCP server exposing Foldkit DevTools to AI agents (Claude Code, Cursor, etc.)", | ||
@@ -20,3 +20,3 @@ "type": "module", | ||
| "effect": "4.0.0-rc.112", | ||
| "foldkit": "0.156.0-canary.4aab52dcbe58" | ||
| "foldkit": "0.156.0-canary.57e24366c899" | ||
| }, | ||
@@ -34,3 +34,3 @@ "dependencies": { | ||
| "typescript": "^7.0.2", | ||
| "foldkit": "0.156.0-canary.4aab52dcbe58" | ||
| "foldkit": "0.156.0-canary.57e24366c899" | ||
| }, | ||
@@ -37,0 +37,0 @@ "files": [ |
Sorry, the diff of this file is too big to display
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
1536851
0.02%43007
0.04%