@agentistics/mcp 2.77.0 → 2.78.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.
- package/dist/agentistics-mcp.js +287 -1
- package/package.json +1 -1
package/dist/agentistics-mcp.js
CHANGED
|
@@ -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);
|