@casys/mcp-erpnext 3.1.0-beta.10 → 3.1.0-beta.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -84,10 +84,11 @@ the current version's highlights.
84
84
 
85
85
  > **3.1 beta preview:** the beta keeps the 3.0 tool surface and adds a generic
86
86
  > document viewer, child tables, document attachments, in-view navigation, and
87
- > active context. **3.1.0-beta.10** hardens the read-only Buy capture and
88
- > immutable recorded-session viewer introduced in beta.9. Features remain
89
- > capability-gated by the MCP host. In particular, downloads require both
90
- > proxied server tools and the MCP Apps `downloadFile` capability. Buy evidence
87
+ > active context. **3.1.0-beta.11** adds reversible context selection, compact
88
+ > Kanban details with distinct Timesheet counts, exact selected-document
89
+ > navigation, five more host languages, and correct generic Company columns. It
90
+ > also retains bounded metadata for unpriced Buy lines and adds offline demo
91
+ > import plans. Features remain capability-gated by the MCP host; Buy evidence
91
92
  > does not purchase or qualify a live ERP.
92
93
 
93
94
  ## Documentation
@@ -265,7 +266,7 @@ live ERPNext instance.
265
266
  caller cannot pass `sourceInstance`, URL, credentials, `capturedAt`, or a
266
267
  digest. Digital Thread stores those bytes in its own CAS; this server does not
267
268
  keep a second CAS.
268
- - App: `io.casys.mcp-erpnext.buy-evidence` `3.1.0-beta.10`, resource
269
+ - App: `io.casys.mcp-erpnext.buy-evidence` `3.1.0-beta.11`, resource
269
270
  `ui://mcp-erpnext/buy-evidence-viewer` (`text/html;profile=mcp-app`), manifest
270
271
  `ui://mcp-erpnext/buy-evidence-manifest` (`application/json`),
271
272
  `acceptedActions` = `viewer.session.apply` only. Complete, partial,
@@ -274,8 +275,12 @@ live ERPNext instance.
274
275
  Digital Thread artefact (`provenance.bundleRef`), not a hash of the displayed
275
276
  projection.
276
277
  - Schemas: `io.casys.mcp-erpnext.buy-source-capture/1.0`,
277
- `io.casys.mcp-erpnext.buy-recorded-result/1.0`,
278
+ `io.casys.mcp-erpnext.buy-recorded-result/1.0` and `/2.0`,
278
279
  `io.casys.mcp-erpnext.buy-recorded-session/1.0`.
280
+ - Result `/2.0` carries bounded `excludedLines` metadata for selected lines
281
+ absent from priced `lines`: exact line ID, quantity, unit, and stated reason.
282
+ It carries no amount, currency, or price source; covered subtotals remain
283
+ sealed values and unresolved lines remain visible.
279
284
  - The viewer is built with the other MCP Apps
280
285
  (`cd src/ui && npm ci && node
281
286
  build-all.mjs`). Published JSR/npm artifacts
@@ -370,6 +375,11 @@ started, and [AGENTS.md](AGENTS.md) for the full architecture and conventions.
370
375
 
371
376
  MIT
372
377
 
