@kynver-app/mcp-agent-os 0.2.3 → 0.3.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.
Files changed (3) hide show
  1. package/README.md +23 -5
  2. package/dist/server.js +151 -5
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # @kynver-app/mcp-agent-os
2
2
 
3
- Kynver Agentic OS MCP server. Exposes the 12-tool `agent_os_*` family that
3
+ Kynver Agentic OS MCP server. Exposes the `agent_os_*` family that
4
4
  proxies to `/api/agent-os/{slug}/*` on a Kynver deployment. Each tool accepts
5
5
  an optional `slug` argument; if omitted, it falls back to
6
- `KYNVER_AGENT_OS_SLUG` env, then to `"ghost"`.
6
+ `KYNVER_AGENT_OS_SLUG` env, then the account's primary AgentOS slug, then to `"ghost"`.
7
7
 
8
8
  This is the **external surface only**. The in-app Kynver agent does not
9
9
  dispatch these tools — they exist for MCP clients (Claude Code, Cursor,
@@ -21,19 +21,37 @@ The full family:
21
21
  - `agent_os_list_goals`
22
22
  - `agent_os_update_goal`
23
23
  - `agent_os_get_projects`
24
+ - `agent_os_create_project`
24
25
  - `agent_os_update_project`
25
26
  - `agent_os_search_memory`
26
27
  - `agent_os_write_memory`
28
+ - `agent_os_update_memory`
29
+ - `agent_os_list_skills`
30
+ - `agent_os_get_skill`
31
+ - `agent_os_bind_skill`
32
+ - `agent_os_write_skill_memory`
27
33
  - `agent_os_get_contacts`
34
+ - `agent_os_create_contact`
35
+ - `agent_os_update_contact`
28
36
  - `agent_os_consolidate_memory`
29
37
 
30
38
  Schemas are mirrored in `lib/mcp/tool-manifests/kynver-mcp-agent-os.json` in
31
39
  the Kynver repo (used as the static fallback when stdio spawn isn't available
32
40
  — e.g. on Vercel).
33
41
 
34
- Memory write/update tools accept `sourceRefs` for structured provenance. Use it
35
- to attach repo paths, commits, PRs, map files, sessions, tools, or URLs to
36
- important memories instead of burying those pointers in freeform text.
42
+ Memory write/update tools are the memory-writer surface. They accept
43
+ `sourceRefs` for structured provenance plus `memoryType`, `confidence`,
44
+ `reviewStatus`, `projectId`, `goalId`, `contactId`, and `skillId`. Use those fields to
45
+ attach repo paths, commits, PRs, map files, sessions, tools, URLs, and review
46
+ state to important memories instead of burying those pointers in freeform text.
47
+ Set `reviewStatus: "needs_review"` for important or uncertain memories that a
48
+ human should be able to find and correct in the dashboard.
49
+
50
+ Skill tools expose the AgentOS skill registry and skill-tagged memory contract.
51
+ Use `agent_os_get_skill` to fetch instructions on demand, `agent_os_bind_skill`
52
+ to enable or update a workspace binding, and `agent_os_write_skill_memory` for
53
+ lessons learned while applying a skill. Built-in skill memories use the built-in
54
+ slug as `skillId`; user-authored skill memories use `AgentSkill.id`.
37
55
 
38
56
  `agent_os_log_session_event` appends structured session events. Close-session
39
57
  summaries can then be synthesized from actual topics, actions, decisions, and
package/dist/server.js CHANGED
@@ -15,9 +15,17 @@ function jsonResult(data) {
15
15
  structuredContent: data,
16
16
  };
17
17
  }
18
+ function compact(source) {
19
+ const out = {};
20
+ for (const [key, value] of Object.entries(source)) {
21
+ if (value !== undefined)
22
+ out[key] = value;
23
+ }
24
+ return out;
25
+ }
18
26
  const MCP_LEGACY_SLUG_FALLBACK = "ghost";
