@kynver-app/mcp-agent-os 0.3.46 → 0.3.47

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.
@@ -4,7 +4,7 @@ import { createServer } from "node:http";
4
4
  import { timingSafeEqual } from "node:crypto";
5
5
  import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
6
6
  export const MAX_SSE_BODY_BYTES = 1 * 1024 * 1024;
7
- const FORBIDDEN_QUERY_KEYS = ["secret", "userId"];
7
+ const FORBIDDEN_QUERY_KEYS = ["apiKey", "secret", "userId"];
8
8
  export function headerValue(req, name) {
9
9
  const v = req.headers[name];
10
10
  return typeof v === "string" ? v : Array.isArray(v) ? (v[0] ?? null) : null;
@@ -19,9 +19,6 @@ export function timingSafeEqualString(a, b) {
19
19
  export function hasForbiddenQueryAuth(url) {
20
20
  return FORBIDDEN_QUERY_KEYS.some((key) => url.searchParams.has(key));
21
21
  }
22
- function queryApiKey(url) {
23
- return url.searchParams.get("apiKey")?.trim() ?? "";
24
- }
25
22
  export function resolveListenHost() {
26
23
  const configured = process.env.MCP_SSE_HOST?.trim();
27
24
  return configured || "127.0.0.1";
@@ -130,7 +127,7 @@ function resolveInternalAuth(req, serviceSecret) {
130
127
  }
131
128
  function verifyPostAuth(req, url, sessionAuth, serviceSecret) {
132
129
  if (sessionAuth.kind === "apiKey") {
133
- const token = bearerToken(req) || queryApiKey(url);
130
+ const token = bearerToken(req);
134
131
  return token.length > 0 && timingSafeEqualString(token, sessionAuth.apiKey);
135
132
  }
136
133
  const internal = resolveInternalAuth(req, serviceSecret);
@@ -170,7 +167,6 @@ export function startKynverMcpSseServer(options) {
170
167
  const maxSessionsPerUser = intFromEnv("MCP_SSE_MAX_SESSIONS_PER_USER", 20);
171
168
  const idleTimeoutMs = intFromEnv("MCP_SSE_IDLE_TIMEOUT_MS", 5 * 60 * 1000);
172
169
  const rateLimitPerMin = intFromEnv("MCP_SSE_RATE_LIMIT_PER_MIN", 120);
173
- const rejectQueryApiKey = /^(1|true|yes)$/i.test(process.env.MCP_SSE_REJECT_QUERY_APIKEY ?? "");
174
170
  const rateLimiter = createFixedWindowRateLimiter(rateLimitPerMin, 60 * 1000);
175
171
  // Close idle SSE sessions so a flood of half-open connections can't pin memory.
176
172
  const idleSweep = setInterval(() => {
@@ -198,15 +194,6 @@ export function startKynverMcpSseServer(options) {
198
194
  });
199
195
  return;
200
196
  }
201
- if (url.searchParams.has("apiKey")) {
202
- if (rejectQueryApiKey) {
203
- json(res, 400, {
204
- error: "apiKey via query param is disabled. Use Authorization: Bearer <key>.",
205
- });
206
- return;
207
- }
208
- console.warn("[MCP SSE] WARNING: apiKey in query string may leak via logs. Prefer Authorization header when your client supports it.");
209
- }
210
197
  let userId = null;
211
198
  let auth = null;
212
199
  const internal = serviceSecret ? resolveInternalAuth(req, serviceSecret) : null;
@@ -215,7 +202,7 @@ export function startKynverMcpSseServer(options) {
215
202
  auth = internal.auth;
216
203
  }
217
204
  else {
218
- const apiKey = bearerToken(req) || queryApiKey(url);
205
+ const apiKey = bearerToken(req);
219
206
  if (apiKey) {
220
207
  userId = await resolveUserFromApiKey(baseUrl, apiKey);
221
208
  if (userId)
package/dist/server.js CHANGED
@@ -11,6 +11,7 @@ import { z } from "zod";
11
11
  import { get, post, patch } from "./lib/kynver-client.js";
12
12
  import { registerPlanTools } from "./tools/plans.js";
13
13
  import { registerPlanProgressTools } from "./tools/plan-progress.js";
14
+ import { registerPlanToFactoryTools } from "./tools/plan-to-factory.js";
14
15
  import { registerTaskTools } from "./tools/tasks.js";
15
16
  import { registerActionRequiredTools } from "./tools/action-required.js";
16
17
  import { registerGraphTools } from "./tools/graph.js";
@@ -709,6 +710,7 @@ export function createAgentOsServer() {
709
710
  // First-class AgentOS plans (Phase 5A): versioned operational artifacts.
710
711
  registerPlanTools({ register, resolveToolSlug, jsonResult, compact });
711
712
  registerPlanProgressTools({ register, resolveToolSlug, jsonResult, compact });
713
+ registerPlanToFactoryTools({ register, resolveToolSlug, jsonResult, compact });
712
714
  // Action Required inbox: agent_os_ask_human + agent_os_await_action (slice 1).
713
715
  registerActionRequiredTools({ register, jsonResult, compact });
714
716
  // Operational graph insights — Agent SEE (agent_os_graph_query).
@@ -0,0 +1,2 @@
1
+ import type { PlanToolDeps } from "./plans.js";
2
+ export declare function registerPlanToFactoryTools({ register, resolveToolSlug, jsonResult, }: PlanToolDeps): void;
@@ -0,0 +1,23 @@
1
+ import { z } from "zod";
2
+ import { post } from "../lib/kynver-client.js";
3
+ export function registerPlanToFactoryTools({ register, resolveToolSlug, jsonResult, }) {
4
+ const slugField = z
5
+ .string()
6
+ .optional()
7
+ .describe("AgentOS workspace slug. Omit to use env or the server-discovered primary.");
8
+ register("agent_os_plan_run_factory", "Run a plan through the factory: decompose progress rows, mint parent + child harness tasks, wire dependencies and owned paths, and return the next runnable slice.", {
9
+ planId: z.string(),
10
+ dryRun: z.boolean().optional(),
11
+ command: z
12
+ .string()
13
+ .optional()
14
+ .describe('Operator phrase; defaults to "run this plan through the factory".'),
15
+ slug: slugField,
16
+ }, async (args) => {
17
+ const s = await resolveToolSlug(args.slug);
18
+ return jsonResult(await post(`/agent-os/${s}/plans/${args.planId}/run-factory`, {
19
+ dryRun: args.dryRun,
20
+ command: args.command,
21
+ }));
22
+ });
23
+ }
@@ -147,7 +147,7 @@ export function registerTaskTools({ register, resolveToolSlug, jsonResult, compa
147
147
  scheduledFor,
148
148
  dependsOnTaskIds,
149
149
  lastSummary: z.string().optional().describe("Latest progress summary."),
150
- blocker: z.string().optional(),
150
+ blocker: z.string().nullable().optional().describe("Blocker text, or null to clear it."),
151
151
  branch: z.string().optional(),
152
152
  worktreePath: z.string().optional(),
153
153
  prUrl: z.string().optional(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kynver-app/mcp-agent-os",
3
- "version": "0.3.46",
3
+ "version": "0.3.47",
4
4
  "description": "Kynver Agentic OS MCP server \u2014 slug-keyed agent identity, goals, projects, sessions, and long-term memory",
5
5
  "type": "module",
6
6
  "bin": {