373
- Buy result fields use the host locale (EN/FR/ZH). App-level waiting and
374
- rejection screens retain English labels in this beta; host-context support for
375
- those shared surface screens remains an upstream MCP View follow-up.
378
+ Viewers and Buy result fields use the host locale: English, French, Simplified
379
+ Chinese, Traditional Chinese, Hindi, Bengali, Tamil and Urdu. Chinese script
380
+ tags take precedence over region tags; `zh-TW`, `zh-HK` and `zh-MO` select
381
+ Traditional Chinese when no script is specified. Urdu uses right-to-left
382
+ document direction, and a later host locale change updates the language and
383
+ direction without reloading the viewer. App-level waiting and rejection screens
384
+ retain English labels in this beta; host-context support for those shared
385
+ surface screens remains an upstream MCP View follow-up.
package/mcp-erpnext.mjs CHANGED
@@ -4154,13 +4154,14 @@ var require_fast_uri2 = __commonJS({
4154
4154
  if (!malformedIPLiteral) {
4155
4155
  malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
4156
4156
  }
4157
- if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
4158
- if (uri.indexOf("%") !== -1) {
4159
- if (parsed.host !== void 0 && !malformedIPLiteral) {
4160
- const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
4161
- parsed.host = reescapeHostDelimiters(host, isIP);
4162
- }
4157
+ if (uri.indexOf("%") !== -1 && parsed.host !== void 0 && !malformedIPLiteral) {
4158
+ let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
4159
+ if (!isIP) {
4160
+ host = normalizePercentEncoding(host.toLowerCase());
4163
4161
  }
4162
+ parsed.host = reescapeHostDelimiters(host, isIP);
4163
+ }
4164
+ if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
4164
4165
  if (parsed.path) {
4165
4166
  parsed.path = normalizePathEncoding(parsed.path);
4166
4167
  }
@@ -16000,9 +16001,6 @@ function members(proto, table2) {
16000
16001
  else
16001
16002
  defineBound(proto, key, desc.value);
16002
16003
  }
16003
- for (const sym of Object.getOwnPropertySymbols(table2)) {
16004
- defineBound(proto, sym, table2[sym]);
16005
- }
16006
16004
  }
16007
16005
  function own(inst, key, value, enumerable = true) {
16008
16006
  Object.defineProperty(inst, key, { configurable: true, writable: true, enumerable, value });
@@ -16155,8 +16153,7 @@ function $constructor(name, initializer3, proto, params) {
16155
16153
  } finally {
16156
16154
  _zodDesc.value = void 0;
16157
16155
  }
16158
- }
16159
- if (inst._zod.traits.has(name)) {
16156
+ } else if (inst._zod.traits.has(name)) {
16160
16157
  return;
16161
16158
  }
16162
16159
  inst._zod.traits.add(name);
@@ -16919,7 +16916,7 @@ ${content.join("\n")}
16919
16916
  var version = {
16920
16917
  major: 4,
16921
16918
  minor: 6,
16922
- patch: 2
16919
+ patch: 5
16923
16920
  };
16924
16921
 
16925
16922
  // node_modules/zod/v4/core/schemas.js
@@ -17107,11 +17104,32 @@ var $ZodEmail = /* @__PURE__ */ $constructor("$ZodEmail", (inst, def) => {
17107
17104
  });
17108
17105
  var URL_BAD_FORMAT = 1;
17109
17106
  var URL_UNPARSEABLE = 2;
17107
+ function canParseURL(input) {
17108
+ try {
17109
+ if (typeof URL !== "undefined" && typeof URL.canParse === "function")
17110
+ return URL.canParse(input);
17111
+ new URL(input);
17112
+ return true;
17113
+ } catch {
17114
+ return false;
17115
+ }
17116
+ }
17117
+ function validateURL(trimmed, def) {
17118
+ if (!("normalize" in def) && !("hostname" in def) && !("protocol" in def)) {
17119
+ return canParseURL(trimmed) || URL_UNPARSEABLE;
17120
+ }
17121
+ return parseURLObject(trimmed, def);
17122
+ }
17110
17123
  function parseURLObject(trimmed, def) {
17111
17124
  if (!def.normalize && def.protocol?.source === httpProtocol.source && !/^https?:\/\//i.test(trimmed)) {
17112
17125
  return URL_BAD_FORMAT;
17113
17126
  }
17114
17127
  try {
17128
+ if (typeof URL !== "undefined") {
17129
+ const URLStatic = URL;
17130
+ if (typeof URLStatic.parse === "function")
17131
+ return URLStatic.parse(trimmed) ?? URL_UNPARSEABLE;
17132
+ }
17115
17133
  return new URL(trimmed);
17116
17134
  } catch {
17117
17135
  return URL_UNPARSEABLE;
@@ -17134,7 +17152,7 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
17134
17152
  inst._zod.check = (payload) => {
17135
17153
  try {
17136
17154
  const trimmed = payload.value.trim();
17137
- const url2 = parseURLObject(trimmed, def);
17155
+ const url2 = validateURL(trimmed, def);
17138
17156
  if (url2 === URL_BAD_FORMAT) {
17139
17157
  payload.issues.push({
17140
17158
  code: "invalid_format",
@@ -17156,6 +17174,10 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
17156
17174
  });
17157
17175
  return;
17158
17176
  }
17177
+ if (url2 === true) {
17178
+ payload.value = stripTabAndNewline(trimmed);
17179
+ return;
17180
+ }
17159
17181
  if (def.hostname && !urlHostnameOk(url2, def.hostname)) {
17160
17182
  payload.issues.push({
17161
17183
  code: "invalid_format",
@@ -17245,12 +17267,7 @@ var ipv6Alphabet = /^[0-9a-fA-F:.]+$/;
17245
17267
  function isValidIPv6(value) {
17246
17268
  if (!ipv6Alphabet.test(value))
17247
17269
  return false;
17248
- try {
17249
- new URL(`http://[${value}]`);
17250
- return true;
17251
- } catch {
17252
- return false;
17253
- }
17270
+ return canParseURL(`http://[${value}]`);
17254
17271
  }
17255
17272
  var $ZodIPv6 = /* @__PURE__ */ $constructor("$ZodIPv6", (inst, def) => {
17256
17273
  def.pattern ?? (def.pattern = ipv6);
@@ -18620,7 +18637,7 @@ var $ZodCyclicError = class extends Error {
18620
18637
  var STATE = "~memo";
18621
18638
  var NO_ISSUES = [];
18622
18639
  function isRef(value) {
18623
- return value !== null && (typeof value === "object" || typeof value === "function");
18640
+ return value !== null && typeof value === "object";
18624
18641
  }
18625
18642
  function cloneIssues(issues) {
18626
18643
  return issues.map((iss) => iss.path ? { ...iss, path: iss.path.slice() } : { ...iss });
@@ -18669,9 +18686,6 @@ function isRecursive(inst, stack, resolve) {
18669
18686
  check(def.catchall);
18670
18687
  break;
18671
18688
  }
18672
- case "properties":
18673
- merge2(shape(def.shape, false));
18674
- break;
18675
18689
  case "array":
18676
18690
  check(def.element);
18677
18691
  break;
@@ -18927,6 +18941,7 @@ var error = () => {
18927
18941
  base64url: "base64url-encoded string",
18928
18942
  json_string: "JSON string",
18929
18943
  e164: "E.164 number",
18944
+ currency_code: "currency code",
18930
18945
  credit_card: "credit card number",
18931
18946
  iban: "IBAN",
18932
18947
  jwt: "JWT",
@@ -19060,20 +19075,18 @@ function registry() {
19060
19075
  var globalRegistry = globalThis.__zod_globalRegistry;
19061
19076
 
19062
19077
  // node_modules/zod/v4/core/api.js
19078
+ function snapshotChecks(def) {
19079
+ if (def.checks)
19080
+ def.checks = [...def.checks];
19081
+ return def;
19082
+ }
19063
19083
  // @__NO_SIDE_EFFECTS__
19064
19084
  function _string(Class2, params) {
19065
- return new Class2({
19066
- type: "string",
19067
- ...normalizeParams(params)
19068
- });
19085
+ return new Class2(snapshotChecks({ type: "string", ...normalizeParams(params) }));
19069
19086
  }
19070
19087
  // @__NO_SIDE_EFFECTS__
19071
19088
  function _coercedString(Class2, params) {
19072
- return new Class2({
19073
- type: "string",
19074
- coerce: true,
19075
- ...normalizeParams(params)
19076
- });
19089
+ return new Class2(snapshotChecks({ type: "string", coerce: true, ...normalizeParams(params) }));
19077
19090
  }
19078
19091
  // @__NO_SIDE_EFFECTS__
19079
19092
  function _email(Class2, params) {
@@ -19340,20 +19353,11 @@ function _isoDuration(Class2, params) {
19340
19353
  }
19341
19354
  // @__NO_SIDE_EFFECTS__
19342
19355
  function _number(Class2, params) {
19343
- return new Class2({
19344
- type: "number",
19345
- checks: [],
19346
- ...normalizeParams(params)
19347
- });
19356
+ return new Class2(snapshotChecks({ type: "number", checks: [], ...normalizeParams(params) }));
19348
19357
  }
19349
19358
  // @__NO_SIDE_EFFECTS__
19350
19359
  function _coercedNumber(Class2, params) {
19351
- return new Class2({
19352
- type: "number",
19353
- coerce: true,
19354
- checks: [],
19355
- ...normalizeParams(params)
19356
- });
19360
+ return new Class2(snapshotChecks({ type: "number", coerce: true, checks: [], ...normalizeParams(params) }));
19357
19361
  }
19358
19362
  // @__NO_SIDE_EFFECTS__
19359
19363
  function _int(Class2, params) {
@@ -20516,17 +20520,15 @@ var objectProcessor = (schema, ctx, _json, params) => {
20516
20520
  path: [...params.path, "properties", key]
20517
20521
  }));
20518
20522
  }
20519
- const allKeys = new Set(Object.keys(shape));
20520
- const requiredKeys = new Set([...allKeys].filter((key) => {
20523
+ const requiredKeys = [];
20524
+ for (const key of Object.keys(shape)) {
20521
20525
  const field = def.shape[key];
20522
- if (ctx.io === "input") {
20523
- return inputOptin(field) === void 0;
20524
- } else {
20525
- return field._zod.optout === void 0;
20526
+ if (ctx.io === "input" ? inputOptin(field) === void 0 : field._zod.optout === void 0) {
20527
+ requiredKeys.push(key);
20526
20528
  }
20527
- }));
20528
- if (requiredKeys.size > 0) {
20529
- json.required = Array.from(requiredKeys);
20529
+ }
20530
+ if (requiredKeys.length > 0) {
20531
+ json.required = requiredKeys;
20530
20532
  }
20531
20533
  if (def.catchall?._zod.def.type === "never") {
20532
20534
  json.additionalProperties = false;
@@ -20540,31 +20542,6 @@ var objectProcessor = (schema, ctx, _json, params) => {
20540
20542
  });
20541
20543
  }
20542
20544
  };
20543
- var propertiesProcessor = (schema, ctx, _json, params) => {
20544
- const json = _json;
20545
- const def = schema._zod.def;
20546
- if (Object.getOwnPropertySymbols(def.shape).length && handleUnrepresentable(schema, ctx, json, params, "Symbol keys cannot be represented in JSON Schema")) {
20547
- return;
20548
- }
20549
- if (ctx.io === "output") {
20550
- for (const key in def.shape) {
20551
- if (isTransforming(def.shape[key]) && handleUnrepresentable(schema, ctx, json, params, `z.properties() returns its input, so the output of a transforming schema at key "${key}" cannot be represented in JSON Schema`)) {
20552
- return;
20553
- }
20554
- }
20555
- }
20556
- json.type = "object";
20557
- json.properties = {};
20558
- for (const key in def.shape) {
20559
- assignProp(json.properties, key, processSchema(def.shape[key], ctx, {
20560
- ...params,
20561
- path: [...params.path, "properties", key]
20562
- }));
20563
- }
20564
- const required2 = Object.keys(def.shape).filter((key) => inputOptin(def.shape[key]) === void 0);
20565
- if (required2.length > 0)
20566
- json.required = required2;
20567
- };
20568
20545
  var unionProcessor = (schema, ctx, json, params) => {
20569
20546
  const def = schema._zod.def;
20570
20547
  const isExclusive = def.inclusive === false;
@@ -20884,7 +20861,6 @@ var allProcessors = {
20884
20861
  file: fileProcessor,
20885
20862
  success: successProcessor,
20886
20863
  custom: customProcessor,
20887
- properties: propertiesProcessor,
20888
20864
  function: functionProcessor,
20889
20865
  transform: transformProcessor,
20890
20866
  map: mapProcessor,
@@ -38626,7 +38602,10 @@ var HonoRequest = class {
38626
38602
  if (anyCachedKey === "json") {
38627
38603
  body = JSON.stringify(body);
38628
38604
  }
38629
- return new Response(body)[key]();
38605
+ const contentType = anyCachedKey === "formData" ? void 0 : raw2.headers.get("content-type");
38606
+ return new Response(body, {
38607
+ headers: contentType ? { "Content-Type": contentType } : void 0
38608
+ })[key]();
38630
38609
  });
38631
38610
  }
38632
38611
  return bodyCache[key] = raw2[key]();
@@ -39259,7 +39238,7 @@ var Context = class {
39259
39238
  const locationString = String(location);
39260
39239
  this.header(
39261
39240
  "Location",
39262
- // Multibyes should be encoded
39241
+ // Multibytes should be encoded
39263
39242
  // eslint-disable-next-line no-control-regex
39264
39243
  !/[^\x00-\xFF]/.test(locationString) ? locationString : encodeURI(locationString)
39265
39244
  );
@@ -54168,6 +54147,8 @@ function isEmptyPartyAccountCurrencyNone(text) {
54168
54147
  }
54169
54148
 
54170
54149
  // src/tools/operations.ts
54150
+ var DOC_LIST_MAX_LIMIT = 5e3;
54151
+ var DOC_LIST_MAX_OFFSET = 1e5;
54171
54152
  function bytesToBase64(bytes) {
54172
54153
  const chunkSize = 32 * 1024;
54173
54154
  let binary = "";
@@ -54675,7 +54656,7 @@ var operationsTools = [
54675
54656
  name: "erpnext_doc_list",
54676
54657
  annotations: { readOnlyHint: true },
54677
54658
  _meta: DOCLIST_META,
54678
- description: "List any ERPNext documents by DocType. Useful for DocTypes not covered by dedicated tools. Supports field selection, filters (as JSON array), and limit.",
54659
+ description: "List any ERPNext documents by DocType. Useful for DocTypes not covered by dedicated tools. Supports field selection, filters (as JSON array), bounded pagination, and an optional fresh read.",
54679
54660
  category: "operations",
54680
54661
  inputSchema: {
54681
54662
  type: "object",
@@ -54739,7 +54720,22 @@ var operationsTools = [
54739
54720
  ]
54740
54721
  }
54741
54722
  },
54742
- limit: { type: "number", description: "Max results (default 20)" },
54723
+ limit: {
54724
+ type: "integer",
54725
+ minimum: 1,
54726
+ maximum: DOC_LIST_MAX_LIMIT,
54727
+ description: "Max results (default 20, maximum 5000)"
54728
+ },
54729
+ offset: {
54730
+ type: "integer",
54731
+ minimum: 0,
54732
+ maximum: DOC_LIST_MAX_OFFSET,
54733
+ description: "Pagination offset (default 0, maximum 100000)"
54734
+ },
54735
+ skip_cache: {
54736
+ type: "boolean",
54737
+ description: "Force a fresh ERPNext read instead of using the short-lived list cache"
54738
+ },
54743
54739
  order_by: {
54744
54740
  type: "string",
54745
54741
  description: "Order by clause (e.g. 'modified desc', 'name asc')"
@@ -54751,16 +54747,34 @@ var operationsTools = [
54751
54747
  if (!input.doctype) {
54752
54748
  throw new Error("[erpnext_doc_list] 'doctype' is required");
54753
54749
  }
54750
+ if (input.limit !== void 0 && (typeof input.limit !== "number" || !Number.isInteger(input.limit) || input.limit < 1 || input.limit > DOC_LIST_MAX_LIMIT)) {
54751
+ throw new Error(
54752
+ `[erpnext_doc_list] 'limit' must be an integer between 1 and ${DOC_LIST_MAX_LIMIT}`
54753
+ );
54754
+ }
54755
+ if (input.offset !== void 0 && (typeof input.offset !== "number" || !Number.isInteger(input.offset) || input.offset < 0 || input.offset > DOC_LIST_MAX_OFFSET)) {
54756
+ throw new Error(
54757
+ `[erpnext_doc_list] 'offset' must be an integer between 0 and ${DOC_LIST_MAX_OFFSET}`
54758
+ );
54759
+ }
54760
+ if (input.skip_cache !== void 0 && typeof input.skip_cache !== "boolean") {
54761
+ throw new Error("[erpnext_doc_list] 'skip_cache' must be a boolean");
54762
+ }
54754
54763
  const limit = input.limit ?? 20;
54755
54764
  const fields = input.fields ?? ["name", "modified"];
54756
54765
  const filters = input.filters ?? [];
54757
54766
  const order_by = input.order_by ?? "modified desc";
54758
- const docs = await ctx.client.list(input.doctype, {
54767
+ const offset = input.offset;
54768
+ const listOptions = {
54759
54769
  fields,
54760
54770
  filters,
54761
54771
  limit,
54772
+ ...offset !== void 0 ? { limit_start: offset } : {},
54762
54773
  order_by
54763
- });
54774
+ };
54775
+ const docs = input.skip_cache === true ? await ctx.client.list(input.doctype, listOptions, {
54776
+ skipCache: true
54777
+ }) : await ctx.client.list(input.doctype, listOptions);
54764
54778
  return {
54765
54779
  doctype: input.doctype,
54766
54780
  count: docs.length,
@@ -57470,12 +57484,13 @@ var kanbanTools = [
57470
57484
  // src/buy/identities.ts
57471
57485
  var BUY_SOURCE_CAPTURE_SCHEMA = "io.casys.mcp-erpnext.buy-source-capture/1.0";
57472
57486
  var BUY_RECORDED_RESULT_SCHEMA = "io.casys.mcp-erpnext.buy-recorded-result/1.0";
57487
+ var BUY_RECORDED_RESULT_SCHEMA_V2 = "io.casys.mcp-erpnext.buy-recorded-result/2.0";
57473
57488
  var BUY_RECORDED_SESSION_SCHEMA = "io.casys.mcp-erpnext.buy-recorded-session/1.0";
57474
57489
  var BUY_EVIDENCE_VIEWER_URI = "ui://mcp-erpnext/buy-evidence-viewer";
57475
57490
  var BUY_VIEW_APP_MANIFEST_URI = "ui://mcp-erpnext/buy-evidence-manifest";
57476
57491
  var BUY_VIEW_APP_ID = "io.casys.mcp-erpnext.buy-evidence";
57477
57492
  var BUY_VIEW_APP_TITLE = "ERPNext Buy Evidence";
57478
- var BUY_VIEW_APP_VERSION = "3.1.0-beta.10";
57493
+ var BUY_VIEW_APP_VERSION = "3.1.0-beta.11";
57479
57494
  var BUY_SOURCE_INSTANCE_KIND = "erpnext-site";
57480
57495
  var BUY_CAPTURE_DOCTYPE = [
57481
57496
  "Item",
@@ -60249,7 +60264,7 @@ var BUY_VIEW_APP_MANIFEST = {
60249
60264
  resources: [{
60250
60265
  uri: BUY_EVIDENCE_VIEWER_URI,
60251
60266
  ownership: "whole-view",
60252
- resultSchemas: [BUY_RECORDED_RESULT_SCHEMA],
60267
+ resultSchemas: [BUY_RECORDED_RESULT_SCHEMA, BUY_RECORDED_RESULT_SCHEMA_V2],
60253
60268
  acceptedActions: [VIEWER_SESSION_APPLY_ACTION],
60254
60269
  sessionSchemas: [BUY_RECORDED_SESSION_SCHEMA]
60255
60270
  }]
@@ -60313,9 +60328,9 @@ function parseBuyViewAppManifest(value) {
60313
60328
  resource.resultSchemas,
60314
60329
  "Buy View App manifest.resources[0].resultSchemas"
60315
60330
  );
60316
- if (resultSchemas.length !== 1 || resultSchemas[0] !== BUY_RECORDED_RESULT_SCHEMA) {
60331
+ if (resultSchemas.length !== 2 || resultSchemas[0] !== BUY_RECORDED_RESULT_SCHEMA || resultSchemas[1] !== BUY_RECORDED_RESULT_SCHEMA_V2) {
60317
60332
  throw new TypeError(
60318
- "Buy View App manifest result schemas must be io.casys.mcp-erpnext.buy-recorded-result/1.0 exactly."
60333
+ "Buy View App manifest result schemas must list buy-recorded-result/1.0 then /2.0 exactly."
60319
60334
  );
60320
60335
  }
60321
60336
  const acceptedActions = denseArray(
@@ -60622,7 +60637,7 @@ async function main() {
60622
60637
  );
60623
60638
  const server = new McpApp({
60624
60639
  name: "mcp-erpnext",
60625
- version: "3.1.0-beta.10",
60640
+ version: "3.1.0-beta.11",
60626
60641
  transport: "stateless",
60627
60642
  cache: {
60628
60643
  ttlMs: 36e5,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@casys/mcp-erpnext",
3
- "version": "3.1.0-beta.10",
3
+ "version": "3.1.0-beta.11",
4
4
  "description": "MCP server for ERPNext with interactive UI viewers",
5
5
  "type": "module",
6
6
  "bin": {