extrait 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -233,6 +233,7 @@ Run examples with: `bun run dev <example-name>`
233
233
  Available examples:
234
234
  - `streaming` - Real LLM streaming + snapshot self-check ([streaming.ts](examples/streaming.ts))
235
235
  - `streaming-with-tools` - Real text streaming with MCP tools + self-check ([streaming-with-tools.ts](examples/streaming-with-tools.ts))
236
+ - `abort-signal` - Start a generation then cancel quickly with `AbortSignal` ([abort-signal.ts](examples/abort-signal.ts))
236
237
  - `simple` - Basic structured output with streaming ([simple.ts](examples/simple.ts))
237
238
  - `sentiment-analysis` - Enum validation, strict mode ([sentiment-analysis.ts](examples/sentiment-analysis.ts))
238
239
  - `data-extraction` - Complex nested schemas, self-healing ([data-extraction.ts](examples/data-extraction.ts))
@@ -243,6 +244,7 @@ Pass arguments after the example name:
243
244
  ```bash
244
245
  bun run dev streaming
245
246
  bun run dev streaming-with-tools
247
+ bun run dev abort-signal 120 "JSON cancellation demo"
246
248
  bun run dev simple "Bun.js runtime"
247
249
  bun run dev sentiment-analysis "I love this product."
248
250
  bun run dev multi-step-reasoning "Why is the sky blue?"
package/dist/index.cjs CHANGED
@@ -1294,11 +1294,42 @@ async function executeMCPToolCalls(calls, toolset, context) {
1294
1294
  throw new Error("Received a function tool call without id or name.");
1295
1295
  }
1296
1296
  const tool = toolset.byName.get(toolName);
1297
+ const parsedArguments = parseToolArguments(call.arguments);
1297
1298
  if (!tool) {
1298
- throw new Error(`No MCP tool registered for "${toolName}".`);
1299
+ const errorMessage = context.request.unknownToolError ? context.request.unknownToolError(toolName) : `Tool "${toolName}" is not registered in the current toolset.`;
1300
+ const metadata2 = {
1301
+ id: callId,
1302
+ type: call.type ?? "function",
1303
+ name: toolName,
1304
+ arguments: parsedArguments,
1305
+ error: errorMessage
1306
+ };
1307
+ const startedAt2 = new Date().toISOString();
1308
+ const execution = {
1309
+ callId,
1310
+ type: metadata2.type,
1311
+ name: toolName,
1312
+ clientId: "__unregistered__",
1313
+ remoteName: toolName,
1314
+ arguments: parsedArguments,
1315
+ error: errorMessage,
1316
+ round: context.round,
1317
+ provider: context.provider,
1318
+ model: context.model,
1319
+ handledLocally: true,
1320
+ startedAt: startedAt2,
1321
+ durationMs: 0
1322
+ };
1323
+ emitToolExecution(context.request, execution);
1324
+ out.push({ call: metadata2, execution });
1325
+ continue;
1299
1326
  }
1300
- const parsedArguments = parseToolArguments(call.arguments);
1301
- const args = isRecord(parsedArguments) ? parsedArguments : {};
1327
+ const rawArgs = isRecord(parsedArguments) ? parsedArguments : {};
1328
+ const args = context.request.transformToolArguments ? await context.request.transformToolArguments(rawArgs, {
1329
+ name: toolName,
1330
+ remoteName: tool.remoteName,
1331
+ clientId: tool.clientId
1332
+ }) : rawArgs;
1302
1333
  const metadata = {
1303
1334
  id: callId,
1304
1335
  type: call.type ?? "function",
@@ -1617,7 +1648,8 @@ function createOpenAICompatibleAdapter(options) {
1617
1648
  temperature: request.temperature,
1618
1649
  max_tokens: request.maxTokens,
1619
1650
  stream: true
1620
- }))
1651
+ })),
1652
+ signal: request.signal
1621
1653
  });
1622
1654
  if (!response.ok) {
1623
1655
  const message = await response.text();
@@ -1688,7 +1720,8 @@ async function completeWithChatCompletionsPassThrough(options, fetcher, path, re
1688
1720
  temperature: request.temperature,
1689
1721
  max_tokens: request.maxTokens,
1690
1722
  stream: false
1691
- }))
1723
+ })),
1724
+ signal: request.signal
1692
1725
  });
1693
1726
  if (!response.ok) {
1694
1727
  const message = await response.text();
@@ -1732,7 +1765,8 @@ async function completeWithChatCompletionsWithMCP(options, fetcher, path, reques
1732
1765
  tools: transportTools,
1733
1766
  tool_choice: request.toolChoice,
1734
1767
  parallel_tool_calls: request.parallelToolCalls
1735
- }))
1768
+ })),
1769
+ signal: request.signal
1736
1770
  });
1737
1771
  if (!response.ok) {
1738
1772
  const message = await response.text();
@@ -1797,7 +1831,8 @@ async function completeWithResponsesAPIPassThrough(options, fetcher, path, reque
1797
1831
  previous_response_id: pickString(body?.previous_response_id),
1798
1832
  temperature: request.temperature,
1799
1833
  max_output_tokens: request.maxTokens
1800
- }))
1834
+ })),
1835
+ signal: request.signal
1801
1836
  });
1802
1837
  if (!response.ok) {
1803
1838
  const message = await response.text();
@@ -1839,7 +1874,8 @@ async function completeWithResponsesAPIWithMCP(options, fetcher, path, request)
1839
1874
  tools: transportTools,
1840
1875
  tool_choice: request.toolChoice,
1841
1876
  parallel_tool_calls: request.parallelToolCalls
1842
- }))
1877
+ })),
1878
+ signal: request.signal
1843
1879
  });
1844
1880
  if (!response.ok) {
1845
1881
  const message = await response.text();
@@ -1915,7 +1951,8 @@ async function streamWithChatCompletionsWithMCP(options, fetcher, path, request,
1915
1951
  tool_choice: request.toolChoice,
1916
1952
  parallel_tool_calls: request.parallelToolCalls,
1917
1953
  stream: true
1918
- }))
1954
+ })),
1955
+ signal: request.signal
1919
1956
  });
1920
1957
  if (!response.ok) {
1921
1958
  const message = await response.text();
@@ -2017,7 +2054,8 @@ async function streamWithResponsesAPIPassThrough(options, fetcher, path, request
2017
2054
  temperature: request.temperature,
2018
2055
  max_output_tokens: request.maxTokens,
2019
2056
  stream: true
2020
- }))
2057
+ })),
2058
+ signal: request.signal
2021
2059
  });
2022
2060
  if (!response.ok) {
2023
2061
  const message = await response.text();
@@ -2099,7 +2137,8 @@ async function streamWithResponsesAPIWithMCP(options, fetcher, path, request, ca
2099
2137
  tool_choice: request.toolChoice,
2100
2138
  parallel_tool_calls: request.parallelToolCalls,
2101
2139
  stream: true
2102
- }))
2140
+ })),
2141
+ signal: request.signal
2103
2142
  });
2104
2143
  if (!response.ok) {
2105
2144
  const message = await response.text();
@@ -2663,7 +2702,8 @@ function createAnthropicCompatibleAdapter(options) {
2663
2702
  temperature: request.temperature,
2664
2703
  max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
2665
2704
  stream: true
2666
- }))
2705
+ })),
2706
+ signal: request.signal
2667
2707
  });
2668
2708
  if (!response.ok) {
2669
2709
  const message = await response.text();
@@ -2721,7 +2761,8 @@ async function completePassThrough(options, fetcher, path, request) {
2721
2761
  temperature: request.temperature,
2722
2762
  max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
2723
2763
  stream: false
2724
- }))
2764
+ })),
2765
+ signal: request.signal
2725
2766
  });
2726
2767
  if (!response.ok) {
2727
2768
  const message = await response.text();
@@ -2766,7 +2807,8 @@ async function completeWithMCPToolLoop(options, fetcher, path, request) {
2766
2807
  tools,
2767
2808
  tool_choice: toAnthropicToolChoice(request.toolChoice),
2768
2809
  stream: false
2769
- }))
2810
+ })),
2811
+ signal: request.signal
2770
2812
  });
2771
2813
  if (!response.ok) {
2772
2814
  const message = await response.text();
@@ -2849,7 +2891,8 @@ async function streamWithMCPToolLoop(options, fetcher, path, request, callbacks)
2849
2891
  tools,
2850
2892
  tool_choice: toAnthropicToolChoice(request.toolChoice),
2851
2893
  stream: true
2852
- }))
2894
+ })),
2895
+ signal: request.signal
2853
2896
  });
2854
2897
  if (!response.ok) {
2855
2898
  const message = await response.text();
@@ -4226,7 +4269,8 @@ async function callModel(adapter, options) {
4226
4269
  maxToolRounds: options.request?.maxToolRounds,
4227
4270
  onToolExecution: options.request?.onToolExecution,
4228
4271
  toolDebug: options.request?.toolDebug,
4229
- body: options.request?.body
4272
+ body: options.request?.body,
4273
+ signal: options.request?.signal
4230
4274
  };
4231
4275
  emitDebugRequest(options.debug, {
4232
4276
  provider: adapter.provider,
@@ -4640,7 +4684,8 @@ async function createMCPClient(options) {
4640
4684
  return wrapMCPClient({
4641
4685
  id: options.id,
4642
4686
  client,
4643
- transport
4687
+ transport,
4688
+ toolCallTimeoutMs: options.toolCallTimeoutMs
4644
4689
  });
4645
4690
  }
4646
4691
  function wrapMCPClient(options) {
@@ -4660,7 +4705,8 @@ function wrapMCPClient(options) {
4660
4705
  };
4661
4706
  },
4662
4707
  async callTool(params) {
4663
- return options.client.callTool(params);
4708
+ const callOptions = options.toolCallTimeoutMs === undefined ? undefined : { timeout: options.toolCallTimeoutMs };
4709
+ return options.client.callTool(params, undefined, callOptions);
4664
4710
  },
4665
4711
  async close() {
4666
4712
  await options.client.close();
package/dist/index.d.ts CHANGED
@@ -12,4 +12,4 @@ export { createOpenAICompatibleAdapter, type OpenAICompatibleAdapterOptions, } f
12
12
  export { createAnthropicCompatibleAdapter, DEFAULT_ANTHROPIC_MAX_TOKENS, DEFAULT_ANTHROPIC_VERSION, type AnthropicCompatibleAdapterOptions, } from "./providers/anthropic-compatible";
13
13
  export { DEFAULT_MAX_TOOL_ROUNDS } from "./providers/mcp-runtime";
14
14
  export { createDefaultProviderRegistry, createModelAdapter, createProviderRegistry, registerBuiltinProviders, type BuiltinProviderKind, type ModelAdapterConfig, type ProviderFactory, type ProviderRegistry, type ProviderTransportConfig, } from "./providers/registry";
15
- export type { CandidateDiagnostics, ExtractJsonCandidatesOptions, ExtractionCandidate, ExtractionHeuristicsOptions, ExtractionParseHint, HTTPHeaders, LLMAdapter, LLMRequest, LLMResponse, LLMStreamCallbacks, LLMStreamChunk, LLMToolCall, LLMToolDebugOptions, LLMToolExecution, LLMToolOutputTransformer, LLMToolChoice, MCPCallToolParams, MCPListToolsResult, MCPToolClient, MCPToolDescriptor, MCPToolSchema, LLMUsage, MarkdownCodeBlock, MarkdownCodeOptions, ParseLLMOutputOptions, ParseLLMOutputResult, ParseTraceEvent, PipelineError, StructuredAttempt, StructuredCallOptions, StructuredDebugOptions, StructuredError, StructuredMode, StructuredOptions, StructuredPromptBuilder, StructuredPromptContext, StructuredPromptPayload, StructuredPromptResolver, StructuredPromptValue, StructuredResult, StructuredStreamData, StructuredStreamEvent, StructuredStreamInput, StructuredStreamOptions, StructuredSelfHealInput, ThinkDiagnostics, ThinkBlock, StructuredTraceEvent, } from "./types";
15
+ export type { CandidateDiagnostics, ExtractJsonCandidatesOptions, ExtractionCandidate, ExtractionHeuristicsOptions, ExtractionParseHint, HTTPHeaders, LLMAdapter, LLMRequest, LLMResponse, LLMStreamCallbacks, LLMStreamChunk, LLMToolCall, LLMToolDebugOptions, LLMToolExecution, LLMToolOutputTransformer, LLMToolArgumentsTransformer, LLMToolChoice, MCPCallToolParams, MCPListToolsResult, MCPToolClient, MCPToolDescriptor, MCPToolSchema, LLMUsage, MarkdownCodeBlock, MarkdownCodeOptions, ParseLLMOutputOptions, ParseLLMOutputResult, ParseTraceEvent, PipelineError, StructuredAttempt, StructuredCallOptions, StructuredDebugOptions, StructuredError, StructuredMode, StructuredOptions, StructuredPromptBuilder, StructuredPromptContext, StructuredPromptPayload, StructuredPromptResolver, StructuredPromptValue, StructuredResult, StructuredStreamData, StructuredStreamEvent, StructuredStreamInput, StructuredStreamOptions, StructuredSelfHealInput, ThinkDiagnostics, ThinkBlock, StructuredTraceEvent, } from "./types";
package/dist/index.js CHANGED
@@ -1215,11 +1215,42 @@ async function executeMCPToolCalls(calls, toolset, context) {
1215
1215
  throw new Error("Received a function tool call without id or name.");
1216
1216
  }
1217
1217
  const tool = toolset.byName.get(toolName);
1218
+ const parsedArguments = parseToolArguments(call.arguments);
1218
1219
  if (!tool) {
1219
- throw new Error(`No MCP tool registered for "${toolName}".`);
1220
+ const errorMessage = context.request.unknownToolError ? context.request.unknownToolError(toolName) : `Tool "${toolName}" is not registered in the current toolset.`;
1221
+ const metadata2 = {
1222
+ id: callId,
1223
+ type: call.type ?? "function",
1224
+ name: toolName,
1225
+ arguments: parsedArguments,
1226
+ error: errorMessage
1227
+ };
1228
+ const startedAt2 = new Date().toISOString();
1229
+ const execution = {
1230
+ callId,
1231
+ type: metadata2.type,
1232
+ name: toolName,
1233
+ clientId: "__unregistered__",
1234
+ remoteName: toolName,
1235
+ arguments: parsedArguments,
1236
+ error: errorMessage,
1237
+ round: context.round,
1238
+ provider: context.provider,
1239
+ model: context.model,
1240
+ handledLocally: true,
1241
+ startedAt: startedAt2,
1242
+ durationMs: 0
1243
+ };
1244
+ emitToolExecution(context.request, execution);
1245
+ out.push({ call: metadata2, execution });
1246
+ continue;
1220
1247
  }
1221
- const parsedArguments = parseToolArguments(call.arguments);
1222
- const args = isRecord(parsedArguments) ? parsedArguments : {};
1248
+ const rawArgs = isRecord(parsedArguments) ? parsedArguments : {};
1249
+ const args = context.request.transformToolArguments ? await context.request.transformToolArguments(rawArgs, {
1250
+ name: toolName,
1251
+ remoteName: tool.remoteName,
1252
+ clientId: tool.clientId
1253
+ }) : rawArgs;
1223
1254
  const metadata = {
1224
1255
  id: callId,
1225
1256
  type: call.type ?? "function",
@@ -1538,7 +1569,8 @@ function createOpenAICompatibleAdapter(options) {
1538
1569
  temperature: request.temperature,
1539
1570
  max_tokens: request.maxTokens,
1540
1571
  stream: true
1541
- }))
1572
+ })),
1573
+ signal: request.signal
1542
1574
  });
1543
1575
  if (!response.ok) {
1544
1576
  const message = await response.text();
@@ -1609,7 +1641,8 @@ async function completeWithChatCompletionsPassThrough(options, fetcher, path, re
1609
1641
  temperature: request.temperature,
1610
1642
  max_tokens: request.maxTokens,
1611
1643
  stream: false
1612
- }))
1644
+ })),
1645
+ signal: request.signal
1613
1646
  });
1614
1647
  if (!response.ok) {
1615
1648
  const message = await response.text();
@@ -1653,7 +1686,8 @@ async function completeWithChatCompletionsWithMCP(options, fetcher, path, reques
1653
1686
  tools: transportTools,
1654
1687
  tool_choice: request.toolChoice,
1655
1688
  parallel_tool_calls: request.parallelToolCalls
1656
- }))
1689
+ })),
1690
+ signal: request.signal
1657
1691
  });
1658
1692
  if (!response.ok) {
1659
1693
  const message = await response.text();
@@ -1718,7 +1752,8 @@ async function completeWithResponsesAPIPassThrough(options, fetcher, path, reque
1718
1752
  previous_response_id: pickString(body?.previous_response_id),
1719
1753
  temperature: request.temperature,
1720
1754
  max_output_tokens: request.maxTokens
1721
- }))
1755
+ })),
1756
+ signal: request.signal
1722
1757
  });
1723
1758
  if (!response.ok) {
1724
1759
  const message = await response.text();
@@ -1760,7 +1795,8 @@ async function completeWithResponsesAPIWithMCP(options, fetcher, path, request)
1760
1795
  tools: transportTools,
1761
1796
  tool_choice: request.toolChoice,
1762
1797
  parallel_tool_calls: request.parallelToolCalls
1763
- }))
1798
+ })),
1799
+ signal: request.signal
1764
1800
  });
1765
1801
  if (!response.ok) {
1766
1802
  const message = await response.text();
@@ -1836,7 +1872,8 @@ async function streamWithChatCompletionsWithMCP(options, fetcher, path, request,
1836
1872
  tool_choice: request.toolChoice,
1837
1873
  parallel_tool_calls: request.parallelToolCalls,
1838
1874
  stream: true
1839
- }))
1875
+ })),
1876
+ signal: request.signal
1840
1877
  });
1841
1878
  if (!response.ok) {
1842
1879
  const message = await response.text();
@@ -1938,7 +1975,8 @@ async function streamWithResponsesAPIPassThrough(options, fetcher, path, request
1938
1975
  temperature: request.temperature,
1939
1976
  max_output_tokens: request.maxTokens,
1940
1977
  stream: true
1941
- }))
1978
+ })),
1979
+ signal: request.signal
1942
1980
  });
1943
1981
  if (!response.ok) {
1944
1982
  const message = await response.text();
@@ -2020,7 +2058,8 @@ async function streamWithResponsesAPIWithMCP(options, fetcher, path, request, ca
2020
2058
  tool_choice: request.toolChoice,
2021
2059
  parallel_tool_calls: request.parallelToolCalls,
2022
2060
  stream: true
2023
- }))
2061
+ })),
2062
+ signal: request.signal
2024
2063
  });
2025
2064
  if (!response.ok) {
2026
2065
  const message = await response.text();
@@ -2584,7 +2623,8 @@ function createAnthropicCompatibleAdapter(options) {
2584
2623
  temperature: request.temperature,
2585
2624
  max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
2586
2625
  stream: true
2587
- }))
2626
+ })),
2627
+ signal: request.signal
2588
2628
  });
2589
2629
  if (!response.ok) {
2590
2630
  const message = await response.text();
@@ -2642,7 +2682,8 @@ async function completePassThrough(options, fetcher, path, request) {
2642
2682
  temperature: request.temperature,
2643
2683
  max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
2644
2684
  stream: false
2645
- }))
2685
+ })),
2686
+ signal: request.signal
2646
2687
  });
2647
2688
  if (!response.ok) {
2648
2689
  const message = await response.text();
@@ -2687,7 +2728,8 @@ async function completeWithMCPToolLoop(options, fetcher, path, request) {
2687
2728
  tools,
2688
2729
  tool_choice: toAnthropicToolChoice(request.toolChoice),
2689
2730
  stream: false
2690
- }))
2731
+ })),
2732
+ signal: request.signal
2691
2733
  });
2692
2734
  if (!response.ok) {
2693
2735
  const message = await response.text();
@@ -2770,7 +2812,8 @@ async function streamWithMCPToolLoop(options, fetcher, path, request, callbacks)
2770
2812
  tools,
2771
2813
  tool_choice: toAnthropicToolChoice(request.toolChoice),
2772
2814
  stream: true
2773
- }))
2815
+ })),
2816
+ signal: request.signal
2774
2817
  });
2775
2818
  if (!response.ok) {
2776
2819
  const message = await response.text();
@@ -4147,7 +4190,8 @@ async function callModel(adapter, options) {
4147
4190
  maxToolRounds: options.request?.maxToolRounds,
4148
4191
  onToolExecution: options.request?.onToolExecution,
4149
4192
  toolDebug: options.request?.toolDebug,
4150
- body: options.request?.body
4193
+ body: options.request?.body,
4194
+ signal: options.request?.signal
4151
4195
  };
4152
4196
  emitDebugRequest(options.debug, {
4153
4197
  provider: adapter.provider,
@@ -4565,7 +4609,8 @@ async function createMCPClient(options) {
4565
4609
  return wrapMCPClient({
4566
4610
  id: options.id,
4567
4611
  client,
4568
- transport
4612
+ transport,
4613
+ toolCallTimeoutMs: options.toolCallTimeoutMs
4569
4614
  });
4570
4615
  }
4571
4616
  function wrapMCPClient(options) {
@@ -4585,7 +4630,8 @@ function wrapMCPClient(options) {
4585
4630
  };
4586
4631
  },
4587
4632
  async callTool(params) {
4588
- return options.client.callTool(params);
4633
+ const callOptions = options.toolCallTimeoutMs === undefined ? undefined : { timeout: options.toolCallTimeoutMs };
4634
+ return options.client.callTool(params, undefined, callOptions);
4589
4635
  },
4590
4636
  async close() {
4591
4637
  await options.client.close();
package/dist/mcp.d.ts CHANGED
@@ -26,6 +26,7 @@ export interface CreateMCPClientOptions {
26
26
  id: string;
27
27
  transport: MCPTransportConfig;
28
28
  clientInfo?: MCPClientInfo;
29
+ toolCallTimeoutMs?: number;
29
30
  }
30
31
  export interface ManagedMCPToolClient extends MCPToolClient {
31
32
  sdkClient: Client;
@@ -36,5 +37,6 @@ export interface WrapMCPClientOptions {
36
37
  id: string;
37
38
  client: Client;
38
39
  transport?: Transport;
40
+ toolCallTimeoutMs?: number;
39
41
  }
40
42
  export declare function wrapMCPClient(options: WrapMCPClientOptions): ManagedMCPToolClient;
package/dist/types.d.ts CHANGED
@@ -130,8 +130,11 @@ export interface LLMRequest {
130
130
  maxToolRounds?: number;
131
131
  onToolExecution?: (execution: LLMToolExecution) => void;
132
132
  transformToolOutput?: LLMToolOutputTransformer;
133
+ transformToolArguments?: LLMToolArgumentsTransformer;
134
+ unknownToolError?: (toolName: string) => string;
133
135
  toolDebug?: boolean | LLMToolDebugOptions;
134
136
  body?: Record<string, unknown>;
137
+ signal?: AbortSignal;
135
138
  }
136
139
  export interface LLMUsage {
137
140
  inputTokens?: number;
@@ -191,6 +194,11 @@ export interface LLMToolExecution {
191
194
  durationMs?: number;
192
195
  }
193
196
  export type LLMToolOutputTransformer = (output: unknown, execution: Omit<LLMToolExecution, "output" | "durationMs">) => unknown | Promise<unknown>;
197
+ export type LLMToolArgumentsTransformer = (args: Record<string, unknown>, context: {
198
+ name: string;
199
+ remoteName: string;
200
+ clientId: string;
201
+ }) => Record<string, unknown> | Promise<Record<string, unknown>>;
194
202
  export interface LLMToolDebugOptions {
195
203
  enabled?: boolean;
196
204
  logger?: (line: string) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "extrait",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -35,10 +35,11 @@
35
35
  "lint": "bunx tsc -p tsconfig.lint.json",
36
36
  "prepublishOnly": "bun run lint && bun run build && bun run build:types",
37
37
  "test": "bun test tests/ --reporter=dots --only-failures",
38
- "typecheck": "bunx tsc --noEmit"
38
+ "typecheck": "bunx tsc --noEmit",
39
+ "pack": "bun run build:types && bun run build && npm pack"
39
40
  },
40
41
  "dependencies": {
41
- "@modelcontextprotocol/sdk": "^1.26.0",
42
+ "@modelcontextprotocol/sdk": "^1.27.1",
42
43
  "jsonrepair": "^3.13.2",
43
44
  "zod": "^3.25.76"
44
45
  },