@posthog/mcp 0.10.2 → 0.10.4

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.
Files changed (46) hide show
  1. package/dist/extensions/analytics-parameters.d.ts +17 -0
  2. package/dist/extensions/analytics-parameters.d.ts.map +1 -0
  3. package/dist/extensions/analytics-parameters.js +98 -0
  4. package/dist/extensions/analytics-parameters.mjs +52 -0
  5. package/dist/extensions/context-parameters.d.ts +3 -12
  6. package/dist/extensions/context-parameters.d.ts.map +1 -1
  7. package/dist/extensions/context-parameters.js +4 -6
  8. package/dist/extensions/context-parameters.mjs +3 -6
  9. package/dist/extensions/conversation-id.d.ts +2 -17
  10. package/dist/extensions/conversation-id.d.ts.map +1 -1
  11. package/dist/extensions/conversation-id.js +6 -23
  12. package/dist/extensions/conversation-id.mjs +4 -19
  13. package/dist/extensions/instrument-highlevel.d.ts.map +1 -1
  14. package/dist/extensions/instrument-highlevel.js +19 -16
  15. package/dist/extensions/instrument-highlevel.mjs +19 -16
  16. package/dist/extensions/instrumentation.d.ts +4 -6
  17. package/dist/extensions/instrumentation.d.ts.map +1 -1
  18. package/dist/extensions/instrumentation.js +32 -6
  19. package/dist/extensions/instrumentation.mjs +33 -7
  20. package/dist/extensions/intent.d.ts +1 -1
  21. package/dist/extensions/intent.d.ts.map +1 -1
  22. package/dist/extensions/intent.js +2 -2
  23. package/dist/extensions/intent.mjs +2 -2
  24. package/dist/extensions/mcp-sdk-compat.d.ts +1 -0
  25. package/dist/extensions/mcp-sdk-compat.d.ts.map +1 -1
  26. package/dist/extensions/mcp-sdk-compat.js +11 -2
  27. package/dist/extensions/mcp-sdk-compat.mjs +7 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +1 -0
  30. package/dist/index.mjs +1 -0
  31. package/dist/types.d.ts +5 -0
  32. package/dist/types.d.ts.map +1 -1
  33. package/dist/version.d.ts +1 -1
  34. package/dist/version.js +1 -1
  35. package/dist/version.mjs +1 -1
  36. package/package.json +4 -4
  37. package/src/extensions/analytics-parameters.ts +89 -0
  38. package/src/extensions/context-parameters.ts +16 -24
  39. package/src/extensions/conversation-id.ts +18 -43
  40. package/src/extensions/instrument-highlevel.ts +42 -22
  41. package/src/extensions/instrumentation.ts +71 -11
  42. package/src/extensions/intent.ts +7 -1
  43. package/src/extensions/mcp-sdk-compat.ts +15 -0
  44. package/src/index.ts +1 -0
  45. package/src/types.ts +6 -0
  46. package/src/version.ts +1 -1
@@ -4,24 +4,19 @@
4
4
  // Licensed under the MIT License: https://github.com/agentcathq/agentcat-typescript-sdk/blob/main/LICENSE
5
5
 
6
6
  import { uuidv7 } from '@posthog/core'
7
+ import {
8
+ canInjectAnalyticsParameter,
9
+ hasAnalyticsParameter,
10
+ type AnalyticsInjectableJsonSchema,
11
+ } from './analytics-parameters'
7
12
  import { DEFAULT_CONVERSATION_ID_DESCRIPTION } from './constants'
8
13
  import { log } from './logger'
9
14
  import { GET_MORE_TOOLS_NAME } from './tools'
10
15
 
11
16
  export const CONVERSATION_ID_PARAM_NAME = 'conversation_id'
12
17
 
13
- interface JsonSchema {
14
- additionalProperties?: boolean
15
- allOf?: unknown
16
- anyOf?: unknown
17
- oneOf?: unknown
18
- properties?: Record<string, unknown>
19
- required?: string[]
20
- type?: string
21
- }
22
-
23
18
  export interface ConversationIdInjectableTool {
24
- inputSchema?: JsonSchema
19
+ inputSchema?: AnalyticsInjectableJsonSchema
25
20
  name?: string
26
21
  [key: string]: unknown
27
22
  }
