loopctl-mcp-server 2.49.0 → 2.50.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 +2 -1
- package/index.js +51 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -121,7 +121,7 @@ REST endpoint (`PATCH /api/v1/tenants/me/llm-config`), and the docs — so you (
|
|
|
121
121
|
autonomous agent) can self-remediate without a human. Full agent-tenant lifecycle:
|
|
122
122
|
[`docs/onboarding-agent-tenant.md`](../docs/onboarding-agent-tenant.md).
|
|
123
123
|
|
|
124
|
-
## Tools (
|
|
124
|
+
## Tools (96)
|
|
125
125
|
|
|
126
126
|
> Plus **per-tenant generated Context Retriever tools** (`cr_*`) appended
|
|
127
127
|
> dynamically at runtime — see [Dynamic per-tenant Context Retriever
|
|
@@ -161,6 +161,7 @@ Epic 39 Repo Coordination Bus — a lightweight, tenant-isolated channel for age
|
|
|
161
161
|
| `channel_claim` | Claim a handoff `ref` for EXACTLY ONE agent (Epic 40, US-40.B1) — coordinate an out-of-band unit of work (e.g. `handoff:repo#812`) among agents racing on the same repo. INSERT-to-claim: the first to claim `(tenant, project, ref)` wins; a concurrent LOSER gets a distinct 409 `already_claimed` (another agent already owns it — move on, do NOT retry the same ref). Project-scoped by membership. Optional `lease_seconds` (default 3600, max 86400). Required: `project_id`, `ref`. |
|
|
162
162
|
| `channel_release` | Release YOUR OWN handoff claim so the `ref` reopens for another agent (deletes the claim). Owner-scoped: a claim you do not own / cross-tenant / nonexistent returns a byte-identical 404. Required: `project_id`, `ref`. |
|
|
163
163
|
| `channel_done` | Mark YOUR OWN handoff claim done (sets `done_at`) — records you completed the claimed work; the row is retained ~7 days then swept. Owner-scoped like `channel_release`. Required: `project_id`, `ref`. |
|
|
164
|
+
| `channel_graduate` | Graduate a coordination post into the durable Knowledge wiki (Epic 40, US-40.E1). CONTENT-SELECTIVE — ONLY for a genuinely REUSABLE finding with no external tracker, worth another agent reading later; a transient directive should be LEFT TO EXPIRE on its 30-day TTL, never graduated. No automatic graduation. Reuses Knowledge's guardrails, never a bypass: the semantic novelty gate (a near-duplicate returns 200 `deduplicated`, nothing created) plus a secret scan (a denylisted credential returns 422). Records `source_type` `channel_graduation` + the post id, attributed to you; the source post is KEPT (its TTL reclaims it). Project-scoped by membership. Optional `tags`, `category` (default `finding`). Required: `post_id`, `title`. |
|
|
164
165
|
|
|
165
166
|
### Story Tools
|
|
166
167
|
|
package/index.js
CHANGED
|
@@ -557,6 +557,26 @@ async function channelDelete({ post_id }) {
|
|
|
557
557
|
return toContent(result);
|
|
558
558
|
}
|
|
559
559
|
|
|
560
|
+
async function channelGraduate({ post_id, title, tags, category }) {
|
|
561
|
+
// Repo Coordination Bus (Epic 40, US-40.E1): graduate a coordination post into
|
|
562
|
+
// the durable Knowledge wiki on the AGENT key. CONTENT-SELECTIVE — for a
|
|
563
|
+
// genuinely REUSABLE finding with no external tracker, NOT routine handoffs (a
|
|
564
|
+
// transient directive should be left to expire on its 30-day TTL). Reuses
|
|
565
|
+
// Knowledge's semantic novelty gate (a near-duplicate returns 200 deduplicated,
|
|
566
|
+
// nothing created) plus an explicit secret scan (a denylisted credential returns
|
|
567
|
+
// 422) — never a bypass. Project-scoped by membership; tenant/agent server-stamped.
|
|
568
|
+
const payload = { title };
|
|
569
|
+
if (tags) payload.tags = tags;
|
|
570
|
+
if (category) payload.category = category;
|
|
571
|
+
const result = await apiCall(
|
|
572
|
+
"POST",
|
|
573
|
+
`/api/v1/channel/posts/${post_id}/graduate`,
|
|
574
|
+
payload,
|
|
575
|
+
process.env.LOOPCTL_AGENT_KEY,
|
|
576
|
+
);
|
|
577
|
+
return toContent(result);
|
|
578
|
+
}
|
|
579
|
+
|
|
560
580
|
async function deleteProject({ project_id }) {
|
|
561
581
|
const result = await apiCall(
|
|
562
582
|
"DELETE",
|
|
@@ -2431,6 +2451,35 @@ const TOOLS = [
|
|
|
2431
2451
|
required: ["post_id"],
|
|
2432
2452
|
},
|
|
2433
2453
|
},
|
|
2454
|
+
{
|
|
2455
|
+
name: "channel_graduate",
|
|
2456
|
+
description:
|
|
2457
|
+
"Graduate a repo coordination post into the durable Knowledge wiki (Epic 40 Repo Coordination Bus, US-40.E1), on the agent key. CONTENT-SELECTIVE — use this ONLY for a genuinely REUSABLE finding that has no external tracker and is worth another agent reading later (the durable home for a lesson learned). It is NOT the general handoff-durability answer: a transient directive (e.g. 'run this SQL now', 'rebasing branch X') should be LEFT TO EXPIRE on the post's 30-day TTL, never graduated. There is NO automatic graduation — this is always your explicit, deliberate decision. title is REQUIRED; the article body is carried from the post, project_id carries over, and tags are optional. Reuses Knowledge's EXISTING guardrails, never a bypass: the SEMANTIC NOVELTY gate (a near-duplicate returns 200 with deduplicated:true and creates nothing, pointing you at the canonical article) plus an explicit secret scan over the body (a denylisted credential shape returns 422 and nothing lands). The article records source_type 'channel_graduation' + the originating post id, attributed to you. The source post is KEPT (its TTL sweep reclaims it); redact it separately with channel_delete if it must go sooner. Project-scoped by membership; tenant/agent are server-stamped from your verified key. Rate-bounded so it cannot bulk-flood Knowledge from the channel.",
|
|
2458
|
+
inputSchema: {
|
|
2459
|
+
type: "object",
|
|
2460
|
+
properties: {
|
|
2461
|
+
post_id: {
|
|
2462
|
+
type: "string",
|
|
2463
|
+
description: "UUID of the channel post to graduate (must be in your tenant).",
|
|
2464
|
+
},
|
|
2465
|
+
title: {
|
|
2466
|
+
type: "string",
|
|
2467
|
+
description: "Title for the durable Knowledge article (required).",
|
|
2468
|
+
},
|
|
2469
|
+
tags: {
|
|
2470
|
+
type: "array",
|
|
2471
|
+
items: { type: "string" },
|
|
2472
|
+
description: "Optional topical tags for the article.",
|
|
2473
|
+
},
|
|
2474
|
+
category: {
|
|
2475
|
+
type: "string",
|
|
2476
|
+
description:
|
|
2477
|
+
"Optional article category (defaults to 'finding' — a reusable lesson).",
|
|
2478
|
+
},
|
|
2479
|
+
},
|
|
2480
|
+
required: ["post_id", "title"],
|
|
2481
|
+
},
|
|
2482
|
+
},
|
|
2434
2483
|
{
|
|
2435
2484
|
name: "channel_claim",
|
|
2436
2485
|
description:
|
|
@@ -5303,6 +5352,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
5303
5352
|
|
|
5304
5353
|
case "channel_delete":
|
|
5305
5354
|
return await channelDelete(args);
|
|
5355
|
+
case "channel_graduate":
|
|
5356
|
+
return await channelGraduate(args);
|
|
5306
5357
|
|
|
5307
5358
|
case "channel_claim":
|
|
5308
5359
|
return await channelClaim(args);
|