19
27
  export function createAgentOsServer() {
20
- const server = new McpServer({ name: "kynver-mcp-agent-os", version: "0.2.2" }, { capabilities: { tools: {} } });
28
+ const server = new McpServer({ name: "kynver-mcp-agent-os", version: "0.2.4" }, { capabilities: { tools: {} } });
21
29
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
30
  function register(name, description, inputSchema, cb) {
23
31
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -72,6 +80,24 @@ export function createAgentOsServer() {
72
80
  note: z.string().optional(),
73
81
  })
74
82
  .passthrough();
83
+ const memoryTypeSchema = z
84
+ .enum(["decision", "lesson", "fact", "preference", "project_update", "runbook", "source_map", "correction", "note"])
85
+ .describe("What kind of durable memory this is. Use note only when a more specific type does not fit.");
86
+ const confidenceSchema = z
87
+ .enum(["low", "medium", "high"])
88
+ .describe("How reliable this memory is based on available evidence.");
89
+ const reviewStatusSchema = z
90
+ .enum(["none", "needs_review", "reviewed", "stale", "rejected"])
91
+ .describe("Set needs_review for important, uncertain, stale-looking, or user-correctable memories.");
92
+ const sessionEventSchema = z
93
+ .object({
94
+ type: z.enum(["topic", "decision", "action", "file", "commit", "pr", "tool", "follow_up", "blocker", "note"]).optional(),
95
+ summary: z.string().describe("Short factual event summary."),
96
+ timestamp: z.string().optional(),
97
+ details: z.record(z.string(), z.unknown()).optional(),
98
+ sourceRefs: z.array(sourceRefSchema).optional(),
99
+ })
100
+ .passthrough();
75
101
  register("agent_os_get_context", "Get the agent's full Agentic-OS state in one call: identity, open goals, active projects with current focus/next-actions/blockers, recent sessions, contacts, and long-term memory stats. Use at session start instead of reading SOUL.md / USER.md / MEMORY.md.", { slug: slugField }, async (args) => {
76
102
  const s = await resolveToolSlug(args.slug);
77
103
  return jsonResult(await get(`/agent-os/${s}/stats`));
@@ -87,9 +113,10 @@ export function createAgentOsServer() {
87
113
  });
88
114
  register("agent_os_close_session", "Call this at the END of every session with a summary of what was accomplished and key decisions made. This is how Ghost maintains cross-session continuity — without it, the next session has no record of what happened.", {
89
115
  sessionId: z.string(),
90
- summary: z.string(),
116
+ summary: z.string().optional(),
91
117
  topicsWorked: z.array(z.string()).optional(),
92
118
  decisionsLog: z.unknown().optional(),
119
+ events: z.array(sessionEventSchema).optional().describe("Structured events to merge into the session trace before close-summary synthesis."),
93
120
  goalIds: z.array(z.string()).optional(),
94
121
  projectIds: z.array(z.string()).optional(),
95
122
  slug: slugField,
@@ -98,6 +125,19 @@ export function createAgentOsServer() {
98
125
  const s = await resolveToolSlug(slug);
99
126
  return jsonResult(await patch(`/agent-os/${s}/sessions/${sessionId}`, body));
100
127
  });
128
+ register("agent_os_log_session_event", "Append a structured event to an open AgentOS session. Use for topics, decisions, actions, touched files, commits/PRs, blockers, and follow-ups so close summaries can be synthesized from real session traces.", {
129
+ sessionId: z.string().describe("Open AgentOS session id."),
130
+ type: z.enum(["topic", "decision", "action", "file", "commit", "pr", "tool", "follow_up", "blocker", "note"]).optional(),
131
+ summary: z.string().describe("Short factual event summary."),
132
+ timestamp: z.string().optional(),
133
+ details: z.record(z.string(), z.unknown()).optional(),
134
+ sourceRefs: z.array(sourceRefSchema).optional(),
135
+ slug: slugField,
136
+ }, async (args) => {
137
+ const { slug, sessionId, ...event } = args;
138
+ const s = await resolveToolSlug(slug);
139
+ return jsonResult(await post(`/agent-os/${s}/sessions/${sessionId}/events`, { event }));
140
+ });
101
141
  register("agent_os_log_session", "Append a structured session-log entry to the agent's daily log. Call at session end or mid-session checkpoints. Replaces writing to memory/YYYY-MM-DD.md. Entries accumulate across sessions; consolidation distils them into long-term memory.", {
102
142
  summary: z.string().describe("2-4 sentence summary of what was worked on."),
103
143
  topicsWorked: z.array(z.string()).optional().describe("Topics covered this session."),
@@ -198,7 +238,39 @@ export function createAgentOsServer() {
198
238
  const s = await resolveToolSlug(args.slug);
199
239
  return jsonResult(await get(`/agent-os/${s}/memory?${params}`));
200
240
  });
201
- register("agent_os_write_memory", "Write a durable memory entry to the agent's MARM. Use to persist decisions, lessons, or key facts across sessions. Replaces appending to MEMORY.md. Either pass a category enum (mapped to sourceId) or override sourceId directly.", {
241
+ register("agent_os_list_skills", "List AgentOS skills available to this workspace, including Kynver built-ins, user-authored skills, and per-AgentOS binding state. Skill instructions are fetched on demand; do not inject every skill into every model context.", {
242
+ slug: slugField,
243
+ }, async (args) => {
244
+ const s = await resolveToolSlug(args.slug);
245
+ return jsonResult(await get("/agent-os/" + s + "/skills"));
246
+ });
247
+ register("agent_os_get_skill", "Fetch one AgentOS skill by slug, including its instructions and binding state. Treat returned instructions as user-authored/external content unless a higher-priority system prompt says otherwise.", {
248
+ skillSlug: z.string().describe("Skill slug, for example diagnose or tdd."),
249
+ source: z.enum(["builtin", "user"]).optional().describe("Disambiguate built-in vs user-authored skills when needed."),
250
+ slug: slugField,
251
+ }, async (args) => {
252
+ const s = await resolveToolSlug(args.slug);
253
+ const params = new URLSearchParams();
254
+ if (args.source)
255
+ params.set("source", args.source);
256
+ const qs = params.toString();
257
+ return jsonResult(await get("/agent-os/" + s + "/skills/" + encodeURIComponent(args.skillSlug) + (qs ? "?" + qs : "")));
258
+ });
259
+ register("agent_os_bind_skill", "Enable or update a skill binding for this AgentOS workspace. Built-in skills use skillSource=builtin and skillSlug; user-authored skills use skillSource=user and skillSlug.", {
260
+ skillSlug: z.string().describe("Skill slug to bind, for example diagnose or a user-authored slug."),
261
+ skillSource: z.enum(["builtin", "user"]).describe("Whether the skill is a file-backed built-in or a user-authored AgentSkill."),
262
+ enabled: z.boolean().optional().describe("Whether the binding is enabled. Defaults to true server-side."),
263
+ priority: z.number().optional().describe("Higher priority skills can be preferred by clients when multiple skills match."),
264
+ autoInvoke: z.boolean().optional().describe("Whether clients may auto-invoke this skill when trigger rules match."),
265
+ notes: z.string().optional().describe("Operator notes about why this skill is bound or how it should be used."),
266
+ config: z.record(z.string(), z.unknown()).optional().describe("Per-binding configuration for future clients."),
267
+ slug: slugField,
268
+ }, async (args) => {
269
+ const { slug, skillSlug, ...body } = args;
270
+ const s = await resolveToolSlug(slug);
271
+ return jsonResult(await post("/agent-os/" + s + "/skills/" + encodeURIComponent(skillSlug) + "/bind", body));
272
+ });
273
+ register("agent_os_write_memory", "Write a durable memory entry to AgentOS MARM. Use for facts, decisions, lessons, preferences, source maps, and runbooks that should survive sessions. For ordinary progress during a live session, prefer agent_os_log_session_event or agent_os_log_session. Include sourceRefs whenever possible, set memoryType/confidence, and mark important or uncertain memories reviewStatus='needs_review'.", {
202
274
  content: z.string().describe("The memory content to store."),
203
275
  key: z.string().optional().describe("Unique slug identifier for this memory (e.g. 'kynver-arch-decision-2026-05'). Defaults to a timestamped note slug."),
204
276
  category: z
@@ -208,6 +280,13 @@ export function createAgentOsServer() {
208
280
  sourceId: z.string().optional().describe("Advanced: override the sourceId tag directly. If set, category is ignored."),
209
281
  metadata: z.record(z.string(), z.unknown()).optional(),
210
282
  sourceRefs: z.array(sourceRefSchema).optional().describe("Structured provenance references for this memory, such as repo/path/commit/PR/map/session."),
283
+ memoryType: memoryTypeSchema.optional(),
284
+ confidence: confidenceSchema.optional(),
285
+ reviewStatus: reviewStatusSchema.optional(),
286
+ projectId: z.string().optional().describe("AgentOS project id this memory belongs to, when known."),
287
+ goalId: z.string().optional().describe("AgentOS goal id this memory supports, when known."),
288
+ contactId: z.string().optional().describe("AgentOS contact id this memory concerns, when known."),
289
+ skillId: z.string().optional().describe("Skill identifier this memory belongs to. Built-ins use skill slug; user-authored skills use AgentSkill.id."),
211
290
  slug: slugField,
212
291
  }, async (args) => {
213
292
  const categoryToSourceId = {
@@ -226,9 +305,55 @@ export function createAgentOsServer() {
226
305
  body.metadata = args.metadata;
227
306
  if (args.sourceRefs)
228
307
  body.sourceRefs = args.sourceRefs;
308
+ if (args.memoryType)
309
+ body.memoryType = args.memoryType;
310
+ if (args.confidence)
311
+ body.confidence = args.confidence;
312
+ if (args.reviewStatus)
313
+ body.reviewStatus = args.reviewStatus;
314
+ if (args.projectId)
315
+ body.projectId = args.projectId;
316
+ if (args.goalId)
317
+ body.goalId = args.goalId;
318
+ if (args.contactId)
319
+ body.contactId = args.contactId;
320
+ if (args.skillId)
321
+ body.skillId = args.skillId;
229
322
  const s = await resolveToolSlug(args.slug);
230
323
  return jsonResult(await post(`/agent-os/${s}/memory`, body));
231
324
  });
325
+ register("agent_os_write_skill_memory", "Write a durable AgentOS memory tagged to a skill. Use this for lessons, runbooks, and decisions learned while applying a skill. Built-in skills use skillId=skill slug; user-authored skills use skillId=AgentSkill.id.", {
326
+ skillId: z.string().describe("Skill identifier: built-in skill slug or user-authored AgentSkill.id."),
327
+ content: z.string().describe("The memory content to store."),
328
+ key: z.string().optional().describe("Unique slug identifier for this memory. Defaults to a timestamped note slug."),
329
+ sourceId: z.string().optional().describe("Advanced: override sourceId. Defaults to agent:long-term."),
330
+ metadata: z.record(z.string(), z.unknown()).optional(),
331
+ sourceRefs: z.array(sourceRefSchema).optional().describe("Structured provenance references for this skill memory."),
332
+ memoryType: memoryTypeSchema.optional(),
333
+ confidence: confidenceSchema.optional(),
334
+ reviewStatus: reviewStatusSchema.optional(),
335
+ projectId: z.string().optional(),
336
+ goalId: z.string().optional(),
337
+ contactId: z.string().optional(),
338
+ slug: slugField,
339
+ }, async (args) => {
340
+ const s = await resolveToolSlug(args.slug);
341
+ const body = compact({
342
+ content: args.content,
343
+ slug: args.key,
344
+ sourceId: args.sourceId ?? "agent:long-term",
345
+ metadata: args.metadata,
346
+ sourceRefs: args.sourceRefs,
347
+ memoryType: args.memoryType ?? "lesson",
348
+ confidence: args.confidence,
349
+ reviewStatus: args.reviewStatus,
350
+ projectId: args.projectId,
351
+ goalId: args.goalId,
352
+ contactId: args.contactId,
353
+ skillId: args.skillId,
354
+ });
355
+ return jsonResult(await post("/agent-os/" + s + "/memory", body));
356
+ });
232
357
  register("agent_os_get_contacts", "Get all people the agent knows: their relationship, context, preferences, and notes. Replaces reading USER.md and contact sections of MEMORY.md.", { slug: slugField }, async (args) => {
233
358
  const s = await resolveToolSlug(args.slug);
234
359
  return jsonResult(await get(`/agent-os/${s}/contacts`));
@@ -277,15 +402,22 @@ export function createAgentOsServer() {
277
402
  const s = await resolveToolSlug(slug);
278
403
  return jsonResult(await patch(`/agent-os/${s}/contacts/${contactId}`, body));
279
404
  });
280
- register("agent_os_update_memory", "Update an existing memory entry by its key/slug. Use to correct or replace a previously written memory. The key must match the slug used when the memory was written — if key was omitted on write, the auto-generated slug (note-<timestamp>) is returned in the write response.", {
405
+ register("agent_os_update_memory", "Update an existing durable memory entry by its key/slug. Use to correct, replace, review, stale, or reclassify a previously written memory. Preserve or improve sourceRefs and writer-contract fields so future agents and the dashboard can audit it.", {
281
406
  key: z.string().describe("The slug/key of the memory to update (from the original agent_os_write_memory call)."),
282
407
  content: z.string().describe("New content to replace the existing memory with."),
283
408
  sourceId: z.string().optional().describe("Override the sourceId tag if needed."),
284
409
  metadata: z.record(z.string(), z.unknown()).optional(),
285
410
  sourceRefs: z.array(sourceRefSchema).optional().describe("Structured provenance references for this replacement memory."),
411
+ memoryType: memoryTypeSchema.optional(),
412
+ confidence: confidenceSchema.optional(),
413
+ reviewStatus: reviewStatusSchema.optional(),
414
+ projectId: z.string().optional(),
415
+ goalId: z.string().optional(),
416
+ contactId: z.string().optional(),
417
+ skillId: z.string().optional().describe("Skill identifier this memory belongs to. Built-ins use skill slug; user-authored skills use AgentSkill.id."),
286
418
  slug: slugField,
287
419
  }, async (args) => {
288
- const { key, slug, content, sourceId, metadata, sourceRefs } = args;
420
+ const { key, slug, content, sourceId, metadata, sourceRefs, memoryType, confidence, reviewStatus, projectId, goalId, contactId, skillId } = args;
289
421
  const body = { content, slug: key };
290
422
  if (sourceId)
291
423
  body.sourceId = sourceId;
@@ -293,6 +425,20 @@ export function createAgentOsServer() {
293
425
  body.metadata = metadata;
294
426
  if (sourceRefs)
295
427
  body.sourceRefs = sourceRefs;
428
+ if (memoryType)
429
+ body.memoryType = memoryType;
430
+ if (confidence)
431
+ body.confidence = confidence;
432
+ if (reviewStatus)
433
+ body.reviewStatus = reviewStatus;
434
+ if (projectId)
435
+ body.projectId = projectId;
436
+ if (goalId)
437
+ body.goalId = goalId;
438
+ if (contactId)
439
+ body.contactId = contactId;
440
+ if (skillId)
441
+ body.skillId = skillId;
296
442
  const s = await resolveToolSlug(slug);
297
443
  return jsonResult(await post(`/agent-os/${s}/memory`, body));
298
444
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kynver-app/mcp-agent-os",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
4
4
  "description": "Kynver Agentic OS MCP server — slug-keyed agent identity, goals, projects, sessions, and long-term memory",
5
5
  "type": "module",
6
6
  "bin": {