@pairsystems/goodmem-mcp 0.1.5 → 0.1.6

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 (2) hide show
  1. package/dist/index.js +189 -62
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -20988,7 +20988,7 @@ var StdioServerTransport = class {
20988
20988
  // dist/index.js
20989
20989
  var goodmemBaseUrl = process.env.GOODMEM_BASE_URL || "";
20990
20990
  var goodmemApiKey = process.env.GOODMEM_API_KEY || "";
20991
- var BASED_ON_GOODMEM_COMMIT = "1e56d9782c15a55eb93a83f19a18e39fd5ceaa6c";
20991
+ var BASED_ON_GOODMEM_COMMIT = "55768baed550c339bff8ef3893a8e9a024facc90";
20992
20992
  function isConfigured() {
20993
20993
  return goodmemBaseUrl !== "" && goodmemApiKey !== "";
20994
20994
  }
@@ -21050,7 +21050,7 @@ async function callApiNdjson(method, path, body, query) {
21050
21050
  throw new Error(`GoodMem API error ${resp.status}: ${text2}`);
21051
21051
  }
21052
21052
  const text = await resp.text();
21053
- return text.split("\n").filter(Boolean).map((line) => JSON.parse(line));
21053
+ return text.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => JSON.parse(line));
21054
21054
  }
