loopctl-mcp-server 2.44.0 → 2.46.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/README.md +1 -0
- package/index.js +73 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -188,6 +188,7 @@ autonomous agent) can self-remediate without a human. Full agent-tenant lifecycl
|
|
|
188
188
|
| `get_cost_summary` | orch | Get cost/token usage summary for a project, optionally broken down by `agent`, `epic`, or `model`. |
|
|
189
189
|
| `get_story_token_usage` | orch | Get all token usage records for a single story. |
|
|
190
190
|
| `get_cost_anomalies` | orch | Get cost anomaly alerts — stories or agents exceeding expected budgets. Optionally filter by project. |
|
|
191
|
+
| `get_ingestion_anomalies` | orch | Get ingestion-health anomalies — capture_silence (a source_type stopped producing articles) and high_reject_rate (writes rejected at high rate, persisting no article row). Check whether knowledge capture is still landing AND being accepted. |
|
|
191
192
|
| `set_token_budget` | orch | Set a token budget (in millicents) for a project, epic, story, or agent scope. Requires orchestrator role. |
|
|
192
193
|
|
|
193
194
|
### Knowledge Wiki Tools (agent key)
|
package/index.js
CHANGED
|
@@ -824,6 +824,35 @@ async function getCostAnomalies({ project_id, page, page_size }) {
|
|
|
824
824
|
return toContent(result);
|
|
825
825
|
}
|
|
826
826
|
|
|
827
|
+
async function getIngestionAnomalies({
|
|
828
|
+
source_type,
|
|
829
|
+
anomaly_type,
|
|
830
|
+
resolved,
|
|
831
|
+
include_archived,
|
|
832
|
+
page,
|
|
833
|
+
page_size,
|
|
834
|
+
}) {
|
|
835
|
+
const params = new URLSearchParams();
|
|
836
|
+
if (source_type) params.set("source_type", source_type);
|
|
837
|
+
if (anomaly_type) params.set("anomaly_type", anomaly_type);
|
|
838
|
+
if (resolved != null) params.set("resolved", String(resolved));
|
|
839
|
+
if (include_archived != null) params.set("include_archived", String(include_archived));
|
|
840
|
+
if (page != null) params.set("page", String(page));
|
|
841
|
+
if (page_size != null) params.set("page_size", String(page_size));
|
|
842
|
+
|
|
843
|
+
const query = params.toString() ? `?${params}` : "";
|
|
844
|
+
// Orchestrator-gated endpoint (RequireRole :orchestrator). Pass the ORCH key
|
|
845
|
+
// explicitly so a misconfigured single agent-role LOOPCTL_API_KEY fails loudly
|
|
846
|
+
// rather than drifting into an undiagnosable 403.
|
|
847
|
+
const result = await apiCall(
|
|
848
|
+
"GET",
|
|
849
|
+
`/api/v1/ingestion-anomalies${query}`,
|
|
850
|
+
undefined,
|
|
851
|
+
process.env.LOOPCTL_ORCH_KEY
|
|
852
|
+
);
|
|
853
|
+
return toContent(result);
|
|
854
|
+
}
|
|
855
|
+
|
|
827
856
|
async function setTokenBudget({ scope_type, scope_id, budget_millicents, alert_threshold_pct }) {
|
|
828
857
|
const body = { scope_type, scope_id, budget_millicents };
|
|
829
858
|
if (alert_threshold_pct != null) body.alert_threshold_pct = alert_threshold_pct;
|
|
@@ -2751,6 +2780,47 @@ const TOOLS = [
|
|
|
2751
2780
|
required: [],
|
|
2752
2781
|
},
|
|
2753
2782
|
},
|
|
2783
|
+
{
|
|
2784
|
+
name: "get_ingestion_anomalies",
|
|
2785
|
+
description:
|
|
2786
|
+
"Get ingestion-health anomalies — capture_silence (a source_type that was producing " +
|
|
2787
|
+
"articles has gone silent) and high_reject_rate (writes attempted but rejected at high " +
|
|
2788
|
+
"rate — 409 title_conflict / validation drops that persist no article row). Use to check " +
|
|
2789
|
+
"whether knowledge capture is still landing AND being accepted. Paginated (page/page_size); " +
|
|
2790
|
+
"advance `page` to enumerate all. Filter by source_type, anomaly_type, resolved status, or " +
|
|
2791
|
+
"include archived.",
|
|
2792
|
+
inputSchema: {
|
|
2793
|
+
type: "object",
|
|
2794
|
+
properties: {
|
|
2795
|
+
source_type: {
|
|
2796
|
+
type: "string",
|
|
2797
|
+
description: 'Optional: filter to one article source_type (e.g. "session_log").',
|
|
2798
|
+
},
|
|
2799
|
+
anomaly_type: {
|
|
2800
|
+
type: "string",
|
|
2801
|
+
// Keep in sync with Loopctl.Knowledge.IngestionAnomaly @anomaly_types (the
|
|
2802
|
+
// server-side Ecto.Enum + the ingestion_anomalies_anomaly_type_check DB CHECK).
|
|
2803
|
+
enum: ["capture_silence", "high_reject_rate"],
|
|
2804
|
+
description:
|
|
2805
|
+
'Optional: filter by anomaly type — "capture_silence" (writes stopped) or ' +
|
|
2806
|
+
'"high_reject_rate" (writes rejected at high rate).',
|
|
2807
|
+
},
|
|
2808
|
+
resolved: {
|
|
2809
|
+
type: "string",
|
|
2810
|
+
enum: ["false", "true", "all"],
|
|
2811
|
+
description:
|
|
2812
|
+
'Which anomalies to return: "false" = unresolved only (default), "true" = resolved only, "all" = both.',
|
|
2813
|
+
},
|
|
2814
|
+
include_archived: {
|
|
2815
|
+
type: "boolean",
|
|
2816
|
+
description: "Optional: include archived (retired-source) anomalies (default false).",
|
|
2817
|
+
},
|
|
2818
|
+
page: { type: "integer", description: "Page number (default 1)." },
|
|
2819
|
+
page_size: { type: "integer", description: "Anomalies per page (default 20, max 100)." },
|
|
2820
|
+
},
|
|
2821
|
+
required: [],
|
|
2822
|
+
},
|
|
2823
|
+
},
|
|
2754
2824
|
{
|
|
2755
2825
|
name: "set_token_budget",
|
|
2756
2826
|
description:
|
|
@@ -5019,6 +5089,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
5019
5089
|
case "get_cost_anomalies":
|
|
5020
5090
|
return await getCostAnomalies(args);
|
|
5021
5091
|
|
|
5092
|
+
case "get_ingestion_anomalies":
|
|
5093
|
+
return await getIngestionAnomalies(args);
|
|
5094
|
+
|
|
5022
5095
|
case "set_token_budget":
|
|
5023
5096
|
return await setTokenBudget(args);
|
|
5024
5097
|
|