@pairsystems/goodmem-mcp 0.1.11 → 0.1.13

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 (3) hide show
  1. package/README.md +3 -3
  2. package/dist/index.js +44 -19
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -134,7 +134,7 @@ Inspect the built-in model registry. Shows what fields will be auto-inferred for
134
134
  | `goodmem_embedders_update` | Update embedder configuration |
135
135
  | `goodmem_embedders_delete` | Delete an embedder |
136
136
 
137
- **Create parameters**: `display_name` (required), `model_identifier` (required), `credentials` (required for SaaS providers), `provider_type`, `endpoint_url`, `dimensionality` — last three auto-inferred from `model_identifier` for 29 known models.
137
+ **Create parameters**: `display_name` (required), `model_identifier` (required), `credentials` (required for SaaS providers), `provider_type`, `endpoint_url`, `dimensionality` — last three auto-inferred from `model_identifier` for known models.
138
138
 
139
139
  ### LLMs
140
140
 
@@ -146,7 +146,7 @@ Inspect the built-in model registry. Shows what fields will be auto-inferred for
146
146
  | `goodmem_llms_update` | Update LLM configuration |
147
147
  | `goodmem_llms_delete` | Delete an LLM |
148
148
 
149
- **Create parameters**: `display_name` (required), `model_identifier` (required), `credentials` (required for SaaS providers) — `provider_type`, `endpoint_url`, `max_context_length` auto-inferred for 34 known models.
149
+ **Create parameters**: `display_name` (required), `model_identifier` (required), `credentials` (required for SaaS providers) — `provider_type`, `endpoint_url`, `max_context_length` auto-inferred for known models.
150
150
 
151
151
  ### Rerankers
152
152
 
@@ -158,7 +158,7 @@ Inspect the built-in model registry. Shows what fields will be auto-inferred for
158
158
  | `goodmem_rerankers_update` | Update reranker configuration |
159
159
  | `goodmem_rerankers_delete` | Delete a reranker |
160
160
 
161
- **Create parameters**: `display_name` (required), `model_identifier` (required), `credentials` (required for SaaS providers) — `provider_type` and `endpoint_url` auto-inferred for 16 known models.
161
+ **Create parameters**: `display_name` (required), `model_identifier` (required), `credentials` (required for SaaS providers) — `provider_type` and `endpoint_url` auto-inferred for known models.
162
162
 
163
163
  ### Spaces
164
164
 
package/dist/index.js CHANGED
@@ -21050,7 +21050,14 @@ async function callApiNdjson(method, path, body, query, timeoutSec) {
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").map((line) => line.trim()).filter(Boolean).map((line) => JSON.parse(line));
21053
+ const lines = text.split("\n").map((line) => line.trim()).filter(Boolean);
21054
+ return lines.map((line, i) => {
21055
+ try {
21056
+ return JSON.parse(line);
21057
+ } catch (e) {
21058
+ throw new Error(`NDJSON parse error on line ${i + 1}: ${e instanceof Error ? e.message : String(e)}`);
21059
+ }
21060
+ });
21054
21061
  }
