@agentistics/mcp 1.7.5 → 1.7.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.
- package/dist/agentistics-mcp.js +175 -0
- package/package.json +1 -1
package/dist/agentistics-mcp.js
CHANGED
|
@@ -8,6 +8,21 @@ import {
|
|
|
8
8
|
ListToolsRequestSchema
|
|
9
9
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
10
10
|
|
|
11
|
+
// ../core/src/local-models.ts
|
|
12
|
+
var LOCAL_RUNTIME_PREFIXES = [
|
|
13
|
+
"ollama",
|
|
14
|
+
"lmstudio",
|
|
15
|
+
"llamacpp",
|
|
16
|
+
"llama.cpp",
|
|
17
|
+
"local/",
|
|
18
|
+
"localhost"
|
|
19
|
+
];
|
|
20
|
+
function isLocalModelId(modelId) {
|
|
21
|
+
const id = String(modelId ?? "").toLowerCase();
|
|
22
|
+
return LOCAL_RUNTIME_PREFIXES.some((p) => id.startsWith(p));
|
|
23
|
+
}
|
|
24
|
+
var LOCAL_MODEL_PRICE = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
25
|
+
|
|
11
26
|
// ../core/src/types.ts
|
|
12
27
|
var HARNESS_SORT = {
|
|
13
28
|
claude: 0,
|
|
@@ -55,6 +70,8 @@ var MODEL_PRICING = {
|
|
|
55
70
|
function getModelPrice(modelId) {
|
|
56
71
|
if (MODEL_PRICING[modelId])
|
|
57
72
|
return MODEL_PRICING[modelId];
|
|
73
|
+
if (isLocalModelId(modelId))
|
|
74
|
+
return LOCAL_MODEL_PRICE;
|
|
58
75
|
const id = String(modelId ?? "");
|
|
59
76
|
let forwardKey = "";
|
|
60
77
|
let reverseKey = "";
|
|
@@ -378,6 +395,37 @@ var TOOLS = [
|
|
|
378
395
|
},
|
|
379
396
|
required: ["name", "componentIds"]
|
|
380
397
|
}
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
name: "agentistics_tags",
|
|
401
|
+
description: "List all tags — saved cross-cutting filters over repos/projects/machines/teams/accounts — with their aggregate sessions, cost, and tokens. Use for 'what tags exist' or 'how much did tag X cost' questions.",
|
|
402
|
+
inputSchema: { type: "object", properties: {}, required: [] }
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
name: "agentistics_tag_detail",
|
|
406
|
+
description: "Get full detail for one tag by name or id: aggregate totals plus per-source breakdown and distributions (top projects, models, harnesses, repos, members/users), daily activity series, and the active date window. Call agentistics_tags first to find the id/name.",
|
|
407
|
+
inputSchema: {
|
|
408
|
+
type: "object",
|
|
409
|
+
properties: {
|
|
410
|
+
tag: { type: "string", description: "Tag name or id, from agentistics_tags" }
|
|
411
|
+
},
|
|
412
|
+
required: ["tag"]
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
name: "agentistics_repos",
|
|
417
|
+
description: "List repositories, grouped by normalized git remote (independent of local path or which machine produced the session), with session/message/token/cost totals and last-active date. Sessions with no linked repository are grouped under 'unlinked'. Optionally scope to a single harness.",
|
|
418
|
+
inputSchema: { type: "object", properties: { harness: HARNESS_PARAM }, required: [] }
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
name: "agentistics_team_status",
|
|
422
|
+
description: "Get this machine's team-mode status: solo, central, or member. In member mode, lists its central connections (label, endpoint, connected/error state, last push). Use for 'am I connected to a team' or 'what central do I push to' questions.",
|
|
423
|
+
inputSchema: { type: "object", properties: {}, required: [] }
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
name: "agentistics_team_members",
|
|
427
|
+
description: "List members of this team, central only: display name, online/presence status, latency, and last-seen timestamp. For usage/cost per member use agentistics_summary or agentistics_sessions against this central's own /api/data. Returns an explanatory message when this machine is not running as a central (solo/member mode).",
|
|
428
|
+
inputSchema: { type: "object", properties: {}, required: [] }
|
|
381
429
|
}
|
|
382
430
|
];
|
|
383
431
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
|
|
@@ -748,6 +796,133 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
748
796
|
}]
|
|
749
797
|
};
|
|
750
798
|
}
|
|
799
|
+
case "agentistics_tags": {
|
|
800
|
+
const data = await apiGet("/api/tags");
|
|
801
|
+
const tags = data.tags ?? [];
|
|
802
|
+
const rows = tags.map((t) => ({
|
|
803
|
+
id: t._id,
|
|
804
|
+
name: t.name,
|
|
805
|
+
color: t.color ?? null,
|
|
806
|
+
sessions: t.aggregate?.sessions ?? 0,
|
|
807
|
+
estimatedCostUSD: Math.round((t.aggregate?.costUSD ?? 0) * 1e4) / 1e4,
|
|
808
|
+
inputTokens: t.aggregate?.inputTokens ?? 0,
|
|
809
|
+
outputTokens: t.aggregate?.outputTokens ?? 0,
|
|
810
|
+
topProject: t.aggregate?.topProject ?? null,
|
|
811
|
+
topModel: t.aggregate?.topModel ?? null,
|
|
812
|
+
topHarness: t.aggregate?.topHarness ?? null,
|
|
813
|
+
window: t.window ?? null
|
|
814
|
+
}));
|
|
815
|
+
return { content: [{ type: "text", text: JSON.stringify(rows, null, 2) }] };
|
|
816
|
+
}
|
|
817
|
+
case "agentistics_tag_detail": {
|
|
818
|
+
const wanted = (args?.tag ?? "").trim();
|
|
819
|
+
if (!wanted)
|
|
820
|
+
throw new Error("tag is required — pass a name or id from agentistics_tags.");
|
|
821
|
+
const list = await apiGet("/api/tags");
|
|
822
|
+
const tags = list.tags ?? [];
|
|
823
|
+
const match = tags.find((t) => t._id === wanted) ?? tags.find((t) => t.name?.toLowerCase() === wanted.toLowerCase());
|
|
824
|
+
if (!match)
|
|
825
|
+
throw new Error(`No tag matching "${wanted}". Available: ${tags.map((t) => t.name).join(", ") || "(none)"}`);
|
|
826
|
+
const detail = await apiGet(`/api/tags/${encodeURIComponent(match._id)}`);
|
|
827
|
+
const d = detail;
|
|
828
|
+
const bucketTop = (b, n = 5) => (b ?? []).slice(0, n).map((x) => ({ key: x.key, sessions: x.sessions, estimatedCostUSD: Math.round((x.costUSD ?? 0) * 1e4) / 1e4 }));
|
|
829
|
+
return {
|
|
830
|
+
content: [{
|
|
831
|
+
type: "text",
|
|
832
|
+
text: JSON.stringify({
|
|
833
|
+
id: d.tag?._id,
|
|
834
|
+
name: d.tag?.name,
|
|
835
|
+
color: d.tag?.color ?? null,
|
|
836
|
+
window: d.tag?.window ?? null,
|
|
837
|
+
sources: d.tag?.sources ?? [],
|
|
838
|
+
aggregate: {
|
|
839
|
+
sessions: d.tag?.aggregate?.sessions ?? 0,
|
|
840
|
+
estimatedCostUSD: Math.round((d.tag?.aggregate?.costUSD ?? 0) * 1e4) / 1e4,
|
|
841
|
+
inputTokens: d.tag?.aggregate?.inputTokens ?? 0,
|
|
842
|
+
outputTokens: d.tag?.aggregate?.outputTokens ?? 0
|
|
843
|
+
},
|
|
844
|
+
topProjects: bucketTop(d.stats?.projects),
|
|
845
|
+
topModels: bucketTop(d.stats?.models),
|
|
846
|
+
topHarnesses: bucketTop(d.stats?.harnesses),
|
|
847
|
+
topRepos: bucketTop(d.stats?.repos),
|
|
848
|
+
topMembers: bucketTop(d.stats?.members),
|
|
849
|
+
distinctMembers: d.stats?.distinctMembers ?? 0,
|
|
850
|
+
distinctMachines: d.stats?.distinctMachines ?? 0,
|
|
851
|
+
firstSessionDate: d.stats?.firstSessionDate ?? null,
|
|
852
|
+
lastSessionDate: d.stats?.lastSessionDate ?? null
|
|
853
|
+
}, null, 2)
|
|
854
|
+
}]
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
case "agentistics_repos": {
|
|
858
|
+
const harness = args?.harness;
|
|
859
|
+
const data = await apiGet("/api/data");
|
|
860
|
+
const allSessions = filterSessions(data.sessions ?? [], harness);
|
|
861
|
+
const byRemote = {};
|
|
862
|
+
for (const s of allSessions) {
|
|
863
|
+
const key = s.git_remote || "";
|
|
864
|
+
if (!byRemote[key])
|
|
865
|
+
byRemote[key] = { sessions: 0, messages: 0, inputTokens: 0, outputTokens: 0, cacheRead: 0, cacheWrite: 0, costUSD: 0, lastActive: "" };
|
|
866
|
+
const agg = byRemote[key];
|
|
867
|
+
const { input, output, cacheRead, cacheWrite, cost } = sessionTokens(s);
|
|
868
|
+
agg.sessions += 1;
|
|
869
|
+
agg.messages += sessionMessages(s);
|
|
870
|
+
agg.inputTokens += input;
|
|
871
|
+
agg.outputTokens += output;
|
|
872
|
+
agg.cacheRead += cacheRead;
|
|
873
|
+
agg.cacheWrite += cacheWrite;
|
|
874
|
+
agg.costUSD += cost;
|
|
875
|
+
if (s.start_time && String(s.start_time) > agg.lastActive)
|
|
876
|
+
agg.lastActive = String(s.start_time);
|
|
877
|
+
}
|
|
878
|
+
const rows = Object.entries(byRemote).map(([remote, agg]) => ({
|
|
879
|
+
repo: remote || "unlinked",
|
|
880
|
+
remote: remote || null,
|
|
881
|
+
sessions: agg.sessions,
|
|
882
|
+
messages: agg.messages,
|
|
883
|
+
inputTokens: agg.inputTokens,
|
|
884
|
+
outputTokens: agg.outputTokens,
|
|
885
|
+
totalTokens: agg.inputTokens + agg.outputTokens + agg.cacheRead + agg.cacheWrite,
|
|
886
|
+
estimatedCostUSD: Math.round(agg.costUSD * 1e4) / 1e4,
|
|
887
|
+
lastActive: agg.lastActive || null
|
|
888
|
+
})).sort((a, b) => b.totalTokens - a.totalTokens);
|
|
889
|
+
return { content: [{ type: "text", text: JSON.stringify(rows, null, 2) }] };
|
|
890
|
+
}
|
|
891
|
+
case "agentistics_team_status": {
|
|
892
|
+
const prefs = await getPrefs();
|
|
893
|
+
const team2 = prefs.team;
|
|
894
|
+
const mode = team2?.mode ?? "solo";
|
|
895
|
+
const connections = (team2?.connections ?? []).map((c) => ({
|
|
896
|
+
id: c.id,
|
|
897
|
+
label: c.label ?? null,
|
|
898
|
+
endpoint: c.endpoint
|
|
899
|
+
}));
|
|
900
|
+
return {
|
|
901
|
+
content: [{
|
|
902
|
+
type: "text",
|
|
903
|
+
text: JSON.stringify({ mode, connections }, null, 2)
|
|
904
|
+
}]
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
case "agentistics_team_members": {
|
|
908
|
+
const res = await fetch(`${API}/api/team/members`);
|
|
909
|
+
if (res.status === 404) {
|
|
910
|
+
return { content: [{ type: "text", text: "This machine is not running as a central (solo or member mode) — there is no member roster here. Use agentistics_team_status to see the current mode." }] };
|
|
911
|
+
}
|
|
912
|
+
if (!res.ok)
|
|
913
|
+
throw new Error(`GET /api/team/members → HTTP ${res.status}`);
|
|
914
|
+
const data = await res.json();
|
|
915
|
+
const members = data.members ?? [];
|
|
916
|
+
const rows = members.map((m) => ({
|
|
917
|
+
id: m.id,
|
|
918
|
+
name: m.user,
|
|
919
|
+
label: m.label,
|
|
920
|
+
online: m.online ?? false,
|
|
921
|
+
latencyMs: m.latencyMs ?? null,
|
|
922
|
+
lastSeenAt: m.lastSeenAt ?? null
|
|
923
|
+
}));
|
|
924
|
+
return { content: [{ type: "text", text: JSON.stringify(rows, null, 2) }] };
|
|
925
|
+
}
|
|
751
926
|
default:
|
|
752
927
|
throw new Error(`Unknown tool: ${name}`);
|
|
753
928
|
}
|