@@ -29,17 +24,16 @@ export interface ConversationIdInjectableTool {
29
24
  export function addConversationIdToTool<TTool extends ConversationIdInjectableTool>(tool: TTool): TTool {
30
25
  const modifiedTool = { ...tool }
31
26
  const toolName = tool.name || 'unknown'
32
- const schema = modifiedTool.inputSchema as JsonSchema | undefined
33
-
34
- if (schema?.properties?.[CONVERSATION_ID_PARAM_NAME]) {
35
- log(
36
- `WARN: Tool "${toolName}" already has '${CONVERSATION_ID_PARAM_NAME}' parameter. Skipping conversation_id injection.`
37
- )
38
- return modifiedTool
39
- }
40
-
41
- if (schema?.oneOf || schema?.allOf || schema?.anyOf) {
42
- log(`WARN: Tool "${toolName}" has complex schema (oneOf/allOf/anyOf). Skipping conversation_id injection.`)
27
+ const schema = modifiedTool.inputSchema as AnalyticsInjectableJsonSchema | undefined
28
+
29
+ if (!canInjectAnalyticsParameter(schema, CONVERSATION_ID_PARAM_NAME)) {
30
+ if (hasAnalyticsParameter(schema, CONVERSATION_ID_PARAM_NAME)) {
31
+ log(
32
+ `WARN: Tool "${toolName}" already has '${CONVERSATION_ID_PARAM_NAME}' parameter. Skipping conversation_id injection.`
33
+ )
34
+ } else {
35
+ log(`WARN: Tool "${toolName}" has complex schema (oneOf/allOf/anyOf/$ref). Skipping conversation_id injection.`)
36
+ }
43
37
  return modifiedTool
44
38
  }
45
39
 
@@ -51,9 +45,9 @@ export function addConversationIdToTool<TTool extends ConversationIdInjectableTo
51
45
  }
52
46
  }
53
47
 
54
- modifiedTool.inputSchema = JSON.parse(JSON.stringify(modifiedTool.inputSchema)) as JsonSchema
48
+ modifiedTool.inputSchema = JSON.parse(JSON.stringify(modifiedTool.inputSchema)) as AnalyticsInjectableJsonSchema
55
49
 
56
- const inputSchema = modifiedTool.inputSchema as JsonSchema
50
+ const inputSchema = modifiedTool.inputSchema as AnalyticsInjectableJsonSchema
57
51
 
58
52
  if (!inputSchema.properties) {
59
53
  inputSchema.properties = {}
@@ -137,25 +131,6 @@ export function extractConversationId(args: unknown): string | undefined {
137
131
  return trimmed.length > 0 ? trimmed : undefined
138
132
  }
139
133
 
140
- export function cloneRequestWithoutConversationId<
141
- TRequest extends { params?: { arguments?: unknown; [k: string]: unknown } },
142
- >(request: TRequest): TRequest {
143
- if (!request.params || typeof request.params !== 'object') {
144
- return request
145
- }
146
- const args = request.params.arguments
147
- if (!(args && typeof args === 'object')) {
148
- return request
149
- }
150
- return {
151
- ...request,
152
- params: {
153
- ...request.params,
154
- arguments: stripConversationId(args) as typeof request.params.arguments,
155
- },
156
- }
157
- }
158
-
159
134
  export function stripConversationId(args: unknown): unknown {
160
135
  if (!args || typeof args !== 'object' || !(CONVERSATION_ID_PARAM_NAME in (args as Record<string, unknown>))) {
161
136
  return args
@@ -11,7 +11,12 @@ import type {
11
11
  RegisteredTool,
12
12
  ToolCallback,
13
13
  } from '../types'
14
- import { stripConversationId } from './conversation-id'
14
+ import {
15
+ analyticsOwnsParameter,
16
+ getAnalyticsParameterOwnership,
17
+ stripOwnedAnalyticsArguments,
18
+ } from './analytics-parameters'
19
+ import { isContextEnabled } from './context-parameters'
15
20
  import { MCPAnalyticsEventType } from './event-types'
16
21
  import { getServerTrackingData } from './internal'
17
22
  import { log } from './logger'
@@ -78,7 +83,10 @@ function setupListenerToRegisteredTools(server: HighLevelMCPServerLike): void {
78
83
  return Reflect.set(target, property, value)
79
84
  }
80
85
 
81
- const nextValue = addTracingToToolCallbackInternal(value, property, server)
86
+ // The MCP SDK's registry copy is currently stale after update(), but keep this lookup lazy so
87
+ // ownership follows the current schema once the registry reflects live tool state.
88
+ const getCurrentInputSchema = () => value.inputSchema
89
+ const nextValue = addTracingToToolCallbackInternal(value, property, server, getCurrentInputSchema)
82
90
 
83
91
  if (typeof nextValue.update === 'function') {
84
92
  const originalUpdate = nextValue.update
@@ -89,7 +97,8 @@ function setupListenerToRegisteredTools(server: HighLevelMCPServerLike): void {
89
97
  const wrappedTool = addTracingToToolCallbackInternal(
90
98
  { callback: updateObj.callback },
91
99
  property,
92
- server
100
+ server,
101
+ getCurrentInputSchema
93
102
  )
94
103
  updateObj.callback = getToolFunction(wrappedTool)
95
104
  }
@@ -141,12 +150,12 @@ function setupListenerToRegisteredTools(server: HighLevelMCPServerLike): void {
141
150
  function addTracingToToolCallbackInternal(
142
151
  tool: RegisteredTool,
143
152
  toolName: string,
144
- server: HighLevelMCPServerLike
153
+ server: HighLevelMCPServerLike,
154
+ getCurrentInputSchema: () => unknown = () => tool.inputSchema
145
155
  ): RegisteredTool {
146
156
  const originalCallback = getToolFunction(tool)
147
- const missingToolName = resolveMissingCapabilityToolName(
148
- getServerTrackingData(server.server as MCPServerLike)?.options
149
- )
157
+ const options = getServerTrackingData(server.server as MCPServerLike)?.options
158
+ const missingToolName = resolveMissingCapabilityToolName(options)
150
159
 
151
160
  if (wrappedCallbacks.has(originalCallback)) {
152
161
  log(`Tool ${toolName} callback already wrapped, skipping re-wrap`)
@@ -170,15 +179,17 @@ function addTracingToToolCallbackInternal(
170
179
  extra = params[0] as CompatibleRequestHandlerExtra
171
180
  }
172
181
 
173
- const removeContextFromArgs = (input: unknown): unknown => {
174
- if (input && typeof input === 'object' && 'context' in input) {
175
- const { context: _context, ...rest } = input
176
- return rest
177
- }
178
- return input
179
- }
180
-
181
- const cleanedArgs = toolName === missingToolName ? args : stripConversationId(removeContextFromArgs(args))
182
+ const inputSchema = getCurrentInputSchema()
183
+ const cleanedArgs = stripOwnedAnalyticsArguments(args, {
184
+ context:
185
+ toolName !== missingToolName &&
186
+ isContextEnabled(options?.context) &&
187
+ analyticsOwnsParameter(inputSchema, 'context'),
188
+ conversationId:
189
+ toolName !== missingToolName &&
190
+ options?.enableConversationId === true &&
191
+ analyticsOwnsParameter(inputSchema, 'conversation_id'),
192
+ })
182
193
 
183
194
  try {
184
195
  if (cleanedArgs === undefined) {
@@ -209,6 +220,7 @@ function addTracingToToolCallbackInternal(
209
220
  }
210
221
 
211
222
  async function handleToolCallRequest(
223
+ highLevelServer: HighLevelMCPServerLike,
212
224
  server: MCPServerLike,
213
225
  originalCallToolHandler: MCPRequestHandler,
214
226
  request: MCPRequest,
@@ -235,16 +247,19 @@ async function handleToolCallRequest(
235
247
  })
236
248
  }
237
249
 
238
- // The high-level handler re-derives arguments from the original request and
239
- // strips the injected params inside the wrapped callback, so we hand it the
240
- // original request rather than the conversation-stripped one. Errors thrown
241
- // by the tool are stashed on `extra` by the callback wrapper; surface them.
250
+ const toolName = request.params?.name
251
+ const registeredTool = toolName ? highLevelServer._registeredTools[toolName] : undefined
252
+
253
+ // Strip SDK-owned arguments before the MCP SDK validates the registered Zod
254
+ // schema. The callback wrapper repeats the ownership-aware cleanup as a
255
+ // defensive fallback for direct callback invocation.
242
256
  return await captureToolCall({
243
257
  server,
244
258
  data,
245
259
  request,
246
260
  extra,
247
- execute: () => originalCallToolHandler(request, extra),
261
+ execute: (downstreamRequest) => originalCallToolHandler(downstreamRequest as MCPRequest, extra),
262
+ parameterOwnership: registeredTool ? getAnalyticsParameterOwnership(registeredTool.inputSchema) : undefined,
248
263
  takeCapturedError: () => {
249
264
  const captured = extra?.__mcp_analytics_error
250
265
  if (extra) {
@@ -264,7 +279,12 @@ export function instrumentHighLevelServer(server: HighLevelMCPServerLike): void
264
279
  const handlers = {
265
280
  initialize: handleInitializeRequest,
266
281
  'tools/list': handleListToolsRequest,
267
- 'tools/call': handleToolCallRequest,
282
+ 'tools/call': (
283
+ trackedServer: MCPServerLike,
284
+ originalHandler: MCPRequestHandler,
285
+ request: MCPRequest,
286
+ extra: MCPRequestExtra
287
+ ) => handleToolCallRequest(server, trackedServer, originalHandler, request, extra),
268
288
  }
269
289
  patchRequestHandlers(lowLevelServer, handlers)
270
290
 
@@ -5,6 +5,7 @@
5
5
 
6
6
  import type { ListToolsResult } from '@modelcontextprotocol/sdk/types.js'
7
7
  import type {
8
+ AnalyticsParameterOwnership,
8
9
  CompatibleRequestHandlerExtra,
9
10
  MCPAnalyticsData,
10
11
  MCPRequestLike,
@@ -12,12 +13,12 @@ import type {
12
13
  McpEvent,
13
14
  ServerClientInfoLike,
14
15
  } from '../types'
16
+ import { getAnalyticsParameterOwnership, stripOwnedAnalyticsArguments } from './analytics-parameters'
15
17
  import { addContextParameterToTools, getContextDescription, isContextEnabled } from './context-parameters'
16
18
  import {
17
19
  addConversationIdToTools,
18
20
  type ConversationIdResolution,
19
21
  canInjectConversationIdPromptBack,
20
- cloneRequestWithoutConversationId,
21
22
  injectConversationIdPromptBack,
22
23
  resolveConversationId,
23
24
  } from './conversation-id'
@@ -45,11 +46,7 @@ import { applyResolvedMetadata, isToolResultError } from './tracing-helpers'
45
46
 
46
47
  type MCPRequestHandler = (request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra) => Promise<unknown>
47
48
 
48
- /**
49
- * Runs the underlying tool. Receives the request with the SDK-injected
50
- * `conversation_id` stripped; an adapter is free to ignore it (the high-level
51
- * path strips arguments inside the wrapped callback instead).
52
- */
49
+ /** Runs the underlying tool with SDK-owned analytics arguments removed. */
53
50
  type ToolExecutor = (downstreamRequest: MCPRequestLike) => Promise<unknown>
54
51
 
55
52
  interface TraceToolCallParams {
@@ -58,6 +55,8 @@ interface TraceToolCallParams {
58
55
  request: MCPRequestLike
59
56
  extra?: CompatibleRequestHandlerExtra
60
57
  execute: ToolExecutor
58
+ /** Optional schema-derived ownership override for adapters with direct registry access. */
59
+ parameterOwnership?: AnalyticsParameterOwnership
61
60
  /**
62
61
  * Event type to capture. Defaults to a tool call; the `get_more_tools` virtual
63
62
  * tool passes `mcpMissingCapability` so it records a capability gap rather than
@@ -88,15 +87,26 @@ interface TraceToolCallParams {
88
87
  * throws, and the tool's own errors are always re-thrown to the caller.
89
88
  */
90
89
  export async function captureToolCall(params: TraceToolCallParams): Promise<unknown> {
91
- const { server, data, request, extra, execute, eventType, explicitContextIntent, takeCapturedError } = params
92
-
90
+ const {
91
+ server,
92
+ data,
93
+ request,
94
+ extra,
95
+ execute,
96
+ parameterOwnership,
97
+ eventType,
98
+ explicitContextIntent,
99
+ takeCapturedError,
100
+ } = params
101
+
102
+ const ownership = getActiveAnalyticsParameterOwnership(data, request.params?.name, parameterOwnership)
93
103
  const conversation = resolveConversationId(
94
- data.options.enableConversationId ?? false,
104
+ ownership.conversationId,
95
105
  request.params?.arguments,
96
106
  request.params?.name,
97
107
  resolveMissingCapabilityToolName(data.options)
98
108
  )
99
- const downstreamRequest = conversation.conversationId ? cloneRequestWithoutConversationId(request) : request
109
+ const downstreamRequest = cloneRequestWithoutOwnedAnalyticsArguments(request, ownership)
100
110
 
101
111
  // Prepare the event in isolation: if identity/metadata/intent resolution
102
112
  // throws, we drop instrumentation for this call but still run the tool.
@@ -109,6 +119,7 @@ export async function captureToolCall(params: TraceToolCallParams): Promise<unkn
109
119
  extra,
110
120
  startTime,
111
121
  conversation,
122
+ ownership,
112
123
  eventType ?? MCPAnalyticsEventType.mcpToolsCall
113
124
  )
114
125
  if (event && explicitContextIntent) {
@@ -128,6 +139,38 @@ export async function captureToolCall(params: TraceToolCallParams): Promise<unkn
128
139
  return finalResult
129
140
  }
130
141
 
142
+ function getActiveAnalyticsParameterOwnership(
143
+ data: MCPAnalyticsData,
144
+ toolName: string | undefined,
145
+ override?: AnalyticsParameterOwnership
146
+ ): AnalyticsParameterOwnership {
147
+ const ownership = override ?? (toolName ? data.toolAnalyticsParameterOwnership.get(toolName) : undefined)
148
+ const isMissingCapabilityTool = toolName === resolveMissingCapabilityToolName(data.options)
149
+ return {
150
+ context: !isMissingCapabilityTool && isContextEnabled(data.options.context) && ownership?.context === true,
151
+ conversationId:
152
+ !isMissingCapabilityTool && data.options.enableConversationId === true && ownership?.conversationId === true,
153
+ }
154
+ }
155
+
156
+ function cloneRequestWithoutOwnedAnalyticsArguments(
157
+ request: MCPRequestLike,
158
+ ownership: AnalyticsParameterOwnership
159
+ ): MCPRequestLike {
160
+ const args = request.params?.arguments
161
+ const cleanedArgs = stripOwnedAnalyticsArguments(args, ownership)
162
+ if (cleanedArgs === args || !request.params) {
163
+ return request
164
+ }
165
+ return {
166
+ ...request,
167
+ params: {
168
+ ...request.params,
169
+ arguments: cleanedArgs as typeof request.params.arguments,
170
+ },
171
+ }
172
+ }
173
+
131
174
  async function prepareToolCallEvent(
132
175
  server: MCPServerLike,
133
176
  data: MCPAnalyticsData,
@@ -136,6 +179,7 @@ async function prepareToolCallEvent(
136
179
  extra: CompatibleRequestHandlerExtra | undefined,
137
180
  startTime: Date,
138
181
  conversation: ConversationIdResolution,
182
+ ownership: AnalyticsParameterOwnership,
139
183
  eventType: MCPAnalyticsEventType
140
184
  ): Promise<McpEvent | null> {
141
185
  try {
@@ -159,7 +203,7 @@ async function prepareToolCallEvent(
159
203
  stampMetaClientInfo(event, request)
160
204
 
161
205
  await applyResolvedMetadata(event, data, request, extra)
162
- setEventIntent(event, await resolveToolCallIntent(data, request, extra))
206
+ setEventIntent(event, await resolveToolCallIntent(data, request, ownership.context, extra))
163
207
  return event
164
208
  } catch (error) {
165
209
  log(
@@ -336,6 +380,18 @@ export async function handleListToolsRequest(
336
380
  return { tools }
337
381
  }
338
382
 
383
+ function cacheToolAnalyticsParameterOwnership(
384
+ cache: Map<string, AnalyticsParameterOwnership>,
385
+ tools: ListToolsResult['tools']
386
+ ): void {
387
+ // Merge pages and concurrent enumerations; repeated tool names overwrite stale schemas.
388
+ for (const tool of tools) {
389
+ if (tool?.name) {
390
+ cache.set(tool.name, getAnalyticsParameterOwnership(tool.inputSchema))
391
+ }
392
+ }
393
+ }
394
+
339
395
  function collectListedToolNames(tools: ListToolsResult['tools'] | undefined): string[] | undefined {
340
396
  if (!tools || tools.length === 0) {
341
397
  return
@@ -356,6 +412,10 @@ async function getTracedToolsList(
356
412
  const originalResponse = (await originalListToolsHandler(request, extra)) as ListToolsResult
357
413
  let tools = originalResponse.tools || []
358
414
 
415
+ if (data) {
416
+ cacheToolAnalyticsParameterOwnership(data.toolAnalyticsParameterOwnership, tools)
417
+ }
418
+
359
419
  if (data && isContextEnabled(data.options.context)) {
360
420
  tools = addContextParameterToTools(tools, getContextDescription(data.options.context))
361
421
  }
@@ -53,10 +53,16 @@ async function runIntentFallback(
53
53
  export async function resolveToolCallIntent(
54
54
  data: MCPAnalyticsData,
55
55
  request: MCPRequestLike,
56
+ analyticsOwnsContext: boolean,
56
57
  extra?: CompatibleRequestHandlerExtra
57
58
  ): Promise<ResolvedIntent | null> {
58
59
  const contextArgument = getContextArgument(request)
59
- if (isContextEnabled(data.options.context) && request.params?.name !== 'get_more_tools' && contextArgument) {
60
+ if (
61
+ analyticsOwnsContext &&
62
+ isContextEnabled(data.options.context) &&
63
+ request.params?.name !== 'get_more_tools' &&
64
+ contextArgument
65
+ ) {
60
66
  return { intent: contextArgument, source: 'context_parameter' }
61
67
  }
62
68
 
@@ -97,6 +97,21 @@ export function isZ4Schema(schema: unknown): boolean {
97
97
  return !!(schema as ZodV4Internal)._zod
98
98
  }
99
99
 
100
+ function isZodTypeLike(value: unknown): boolean {
101
+ return (
102
+ !!value &&
103
+ typeof value === 'object' &&
104
+ 'parse' in value &&
105
+ typeof value.parse === 'function' &&
106
+ 'safeParse' in value &&
107
+ typeof value.safeParse === 'function'
108
+ )
109
+ }
110
+
111
+ export function isZodRawShapeCompat(schema: unknown): schema is Record<string, unknown> {
112
+ return !!schema && typeof schema === 'object' && Object.values(schema).some(isZodTypeLike)
113
+ }
114
+
100
115
  export function getObjectShape(schema: unknown): Record<string, unknown> | undefined {
101
116
  if (!schema || typeof schema !== 'object') {
102
117
  return
package/src/index.ts CHANGED
@@ -143,6 +143,7 @@ function buildTrackingData(
143
143
  sessionId: newSessionId(),
144
144
  lastActivity: new Date(),
145
145
  identifiedSessions: new IdentityCache(),
146
+ toolAnalyticsParameterOwnership: new Map(),
146
147
  toolCategories: new Map<string, string>(),
147
148
  toolDescriptions: new Map<string, string>(),
148
149
  sessionInfo: getSessionInfo(lowLevelServer, undefined),
package/src/types.ts CHANGED
@@ -271,6 +271,11 @@ export interface SessionInfo {
271
271
  serverVersion?: string
272
272
  }
273
273
 
274
+ export interface AnalyticsParameterOwnership {
275
+ context: boolean
276
+ conversationId: boolean
277
+ }
278
+
274
279
  export interface MCPAnalyticsData {
275
280
  sink: McpEventSink | undefined
276
281
  identifiedSessions: IdentityCache
@@ -280,6 +285,7 @@ export interface MCPAnalyticsData {
280
285
  sessionInfo: SessionInfo
281
286
  /** `token` = recovered from a self-encoded `Mcp-Session-Id` token (see session-token.ts). */
282
287
  sessionSource: 'generated' | 'mcp' | 'token'
288
+ toolAnalyticsParameterOwnership: Map<string, AnalyticsParameterOwnership>
283
289
  toolCategories: Map<string, string>
284
290
  toolDescriptions: Map<string, string>
285
291
  }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '0.10.2'
1
+ export const version = '0.10.4'