loopctl-mcp-server 2.24.0 → 2.26.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/index.js +73 -6
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -848,6 +848,7 @@ async function knowledgeCreate({
|
|
|
848
848
|
tags,
|
|
849
849
|
project_id,
|
|
850
850
|
draft,
|
|
851
|
+
force,
|
|
851
852
|
source_type,
|
|
852
853
|
source_id,
|
|
853
854
|
idempotency_key,
|
|
@@ -868,6 +869,10 @@ async function knowledgeCreate({
|
|
|
868
869
|
// knowledge_publish.
|
|
869
870
|
if (draft) payload.draft = true;
|
|
870
871
|
|
|
872
|
+
// The server-side novelty gate dedups the proposal against the corpus (verdict in
|
|
873
|
+
// the response `gate`). force:true bypasses it.
|
|
874
|
+
if (force) payload.force = true;
|
|
875
|
+
|
|
871
876
|
const result = await apiCall(
|
|
872
877
|
"POST",
|
|
873
878
|
"/api/v1/articles",
|
|
@@ -1022,9 +1027,9 @@ async function knowledgeBulkDelete({
|
|
|
1022
1027
|
|
|
1023
1028
|
async function knowledgeDrafts({ limit, offset, project_id }) {
|
|
1024
1029
|
const params = new URLSearchParams();
|
|
1025
|
-
// Pass `limit` through verbatim (like knowledge_list/index/search) so the
|
|
1026
|
-
//
|
|
1027
|
-
//
|
|
1030
|
+
// Pass `limit` through verbatim (like knowledge_list/index/search) so the server
|
|
1031
|
+
// honors it up to its max page size, clamping above it server-side rather than
|
|
1032
|
+
// silently clamping client-side (which would truncate draft enumeration).
|
|
1028
1033
|
if (limit != null) params.set("limit", String(limit));
|
|
1029
1034
|
if (offset != null) params.set("offset", String(offset));
|
|
1030
1035
|
if (project_id) params.set("project_id", project_id);
|
|
@@ -1033,6 +1038,18 @@ async function knowledgeDrafts({ limit, offset, project_id }) {
|
|
|
1033
1038
|
return toContent(result);
|
|
1034
1039
|
}
|
|
1035
1040
|
|
|
1041
|
+
async function knowledgeConflicts({ limit, offset }) {
|
|
1042
|
+
const params = new URLSearchParams();
|
|
1043
|
+
if (limit != null) params.set("limit", String(limit));
|
|
1044
|
+
if (offset != null) params.set("offset", String(offset));
|
|
1045
|
+
const qs = params.toString();
|
|
1046
|
+
const path = qs
|
|
1047
|
+
? `/api/v1/knowledge/conflicts?${qs}`
|
|
1048
|
+
: "/api/v1/knowledge/conflicts";
|
|
1049
|
+
const result = await apiCall("GET", path, null, process.env.LOOPCTL_AGENT_KEY);
|
|
1050
|
+
return toContent(result);
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1036
1053
|
async function knowledgeLint({ project_id, stale_days, min_coverage, max_per_category }) {
|
|
1037
1054
|
const params = new URLSearchParams();
|
|
1038
1055
|
if (stale_days != null) params.set("stale_days", String(stale_days));
|
|
@@ -2565,6 +2582,13 @@ const TOOLS = [
|
|
|
2565
2582
|
"to agents (search/index/context) right away — no separate publish step is needed. Pass " +
|
|
2566
2583
|
"draft: true to stage the article for later review instead; the response `note` says which " +
|
|
2567
2584
|
"outcome occurred, and a draft can be published afterwards with knowledge_publish. " +
|
|
2585
|
+
"NOVELTY GATE (default ON): the server semantically dedups your proposal against the published " +
|
|
2586
|
+
"corpus and returns a `gate.verdict` — `duplicate` means a near-identical article already exists, " +
|
|
2587
|
+
"so NOTHING was created (HTTP 200, `deduplicated: true`); read/update the article at `data.id` " +
|
|
2588
|
+
"instead (its `gate.similarity` ~1.0). `gated_to_draft` means high overlap, so the article was " +
|
|
2589
|
+
"created as a DRAFT (not published) with the near-neighbors in metadata.proposal_novelty for you " +
|
|
2590
|
+
"to merge or publish. `created` means it was novel and went through normally. Pass force: true to " +
|
|
2591
|
+
"bypass the gate when you intentionally want an article near an existing one. " +
|
|
2568
2592
|
"Concurrency-safe: if a create races/retries against an " +
|
|
2569
2593
|
"existing article with the same title AND an identical body (ignoring surrounding whitespace), the " +
|
|
2570
2594
|
"server returns that existing article idempotently (HTTP 200) instead of a 422. A same-title create " +
|
|
@@ -2600,6 +2624,13 @@ const TOOLS = [
|
|
|
2600
2624
|
"Optional: stage as a draft instead of publishing on create (default false → " +
|
|
2601
2625
|
"published immediately). Publish later with knowledge_publish.",
|
|
2602
2626
|
},
|
|
2627
|
+
force: {
|
|
2628
|
+
type: "boolean",
|
|
2629
|
+
description:
|
|
2630
|
+
"Optional: bypass the novelty gate (default false). When true, the server skips " +
|
|
2631
|
+
"semantic dedup and creates on the requested path even if a near-duplicate exists. " +
|
|
2632
|
+
"Use only when you've already checked and intend an article close to an existing one.",
|
|
2633
|
+
},
|
|
2603
2634
|
idempotency_key: {
|
|
2604
2635
|
type: "string",
|
|
2605
2636
|
description:
|
|
@@ -2833,8 +2864,8 @@ const TOOLS = [
|
|
|
2833
2864
|
description:
|
|
2834
2865
|
"List draft (unpublished) knowledge articles. Requires orchestrator role. " +
|
|
2835
2866
|
"Returns paginated drafts with total_count in meta. Paginate via offset/limit " +
|
|
2836
|
-
"(limit honored up to 1000; a limit above the max is
|
|
2837
|
-
"
|
|
2867
|
+
"(limit honored up to 1000; a limit above the max is clamped to the maximum, " +
|
|
2868
|
+
"never rejected, so pagination stays complete).",
|
|
2838
2869
|
inputSchema: {
|
|
2839
2870
|
type: "object",
|
|
2840
2871
|
properties: {
|
|
@@ -2842,7 +2873,7 @@ const TOOLS = [
|
|
|
2842
2873
|
type: "integer",
|
|
2843
2874
|
description:
|
|
2844
2875
|
"Max drafts per page (default 20, max 1000). A limit above the max is " +
|
|
2845
|
-
"
|
|
2876
|
+
"clamped to the maximum — never rejected — so offset pagination stays complete.",
|
|
2846
2877
|
default: 20,
|
|
2847
2878
|
minimum: 1,
|
|
2848
2879
|
maximum: 1000,
|
|
@@ -2861,6 +2892,39 @@ const TOOLS = [
|
|
|
2861
2892
|
required: [],
|
|
2862
2893
|
},
|
|
2863
2894
|
},
|
|
2895
|
+
{
|
|
2896
|
+
name: "knowledge_conflicts",
|
|
2897
|
+
description:
|
|
2898
|
+
"List potential-conflict article pairs — published articles flagged 'too similar " +
|
|
2899
|
+
"to comfortably coexist' by the auto-linker / nightly lint sweep, highest-overlap " +
|
|
2900
|
+
"first. The KB only FLAGS the pair (via a mechanical similarity threshold); it does " +
|
|
2901
|
+
"NOT decide whether it's a redundancy to merge or a real contradiction — that's your " +
|
|
2902
|
+
"call, with the live context. Each entry has the two articles (id/title/status/" +
|
|
2903
|
+
"category) and their similarity. Read both, then merge (supersede one, knowledge_create " +
|
|
2904
|
+
"the merged article, or PATCH) or, if they genuinely disagree, reconcile. Paginated " +
|
|
2905
|
+
"with total_count in meta. Agent role.",
|
|
2906
|
+
inputSchema: {
|
|
2907
|
+
type: "object",
|
|
2908
|
+
properties: {
|
|
2909
|
+
limit: {
|
|
2910
|
+
type: "integer",
|
|
2911
|
+
description:
|
|
2912
|
+
"Max pairs per page (default 50, max 1000). A limit above the max is clamped " +
|
|
2913
|
+
"to the maximum — never rejected — so offset pagination stays complete.",
|
|
2914
|
+
default: 50,
|
|
2915
|
+
minimum: 1,
|
|
2916
|
+
maximum: 1000,
|
|
2917
|
+
},
|
|
2918
|
+
offset: {
|
|
2919
|
+
type: "integer",
|
|
2920
|
+
description: "Pagination offset. Default 0.",
|
|
2921
|
+
default: 0,
|
|
2922
|
+
minimum: 0,
|
|
2923
|
+
},
|
|
2924
|
+
},
|
|
2925
|
+
required: [],
|
|
2926
|
+
},
|
|
2927
|
+
},
|
|
2864
2928
|
{
|
|
2865
2929
|
name: "knowledge_lint",
|
|
2866
2930
|
description:
|
|
@@ -3481,6 +3545,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3481
3545
|
case "knowledge_drafts":
|
|
3482
3546
|
return await knowledgeDrafts(args);
|
|
3483
3547
|
|
|
3548
|
+
case "knowledge_conflicts":
|
|
3549
|
+
return await knowledgeConflicts(args);
|
|
3550
|
+
|
|
3484
3551
|
case "knowledge_lint":
|
|
3485
3552
|
return await knowledgeLint(args);
|
|
3486
3553
|
|