@kynver-app/mcp-agent-os 0.3.25 → 0.3.27
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/index.js +4 -0
- package/dist/lib/package-version.d.ts +7 -0
- package/dist/lib/package-version.js +44 -0
- package/dist/server.js +5 -1
- package/dist/tools/command-center.d.ts +6 -2
- package/dist/tools/command-center.js +48 -3
- package/dist/tools/graph.js +28 -6
- package/dist/tools/monitor.d.ts +17 -0
- package/dist/tools/monitor.js +51 -0
- package/dist/tools/tasks.js +9 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,7 +5,11 @@
|
|
|
5
5
|
* Env: KYNVER_API_URL, KYNVER_API_KEY (required)
|
|
6
6
|
*/
|
|
7
7
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
8
|
+
import { handleCliVersionFlag } from "./lib/package-version.js";
|
|
8
9
|
import { createAgentOsServer } from "./server.js";
|
|
10
|
+
if (handleCliVersionFlag(process.argv.slice(2), import.meta.url, "kynver-mcp-agent-os")) {
|
|
11
|
+
// exits
|
|
12
|
+
}
|
|
9
13
|
const server = createAgentOsServer();
|
|
10
14
|
const transport = new StdioServerTransport();
|
|
11
15
|
await server.connect(transport);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Read a field from the nearest `package.json` above this module. */
|
|
2
|
+
export declare function readOwnPackageJsonField(moduleUrl: string, field: "version" | "name"): string;
|
|
3
|
+
export declare function readOwnPackageVersion(moduleUrl?: string): string;
|
|
4
|
+
export declare function wantsCliVersion(argv: string[]): boolean;
|
|
5
|
+
export declare function printCliVersionAndExit(version: string, binName?: string): never;
|
|
6
|
+
/** When `--version` / `-v` is present, print package version and exit before side effects. */
|
|
7
|
+
export declare function handleCliVersionFlag(argv: string[], moduleUrl?: string, binName?: string): boolean;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// @generated — synced from packages/kynver-mcp-sse-lib/src/package-version.ts via scripts/sync-mcp-sse-server.mjs
|
|
2
|
+
// Do not edit by hand; change the canonical file and re-run the sync script.
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
function resolvePackageRoot(moduleUrl) {
|
|
7
|
+
let dir = dirname(fileURLToPath(moduleUrl));
|
|
8
|
+
for (let depth = 0; depth < 6; depth += 1) {
|
|
9
|
+
if (existsSync(join(dir, "package.json")))
|
|
10
|
+
return dir;
|
|
11
|
+
const parent = dirname(dir);
|
|
12
|
+
if (parent === dir)
|
|
13
|
+
break;
|
|
14
|
+
dir = parent;
|
|
15
|
+
}
|
|
16
|
+
throw new Error(`package.json not found above ${dirname(fileURLToPath(moduleUrl))}`);
|
|
17
|
+
}
|
|
18
|
+
/** Read a field from the nearest `package.json` above this module. */
|
|
19
|
+
export function readOwnPackageJsonField(moduleUrl, field) {
|
|
20
|
+
const pkgPath = join(resolvePackageRoot(moduleUrl), "package.json");
|
|
21
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
22
|
+
const value = pkg[field];
|
|
23
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
24
|
+
throw new Error(`Missing package.json ${field} at ${pkgPath}`);
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
export function readOwnPackageVersion(moduleUrl = import.meta.url) {
|
|
29
|
+
return readOwnPackageJsonField(moduleUrl, "version");
|
|
30
|
+
}
|
|
31
|
+
export function wantsCliVersion(argv) {
|
|
32
|
+
return argv.some((arg) => arg === "--version" || arg === "-v");
|
|
33
|
+
}
|
|
34
|
+
export function printCliVersionAndExit(version, binName) {
|
|
35
|
+
console.log(binName ? `${binName} ${version}` : version);
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
/** When `--version` / `-v` is present, print package version and exit before side effects. */
|
|
39
|
+
export function handleCliVersionFlag(argv, moduleUrl = import.meta.url, binName) {
|
|
40
|
+
if (!wantsCliVersion(argv))
|
|
41
|
+
return false;
|
|
42
|
+
printCliVersionAndExit(readOwnPackageVersion(moduleUrl), binName);
|
|
43
|
+
return true;
|
|
44
|
+
}
|
package/dist/server.js
CHANGED
|
@@ -18,6 +18,9 @@ import { registerWorkbenchTools } from "./tools/workbench.js";
|
|
|
18
18
|
import { registerCommandCenterTools } from "./tools/command-center.js";
|
|
19
19
|
import { registerMemoryQualityFeedbackTools } from "./tools/memory-quality-feedback.js";
|
|
20
20
|
import { registerOperatingRulesTools } from "./tools/operating-rules.js";
|
|
21
|
+
import { registerMonitorTools } from "./tools/monitor.js";
|
|
22
|
+
import { readOwnPackageVersion } from "./lib/package-version.js";
|
|
23
|
+
const PACKAGE_VERSION = readOwnPackageVersion(import.meta.url);
|
|
21
24
|
function jsonResult(data) {
|
|
22
25
|
return {
|
|
23
26
|
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
@@ -34,7 +37,7 @@ function compact(source) {
|
|
|
34
37
|
}
|
|
35
38
|
const MCP_LEGACY_SLUG_FALLBACK = "ghost";
|
|
36
39
|
export function createAgentOsServer() {
|
|
37
|
-
const server = new McpServer({ name: "kynver-mcp-agent-os", version:
|
|
40
|
+
const server = new McpServer({ name: "kynver-mcp-agent-os", version: PACKAGE_VERSION }, { capabilities: { tools: {} } });
|
|
38
41
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
42
|
function register(name, description, inputSchema, cb) {
|
|
40
43
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -684,5 +687,6 @@ export function createAgentOsServer() {
|
|
|
684
687
|
registerMemoryQualityFeedbackTools({ register, resolveToolSlug, jsonResult, compact });
|
|
685
688
|
// Lane A instruction policy (operating rules boundary).
|
|
686
689
|
registerOperatingRulesTools({ register, resolveToolSlug, jsonResult, compact });
|
|
690
|
+
registerMonitorTools({ register, resolveToolSlug, jsonResult });
|
|
687
691
|
return server;
|
|
688
692
|
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Command Center MCP tools — unified rollup for AgentOS operators.
|
|
3
3
|
*
|
|
4
|
-
* agent_os_command_center_get proxies to GET `/api/agent-os/by-id/{agentOsId}/command-center
|
|
5
|
-
*
|
|
4
|
+
* agent_os_command_center_get proxies to GET `/api/agent-os/by-id/{agentOsId}/command-center`
|
|
5
|
+
* (full rollup; `countSnapshot` is the canonical badge contract aligned with the UI).
|
|
6
|
+
*
|
|
7
|
+
* agent_os_command_center_dashboard_contract_get proxies to
|
|
8
|
+
* `.../command-center/dashboard-contract` — slim verification payload (counts,
|
|
9
|
+
* packageVersionHealth, runtime capacity, activePlanRollups) without graph/hierarchy.
|
|
6
10
|
*/
|
|
7
11
|
type ToolResult = {
|
|
8
12
|
content: {
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Command Center MCP tools — unified rollup for AgentOS operators.
|
|
3
3
|
*
|
|
4
|
-
* agent_os_command_center_get proxies to GET `/api/agent-os/by-id/{agentOsId}/command-center
|
|
5
|
-
*
|
|
4
|
+
* agent_os_command_center_get proxies to GET `/api/agent-os/by-id/{agentOsId}/command-center`
|
|
5
|
+
* (full rollup; `countSnapshot` is the canonical badge contract aligned with the UI).
|
|
6
|
+
*
|
|
7
|
+
* agent_os_command_center_dashboard_contract_get proxies to
|
|
8
|
+
* `.../command-center/dashboard-contract` — slim verification payload (counts,
|
|
9
|
+
* packageVersionHealth, runtime capacity, activePlanRollups) without graph/hierarchy.
|
|
6
10
|
*/
|
|
7
11
|
import { z } from "zod";
|
|
8
12
|
import { get } from "../lib/kynver-client.js";
|
|
@@ -18,7 +22,12 @@ export function registerCommandCenterTools({ register, resolveToolSlug, jsonResu
|
|
|
18
22
|
register("agent_os_command_center_get", [
|
|
19
23
|
"Fetch the unified Command Center rollup for the AgentOS workspace:",
|
|
20
24
|
"plan rollups, project hierarchy, action-required items, DQ inbox, harness summaries,",
|
|
21
|
-
"
|
|
25
|
+
"prReadyNotifications (journal pr_ready events), dailyLandedPrs (journal merge counts:",
|
|
26
|
+
"today/yesterday, rolling 24h/48h, pace + agentReadable summary), runtime capacity, and",
|
|
27
|
+
"packageVersionHealth (managed npm alignment for @kynver-app/runtime).",
|
|
28
|
+
"Includes `countSnapshot` (canonical header-chip / saved-view / review-lane counts — same",
|
|
29
|
+
"contract the dashboard badges use). For a compact runtime verification payload without",
|
|
30
|
+
"operationalGraph/hierarchy, use agent_os_command_center_dashboard_contract_get.",
|
|
22
31
|
"Same aggregate as the browser Command Center. Omit slug to use env/primary workspace;",
|
|
23
32
|
"pass agentOsId when already known from a prior identity fetch.",
|
|
24
33
|
].join(" "), {
|
|
@@ -59,4 +68,40 @@ export function registerCommandCenterTools({ register, resolveToolSlug, jsonResu
|
|
|
59
68
|
const suffix = qs.toString() ? `?${qs.toString()}` : "";
|
|
60
69
|
return jsonResult(await get(`/agent-os/by-id/${encodeURIComponent(agentOsId)}/command-center${suffix}`));
|
|
61
70
|
});
|
|
71
|
+
register("agent_os_command_center_dashboard_contract_get", [
|
|
72
|
+
"Fetch the slim Command Center dashboard contract for runtime verification:",
|
|
73
|
+
"countSnapshot, readiness, packageVersionHealth, runtime capacity, activePlanRollups,",
|
|
74
|
+
"and review-lane totals — same sources as the browser dashboard badges, without",
|
|
75
|
+
"operationalGraph or hierarchy payloads (avoids MCP truncation on large boards).",
|
|
76
|
+
].join(" "), {
|
|
77
|
+
slug: z
|
|
78
|
+
.string()
|
|
79
|
+
.optional()
|
|
80
|
+
.describe("AgentOS slug. Defaults to the configured env/primary AgentOS."),
|
|
81
|
+
agentOsId: z
|
|
82
|
+
.string()
|
|
83
|
+
.optional()
|
|
84
|
+
.describe("Optional AgentOS row id. When omitted, resolved from slug."),
|
|
85
|
+
since: z
|
|
86
|
+
.string()
|
|
87
|
+
.optional()
|
|
88
|
+
.describe("ISO timestamp — only include tasks updated after this instant."),
|
|
89
|
+
limit: z
|
|
90
|
+
.number()
|
|
91
|
+
.optional()
|
|
92
|
+
.describe("Max tasks to load when building counts (server cap 10000)."),
|
|
93
|
+
}, async (args) => {
|
|
94
|
+
const slug = await resolveToolSlug(args.slug);
|
|
95
|
+
const agentOsId = typeof args.agentOsId === "string" && args.agentOsId.trim()
|
|
96
|
+
? args.agentOsId.trim()
|
|
97
|
+
: await resolveAgentOsId(slug);
|
|
98
|
+
const qs = new URLSearchParams();
|
|
99
|
+
if (typeof args.since === "string" && args.since.trim())
|
|
100
|
+
qs.set("since", args.since.trim());
|
|
101
|
+
if (typeof args.limit === "number" && Number.isFinite(args.limit)) {
|
|
102
|
+
qs.set("limit", String(args.limit));
|
|
103
|
+
}
|
|
104
|
+
const suffix = qs.toString() ? `?${qs.toString()}` : "";
|
|
105
|
+
return jsonResult(await get(`/agent-os/by-id/${encodeURIComponent(agentOsId)}/command-center/dashboard-contract${suffix}`));
|
|
106
|
+
});
|
|
62
107
|
}
|
package/dist/tools/graph.js
CHANGED
|
@@ -55,21 +55,40 @@ export function registerGraphTools({ register, resolveToolSlug, jsonResult }) {
|
|
|
55
55
|
return jsonResult(await get(`/agent-os/${slug}/graph/query${suffix}`));
|
|
56
56
|
});
|
|
57
57
|
register("agent_os_graph_view", [
|
|
58
|
-
"Steer the human's open 3D web view (shared focus) — fly the camera to a node,
|
|
59
|
-
"so you and the user are provably
|
|
60
|
-
"
|
|
61
|
-
"
|
|
58
|
+
"Steer the human's open 3D web view (shared focus) — spotlight + fly the camera to a node, a SET",
|
|
59
|
+
"of nodes, or a whole goal constellation, filter, or reset, so you and the user are provably",
|
|
60
|
+
"looking at the same thing while you narrate.",
|
|
61
|
+
"kind=focus spotlights the target(s) and DIMS the rest (isolate); kind=highlight spotlights",
|
|
62
|
+
"WITHOUT dimming. Give exactly one of: nodeId (a single node, e.g. 'task:abc'), nodeIds (an",
|
|
63
|
+
"explicit set — 'frame these three bottlenecks'), or clusterId (the BARE goalId, NOT the",
|
|
64
|
+
"'goal:abc' node id — 'frame this whole goal'). An unrecognized target is dropped silently.",
|
|
65
|
+
"frameAll=false keeps the camera put (spotlight only, no fly). kind=filter sets which type/status",
|
|
66
|
+
"buckets are hidden; kind=reset clears focus + filters + spotlight.",
|
|
62
67
|
"Takes effect only while the user has the 3D Web tab open (delivered over SSE).",
|
|
63
68
|
"Requires Redis in multi-instance/serverless prod to fan out; single-instance dev works without it.",
|
|
64
69
|
].join(" "), {
|
|
65
70
|
slug: z.string().optional().describe("AgentOS slug. Defaults to env/primary."),
|
|
66
71
|
kind: z
|
|
67
72
|
.enum(["focus", "filter", "reset", "highlight"])
|
|
68
|
-
.describe("focus | highlight (
|
|
73
|
+
.describe("focus (spotlight + dim rest) | highlight (spotlight, no dim) | filter | reset."),
|
|
69
74
|
nodeId: z
|
|
70
75
|
.string()
|
|
71
76
|
.optional()
|
|
72
|
-
.describe("
|
|
77
|
+
.describe("focus/highlight: a single target node id (e.g. 'task:abc123')."),
|
|
78
|
+
nodeIds: z
|
|
79
|
+
.array(z.string())
|
|
80
|
+
.optional()
|
|
81
|
+
.describe("focus/highlight: an explicit SET of node ids to frame together."),
|
|
82
|
+
clusterId: z
|
|
83
|
+
.string()
|
|
84
|
+
.optional()
|
|
85
|
+
.describe("focus/highlight: a whole goal constellation = the BARE goalId (the Goal entity id, " +
|
|
86
|
+
"e.g. 'abc'; the value in each node's web3d.constellation.goalId), NOT the prefixed " +
|
|
87
|
+
"'goal:abc' graph node id. An unknown id resolves to nothing (no-op)."),
|
|
88
|
+
frameAll: z
|
|
89
|
+
.boolean()
|
|
90
|
+
.optional()
|
|
91
|
+
.describe("focus/highlight: also fly the camera to frame the set (default true)."),
|
|
73
92
|
hiddenKinds: z
|
|
74
93
|
.array(z.string())
|
|
75
94
|
.optional()
|
|
@@ -83,6 +102,9 @@ export function registerGraphTools({ register, resolveToolSlug, jsonResult }) {
|
|
|
83
102
|
return jsonResult(await post(`/agent-os/${slug}/graph/view`, {
|
|
84
103
|
kind: args.kind,
|
|
85
104
|
nodeId: args.nodeId,
|
|
105
|
+
nodeIds: args.nodeIds,
|
|
106
|
+
clusterId: args.clusterId,
|
|
107
|
+
frameAll: args.frameAll,
|
|
86
108
|
hiddenKinds: args.hiddenKinds,
|
|
87
109
|
hiddenStatuses: args.hiddenStatuses,
|
|
88
110
|
source: "agent",
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness worker monitor MCP tools — backed by AgentOS harness/monitor HTTP routes.
|
|
3
|
+
*/
|
|
4
|
+
type ToolResult = {
|
|
5
|
+
content: {
|
|
6
|
+
type: "text";
|
|
7
|
+
text: string;
|
|
8
|
+
}[];
|
|
9
|
+
structuredContent?: unknown;
|
|
10
|
+
};
|
|
11
|
+
export interface MonitorToolDeps {
|
|
12
|
+
register: (name: string, description: string, inputSchema: Record<string, unknown>, cb: (args: any) => any) => void;
|
|
13
|
+
resolveToolSlug: (explicitSlug?: string) => Promise<string>;
|
|
14
|
+
jsonResult: (data: unknown) => ToolResult;
|
|
15
|
+
}
|
|
16
|
+
export declare function registerMonitorTools({ register, resolveToolSlug, jsonResult, }: MonitorToolDeps): void;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness worker monitor MCP tools — backed by AgentOS harness/monitor HTTP routes.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { post } from "../lib/kynver-client.js";
|
|
6
|
+
const slugField = z
|
|
7
|
+
.string()
|
|
8
|
+
.optional()
|
|
9
|
+
.describe("AgentOS slug. Defaults to env/primary AgentOS.");
|
|
10
|
+
export function registerMonitorTools({ register, resolveToolSlug, jsonResult, }) {
|
|
11
|
+
register("agent_os_monitor_assess", [
|
|
12
|
+
"Assess harness worker health (healthy/stale/orphaned) and auto-complete eligibility",
|
|
13
|
+
"for a run on the runner host disk. Requires the harness run to exist under",
|
|
14
|
+
"KYNVER_HARNESS_ROOT on the server (or operator host posting via runner token).",
|
|
15
|
+
"Distinguishes AgentTask `running` (live executor lease) from plan-row focus.",
|
|
16
|
+
].join(" "), {
|
|
17
|
+
slug: slugField,
|
|
18
|
+
runId: z.string(),
|
|
19
|
+
workerName: z.string().optional().describe("Scope to one worker; omit for all workers in the run."),
|
|
20
|
+
}, async (args) => {
|
|
21
|
+
const slug = await resolveToolSlug(args.slug);
|
|
22
|
+
return jsonResult(await post(`/agent-os/${encodeURIComponent(slug)}/harness/monitor/assess`, {
|
|
23
|
+
runId: args.runId,
|
|
24
|
+
workerName: args.workerName,
|
|
25
|
+
}));
|
|
26
|
+
});
|
|
27
|
+
register("agent_os_monitor_list", "List active local harness monitor sidecars on the runner host (kynver monitor list). Requires runner execution context.", {
|
|
28
|
+
slug: slugField,
|
|
29
|
+
}, async () => {
|
|
30
|
+
return jsonResult({
|
|
31
|
+
note: "Use `kynver monitor list` on the runner host; MCP list is local-disk only.",
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
register("agent_os_monitor_auto_complete", [
|
|
35
|
+
"Run verified terminal auto-complete for one harness worker (poll + POST /harness/completion).",
|
|
36
|
+
"Refuses when blockers exist (heartbeat blocker, landing gate, completionBlocker).",
|
|
37
|
+
"Prefer `kynver monitor auto-complete --run RUN --name WORKER` on the runner host;",
|
|
38
|
+
"this MCP tool documents the contract — remote auto-complete requires runner CLI.",
|
|
39
|
+
].join(" "), {
|
|
40
|
+
slug: slugField,
|
|
41
|
+
runId: z.string(),
|
|
42
|
+
workerName: z.string(),
|
|
43
|
+
}, async (args) => {
|
|
44
|
+
await resolveToolSlug(args.slug);
|
|
45
|
+
return jsonResult({
|
|
46
|
+
ok: false,
|
|
47
|
+
reason: "Remote auto-complete must run via `kynver monitor auto-complete` on the runner host",
|
|
48
|
+
command: `kynver monitor auto-complete --run ${args.runId} --name ${args.workerName}`,
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
package/dist/tools/tasks.js
CHANGED
|
@@ -30,8 +30,14 @@ const taskPriority = z
|
|
|
30
30
|
.describe("Priority — default 'normal'. Create coding/implementation tasks as 'normal' (routine/cleanup 'low'); " +
|
|
31
31
|
"do NOT inherit the parent plan's priority — a task on a critical plan is still 'normal'. A task only " +
|
|
32
32
|
"becomes 'critical' once it is actively BLOCKING progress (and the system already marks blocked tasks " +
|
|
33
|
-
"critical automatically). Reserve manual 'high'/'critical'
|
|
34
|
-
"
|
|
33
|
+
"critical automatically). Reserve manual 'high'/'critical' only when Will explicitly asked or there is a " +
|
|
34
|
+
"live production/security incident — pass priorityEscalationReason quoting him or the incident. The server " +
|
|
35
|
+
"downgrades unsolicited high/critical to normal. If everything is critical, nothing is — keep most tasks at normal/low.");
|
|
36
|
+
const priorityEscalationReason = z
|
|
37
|
+
.string()
|
|
38
|
+
.optional()
|
|
39
|
+
.describe("Required when setting priority to high/critical: quote Will's words or name the live incident. " +
|
|
40
|
+
"Without this (and without explicit escalation in title/description), the API coerces to normal.");
|
|
35
41
|
const taskExecutor = z.enum(["inline", "harness", "acp", "manual"]);
|
|
36
42
|
const taskEventType = z.enum([
|
|
37
43
|
"created",
|
|
@@ -70,6 +76,7 @@ export function registerTaskTools({ register, resolveToolSlug, jsonResult, compa
|
|
|
70
76
|
title: z.string().describe("Short task title (required)."),
|
|
71
77
|
description: z.string().optional(),
|
|
72
78
|
priority: taskPriority.optional(),
|
|
79
|
+
priorityEscalationReason,
|
|
73
80
|
executor: taskExecutor.optional().describe("How the task runs: inline | harness | acp | manual."),
|
|
74
81
|
executorRef: z.string().optional().describe("Opaque ref to the executor process / unit."),
|
|
75
82
|
parentTaskId: z.string().optional().describe("Parent task id when this is one of 2+ coordinated workers."),
|
package/package.json
CHANGED