loopctl-mcp-server 1.4.0 → 1.5.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 +11 -2
- package/index.js +162 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
MCP (Model Context Protocol) server for [loopctl](https://loopctl.com) -- structural trust for AI development loops.
|
|
4
4
|
|
|
5
|
-
Wraps the loopctl REST API into
|
|
5
|
+
Wraps the loopctl REST API into 41 typed MCP tools so AI coding agents (Claude Code, etc.) can interact with loopctl without writing curl commands.
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
@@ -66,7 +66,7 @@ Or if installed locally:
|
|
|
66
66
|
|
|
67
67
|
Key resolution priority: `LOOPCTL_API_KEY` > tool-specific key > `LOOPCTL_ORCH_KEY`.
|
|
68
68
|
|
|
69
|
-
## Tools (
|
|
69
|
+
## Tools (41)
|
|
70
70
|
|
|
71
71
|
### Project Tools
|
|
72
72
|
|
|
@@ -149,6 +149,15 @@ Key resolution priority: `LOOPCTL_API_KEY` > tool-specific key > `LOOPCTL_ORCH_K
|
|
|
149
149
|
| `knowledge_ingest_batch` | Submit up to 50 ingestion items in a single request. Each item has the same shape as `knowledge_ingest`. Returns per-item results. Required: `items`. Optional: batch-level `project_id` default. |
|
|
150
150
|
| `knowledge_ingestion_jobs` | List recent content ingestion jobs (last 7 days, max 50). |
|
|
151
151
|
|
|
152
|
+
### Knowledge Analytics Tools (orchestrator key)
|
|
153
|
+
|
|
154
|
+
| Tool | Description |
|
|
155
|
+
|---|---|
|
|
156
|
+
| `knowledge_analytics_top` | Top accessed knowledge articles for the tenant. Optional: `limit` (default 20, max 100), `since_days` (default 7), `access_type` (`search`, `get`, `context`, `index`). |
|
|
157
|
+
| `knowledge_article_stats` | Per-article usage stats: total accesses, unique agents, by-type breakdown, recent events. Required: `article_id`. |
|
|
158
|
+
| `knowledge_agent_usage` | Per-agent (api_key) knowledge usage: total reads, unique articles, top read articles. Required: `agent_id`. Optional: `limit`, `since_days`. |
|
|
159
|
+
| `knowledge_unused_articles` | Published articles with zero accesses in the window. Optional: `days_unused` (default 30), `limit` (default 50, max 200). |
|
|
160
|
+
|
|
152
161
|
### Discovery Tools
|
|
153
162
|
|
|
154
163
|
| Tool | Description |
|
package/index.js
CHANGED
|
@@ -528,6 +528,55 @@ async function knowledgeIngestionJobs() {
|
|
|
528
528
|
return toContent(result);
|
|
529
529
|
}
|
|
530
530
|
|
|
531
|
+
// --- Knowledge Analytics Tools (orch key) ---
|
|
532
|
+
|
|
533
|
+
async function knowledgeAnalyticsTop({ limit, since_days, access_type } = {}) {
|
|
534
|
+
const params = new URLSearchParams();
|
|
535
|
+
if (limit != null) params.set("limit", String(limit));
|
|
536
|
+
if (since_days != null) params.set("since_days", String(since_days));
|
|
537
|
+
if (access_type) params.set("access_type", access_type);
|
|
538
|
+
const qs = params.toString();
|
|
539
|
+
const path = qs
|
|
540
|
+
? `/api/v1/knowledge/analytics/top-articles?${qs}`
|
|
541
|
+
: "/api/v1/knowledge/analytics/top-articles";
|
|
542
|
+
const result = await apiCall("GET", path, null, process.env.LOOPCTL_ORCH_KEY);
|
|
543
|
+
return toContent(result);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
async function knowledgeArticleStats({ article_id }) {
|
|
547
|
+
const result = await apiCall(
|
|
548
|
+
"GET",
|
|
549
|
+
`/api/v1/knowledge/articles/${article_id}/stats`,
|
|
550
|
+
null,
|
|
551
|
+
process.env.LOOPCTL_ORCH_KEY
|
|
552
|
+
);
|
|
553
|
+
return toContent(result);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
async function knowledgeAgentUsage({ agent_id, limit, since_days } = {}) {
|
|
557
|
+
const params = new URLSearchParams();
|
|
558
|
+
if (limit != null) params.set("limit", String(limit));
|
|
559
|
+
if (since_days != null) params.set("since_days", String(since_days));
|
|
560
|
+
const qs = params.toString();
|
|
561
|
+
const path = qs
|
|
562
|
+
? `/api/v1/knowledge/analytics/agents/${agent_id}?${qs}`
|
|
563
|
+
: `/api/v1/knowledge/analytics/agents/${agent_id}`;
|
|
564
|
+
const result = await apiCall("GET", path, null, process.env.LOOPCTL_ORCH_KEY);
|
|
565
|
+
return toContent(result);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
async function knowledgeUnusedArticles({ days_unused, limit } = {}) {
|
|
569
|
+
const params = new URLSearchParams();
|
|
570
|
+
if (days_unused != null) params.set("days_unused", String(days_unused));
|
|
571
|
+
if (limit != null) params.set("limit", String(limit));
|
|
572
|
+
const qs = params.toString();
|
|
573
|
+
const path = qs
|
|
574
|
+
? `/api/v1/knowledge/analytics/unused-articles?${qs}`
|
|
575
|
+
: "/api/v1/knowledge/analytics/unused-articles";
|
|
576
|
+
const result = await apiCall("GET", path, null, process.env.LOOPCTL_ORCH_KEY);
|
|
577
|
+
return toContent(result);
|
|
578
|
+
}
|
|
579
|
+
|
|
531
580
|
async function knowledgeExport({ project_id }) {
|
|
532
581
|
const basePath = project_id
|
|
533
582
|
? `/api/v1/projects/${project_id}/knowledge/export`
|
|
@@ -1437,6 +1486,106 @@ const TOOLS = [
|
|
|
1437
1486
|
},
|
|
1438
1487
|
},
|
|
1439
1488
|
|
|
1489
|
+
// Knowledge Analytics Tools (orchestrator key)
|
|
1490
|
+
{
|
|
1491
|
+
name: "knowledge_analytics_top",
|
|
1492
|
+
description:
|
|
1493
|
+
"Return the top accessed knowledge articles for the tenant. " +
|
|
1494
|
+
"Use to identify which articles agents actually read. Requires orchestrator role.",
|
|
1495
|
+
inputSchema: {
|
|
1496
|
+
type: "object",
|
|
1497
|
+
properties: {
|
|
1498
|
+
limit: {
|
|
1499
|
+
type: "integer",
|
|
1500
|
+
description: "Max rows to return. Default 20, max 100.",
|
|
1501
|
+
minimum: 1,
|
|
1502
|
+
maximum: 100,
|
|
1503
|
+
},
|
|
1504
|
+
since_days: {
|
|
1505
|
+
type: "integer",
|
|
1506
|
+
description: "Look back this many days. Default 7.",
|
|
1507
|
+
minimum: 1,
|
|
1508
|
+
maximum: 365,
|
|
1509
|
+
},
|
|
1510
|
+
access_type: {
|
|
1511
|
+
type: "string",
|
|
1512
|
+
enum: ["search", "get", "context", "index"],
|
|
1513
|
+
description: "Optional: restrict to a single access type.",
|
|
1514
|
+
},
|
|
1515
|
+
},
|
|
1516
|
+
required: [],
|
|
1517
|
+
},
|
|
1518
|
+
},
|
|
1519
|
+
{
|
|
1520
|
+
name: "knowledge_article_stats",
|
|
1521
|
+
description:
|
|
1522
|
+
"Return per-article usage statistics: total accesses, unique agents, " +
|
|
1523
|
+
"by-type breakdown, and the 10 most recent events. Requires orchestrator role.",
|
|
1524
|
+
inputSchema: {
|
|
1525
|
+
type: "object",
|
|
1526
|
+
properties: {
|
|
1527
|
+
article_id: {
|
|
1528
|
+
type: "string",
|
|
1529
|
+
description: "The UUID of the article to inspect.",
|
|
1530
|
+
},
|
|
1531
|
+
},
|
|
1532
|
+
required: ["article_id"],
|
|
1533
|
+
},
|
|
1534
|
+
},
|
|
1535
|
+
{
|
|
1536
|
+
name: "knowledge_agent_usage",
|
|
1537
|
+
description:
|
|
1538
|
+
"Return knowledge usage for a specific agent (api_key): total reads, " +
|
|
1539
|
+
"unique articles, access type breakdown, and top read articles. " +
|
|
1540
|
+
"Requires orchestrator role.",
|
|
1541
|
+
inputSchema: {
|
|
1542
|
+
type: "object",
|
|
1543
|
+
properties: {
|
|
1544
|
+
agent_id: {
|
|
1545
|
+
type: "string",
|
|
1546
|
+
description: "API key UUID identifying the agent identity.",
|
|
1547
|
+
},
|
|
1548
|
+
limit: {
|
|
1549
|
+
type: "integer",
|
|
1550
|
+
description: "Max top articles to return. Default 20, max 100.",
|
|
1551
|
+
minimum: 1,
|
|
1552
|
+
maximum: 100,
|
|
1553
|
+
},
|
|
1554
|
+
since_days: {
|
|
1555
|
+
type: "integer",
|
|
1556
|
+
description: "Look back this many days. Default 7.",
|
|
1557
|
+
minimum: 1,
|
|
1558
|
+
maximum: 365,
|
|
1559
|
+
},
|
|
1560
|
+
},
|
|
1561
|
+
required: ["agent_id"],
|
|
1562
|
+
},
|
|
1563
|
+
},
|
|
1564
|
+
{
|
|
1565
|
+
name: "knowledge_unused_articles",
|
|
1566
|
+
description:
|
|
1567
|
+
"Return published articles that have not been accessed in the configured " +
|
|
1568
|
+
"time window. Use to identify dead-weight knowledge. Requires orchestrator role.",
|
|
1569
|
+
inputSchema: {
|
|
1570
|
+
type: "object",
|
|
1571
|
+
properties: {
|
|
1572
|
+
days_unused: {
|
|
1573
|
+
type: "integer",
|
|
1574
|
+
description: "Window length in days. Default 30.",
|
|
1575
|
+
minimum: 1,
|
|
1576
|
+
maximum: 365,
|
|
1577
|
+
},
|
|
1578
|
+
limit: {
|
|
1579
|
+
type: "integer",
|
|
1580
|
+
description: "Max rows to return. Default 50, max 200.",
|
|
1581
|
+
minimum: 1,
|
|
1582
|
+
maximum: 200,
|
|
1583
|
+
},
|
|
1584
|
+
},
|
|
1585
|
+
required: [],
|
|
1586
|
+
},
|
|
1587
|
+
},
|
|
1588
|
+
|
|
1440
1589
|
// Discovery Tools
|
|
1441
1590
|
{
|
|
1442
1591
|
name: "list_routes",
|
|
@@ -1589,6 +1738,19 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1589
1738
|
case "knowledge_ingestion_jobs":
|
|
1590
1739
|
return await knowledgeIngestionJobs();
|
|
1591
1740
|
|
|
1741
|
+
// Knowledge Analytics Tools
|
|
1742
|
+
case "knowledge_analytics_top":
|
|
1743
|
+
return await knowledgeAnalyticsTop(args);
|
|
1744
|
+
|
|
1745
|
+
case "knowledge_article_stats":
|
|
1746
|
+
return await knowledgeArticleStats(args);
|
|
1747
|
+
|
|
1748
|
+
case "knowledge_agent_usage":
|
|
1749
|
+
return await knowledgeAgentUsage(args);
|
|
1750
|
+
|
|
1751
|
+
case "knowledge_unused_articles":
|
|
1752
|
+
return await knowledgeUnusedArticles(args);
|
|
1753
|
+
|
|
1592
1754
|
// Discovery Tools
|
|
1593
1755
|
case "list_routes":
|
|
1594
1756
|
return await listRoutes();
|