@agentistics/mcp 2.77.0 → 2.79.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -171,6 +171,51 @@ var DEFAULT_TEAM = Object.freeze({
171
171
  connections: Object.freeze([])
172
172
  });
173
173
  var SHARE_SOURCE_TYPES = new Set(["repo", "project", "none"]);
174
+ // ../core/src/redact.ts
175
+ var REDACTION = "[REDACTED]";
176
+ var PLACEHOLDER = /^(\*+|x+|\.+|-+|<[^>]*>|\{[^}]*\}|\$\{?[A-Z_][A-Z0-9_]*\}?|your[-_]?\w*|todo|changeme|none|null|nil|empty|redacted|\[redacted\])$/i;
177
+ function looksSecret(value) {
178
+ const v = value.trim().replace(/^["']|["']$/g, "");
179
+ if (v.length < 12)
180
+ return false;
181
+ if (PLACEHOLDER.test(v))
182
+ return false;
183
+ if (/^\d+$/.test(v))
184
+ return false;
185
+ if (/\s/.test(v))
186
+ return false;
187
+ const classes = [/[a-z]/.test(v), /[A-Z]/.test(v), /\d/.test(v), /[^A-Za-z0-9]/.test(v)].filter(Boolean).length;
188
+ return classes >= 2;
189
+ }
190
+ function guarded(whole, prefix, value) {
191
+ return looksSecret(value) ? `${prefix}${REDACTION}` : whole;
192
+ }
193
+ var STRONG = [
194
+ /-----BEGIN[^-]*PRIVATE KEY-----[\s\S]*?-----END[^-]*PRIVATE KEY-----/g,
195
+ /\bgithub_pat_[A-Za-z0-9_]{20,}/g,
196
+ /\bgh[pousr]_[A-Za-z0-9]{20,}/g,
197
+ /\bsk-ant-[A-Za-z0-9\-_]{16,}/g,
198
+ /\bsk-(?:proj-)?[A-Za-z0-9\-_]{20,}/g,
199
+ /\bxox[baprs]-[A-Za-z0-9-]{10,}/g,
200
+ /\bAIza[A-Za-z0-9\-_]{35}/g,
201
+ /\bAKIA[0-9A-Z]{16}\b/g,
202
+ /\beyJ[A-Za-z0-9\-_]{8,}\.eyJ[A-Za-z0-9\-_]{8,}\.[A-Za-z0-9\-_]{8,}/g,
203
+ /\bact1_[A-Za-z0-9\-_]+\.[A-Za-z0-9]{16,}/g
204
+ ];
205
+ var URI_CREDENTIAL = /\b([a-z][a-z0-9+.\-]*:\/\/[^\s:/@"']+:)([^\s@"']+)@/gi;
206
+ var ASSIGNMENT = /(^|[^A-Za-z0-9_])((?:[A-Za-z0-9]+[_-])*(?:pass(?:word|wd)?|pwd|secret|token|auth|credentials?|api[_-]?key|access[_-]?key|private[_-]?key)[a-z0-9_-]*\s*[:=]\s*)(["']?[^\s"',;]+["']?)/gi;
207
+ var BEARER = /\b(Bearer\s+)([A-Za-z0-9\-._~+/]{12,}=*)/g;
208
+ function redactSecrets(text) {
209
+ if (typeof text !== "string" || text === "")
210
+ return "";
211
+ let out = text;
212
+ for (const re of STRONG)
213
+ out = out.replace(re, REDACTION);
214
+ out = out.replace(URI_CREDENTIAL, (whole, prefix, pw) => PLACEHOLDER.test(pw) ? whole : `${prefix}${REDACTION}@`);
215
+ out = out.replace(ASSIGNMENT, (whole, lead, prefix, value) => guarded(whole, `${lead}${prefix}`, value));
216
+ out = out.replace(BEARER, (whole, prefix, value) => guarded(whole, prefix, value));
217
+ return out;
218
+ }
174
219
  // ../core/src/plan-catalog.ts
175
220
  var CLAUDE_PRICING = "https://claude.com/pricing";
176
221
  var COPILOT_PRICING = "https://github.com/features/copilot/plans";
@@ -815,6 +860,224 @@ function harnessParam() {
815
860
  };
816
861
  }
817
862
 
863
+ // agent-audit.ts
864
+ import { createHash } from "node:crypto";
865
+ import * as nodeFs from "node:fs";
866
+ import { homedir } from "node:os";
867
+ import { dirname, join } from "node:path";
868
+ var AUDIT_ROTATE_BYTES = 10 * 1024 * 1024;
869
+ var AUDIT_KEEP_FILES = 3;
870
+ function defaultAuditPath(env = process.env) {
871
+ return join(env.AGENTISTICS_DIR ?? join(homedir(), ".agentistics"), "agent-audit.jsonl");
872
+ }
873
+ var TARGET_KEYS = [
874
+ "ref",
875
+ "id",
876
+ "taskId",
877
+ "subtaskId",
878
+ "sessionId",
879
+ "session",
880
+ "sessions",
881
+ "group",
882
+ "parentGroupId",
883
+ "blockedBy",
884
+ "componentId",
885
+ "instanceId",
886
+ "tag",
887
+ "remove"
888
+ ];
889
+ var ID_SHAPE = /^[A-Za-z0-9][A-Za-z0-9_.:@-]{0,79}$/;
890
+ var MAX_TARGETS = 20;
891
+ function asId(v) {
892
+ if (typeof v !== "string" || !ID_SHAPE.test(v))
893
+ return null;
894
+ return redactSecrets(v) === v ? v : null;
895
+ }
896
+ function targetsOf(args) {
897
+ const out = [];
898
+ let omitted = 0;
899
+ if (!args || typeof args !== "object")
900
+ return { targets: out, omitted };
901
+ const a = args;
902
+ for (const key of TARGET_KEYS) {
903
+ const raw = a[key];
904
+ if (raw === undefined || raw === null || typeof raw === "boolean")
905
+ continue;
906
+ for (const v of Array.isArray(raw) ? raw : [raw]) {
907
+ const id = asId(v);
908
+ if (id === null) {
909
+ omitted++;
910
+ continue;
911
+ }
912
+ if (out.length >= MAX_TARGETS) {
913
+ omitted++;
914
+ continue;
915
+ }
916
+ if (!out.includes(id))
917
+ out.push(id);
918
+ }
919
+ }
920
+ return { targets: out, omitted };
921
+ }
922
+ function canonical(v) {
923
+ if (Array.isArray(v))
924
+ return `[${v.map(canonical).join(",")}]`;
925
+ if (v && typeof v === "object") {
926
+ const o = v;
927
+ return `{${Object.keys(o).sort().map((k) => `${JSON.stringify(k)}:${canonical(o[k])}`).join(",")}}`;
928
+ }
929
+ return JSON.stringify(v ?? null);
930
+ }
931
+ function argsHash(args) {
932
+ return createHash("sha256").update(canonical(args ?? {})).digest("hex").slice(0, 16);
933
+ }
934
+ function label(v) {
935
+ if (typeof v !== "string")
936
+ return;
937
+ const t = v.trim().slice(0, 64);
938
+ if (!/^[\w.:@/ -]{1,64}$/.test(t))
939
+ return;
940
+ return redactSecrets(t) === t ? t : undefined;
941
+ }
942
+ function actorOf(client, args, naySession) {
943
+ const a = args && typeof args === "object" ? args : {};
944
+ const declared = label(a.actor) ?? label(a.by);
945
+ const nay = naySession !== undefined ? asId(naySession) ?? undefined : undefined;
946
+ return {
947
+ client: label(client?.name) ?? null,
948
+ clientVersion: label(client?.version) ?? null,
949
+ ...declared !== undefined ? { declared } : {},
950
+ ...nay !== undefined ? { naySession: nay } : {}
951
+ };
952
+ }
953
+ function outcomeOf(result) {
954
+ if (result === "unknown_tool")
955
+ return "unknown_tool";
956
+ if (!result.isError)
957
+ return "ok";
958
+ const m = /→ HTTP (\d{3})\b/.exec(result.errorText ?? "");
959
+ return m ? `http_${Number(m[1])}` : "error";
960
+ }
961
+ function isKnownTool(name) {
962
+ return Object.prototype.hasOwnProperty.call(AGENT_TOOL_POLICY, name);
963
+ }
964
+ function riskOf(name) {
965
+ return isKnownTool(name) ? AGENT_TOOL_POLICY[name].risk : null;
966
+ }
967
+ function buildToolAuditRecord(input) {
968
+ const known = isKnownTool(input.name);
969
+ const { targets, omitted } = targetsOf(input.args);
970
+ return {
971
+ v: 1,
972
+ kind: "tool",
973
+ at: input.at.toISOString(),
974
+ actor: actorOf(input.client, input.args, input.naySession),
975
+ tool: known ? input.name : null,
976
+ risk: riskOf(input.name),
977
+ targets,
978
+ ...omitted > 0 ? { targetsOmitted: omitted } : {},
979
+ argsHash: argsHash(input.args),
980
+ outcome: known ? outcomeOf(input.result) : "unknown_tool"
981
+ };
982
+ }
983
+ function hourOf(at) {
984
+ return at.toISOString().slice(0, 13);
985
+ }
986
+ function readCountRecord(hour, counts) {
987
+ return { v: 1, kind: "reads", hour, counts: { ...counts } };
988
+ }
989
+ function rotatedPath(path, n) {
990
+ return n === 0 ? path : `${path}.${n}`;
991
+ }
992
+ function createAgentAuditSink(opts = {}) {
993
+ const path = opts.path ?? defaultAuditPath();
994
+ const maxBytes = opts.maxBytes ?? AUDIT_ROTATE_BYTES;
995
+ const keep = Math.max(1, opts.keep ?? AUDIT_KEEP_FILES);
996
+ const fs = opts.fs ?? nodeFs;
997
+ const now = opts.now ?? (() => new Date);
998
+ let written = 0;
999
+ let writeFailures = 0;
1000
+ let pendingDropped = 0;
1001
+ let modeChecked = false;
1002
+ let readHour = null;
1003
+ let readCounts = {};
1004
+ function sizeOf(p) {
1005
+ try {
1006
+ return fs.statSync(p).size;
1007
+ } catch {
1008
+ return 0;
1009
+ }
1010
+ }
1011
+ function rotate() {
1012
+ fs.rmSync(rotatedPath(path, keep - 1), { force: true });
1013
+ for (let n = keep - 2;n >= 0; n--) {
1014
+ const from = rotatedPath(path, n);
1015
+ try {
1016
+ fs.renameSync(from, rotatedPath(path, n + 1));
1017
+ } catch (e) {
1018
+ if (e?.code !== "ENOENT")
1019
+ throw e;
1020
+ }
1021
+ }
1022
+ modeChecked = false;
1023
+ }
1024
+ function write(rec) {
1025
+ try {
1026
+ const line = `${JSON.stringify(pendingDropped > 0 ? { ...rec, dropped: pendingDropped } : rec)}
1027
+ `;
1028
+ if (!modeChecked)
1029
+ fs.mkdirSync(dirname(path), { recursive: true, mode: 448 });
1030
+ if (keep > 1 && sizeOf(path) + Buffer.byteLength(line) > maxBytes && sizeOf(path) > 0)
1031
+ rotate();
1032
+ else if (keep === 1 && sizeOf(path) + Buffer.byteLength(line) > maxBytes)
1033
+ fs.rmSync(path, { force: true });
1034
+ fs.appendFileSync(path, line, { mode: 384 });
1035
+ if (!modeChecked) {
1036
+ fs.chmodSync(path, 384);
1037
+ modeChecked = true;
1038
+ }
1039
+ written++;
1040
+ pendingDropped = 0;
1041
+ } catch {
1042
+ writeFailures++;
1043
+ pendingDropped++;
1044
+ }
1045
+ }
1046
+ function flushReads() {
1047
+ if (readHour === null || Object.keys(readCounts).length === 0)
1048
+ return;
1049
+ const rec = readCountRecord(readHour, readCounts);
1050
+ readHour = null;
1051
+ readCounts = {};
1052
+ write(rec);
1053
+ }
1054
+ return {
1055
+ recordCall(input) {
1056
+ try {
1057
+ const at = now();
1058
+ const hour = hourOf(at);
1059
+ if (readHour !== null && readHour !== hour)
1060
+ flushReads();
1061
+ if (riskOf(input.name) === "R") {
1062
+ readHour = hour;
1063
+ readCounts[input.name] = (readCounts[input.name] ?? 0) + 1;
1064
+ return;
1065
+ }
1066
+ write(buildToolAuditRecord({ ...input, at }));
1067
+ } catch {
1068
+ writeFailures++;
1069
+ pendingDropped++;
1070
+ }
1071
+ },
1072
+ flush() {
1073
+ flushReads();
1074
+ },
1075
+ stats() {
1076
+ return { written, writeFailures, pendingDropped };
1077
+ }
1078
+ };
1079
+ }
1080
+
818
1081
  // agentistics-mcp.ts
819
1082
  var API = process.env.AGENTISTICS_API ?? "http://localhost:47291";
820
1083
  var HARNESS_PARAM = harnessParam();
@@ -1385,7 +1648,30 @@ var TOOLS = [
1385
1648
  }
1386
1649
  ];
1387
1650
  server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
1651
+ var audit = createAgentAuditSink();
1652
+ process.on("exit", () => audit.flush());
1653
+ for (const sig of ["SIGINT", "SIGTERM"]) {
1654
+ process.on(sig, () => {
1655
+ audit.flush();
1656
+ process.exit(0);
1657
+ });
1658
+ }
1388
1659
  server.setRequestHandler(CallToolRequestSchema, async (req) => {
1660
+ const result = await callTool(req);
1661
+ const first = result.content?.[0];
1662
+ audit.recordCall({
1663
+ name: req.params.name,
1664
+ args: req.params.arguments,
1665
+ client: server.getClientVersion(),
1666
+ naySession: process.env.AGENTISTICS_NAY_SESSION,
1667
+ result: {
1668
+ isError: result.isError === true,
1669
+ errorText: first && first.type === "text" ? first.text : undefined
1670
+ }
1671
+ });
1672
+ return result;
1673
+ });
1674
+ async function callTool(req) {
1389
1675
  const { name, arguments: args } = req.params;
1390
1676
  try {
1391
1677
  switch (name) {
@@ -2064,6 +2350,6 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
2064
2350
  isError: true
2065
2351
  };
2066
2352
  }
2067
- });
2353
+ }
2068
2354
  var transport = new StdioServerTransport;
2069
2355
  await server.connect(transport);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentistics/mcp",
3
- "version": "2.77.0",
3
+ "version": "2.79.0",
4
4
  "description": "Agentistics MCP server — Claude Code analytics for Claude Desktop and Claude Code",
5
5
  "type": "module",
6
6
  "main": "./dist/agentistics-mcp.js",