21055
21062
  var MODEL_REGISTRY = {
21056
21063
  "embedders": {
@@ -21885,6 +21892,9 @@ function checkCredentialRequired(args) {
21885
21892
  throw new Error(`Provider '${provider}' at '${endpointUrl}' requires credentials. Pass credentials: { kind: "CREDENTIAL_KIND_API_KEY", apiKey: { inlineSecret: "your-key-here" } }`);
21886
21893
  }
21887
21894
  }
21895
+ function camelToSnake(s) {
21896
+ return s.replace(/([A-Z]+)([A-Z][a-z]{2,})/g, "$1_$2").replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
21897
+ }
21888
21898
  function autoInferFromRegistry(registryType, args) {
21889
21899
  const result = { ...args };
21890
21900
  const modelId = result.model_identifier;
@@ -21892,9 +21902,6 @@ function autoInferFromRegistry(registryType, args) {
21892
21902
  return result;
21893
21903
  const registry2 = MODEL_REGISTRY[registryType] ?? {};
21894
21904
  const entry = registry2[modelId];
21895
- function camelToSnake(s) {
21896
- return s.replace(/([A-Z]+)([A-Z][a-z]{2,})/g, "$1_$2").replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
21897
- }
21898
21905
  if (entry) {
21899
21906
  for (const [key, value] of Object.entries(entry)) {
21900
21907
  const snakeKey = camelToSnake(key);
@@ -21920,7 +21927,7 @@ function autoInferFromRegistry(registryType, args) {
21920
21927
  }
21921
21928
  var server = new McpServer({
21922
21929
  name: "goodmem",
21923
- version: "0.1.11"
21930
+ version: "0.1.13"
21924
21931
  });
21925
21932
  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
21933
  base_url: external_exports.string().describe("GoodMem server URL (e.g., https://your-server.example.com)"),
@@ -21961,11 +21968,23 @@ server.tool("goodmem_lookup_model", "Look up a model in the registry to see its
21961
21968
  const registry2 = MODEL_REGISTRY[registryKey] ?? {};
21962
21969
  const entry = registry2[args.model_identifier];
21963
21970
  if (entry) {
21971
+ const snakeEntry = {};
21972
+ for (const [k, v] of Object.entries(entry)) {
21973
+ if (k === "dimensions") {
21974
+ const dims = v;
21975
+ if (dims?.default !== void 0) {
21976
+ snakeEntry.dimensionality = dims.default;
21977
+ }
21978
+ } else {
21979
+ snakeEntry[camelToSnake(k)] = v;
21980
+ }
21981
+ }
21982
+ const providerType = entry.providerType;
21964
21983
  return { content: [{ type: "text", text: JSON.stringify({
21965
21984
  model_identifier: args.model_identifier,
21966
21985
  type: label,
21967
- ...entry,
21968
- endpointUrl: PROVIDER_ENDPOINTS[entry.providerType] ?? void 0
21986
+ ...snakeEntry,
21987
+ endpoint_url: providerType ? PROVIDER_ENDPOINTS[providerType] : void 0
21969
21988
  }, null, 2) }] };
21970
21989
  }
21971
21990
  }
@@ -21975,7 +21994,7 @@ ${allModels.join("\n")}` }] };
21975
21994
  });
21976
21995
  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 () => {
21977
21996
  return { content: [{ type: "text", text: JSON.stringify({
21978
- mcpVersion: "0.1.11",
21997
+ mcpVersion: "0.1.13",
21979
21998
  basedOnGoodmemCommit: BASED_ON_GOODMEM_COMMIT
21980
21999
  }, null, 2) }] };
21981
22000
  });
@@ -22085,7 +22104,7 @@ function registerTools() {
22085
22104
  quotaProjectId: external_exports.string().describe("Optional quota project used for billing").optional()
22086
22105
  }).passthrough().describe("Configuration when kind is CREDENTIAL_KIND_GCP_ADC").optional(),
22087
22106
  labels: external_exports.any().describe('Optional annotations to aid operators (e.g., "owner=vertex")').optional()
22088
- }).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(),
22107
+ }).passthrough().describe("Structured credential payload describing how to authenticate with the provider. Required for SaaS providers; optional for local or proxy providers.").optional(),
22089
22108
  labels: external_exports.record(external_exports.string(), external_exports.string()).describe("User-defined labels for categorization").optional(),
22090
22109
  version: external_exports.string().describe("Version information").optional(),
22091
22110
  monitoring_endpoint: external_exports.string().describe("Monitoring endpoint URL").optional(),
@@ -22248,7 +22267,7 @@ function registerTools() {
22248
22267
  quotaProjectId: external_exports.string().describe("Optional quota project used for billing").optional()
22249
22268
  }).passthrough().describe("Configuration when kind is CREDENTIAL_KIND_GCP_ADC").optional(),
22250
22269
  labels: external_exports.any().describe('Optional annotations to aid operators (e.g., "owner=vertex")').optional()
22251
- }).passthrough().describe("Structured credential payload describing how to authenticate with the provider. Omit for deployments that do not require credentials.").optional(),
22270
+ }).passthrough().describe("Structured credential payload describing how to authenticate with the provider. Required for SaaS providers; optional for local or proxy providers.").optional(),
22252
22271
  labels: external_exports.record(external_exports.string(), external_exports.string()).describe("User-defined labels for categorization").optional(),
22253
22272
  version: external_exports.string().describe("Version information").optional(),
22254
22273
  monitoring_endpoint: external_exports.string().describe("Monitoring endpoint URL").optional(),
@@ -22454,7 +22473,7 @@ function registerTools() {
22454
22473
  }).passthrough().describe("Chunking strategy for this memory (if not provided, uses space default)").optional(),
22455
22474
  extractPageImages: external_exports.boolean().describe("Optional hint to extract page images for eligible document types (for example, PDFs)").optional(),
22456
22475
  fileField: external_exports.string().describe("Optional multipart file field name to bind binary content; required when multiple files are uploaded in a batch multipart request.").optional()
22457
- }).passthrough()).describe("Array of memory creation requests.")
22476
+ }).passthrough()).min(1).describe("Array of memory creation requests.")
22458
22477
  }, async (args) => {
22459
22478
  const body = {};
22460
22479
  if (args.requests !== void 0)
@@ -22493,7 +22512,7 @@ function registerTools() {
22493
22512
  const result = await callApi("POST", `/v1/memories:batchGet`, body);
22494
22513
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22495
22514
  });
22496
- server.tool("goodmem_memories_create", "Create a new memory", {
22515
+ server.tool("goodmem_memories_create", "Create a memory from text content or base64-encoded content. Content must be provided via exactly one of `original_content` or `original_content_b64`.", {
22497
22516
  memory_id: external_exports.string().describe("Optional client-provided UUID for the memory. If omitted, the server generates one. Returns ALREADY_EXISTS if the ID is already in use.").optional(),
22498
22517
  space_id: external_exports.string().describe("ID of the space where this memory will be stored"),
22499
22518
  original_content: external_exports.string().describe("Original content as plain text (use either this or originalContentB64)").optional(),
@@ -22564,7 +22583,7 @@ function registerTools() {
22564
22583
  const result = await callApi("GET", `/v1/memories/${encodeURIComponent(String(args.id))}`, void 0, query);
22565
22584
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22566
22585
  });
22567
- server.tool("goodmem_memories_list", "List memories in a space", {
22586
+ server.tool("goodmem_memories_list", "Lists memories within a given space. Results are paginated \u2014 the returned `Page` eagerly fetches the first page. Access `.data` for items and `.next_token` to resume. Use `for mem in page` to auto-paginate all pages, `page_size` to control items per API call, and `max_items` to cap total results.", {
22568
22587
  space_id: external_exports.string().describe("The UUID of the space containing the memories"),
22569
22588
  include_content: external_exports.boolean().describe("Whether to include the original content in the response (defaults to false).").optional(),
22570
22589
  include_processing_history: external_exports.boolean().describe("Whether to include background job processing history in the response (defaults to false).").optional(),
@@ -22620,7 +22639,7 @@ function registerTools() {
22620
22639
  const result = await callApi("GET", `/v1/memories/${encodeURIComponent(String(args.id))}/pages`, void 0, query);
22621
22640
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22622
22641
  });
22623
- server.tool("goodmem_memories_retrieve", "Advanced semantic memory retrieval with JSON", {
22642
+ server.tool("goodmem_memories_retrieve", "Performs a streaming semantic search across one or more memory spaces and returns matching chunks ranked by relevance as well as LLM-postprocessed results (like summarization, question-answering, etc.).", {
22624
22643
  message: external_exports.string().describe("Primary query/message for semantic search."),
22625
22644
  context: external_exports.array(external_exports.object({
22626
22645
  text: external_exports.string().describe("Text content for this context item.").optional(),
@@ -22647,6 +22666,10 @@ function registerTools() {
22647
22666
  name: external_exports.string().describe("Fully qualified factory class name of the post-processor to apply."),
22648
22667
  config: external_exports.any().describe("Configuration parameters for the post-processor. Fields depend on the selected processor; see the linked documentation for the built-in ChatPostProcessor schema.").optional()
22649
22668
  }).passthrough().describe("Optional post-processor configuration to transform retrieval results.").optional(),
22669
+ logging: external_exports.object({
22670
+ enabled: external_exports.boolean().describe("Opts this request in to durable server-side request logging."),
22671
+ callerAttributes: external_exports.any().describe("Optional flat scalar attributes attached to the persisted log row. Supported value types are string, integer, floating-point, and boolean.").optional()
22672
+ }).passthrough().describe("Optional durable request logging block for POST retrieve requests. Supply logging.enabled=true to opt in, and optionally attach flat scalar logging.callerAttributes for persisted experiment or tracing metadata.").optional(),
22650
22673
  timeout_sec: external_exports.number().int().describe("Maximum seconds to wait for the streaming response (default: 200).").optional()
22651
22674
  }, async (args) => {
22652
22675
  const body = {};
@@ -22666,10 +22689,12 @@ function registerTools() {
22666
22689
  body["hnsw"] = args.hnsw;
22667
22690
  if (args.post_processor !== void 0)
22668
22691
  body["postProcessor"] = args.post_processor;
22692
+ if (args.logging !== void 0)
22693
+ body["logging"] = args.logging;
22669
22694
  const result = await callApiNdjson("POST", `/v1/memories:retrieve`, body, void 0, args.timeout_sec);
22670
22695
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22671
22696
  });
22672
- server.tool("goodmem_ocr_document", "Run OCR on a document or image", {
22697
+ server.tool("goodmem_ocr_document", "Run OCR on a document or image. Pass base64-encoded document bytes as `content`. Optionally specify `format` (e.g., PDF, PNG) \u2014 if omitted, the server auto-detects.", {
22673
22698
  content: external_exports.string().describe("Base64-encoded document bytes"),
22674
22699
  format: external_exports.enum(["AUTO", "PDF", "TIFF", "PNG", "JPEG", "BMP"]).describe("Input format hint (AUTO, PDF, TIFF, PNG, JPEG, BMP)").optional(),
22675
22700
  include_raw_json: external_exports.boolean().describe("Include raw OCR JSON payload in the response").optional(),
@@ -22717,7 +22742,7 @@ function registerTools() {
22717
22742
  quotaProjectId: external_exports.string().describe("Optional quota project used for billing").optional()
22718
22743
  }).passthrough().describe("Configuration when kind is CREDENTIAL_KIND_GCP_ADC").optional(),
22719
22744
  labels: external_exports.any().describe('Optional annotations to aid operators (e.g., "owner=vertex")').optional()
22720
- }).passthrough().describe("Structured credential payload describing how to authenticate with the provider. Required for SaaS providers; optional for local deployments.").optional(),
22745
+ }).passthrough().describe("Structured credential payload describing how to authenticate with the provider. Required for SaaS providers; optional for local or proxy providers.").optional(),
22721
22746
  labels: external_exports.record(external_exports.string(), external_exports.string()).describe("User-defined labels for categorization").optional(),
22722
22747
  version: external_exports.string().describe("Version information").optional(),
22723
22748
  monitoring_endpoint: external_exports.string().describe("Monitoring endpoint URL").optional(),
@@ -22847,7 +22872,7 @@ function registerTools() {
22847
22872
  space_embedders: external_exports.array(external_exports.object({
22848
22873
  embedderId: external_exports.string().describe("The UUID for the embedder to associate with the space."),
22849
22874
  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()
22850
- }).passthrough()).describe("List of embedder configurations to associate with this space. At least one embedder configuration is required. Each specifies an embedder ID and a relative default retrieval weight used when no per-request overrides are provided."),
22875
+ }).passthrough()).min(1).describe("List of embedder configurations to associate with this space. At least one embedder configuration is required. Each specifies an embedder ID and a relative default retrieval weight used when no per-request overrides are provided."),
22851
22876
  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(),
22852
22877
  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(),
22853
22878
  default_chunking_config: external_exports.object({
@@ -22899,7 +22924,7 @@ function registerTools() {
22899
22924
  const result = await callApi("GET", `/v1/spaces/${encodeURIComponent(String(args.id))}`, void 0);
22900
22925
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22901
22926
  });
22902
- server.tool("goodmem_spaces_list", "List spaces", {
22927
+ server.tool("goodmem_spaces_list", "List spaces accessible to the caller, with optional filtering by owner, labels, and name. Results are paginated \u2014 the returned `Page` eagerly fetches the first page. Access `.data` for items and `.next_token` to resume. Use `for space in page` to auto-paginate all pages, `page_size` to control items per API call, and `max_items` to cap total results.", {
22903
22928
  owner_id: external_exports.string().describe("Filter spaces by owner ID. With LIST_SPACE_ANY permission and ownerId omitted, returns all visible spaces. Otherwise returns caller-owned spaces only. Specifying ownerId without LIST_SPACE_ANY returns PERMISSION_DENIED.").optional(),
22904
22929
  name_filter: external_exports.string().describe("Filter spaces by name using glob pattern matching").optional(),
22905
22930
  max_results: external_exports.number().int().describe("Maximum number of results to return in a single page (defaults to 50, clamped to [1, 1000])").optional(),
@@ -22955,7 +22980,7 @@ function registerTools() {
22955
22980
  const result = await callApi("POST", `/v1/system/init`, void 0);
22956
22981
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
22957
22982
  });
22958
- server.tool("goodmem_users_get", "Get a user by ID", {
22983
+ server.tool("goodmem_users_get", "Retrieves a user by ID or email address. Exactly one of `id` and `email` must be provided. For getting your own profile, use `client.users.me()`.", {
22959
22984
  id: external_exports.string().describe("The UUID of the user to retrieve").optional(),
22960
22985
  email: external_exports.string().describe("The email address of the user to retrieve").optional()
22961
22986
  }, async (args) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pairsystems/goodmem-mcp",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "GoodMem MCP server \u2014 exposes GoodMem API as MCP tools",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",