21055
21055
  var MODEL_REGISTRY = {
21056
21056
  "embedders": {
@@ -21920,7 +21920,7 @@ function autoInferFromRegistry(registryType, args) {
21920
21920
  }
21921
21921
  var server = new McpServer({
21922
21922
  name: "goodmem",
21923
- version: "0.1.5"
21923
+ version: "0.1.6"
21924
21924
  });
21925
21925
  server.tool("goodmem_configure", "Configure GoodMem server connection. Call this before using other GoodMem tools if GOODMEM_BASE_URL and GOODMEM_API_KEY environment variables are not set. Session credentials override environment variables.", {
21926
21926
  base_url: external_exports.string().describe("GoodMem server URL (e.g., https://your-server.example.com)"),
@@ -21970,7 +21970,7 @@ ${allModels.join("\n")}` }] };
21970
21970
  });
21971
21971
  server.tool("goodmem_client_info", "Return the MCP client package version and the goodmem server commit it was built against. No server connection required.", {}, async () => {
21972
21972
  return { content: [{ type: "text", text: JSON.stringify({
21973
- mcpVersion: "0.1.5",
21973
+ mcpVersion: "0.1.6",
21974
21974
  basedOnGoodmemCommit: BASED_ON_GOODMEM_COMMIT
21975
21975
  }, null, 2) }] };
21976
21976
  });
@@ -22013,7 +22013,7 @@ function registerTools() {
22013
22013
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22014
22014
  });
22015
22015
  server.tool("goodmem_apikeys_create", "Create a new API key", {
22016
- labels: external_exports.record(external_exports.string(), external_exports.string()).describe("Key-value pairs of metadata associated with the API key. Used for organization and filtering.").optional(),
22016
+ labels: external_exports.any().describe("Key-value pairs of metadata associated with the API key. Used for organization and filtering.").optional(),
22017
22017
  expires_at: external_exports.number().int().describe("Expiration timestamp in milliseconds since epoch. If not provided, the key does not expire.").optional(),
22018
22018
  api_key_id: external_exports.string().describe("Optional client-provided UUID for idempotent creation. If not provided, server generates a new UUID. Returns ALREADY_EXISTS if ID is already in use.").optional()
22019
22019
  }, async (args) => {
@@ -22028,7 +22028,7 @@ function registerTools() {
22028
22028
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22029
22029
  });
22030
22030
  server.tool("goodmem_apikeys_delete", "Delete an API key", {
22031
- id: external_exports.string().describe("The unique identifier of the API key to delete")
22031
+ id: external_exports.string().describe("The UUID of the API key to delete")
22032
22032
  }, async (args) => {
22033
22033
  await callApi("DELETE", `/v1/apikeys/${encodeURIComponent(String(args.id))}`, void 0);
22034
22034
  return { content: [{ type: "text", text: "Deleted successfully." }] };
@@ -22038,10 +22038,10 @@ function registerTools() {
22038
22038
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22039
22039
  });
22040
22040
  server.tool("goodmem_apikeys_update", "Update an API key", {
22041
- id: external_exports.string().describe("The unique identifier of the API key to update"),
22041
+ id: external_exports.string().describe("The UUID of the API key to update"),
22042
22042
  status: external_exports.string().describe("New status for the API key. Allowed values: ACTIVE, INACTIVE.").optional(),
22043
- replace_labels: external_exports.record(external_exports.string(), external_exports.string()).describe("Replace all existing labels with this set. Mutually exclusive with mergeLabels.").optional(),
22044
- merge_labels: external_exports.record(external_exports.string(), external_exports.string()).describe("Merge these labels with existing ones. Mutually exclusive with replaceLabels.").optional()
22043
+ replace_labels: external_exports.any().describe("Replace all existing labels with this set. Mutually exclusive with mergeLabels.").optional(),
22044
+ merge_labels: external_exports.any().describe("Merge these labels with existing ones. Mutually exclusive with replaceLabels.").optional()
22045
22045
  }, async (args) => {
22046
22046
  const body = {};
22047
22047
  if (args.status !== void 0)
@@ -22066,11 +22066,22 @@ function registerTools() {
22066
22066
  supported_modalities: external_exports.array(external_exports.enum(["TEXT", "IMAGE", "AUDIO", "VIDEO"])).describe("Supported content modalities (defaults to TEXT if not provided) (auto-inferred from model_identifier if omitted)").optional(),
22067
22067
  credentials: external_exports.object({
22068
22068
  kind: external_exports.enum(["CREDENTIAL_KIND_UNSPECIFIED", "CREDENTIAL_KIND_API_KEY", "CREDENTIAL_KIND_GCP_ADC"]).describe("Selected credential strategy"),
22069
- apiKey: external_exports.any().describe("Configuration when kind is CREDENTIAL_KIND_API_KEY").optional(),
22070
- gcpAdc: external_exports.any().describe("Configuration when kind is CREDENTIAL_KIND_GCP_ADC").optional(),
22069
+ apiKey: external_exports.object({
22070
+ inlineSecret: external_exports.string().describe("Secret stored directly in GoodMem (mutually exclusive with secretRef)").optional(),
22071
+ secretRef: external_exports.object({
22072
+ uri: external_exports.string().describe("URI identifying where the secret can be resolved (e.g., vault://, env://)"),
22073
+ hints: external_exports.record(external_exports.string(), external_exports.unknown()).describe('Optional metadata to help resolvers decode the secret (e.g., {"encoding":"base64"})').optional()
22074
+ }).passthrough().describe("Reference to an external secret manager entry (mutually exclusive with inlineSecret)").optional(),
22075
+ headerName: external_exports.string().describe("Desired HTTP header to carry the credential (defaults to Authorization)").optional(),
22076
+ prefix: external_exports.string().describe('Optional prefix prepended to the secret (e.g., "Bearer ")').optional()
22077
+ }).passthrough().describe("Configuration when kind is CREDENTIAL_KIND_API_KEY").optional(),
22078
+ gcpAdc: external_exports.object({
22079
+ scopes: external_exports.any().describe("Additional OAuth scopes. Empty list falls back to the default cloud-platform scope.").optional(),
22080
+ quotaProjectId: external_exports.string().describe("Optional quota project used for billing").optional()
22081
+ }).passthrough().describe("Configuration when kind is CREDENTIAL_KIND_GCP_ADC").optional(),
22071
22082
  labels: external_exports.record(external_exports.string(), external_exports.string()).describe('Optional annotations to aid operators (e.g., "owner=vertex")').optional()
22072
22083
  }).passthrough().describe("Structured credential payload describing how to authenticate with the provider. Required for SaaS providers such as COHERE, JINA, and VOYAGE; optional for local or proxy providers.").optional(),
22073
- labels: external_exports.record(external_exports.string(), external_exports.string()).describe("User-defined labels for categorization").optional(),
22084
+ labels: external_exports.any().describe("User-defined labels for categorization").optional(),
22074
22085
  version: external_exports.string().describe("Version information").optional(),
22075
22086
  monitoring_endpoint: external_exports.string().describe("Monitoring endpoint URL").optional(),
22076
22087
  owner_id: external_exports.string().describe("Optional owner ID. If not provided, derived from the authentication context. Requires CREATE_EMBEDDER_ANY permission if specified.").optional(),
@@ -22115,13 +22126,13 @@ function registerTools() {
22115
22126
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22116
22127
  });
22117
22128
  server.tool("goodmem_embedders_delete", "Delete an embedder", {
22118
- id: external_exports.string().describe("The unique identifier of the embedder to delete")
22129
+ id: external_exports.string().describe("The UUID of the embedder to delete")
22119
22130
  }, async (args) => {
22120
22131
  await callApi("DELETE", `/v1/embedders/${encodeURIComponent(String(args.id))}`, void 0);
22121
22132
  return { content: [{ type: "text", text: "Deleted successfully." }] };
22122
22133
  });
22123
22134
  server.tool("goodmem_embedders_get", "Get an embedder by ID", {
22124
- id: external_exports.string().describe("The unique identifier of the embedder to retrieve")
22135
+ id: external_exports.string().describe("The UUID of the embedder to retrieve")
22125
22136
  }, async (args) => {
22126
22137
  const result = await callApi("GET", `/v1/embedders/${encodeURIComponent(String(args.id))}`, void 0);
22127
22138
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
@@ -22144,7 +22155,7 @@ function registerTools() {
22144
22155
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22145
22156
  });
22146
22157
  server.tool("goodmem_embedders_update", "Update an embedder", {
22147
- id: external_exports.string().describe("The unique identifier of the embedder to update"),
22158
+ id: external_exports.string().describe("The UUID of the embedder to update"),
22148
22159
  display_name: external_exports.string().describe("User-facing name of the embedder").optional(),
22149
22160
  description: external_exports.string().describe("Description of the embedder").optional(),
22150
22161
  endpoint_url: external_exports.string().describe("API endpoint URL").optional(),
@@ -22155,12 +22166,23 @@ function registerTools() {
22155
22166
  supported_modalities: external_exports.array(external_exports.enum(["TEXT", "IMAGE", "AUDIO", "VIDEO"])).describe("Supported content modalities").optional(),
22156
22167
  credentials: external_exports.object({
22157
22168
  kind: external_exports.enum(["CREDENTIAL_KIND_UNSPECIFIED", "CREDENTIAL_KIND_API_KEY", "CREDENTIAL_KIND_GCP_ADC"]).describe("Selected credential strategy"),
22158
- apiKey: external_exports.any().describe("Configuration when kind is CREDENTIAL_KIND_API_KEY").optional(),
22159
- gcpAdc: external_exports.any().describe("Configuration when kind is CREDENTIAL_KIND_GCP_ADC").optional(),
22169
+ apiKey: external_exports.object({
22170
+ inlineSecret: external_exports.string().describe("Secret stored directly in GoodMem (mutually exclusive with secretRef)").optional(),
22171
+ secretRef: external_exports.object({
22172
+ uri: external_exports.string().describe("URI identifying where the secret can be resolved (e.g., vault://, env://)"),
22173
+ hints: external_exports.record(external_exports.string(), external_exports.unknown()).describe('Optional metadata to help resolvers decode the secret (e.g., {"encoding":"base64"})').optional()
22174
+ }).passthrough().describe("Reference to an external secret manager entry (mutually exclusive with inlineSecret)").optional(),
22175
+ headerName: external_exports.string().describe("Desired HTTP header to carry the credential (defaults to Authorization)").optional(),
22176
+ prefix: external_exports.string().describe('Optional prefix prepended to the secret (e.g., "Bearer ")').optional()
22177
+ }).passthrough().describe("Configuration when kind is CREDENTIAL_KIND_API_KEY").optional(),
22178
+ gcpAdc: external_exports.object({
22179
+ scopes: external_exports.any().describe("Additional OAuth scopes. Empty list falls back to the default cloud-platform scope.").optional(),
22180
+ quotaProjectId: external_exports.string().describe("Optional quota project used for billing").optional()
22181
+ }).passthrough().describe("Configuration when kind is CREDENTIAL_KIND_GCP_ADC").optional(),
22160
22182
  labels: external_exports.record(external_exports.string(), external_exports.string()).describe('Optional annotations to aid operators (e.g., "owner=vertex")').optional()
22161
22183
  }).passthrough().describe("Structured credential payload describing how to authenticate with the provider").optional(),
22162
- replace_labels: external_exports.record(external_exports.string(), external_exports.string()).describe("Replace all existing labels with these (mutually exclusive with mergeLabels)").optional(),
22163
- merge_labels: external_exports.record(external_exports.string(), external_exports.string()).describe("Merge these labels with existing ones (mutually exclusive with replaceLabels)").optional(),
22184
+ replace_labels: external_exports.any().describe("Replace all existing labels with these (mutually exclusive with mergeLabels)").optional(),
22185
+ merge_labels: external_exports.any().describe("Merge these labels with existing ones (mutually exclusive with replaceLabels)").optional(),
22164
22186
  version: external_exports.string().describe("Version information").optional(),
22165
22187
  monitoring_endpoint: external_exports.string().describe("Monitoring endpoint URL").optional()
22166
22188
  }, async (args) => {
@@ -22204,11 +22226,22 @@ function registerTools() {
22204
22226
  supported_modalities: external_exports.array(external_exports.enum(["TEXT", "IMAGE", "AUDIO", "VIDEO"])).describe("Supported content modalities (defaults to TEXT if not provided) (auto-inferred from model_identifier if omitted)").optional(),
22205
22227
  credentials: external_exports.object({
22206
22228
  kind: external_exports.enum(["CREDENTIAL_KIND_UNSPECIFIED", "CREDENTIAL_KIND_API_KEY", "CREDENTIAL_KIND_GCP_ADC"]).describe("Selected credential strategy"),
22207
- apiKey: external_exports.any().describe("Configuration when kind is CREDENTIAL_KIND_API_KEY").optional(),
22208
- gcpAdc: external_exports.any().describe("Configuration when kind is CREDENTIAL_KIND_GCP_ADC").optional(),
22229
+ apiKey: external_exports.object({
22230
+ inlineSecret: external_exports.string().describe("Secret stored directly in GoodMem (mutually exclusive with secretRef)").optional(),
22231
+ secretRef: external_exports.object({
22232
+ uri: external_exports.string().describe("URI identifying where the secret can be resolved (e.g., vault://, env://)"),
22233
+ hints: external_exports.record(external_exports.string(), external_exports.unknown()).describe('Optional metadata to help resolvers decode the secret (e.g., {"encoding":"base64"})').optional()
22234
+ }).passthrough().describe("Reference to an external secret manager entry (mutually exclusive with inlineSecret)").optional(),
22235
+ headerName: external_exports.string().describe("Desired HTTP header to carry the credential (defaults to Authorization)").optional(),
22236
+ prefix: external_exports.string().describe('Optional prefix prepended to the secret (e.g., "Bearer ")').optional()
22237
+ }).passthrough().describe("Configuration when kind is CREDENTIAL_KIND_API_KEY").optional(),
22238
+ gcpAdc: external_exports.object({
22239
+ scopes: external_exports.any().describe("Additional OAuth scopes. Empty list falls back to the default cloud-platform scope.").optional(),
22240
+ quotaProjectId: external_exports.string().describe("Optional quota project used for billing").optional()
22241
+ }).passthrough().describe("Configuration when kind is CREDENTIAL_KIND_GCP_ADC").optional(),
22209
22242
  labels: external_exports.record(external_exports.string(), external_exports.string()).describe('Optional annotations to aid operators (e.g., "owner=vertex")').optional()
22210
22243
  }).passthrough().describe("Structured credential payload describing how to authenticate with the provider. Omit for deployments that do not require credentials.").optional(),
22211
- labels: external_exports.record(external_exports.string(), external_exports.string()).describe("User-defined labels for categorization").optional(),
22244
+ labels: external_exports.any().describe("User-defined labels for categorization").optional(),
22212
22245
  version: external_exports.string().describe("Version information").optional(),
22213
22246
  monitoring_endpoint: external_exports.string().describe("Monitoring endpoint URL").optional(),
22214
22247
  capabilities: external_exports.object({
@@ -22229,7 +22262,7 @@ function registerTools() {
22229
22262
  stopSequences: external_exports.any().describe("Generation stop sequences (\u226410 sequences; each \u2264100 chars; generation halts on exact match)").optional()
22230
22263
  }).passthrough().describe("Default sampling parameters for generation requests").optional(),
22231
22264
  max_context_length: external_exports.number().int().describe("Maximum context window size in tokens").optional(),
22232
- client_config: external_exports.record(external_exports.string(), external_exports.unknown()).describe("Provider-specific client configuration as flexible JSON structure").optional(),
22265
+ client_config: external_exports.any().describe("Provider-specific client configuration as flexible JSON structure").optional(),
22233
22266
  owner_id: external_exports.string().describe("Optional owner ID. If not provided, derived from the authentication context. Requires CREATE_LLM_ANY permission if specified.").optional(),
22234
22267
  llm_id: external_exports.string().describe("Optional client-provided UUID for idempotent creation. If not provided, server generates a new UUID. Returns ALREADY_EXISTS if ID is already in use.").optional()
22235
22268
  }, async (args) => {
@@ -22274,13 +22307,13 @@ function registerTools() {
22274
22307
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22275
22308
  });
22276
22309
  server.tool("goodmem_llms_delete", "Delete an LLM", {
22277
- id: external_exports.string().describe("The unique identifier of the LLM to delete")
22310
+ id: external_exports.string().describe("The UUID of the LLM to delete")
22278
22311
  }, async (args) => {
22279
22312
  await callApi("DELETE", `/v1/llms/${encodeURIComponent(String(args.id))}`, void 0);
22280
22313
  return { content: [{ type: "text", text: "Deleted successfully." }] };
22281
22314
  });
22282
22315
  server.tool("goodmem_llms_get", "Get an LLM by ID", {
22283
- id: external_exports.string().describe("The unique identifier of the LLM to retrieve")
22316
+ id: external_exports.string().describe("The UUID of the LLM to retrieve")
22284
22317
  }, async (args) => {
22285
22318
  const result = await callApi("GET", `/v1/llms/${encodeURIComponent(String(args.id))}`, void 0);
22286
22319
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
@@ -22303,7 +22336,7 @@ function registerTools() {
22303
22336
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22304
22337
  });
22305
22338
  server.tool("goodmem_llms_update", "Update an LLM", {
22306
- id: external_exports.string().describe("The unique identifier of the LLM to update"),
22339
+ id: external_exports.string().describe("The UUID of the LLM to update"),
22307
22340
  display_name: external_exports.string().describe("Update display name").optional(),
22308
22341
  description: external_exports.string().describe("Update description").optional(),
22309
22342
  endpoint_url: external_exports.string().describe("Update endpoint base URL (OpenAI-compatible base, typically ends with /v1)").optional(),
@@ -22312,8 +22345,19 @@ function registerTools() {
22312
22345
  supported_modalities: external_exports.array(external_exports.enum(["TEXT", "IMAGE", "AUDIO", "VIDEO"])).describe("Update supported modalities (if array contains \u22651 elements, replaces stored set; if empty or omitted, no change)").optional(),
22313
22346
  credentials: external_exports.object({
22314
22347
  kind: external_exports.enum(["CREDENTIAL_KIND_UNSPECIFIED", "CREDENTIAL_KIND_API_KEY", "CREDENTIAL_KIND_GCP_ADC"]).describe("Selected credential strategy"),
22315
- apiKey: external_exports.any().describe("Configuration when kind is CREDENTIAL_KIND_API_KEY").optional(),
22316
- gcpAdc: external_exports.any().describe("Configuration when kind is CREDENTIAL_KIND_GCP_ADC").optional(),
22348
+ apiKey: external_exports.object({
22349
+ inlineSecret: external_exports.string().describe("Secret stored directly in GoodMem (mutually exclusive with secretRef)").optional(),
22350
+ secretRef: external_exports.object({
22351
+ uri: external_exports.string().describe("URI identifying where the secret can be resolved (e.g., vault://, env://)"),
22352
+ hints: external_exports.record(external_exports.string(), external_exports.unknown()).describe('Optional metadata to help resolvers decode the secret (e.g., {"encoding":"base64"})').optional()
22353
+ }).passthrough().describe("Reference to an external secret manager entry (mutually exclusive with inlineSecret)").optional(),
22354
+ headerName: external_exports.string().describe("Desired HTTP header to carry the credential (defaults to Authorization)").optional(),
22355
+ prefix: external_exports.string().describe('Optional prefix prepended to the secret (e.g., "Bearer ")').optional()
22356
+ }).passthrough().describe("Configuration when kind is CREDENTIAL_KIND_API_KEY").optional(),
22357
+ gcpAdc: external_exports.object({
22358
+ scopes: external_exports.any().describe("Additional OAuth scopes. Empty list falls back to the default cloud-platform scope.").optional(),
22359
+ quotaProjectId: external_exports.string().describe("Optional quota project used for billing").optional()
22360
+ }).passthrough().describe("Configuration when kind is CREDENTIAL_KIND_GCP_ADC").optional(),
22317
22361
  labels: external_exports.record(external_exports.string(), external_exports.string()).describe('Optional annotations to aid operators (e.g., "owner=vertex")').optional()
22318
22362
  }).passthrough().describe("Update credentials").optional(),
22319
22363
  version: external_exports.string().describe("Update version information").optional(),
@@ -22336,9 +22380,9 @@ function registerTools() {
22336
22380
  stopSequences: external_exports.any().describe("Generation stop sequences (\u226410 sequences; each \u2264100 chars; generation halts on exact match)").optional()
22337
22381
  }).passthrough().describe("Update default sampling parameters").optional(),
22338
22382
  max_context_length: external_exports.number().int().describe("Update maximum context window size in tokens").optional(),
22339
- client_config: external_exports.record(external_exports.string(), external_exports.unknown()).describe("Update provider-specific client configuration (replaces entire config; no merging)").optional(),
22340
- replace_labels: external_exports.record(external_exports.string(), external_exports.string()).describe("Replace all existing labels with this set. Empty map clears all labels. Cannot be used with mergeLabels.").optional(),
22341
- merge_labels: external_exports.record(external_exports.string(), external_exports.string()).describe("Merge with existing labels: upserts with overwrite. Labels not mentioned are preserved. Cannot be used with replaceLabels.").optional()
22383
+ client_config: external_exports.any().describe("Update provider-specific client configuration (replaces entire config; no merging)").optional(),
22384
+ replace_labels: external_exports.any().describe("Replace all existing labels with this set. Empty map clears all labels. Cannot be used with mergeLabels.").optional(),
22385
+ merge_labels: external_exports.any().describe("Merge with existing labels: upserts with overwrite. Labels not mentioned are preserved. Cannot be used with replaceLabels.").optional()
22342
22386
  }, async (args) => {
22343
22387
  const body = {};
22344
22388
  if (args.display_name !== void 0)
@@ -22386,7 +22430,11 @@ function registerTools() {
22386
22430
  server.tool("goodmem_memories_batch_delete", "Delete memories in batch", {
22387
22431
  requests: external_exports.array(external_exports.object({
22388
22432
  memoryId: external_exports.string().describe("Deletes one specific memory by UUID").optional(),
22389
- filterSelector: external_exports.any().describe("Deletes a filtered set of memories within a specific space").optional()
22433
+ filterSelector: external_exports.object({
22434
+ spaceId: external_exports.string().describe("Space ID scope for the filtered delete"),
22435
+ statusFilter: external_exports.string().describe("Optional processing status filter (PENDING, PROCESSING, COMPLETED, FAILED)").optional(),
22436
+ filter: external_exports.string().describe("Optional metadata filter expression").optional()
22437
+ }).passthrough().describe("Deletes a filtered set of memories within a specific space").optional()
22390
22438
  }).passthrough()).describe("Array of delete selectors")
22391
22439
  }, async (args) => {
22392
22440
  const body = {};
@@ -22417,11 +22465,23 @@ function registerTools() {
22417
22465
  original_content_b64: external_exports.string().describe("Original content as base64-encoded binary data (use either this or originalContent)").optional(),
22418
22466
  original_content_ref: external_exports.string().describe("Reference to external content location").optional(),
22419
22467
  content_type: external_exports.string().describe("MIME type of the content"),
22420
- metadata: external_exports.record(external_exports.string(), external_exports.unknown()).describe("Additional metadata for the memory").optional(),
22468
+ metadata: external_exports.any().describe("Additional metadata for the memory").optional(),
22421
22469
  chunking_config: external_exports.object({
22422
22470
  none: external_exports.any().describe("No chunking strategy - preserve original content as single unit").optional(),
22423
- recursive: external_exports.any().describe("Recursive hierarchical chunking strategy with configurable separators").optional(),
22424
- sentence: external_exports.any().describe("Sentence-based chunking strategy with language detection").optional()
22471
+ recursive: external_exports.object({
22472
+ chunkSize: external_exports.number().int().describe("Maximum size of a chunk (should be \u2264 context window)"),
22473
+ chunkOverlap: external_exports.number().int().describe("Sliding overlap between chunks"),
22474
+ separators: external_exports.any().describe("Hierarchical separator list (order = preference)").optional(),
22475
+ keepStrategy: external_exports.enum(["KEEP_NONE", "KEEP_START", "KEEP_END"]).describe("How to handle separators after splitting. KEEP_NONE is deprecated and behaves as KEEP_END."),
22476
+ separatorIsRegex: external_exports.boolean().describe("Whether separators are regex patterns").optional(),
22477
+ lengthMeasurement: external_exports.enum(["CHARACTER_COUNT", "TOKEN_COUNT", "CUSTOM"]).describe("How to measure chunk length")
22478
+ }).passthrough().describe("Recursive hierarchical chunking strategy with configurable separators").optional(),
22479
+ sentence: external_exports.object({
22480
+ maxChunkSize: external_exports.number().int().describe("Maximum size of a chunk"),
22481
+ minChunkSize: external_exports.number().int().describe("Minimum size before creating a new chunk"),
22482
+ enableLanguageDetection: external_exports.boolean().describe("Whether to detect language for better segmentation").optional(),
22483
+ lengthMeasurement: external_exports.enum(["CHARACTER_COUNT", "TOKEN_COUNT", "CUSTOM"]).describe("How to measure chunk length")
22484
+ }).passthrough().describe("Sentence-based chunking strategy with language detection").optional()
22425
22485
  }).passthrough().describe("Chunking strategy for this memory (if not provided, uses space default)").optional(),
22426
22486
  extract_page_images: external_exports.boolean().describe("Optional hint to extract page images for eligible document types (for example, PDFs)").optional()
22427
22487
  }, async (args) => {
@@ -22448,13 +22508,13 @@ function registerTools() {
22448
22508
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22449
22509
  });
22450
22510
  server.tool("goodmem_memories_delete", "Delete a memory", {
22451
- id: external_exports.string().describe("The unique identifier of the memory to delete")
22511
+ id: external_exports.string().describe("The UUID of the memory to delete")
22452
22512
  }, async (args) => {
22453
22513
  await callApi("DELETE", `/v1/memories/${encodeURIComponent(String(args.id))}`, void 0);
22454
22514
  return { content: [{ type: "text", text: "Deleted successfully." }] };
22455
22515
  });
22456
22516
  server.tool("goodmem_memories_get", "Get a memory by ID", {
22457
- id: external_exports.string().describe("The unique identifier of the memory to retrieve"),
22517
+ id: external_exports.string().describe("The UUID of the memory to retrieve"),
22458
22518
  include_content: external_exports.boolean().describe("Whether to include the original content in the response (defaults to false). The snake_case alias include_content is also accepted.").optional(),
22459
22519
  include_processing_history: external_exports.boolean().describe("Whether to include background job processing history in the response (defaults to false). The snake_case alias include_processing_history is also accepted.").optional()
22460
22520
  }, async (args) => {
@@ -22467,7 +22527,7 @@ function registerTools() {
22467
22527
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22468
22528
  });
22469
22529
  server.tool("goodmem_memories_list", "List memories in a space", {
22470
- space_id: external_exports.string().describe("The unique identifier of the space containing the memories"),
22530
+ space_id: external_exports.string().describe("The UUID of the space containing the memories"),
22471
22531
  include_content: external_exports.boolean().describe("Whether to include the original content in the response (defaults to false). The snake_case alias include_content is also accepted.").optional(),
22472
22532
  include_processing_history: external_exports.boolean().describe("Whether to include background job processing history in the response (defaults to false). The snake_case alias include_processing_history is also accepted.").optional(),
22473
22533
  status_filter: external_exports.string().describe("Filter memories by processing status (PENDING, PROCESSING, COMPLETED, FAILED). The snake_case alias status_filter is also accepted.").optional(),
@@ -22526,10 +22586,13 @@ function registerTools() {
22526
22586
  message: external_exports.string().describe("Primary query/message for semantic search."),
22527
22587
  context: external_exports.array(external_exports.object({
22528
22588
  text: external_exports.string().describe("Text content for this context item.").optional(),
22529
- binary: external_exports.any().describe("Binary content for this context item.").optional()
22589
+ binary: external_exports.object({
22590
+ contentType: external_exports.string().describe("MIME type of the binary content."),
22591
+ data: external_exports.string().describe("Base64-encoded binary data.")
22592
+ }).passthrough().describe("Binary content for this context item.").optional()
22530
22593
  }).passthrough()).describe("Optional context items (text or binary) to provide additional context for the search.").optional(),
22531
22594
  space_keys: external_exports.array(external_exports.object({
22532
- spaceId: external_exports.string().describe("The unique identifier for the space to search."),
22595
+ spaceId: external_exports.string().describe("The UUID for the space to search."),
22533
22596
  embedderWeights: external_exports.any().describe("Optional per-embedder weight overrides for this space. If not specified, database defaults are used.").optional(),
22534
22597
  filter: external_exports.string().describe("Optional filter expression that must evaluate to true for memories in this space.").optional()
22535
22598
  }).passthrough()).describe("List of spaces to search with optional per-embedder weight overrides."),
@@ -22601,11 +22664,22 @@ function registerTools() {
22601
22664
  supported_modalities: external_exports.array(external_exports.enum(["TEXT", "IMAGE", "AUDIO", "VIDEO"])).describe("Supported content modalities (defaults to TEXT if not provided) (auto-inferred from model_identifier if omitted)").optional(),
22602
22665
  credentials: external_exports.object({
22603
22666
  kind: external_exports.enum(["CREDENTIAL_KIND_UNSPECIFIED", "CREDENTIAL_KIND_API_KEY", "CREDENTIAL_KIND_GCP_ADC"]).describe("Selected credential strategy"),
22604
- apiKey: external_exports.any().describe("Configuration when kind is CREDENTIAL_KIND_API_KEY").optional(),
22605
- gcpAdc: external_exports.any().describe("Configuration when kind is CREDENTIAL_KIND_GCP_ADC").optional(),
22667
+ apiKey: external_exports.object({
22668
+ inlineSecret: external_exports.string().describe("Secret stored directly in GoodMem (mutually exclusive with secretRef)").optional(),
22669
+ secretRef: external_exports.object({
22670
+ uri: external_exports.string().describe("URI identifying where the secret can be resolved (e.g., vault://, env://)"),
22671
+ hints: external_exports.record(external_exports.string(), external_exports.unknown()).describe('Optional metadata to help resolvers decode the secret (e.g., {"encoding":"base64"})').optional()
22672
+ }).passthrough().describe("Reference to an external secret manager entry (mutually exclusive with inlineSecret)").optional(),
22673
+ headerName: external_exports.string().describe("Desired HTTP header to carry the credential (defaults to Authorization)").optional(),
22674
+ prefix: external_exports.string().describe('Optional prefix prepended to the secret (e.g., "Bearer ")').optional()
22675
+ }).passthrough().describe("Configuration when kind is CREDENTIAL_KIND_API_KEY").optional(),
22676
+ gcpAdc: external_exports.object({
22677
+ scopes: external_exports.any().describe("Additional OAuth scopes. Empty list falls back to the default cloud-platform scope.").optional(),
22678
+ quotaProjectId: external_exports.string().describe("Optional quota project used for billing").optional()
22679
+ }).passthrough().describe("Configuration when kind is CREDENTIAL_KIND_GCP_ADC").optional(),
22606
22680
  labels: external_exports.record(external_exports.string(), external_exports.string()).describe('Optional annotations to aid operators (e.g., "owner=vertex")').optional()
22607
22681
  }).passthrough().describe("Structured credential payload describing how to authenticate with the provider. Required for SaaS providers; optional for local deployments.").optional(),
22608
- labels: external_exports.record(external_exports.string(), external_exports.string()).describe("User-defined labels for categorization").optional(),
22682
+ labels: external_exports.any().describe("User-defined labels for categorization").optional(),
22609
22683
  version: external_exports.string().describe("Version information").optional(),
22610
22684
  monitoring_endpoint: external_exports.string().describe("Monitoring endpoint URL").optional(),
22611
22685
  owner_id: external_exports.string().describe("Optional owner ID. If not provided, derived from the authentication context. Requires CREATE_RERANKER_ANY permission if specified.").optional(),
@@ -22644,13 +22718,13 @@ function registerTools() {
22644
22718
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22645
22719
  });
22646
22720
  server.tool("goodmem_rerankers_delete", "Delete a reranker", {
22647
- id: external_exports.string().describe("The unique identifier of the reranker to delete")
22721
+ id: external_exports.string().describe("The UUID of the reranker to delete")
22648
22722
  }, async (args) => {
22649
22723
  await callApi("DELETE", `/v1/rerankers/${encodeURIComponent(String(args.id))}`, void 0);
22650
22724
  return { content: [{ type: "text", text: "Deleted successfully." }] };
22651
22725
  });
22652
22726
  server.tool("goodmem_rerankers_get", "Get a reranker by ID", {
22653
- id: external_exports.string().describe("The unique identifier of the reranker to retrieve")
22727
+ id: external_exports.string().describe("The UUID of the reranker to retrieve")
22654
22728
  }, async (args) => {
22655
22729
  const result = await callApi("GET", `/v1/rerankers/${encodeURIComponent(String(args.id))}`, void 0);
22656
22730
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
@@ -22673,7 +22747,7 @@ function registerTools() {
22673
22747
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22674
22748
  });
22675
22749
  server.tool("goodmem_rerankers_update", "Update a reranker", {
22676
- id: external_exports.string().describe("The unique identifier of the reranker to update"),
22750
+ id: external_exports.string().describe("The UUID of the reranker to update"),
22677
22751
  display_name: external_exports.string().describe("User-facing name of the reranker").optional(),
22678
22752
  description: external_exports.string().describe("Description of the reranker").optional(),
22679
22753
  endpoint_url: external_exports.string().describe("API endpoint URL").optional(),
@@ -22682,12 +22756,23 @@ function registerTools() {
22682
22756
  supported_modalities: external_exports.array(external_exports.enum(["TEXT", "IMAGE", "AUDIO", "VIDEO"])).describe("Supported content modalities").optional(),
22683
22757
  credentials: external_exports.object({
22684
22758
  kind: external_exports.enum(["CREDENTIAL_KIND_UNSPECIFIED", "CREDENTIAL_KIND_API_KEY", "CREDENTIAL_KIND_GCP_ADC"]).describe("Selected credential strategy"),
22685
- apiKey: external_exports.any().describe("Configuration when kind is CREDENTIAL_KIND_API_KEY").optional(),
22686
- gcpAdc: external_exports.any().describe("Configuration when kind is CREDENTIAL_KIND_GCP_ADC").optional(),
22759
+ apiKey: external_exports.object({
22760
+ inlineSecret: external_exports.string().describe("Secret stored directly in GoodMem (mutually exclusive with secretRef)").optional(),
22761
+ secretRef: external_exports.object({
22762
+ uri: external_exports.string().describe("URI identifying where the secret can be resolved (e.g., vault://, env://)"),
22763
+ hints: external_exports.record(external_exports.string(), external_exports.unknown()).describe('Optional metadata to help resolvers decode the secret (e.g., {"encoding":"base64"})').optional()
22764
+ }).passthrough().describe("Reference to an external secret manager entry (mutually exclusive with inlineSecret)").optional(),
22765
+ headerName: external_exports.string().describe("Desired HTTP header to carry the credential (defaults to Authorization)").optional(),
22766
+ prefix: external_exports.string().describe('Optional prefix prepended to the secret (e.g., "Bearer ")').optional()
22767
+ }).passthrough().describe("Configuration when kind is CREDENTIAL_KIND_API_KEY").optional(),
22768
+ gcpAdc: external_exports.object({
22769
+ scopes: external_exports.any().describe("Additional OAuth scopes. Empty list falls back to the default cloud-platform scope.").optional(),
22770
+ quotaProjectId: external_exports.string().describe("Optional quota project used for billing").optional()
22771
+ }).passthrough().describe("Configuration when kind is CREDENTIAL_KIND_GCP_ADC").optional(),
22687
22772
  labels: external_exports.record(external_exports.string(), external_exports.string()).describe('Optional annotations to aid operators (e.g., "owner=vertex")').optional()
22688
22773
  }).passthrough().describe("Structured credential payload describing how to authenticate with the provider. Omit to keep existing credentials.").optional(),
22689
- replace_labels: external_exports.record(external_exports.string(), external_exports.string()).describe("Replace all existing labels with these (mutually exclusive with mergeLabels)").optional(),
22690
- merge_labels: external_exports.record(external_exports.string(), external_exports.string()).describe("Merge these labels with existing ones (mutually exclusive with replaceLabels)").optional(),
22774
+ replace_labels: external_exports.any().describe("Replace all existing labels with these (mutually exclusive with mergeLabels)").optional(),
22775
+ merge_labels: external_exports.any().describe("Merge these labels with existing ones (mutually exclusive with replaceLabels)").optional(),
22691
22776
  version: external_exports.string().describe("Version information").optional(),
22692
22777
  monitoring_endpoint: external_exports.string().describe("Monitoring endpoint URL").optional()
22693
22778
  }, async (args) => {
@@ -22719,17 +22804,29 @@ function registerTools() {
22719
22804
  });
22720
22805
  server.tool("goodmem_spaces_create", "Create a new Space", {
22721
22806
  name: external_exports.string().describe("The desired name for the space. Must be unique within the user's scope."),
22722
- labels: external_exports.record(external_exports.string(), external_exports.string()).describe("A set of key-value pairs to categorize or tag the space. Used for filtering and organizational purposes.").optional(),
22807
+ labels: external_exports.any().describe("A set of key-value pairs to categorize or tag the space. Used for filtering and organizational purposes.").optional(),
22723
22808
  space_embedders: external_exports.array(external_exports.object({
22724
- embedderId: external_exports.string().describe("The unique identifier for the embedder to associate with the space."),
22809
+ embedderId: external_exports.string().describe("The UUID for the embedder to associate with the space."),
22725
22810
  defaultRetrievalWeight: external_exports.number().describe("Relative weight for this embedder used by default during retrieval. If omitted, defaults to 1.0; values need not sum to 1 and can be overridden per request.").optional()
22726
22811
  }).passthrough()).describe("List of embedder configurations to associate with this space. Each specifies an embedder ID and a relative default retrieval weight used when no per-request overrides are provided."),
22727
22812
  public_read: external_exports.boolean().describe("Indicates if the space and its memories can be read by unauthenticated users or users other than the owner. Defaults to false.").optional(),
22728
22813
  owner_id: external_exports.string().describe("Optional owner ID. If not provided, derived from the authentication context. Requires CREATE_SPACE_ANY permission if specified.").optional(),
22729
22814
  default_chunking_config: external_exports.object({
22730
22815
  none: external_exports.any().describe("No chunking strategy - preserve original content as single unit").optional(),
22731
- recursive: external_exports.any().describe("Recursive hierarchical chunking strategy with configurable separators").optional(),
22732
- sentence: external_exports.any().describe("Sentence-based chunking strategy with language detection").optional()
22816
+ recursive: external_exports.object({
22817
+ chunkSize: external_exports.number().int().describe("Maximum size of a chunk (should be \u2264 context window)"),
22818
+ chunkOverlap: external_exports.number().int().describe("Sliding overlap between chunks"),
22819
+ separators: external_exports.any().describe("Hierarchical separator list (order = preference)").optional(),
22820
+ keepStrategy: external_exports.enum(["KEEP_NONE", "KEEP_START", "KEEP_END"]).describe("How to handle separators after splitting. KEEP_NONE is deprecated and behaves as KEEP_END."),
22821
+ separatorIsRegex: external_exports.boolean().describe("Whether separators are regex patterns").optional(),
22822
+ lengthMeasurement: external_exports.enum(["CHARACTER_COUNT", "TOKEN_COUNT", "CUSTOM"]).describe("How to measure chunk length")
22823
+ }).passthrough().describe("Recursive hierarchical chunking strategy with configurable separators").optional(),
22824
+ sentence: external_exports.object({
22825
+ maxChunkSize: external_exports.number().int().describe("Maximum size of a chunk"),
22826
+ minChunkSize: external_exports.number().int().describe("Minimum size before creating a new chunk"),
22827
+ enableLanguageDetection: external_exports.boolean().describe("Whether to detect language for better segmentation").optional(),
22828
+ lengthMeasurement: external_exports.enum(["CHARACTER_COUNT", "TOKEN_COUNT", "CUSTOM"]).describe("How to measure chunk length")
22829
+ }).passthrough().describe("Sentence-based chunking strategy with language detection").optional()
22733
22830
  }).passthrough().describe("Default chunking strategy for memories in this space"),
22734
22831
  space_id: external_exports.string().describe("Optional client-provided UUID for idempotent creation. If not provided, server generates a new UUID. Returns ALREADY_EXISTS if ID is already in use.").optional()
22735
22832
  }, async (args) => {
@@ -22752,13 +22849,13 @@ function registerTools() {
22752
22849
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22753
22850
  });
22754
22851
  server.tool("goodmem_spaces_delete", "Delete a space", {
22755
- id: external_exports.string().describe("The unique identifier of the space to delete")
22852
+ id: external_exports.string().describe("The UUID of the space to delete")
22756
22853
  }, async (args) => {
22757
22854
  await callApi("DELETE", `/v1/spaces/${encodeURIComponent(String(args.id))}`, void 0);
22758
22855
  return { content: [{ type: "text", text: "Deleted successfully." }] };
22759
22856
  });
22760
22857
  server.tool("goodmem_spaces_get", "Get a space by ID", {
22761
- id: external_exports.string().describe("The unique identifier of the space to retrieve")
22858
+ id: external_exports.string().describe("The UUID of the space to retrieve")
22762
22859
  }, async (args) => {
22763
22860
  const result = await callApi("GET", `/v1/spaces/${encodeURIComponent(String(args.id))}`, void 0);
22764
22861
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
@@ -22793,11 +22890,11 @@ function registerTools() {
22793
22890
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22794
22891
  });
22795
22892
  server.tool("goodmem_spaces_update", "Update a space", {
22796
- id: external_exports.string().describe("The unique identifier of the space to update"),
22893
+ id: external_exports.string().describe("The UUID of the space to update"),
22797
22894
  name: external_exports.string().describe("The new name for the space.").optional(),
22798
22895
  public_read: external_exports.boolean().describe("Whether the space is publicly readable by all users.").optional(),
22799
- replace_labels: external_exports.record(external_exports.string(), external_exports.string()).describe("Labels to replace all existing labels. Mutually exclusive with mergeLabels.").optional(),
22800
- merge_labels: external_exports.record(external_exports.string(), external_exports.string()).describe("Labels to merge with existing labels. Mutually exclusive with replaceLabels.").optional()
22896
+ replace_labels: external_exports.any().describe("Labels to replace all existing labels. Mutually exclusive with mergeLabels.").optional(),
22897
+ merge_labels: external_exports.any().describe("Labels to merge with existing labels. Mutually exclusive with replaceLabels.").optional()
22801
22898
  }, async (args) => {
22802
22899
  const body = {};
22803
22900
  if (args.name !== void 0)
@@ -22820,12 +22917,12 @@ function registerTools() {
22820
22917
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22821
22918
  });
22822
22919
  server.tool("goodmem_users_get", "Get a user by ID", {
22823
- id: external_exports.string().describe("The unique identifier of the user to retrieve").optional(),
22920
+ id: external_exports.string().describe("The UUID of the user to retrieve").optional(),
22824
22921
  email: external_exports.string().describe("The email address of the user to retrieve").optional()
22825
22922
  }, async (args) => {
22826
- if (args.id && args.email)
22923
+ if (args.id !== void 0 && args.email !== void 0)
22827
22924
  throw new Error("Exactly one of 'id', 'email' must be provided, not both.");
22828
- if (!args.id && !args.email)
22925
+ if (args.id === void 0 && args.email === void 0)
22829
22926
  throw new Error("Exactly one of 'id', 'email' must be provided.");
22830
22927
  const url = args.email ? `/v1/users/email/${encodeURIComponent(String(args.email))}` : `/v1/users/${encodeURIComponent(String(args.id))}`;
22831
22928
  const result = await callApi("GET", url, void 0);
@@ -22837,9 +22934,39 @@ function registerTools() {
22837
22934
  });
22838
22935
  }
22839
22936
  registerTools();
22937
+ async function healthCheck() {
22938
+ if (!isConfigured()) {
22939
+ console.error("[goodmem-mcp] Not configured \u2014 set GOODMEM_BASE_URL and GOODMEM_API_KEY, or call goodmem_configure.");
22940
+ return;
22941
+ }
22942
+ try {
22943
+ const url = new URL("/v1/system/info", goodmemBaseUrl);
22944
+ const resp = await fetch(url.toString(), {
22945
+ headers: { "x-api-key": goodmemApiKey },
22946
+ signal: AbortSignal.timeout(1e4)
22947
+ });
22948
+ if (resp.ok) {
22949
+ const info = await resp.json();
22950
+ console.error(`[goodmem-mcp] Connected to ${goodmemBaseUrl} (server ${info.version ?? "unknown"}).`);
22951
+ } else {
22952
+ const text = await resp.text();
22953
+ console.error(`[goodmem-mcp] Health check failed (${resp.status}): ${text}`);
22954
+ }
22955
+ } catch (err) {
22956
+ const msg = err instanceof Error ? err.message : String(err);
22957
+ if (msg.includes("CERT") || msg.includes("certificate") || msg.includes("self-signed") || msg.includes("self signed") || msg.includes("UNABLE_TO_VERIFY")) {
22958
+ console.error(`[goodmem-mcp] TLS certificate error: ${msg}
22959
+ If using self-signed certs, set NODE_TLS_REJECT_UNAUTHORIZED=0 (dev only)
22960
+ or NODE_EXTRA_CA_CERTS=/path/to/rootCA.pem in your MCP server env config.`);
22961
+ } else {
22962
+ console.error(`[goodmem-mcp] Cannot reach ${goodmemBaseUrl}: ${msg}`);
22963
+ }
22964
+ }
22965
+ }
22840
22966
  async function main() {
22841
22967
  const transport = new StdioServerTransport();
22842
22968
  await server.connect(transport);
22969
+ healthCheck();
22843
22970
  }
22844
22971
  main().catch((err) => {
22845
22972
  console.error("Fatal:", err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pairsystems/goodmem-mcp",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "GoodMem MCP server \u2014 exposes GoodMem API as MCP tools",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",