@stigmer/mcp-server 3.12.1 → 3.12.3
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/cli/mcp-server-stigmer.js +5 -3
- package/domains/agentexecutions/fetch.d.ts.map +1 -1
- package/domains/agentexecutions/fetch.js +3 -4
- package/domains/agentexecutions/fetch.js.map +1 -1
- package/gen/mcpserver.js +1 -1
- package/gen/mcpserver.js.map +1 -1
- package/gen/workflow.js +6 -6
- package/gen/workflow.js.map +1 -1
- package/package.json +3 -3
- package/readiness.d.ts +27 -0
- package/readiness.d.ts.map +1 -0
- package/readiness.js +81 -0
- package/readiness.js.map +1 -0
- package/server.d.ts.map +1 -1
- package/server.js +51 -17
- package/server.js.map +1 -1
- package/src/domains/agentexecutions/fetch.ts +3 -4
- package/src/gen/mcpserver.ts +1 -1
- package/src/gen/workflow.ts +6 -6
- package/src/http.integration.test.ts +46 -6
- package/src/readiness.test.ts +90 -0
- package/src/readiness.ts +94 -0
- package/src/server.ts +58 -15
package/server.js
CHANGED
|
@@ -14,6 +14,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
14
14
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
15
15
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
16
16
|
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
17
|
+
import { createReadinessCheck } from "./readiness.js";
|
|
17
18
|
import { registerAgentExecutionTools } from "./domains/agentexecutions/tools.js";
|
|
18
19
|
import { registerAgentResources } from "./domains/agents/resources.js";
|
|
19
20
|
import { registerAgentTools } from "./domains/agents/tools.js";
|
|
@@ -208,9 +209,10 @@ export function routedServerFactory(target) {
|
|
|
208
209
|
*/
|
|
209
210
|
export async function serveHttp(makeServer, cfg, signal) {
|
|
210
211
|
const sessions = new Map();
|
|
212
|
+
const checkReady = createReadinessCheck(cfg.stigmerServerAddress);
|
|
211
213
|
const httpServer = createHttpServer((req, res) => {
|
|
212
214
|
logAccess(req, res);
|
|
213
|
-
void routeRequest(req, res, sessions, makeServer, cfg);
|
|
215
|
+
void routeRequest(req, res, sessions, makeServer, cfg, checkReady);
|
|
214
216
|
});
|
|
215
217
|
const addr = `:${cfg.httpPort}`;
|
|
216
218
|
return new Promise((resolve, reject) => {
|
|
@@ -257,20 +259,39 @@ export async function serveBoth(target, cfg, signal) {
|
|
|
257
259
|
}
|
|
258
260
|
}
|
|
259
261
|
/**
|
|
260
|
-
* Route an inbound HTTP request: liveness
|
|
261
|
-
* extraction, then delegation to the session's MCP transport (reusing an
|
|
262
|
+
* Route an inbound HTTP request: liveness/readiness probes, the non-validating
|
|
263
|
+
* Bearer extraction, then delegation to the session's MCP transport (reusing an
|
|
262
264
|
* existing session or creating one for an `initialize` request).
|
|
263
265
|
*
|
|
264
266
|
* The token is never validated here — presence is the only check, and it is
|
|
265
267
|
* forwarded unchanged to stigmer-server which performs validation. This mirrors
|
|
266
268
|
* the Go authMiddleware exactly (inventory §4.2).
|
|
269
|
+
*
|
|
270
|
+
* Every refusal is a JSON-RPC-framed error (the SDK transport's own
|
|
271
|
+
* convention — see jsonRpcError), never text/plain: strict MCP clients parse
|
|
272
|
+
* the body, and the spec keys session recovery on a recognizable 404.
|
|
267
273
|
*/
|
|
268
|
-
async function routeRequest(req, res, sessions, makeServer, cfg) {
|
|
274
|
+
async function routeRequest(req, res, sessions, makeServer, cfg, checkReady) {
|
|
269
275
|
if (req.method === "GET" && req.url === "/health") {
|
|
270
276
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
271
277
|
res.end(`{"status":"ok"}\n`);
|
|
272
278
|
return;
|
|
273
279
|
}
|
|
280
|
+
// Readiness = liveness AND a working backend hop (see readiness.ts for why
|
|
281
|
+
// only the readiness probe may point here). Public like /health: Kubernetes
|
|
282
|
+
// probes carry no bearer.
|
|
283
|
+
if (req.method === "GET" && requestPath(req) === "/ready") {
|
|
284
|
+
const result = await checkReady();
|
|
285
|
+
if (result.ready) {
|
|
286
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
287
|
+
res.end(`{"status":"ready"}\n`);
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
res.writeHead(503, { "Content-Type": "application/json" });
|
|
291
|
+
res.end(JSON.stringify({ status: "unready", reason: result.reason }) + "\n");
|
|
292
|
+
}
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
274
295
|
// RFC 9728 Protected Resource Metadata — public, unauthenticated, and served
|
|
275
296
|
// only when OAuth discovery is enabled. CORS-open so browser-based clients
|
|
276
297
|
// (e.g. Claude Desktop's connector GUI) can discover the authorization server.
|
|
@@ -283,12 +304,11 @@ async function routeRequest(req, res, sessions, makeServer, cfg) {
|
|
|
283
304
|
if (cfg.httpAuthEnabled) {
|
|
284
305
|
const token = extractBearerToken(req);
|
|
285
306
|
if (token === "") {
|
|
286
|
-
const headers = { "Content-Type": "text/plain" };
|
|
287
307
|
// RFC 9728 §5.1: point OAuth-capable clients at the metadata document.
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
res
|
|
308
|
+
const challenge = cfg.oauth.enabled
|
|
309
|
+
? { "WWW-Authenticate": bearerChallenge(cfg) }
|
|
310
|
+
: undefined;
|
|
311
|
+
jsonRpcError(res, 401, -32000, "missing or malformed Authorization: Bearer header", challenge);
|
|
292
312
|
return;
|
|
293
313
|
}
|
|
294
314
|
req.auth = { token, clientId: "stigmer-mcp-passthrough", scopes: [] };
|
|
@@ -299,8 +319,12 @@ async function routeRequest(req, res, sessions, makeServer, cfg) {
|
|
|
299
319
|
if (sessionId !== undefined) {
|
|
300
320
|
const transport = sessions.get(sessionId);
|
|
301
321
|
if (transport === undefined) {
|
|
302
|
-
|
|
303
|
-
|
|
322
|
+
// 404 + code -32001 is the SDK transport's session-not-found shape, and
|
|
323
|
+
// the streamable-HTTP spec's recovery signal: on it, a client MUST open
|
|
324
|
+
// a new session with a fresh InitializeRequest. Losing sessions on pod
|
|
325
|
+
// restart is expected here — they are in-memory by design (single
|
|
326
|
+
// replica; see the deployment overlay).
|
|
327
|
+
jsonRpcError(res, 404, -32001, "Session not found: unknown or expired MCP session");
|
|
304
328
|
return;
|
|
305
329
|
}
|
|
306
330
|
await transport.handleRequest(req, res);
|
|
@@ -308,14 +332,12 @@ async function routeRequest(req, res, sessions, makeServer, cfg) {
|
|
|
308
332
|
}
|
|
309
333
|
// No session → only an initialize POST may open one.
|
|
310
334
|
if (req.method !== "POST") {
|
|
311
|
-
res
|
|
312
|
-
res.end("missing Mcp-Session-Id header");
|
|
335
|
+
jsonRpcError(res, 400, -32000, "Bad Request: Mcp-Session-Id header is required");
|
|
313
336
|
return;
|
|
314
337
|
}
|
|
315
338
|
const body = await readJsonBody(req);
|
|
316
339
|
if (!isInitializeRequest(body)) {
|
|
317
|
-
res
|
|
318
|
-
res.end("Bad Request: an initialize request is required to open a session");
|
|
340
|
+
jsonRpcError(res, 400, -32000, "Bad Request: an initialize request is required to open a session");
|
|
319
341
|
return;
|
|
320
342
|
}
|
|
321
343
|
// Route recognition happens exactly where the roster choice happens.
|
|
@@ -323,8 +345,7 @@ async function routeRequest(req, res, sessions, makeServer, cfg) {
|
|
|
323
345
|
// routedServerFactory for the incident this prevents.
|
|
324
346
|
const server = makeServer(path);
|
|
325
347
|
if (server === undefined) {
|
|
326
|
-
res
|
|
327
|
-
res.end(`unknown MCP route: ${path}`);
|
|
348
|
+
jsonRpcError(res, 404, -32000, `unknown MCP route: ${path}`);
|
|
328
349
|
return;
|
|
329
350
|
}
|
|
330
351
|
const transport = new StreamableHTTPServerTransport({
|
|
@@ -353,6 +374,19 @@ export function stdioServer(target, cfg) {
|
|
|
353
374
|
return createChannelsServer(target);
|
|
354
375
|
return createServer(target);
|
|
355
376
|
}
|
|
377
|
+
/**
|
|
378
|
+
* Write a JSON-RPC-framed refusal, byte-compatible with the SDK transport's
|
|
379
|
+
* own createJsonErrorResponse: `{"jsonrpc":"2.0","error":{code,message},"id":null}`
|
|
380
|
+
* with Content-Type application/json. The HTTP status stays authoritative (the
|
|
381
|
+
* streamable-HTTP spec keys on it); the body exists for strict MCP clients
|
|
382
|
+
* that parse refusals instead of surfacing an opaque content-type error
|
|
383
|
+
* (stigmer/stigmer#316). Code -32001 is reserved for session-not-found; the
|
|
384
|
+
* transport-level family uses -32000, both per the SDK's convention.
|
|
385
|
+
*/
|
|
386
|
+
function jsonRpcError(res, status, code, message, headers) {
|
|
387
|
+
res.writeHead(status, { "Content-Type": "application/json", ...headers });
|
|
388
|
+
res.end(JSON.stringify({ jsonrpc: "2.0", error: { code, message }, id: null }));
|
|
389
|
+
}
|
|
356
390
|
/** Return a single header value, collapsing the array form Node may produce. */
|
|
357
391
|
function headerValue(req, name) {
|
|
358
392
|
const v = req.headers[name];
|
package/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,12 +23,11 @@ export const DEFAULT_MESSAGE_LIMIT = 5;
|
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Bulky status fields pruned from the compact view. These are server-side
|
|
26
|
-
* bookkeeping (
|
|
27
|
-
*
|
|
28
|
-
*
|
|
26
|
+
* bookkeeping (append-only approval ledger, Temporal callback token) and
|
|
27
|
+
* sub-agent transcripts — none of which the poll loop (phase? messages?
|
|
28
|
+
* approvals?) needs.
|
|
29
29
|
*/
|
|
30
30
|
const COMPACT_PRUNED_STATUS_FIELDS = [
|
|
31
|
-
"resolved_context",
|
|
32
31
|
"approval_events",
|
|
33
32
|
"callback_token",
|
|
34
33
|
"sub_agent_executions",
|
package/src/gen/mcpserver.ts
CHANGED
|
@@ -27,7 +27,7 @@ export const McpServerInputShape = {
|
|
|
27
27
|
http: z.lazy(() => HttpServerConfigInputSchema).optional().describe("HTTP-based server (HTTP + Server-Sent Events communication). Used for remote/managed MCP services accessible over the network."),
|
|
28
28
|
default_enabled_tools: z.array(z.string()).optional().describe("Default tools to enable from this MCP server. Empty list means all tools are enabled by default. Applies whenever an agent's McpServerUsage.enabled_tools is empty."),
|
|
29
29
|
env: z.record(z.lazy(() => EnvVarDeclarationInputSchema)).optional().describe("Environment variable declarations for this MCP server. Keys are variable names; values describe their metadata and optionality."),
|
|
30
|
-
pinned_tool_approvals: z.array(z.lazy(() => ToolApprovalPolicyInputSchema)).optional().describe("
|
|
30
|
+
pinned_tool_approvals: z.array(z.lazy(() => ToolApprovalPolicyInputSchema)).optional().describe("Tools pinned by the MCP server owner to always require approval."),
|
|
31
31
|
repository_url: z.string().optional().describe("URL of the upstream source repository for this MCP server. Shown in the marketplace so users can inspect the implementation for trust and transparency. Example: 'https://github.com/modelcontextprotocol/servers'"),
|
|
32
32
|
github_stars: z.number().optional().describe("GitHub star count at the time of curation. Used as a popularity signal in marketplace display. 0 if unknown or non-GitHub repository."),
|
|
33
33
|
auth: z.lazy(() => McpServerAuthInputSchema).optional().describe("OAuth authentication configuration for automated credential acquisition. When set, the MCP server's Connect page offers an OAuth flow instead of (or in addition to) manual credential entry. The acquired access token is stored in a system-managed environment (identified by grant.environment_id) as the env var named by auth.target_env_var. That env var must also be declared in env so the execution pipeline knows about it."),
|
package/src/gen/workflow.ts
CHANGED
|
@@ -78,7 +78,7 @@ type RunConfigInput = z.infer<typeof RunConfigInputSchema>;
|
|
|
78
78
|
const AgentCallOutputContractInputSchema = z.object({
|
|
79
79
|
schema: z.record(z.unknown()).describe("JSON Schema that the agent's structured output must conform to. Standard JSON Schema (draft 2020-12 or compatible). The workflow runner extracts JSON from the agent's final response and validates it against this schema. If validation fails, the on_invalid policy determines what happens next. The schema is carried as a google.protobuf.Struct to preserve the existing kind+Struct envelope pattern and allow YAML authors to write standard JSON Schema inline without a Stigmer-specific schema language."),
|
|
80
80
|
on_invalid: z.string().optional().describe("Policy when agent output fails schema validation. Default: ON_INVALID_FAIL (task fails immediately). Allowed values: ON_INVALID_FAIL, ON_INVALID_RETRY, ON_INVALID_FALLBACK."),
|
|
81
|
-
max_retries: z.number().optional().describe("Maximum retry attempts when on_invalid is ON_INVALID_RETRY. Each retry re-prompts the agent with the specific validation errors and the expected schema, giving the agent an opportunity to self-correct. Only meaningful when on_invalid is ON_INVALID_RETRY; ignored otherwise. Default:
|
|
81
|
+
max_retries: z.number().optional().describe("Maximum retry attempts when on_invalid is ON_INVALID_RETRY. Each retry re-prompts the agent with the specific validation errors and the expected schema, giving the agent an opportunity to self-correct. Only meaningful when on_invalid is ON_INVALID_RETRY; ignored otherwise. Default: 2 (the runner's retry loop). Valid range when set: 1-5. Unset (0) is valid: proto3 implicit presence makes an omitted field indistinguishable from 0, so the range rule must not fire on it (#673)."),
|
|
82
82
|
fallback_task: z.string().optional().describe("Target task to branch to when schema validation cannot be resolved. Used in two scenarios: 1. on_invalid is ON_INVALID_RETRY and all retries are exhausted 2. on_invalid is ON_INVALID_FALLBACK (immediate branch, no retry) Must reference a valid task name in the same workflow. When empty and retries are exhausted, the task fails."),
|
|
83
83
|
});
|
|
84
84
|
type AgentCallOutputContractInput = z.infer<typeof AgentCallOutputContractInputSchema>;
|
|
@@ -121,7 +121,7 @@ const AgentCallTaskConfigInputSchema = z.object({
|
|
|
121
121
|
env: z.record(z.string()).optional().describe("Runtime environment variables to pass to the agent. Values can be literal strings or JQ expressions that reference workflow context or secrets. Example: {'GITHUB_TOKEN': '${ .secrets.GH_TOKEN }'} Optional."),
|
|
122
122
|
run_config: z.lazy(() => RunConfigInputSchema).optional().describe("Per-call model choice and run bounds. Unset fields inherit the platform defaults."),
|
|
123
123
|
output: z.lazy(() => AgentCallOutputContractInputSchema).optional().describe("Structured output contract for this agent call. When set, the workflow runner extracts structured JSON from the agent's final response and validates it against the declared schema. The validated JSON is placed in the task output under the 'structured' key, enabling reliable downstream routing via switch_case expressions. When not set, the task output contains the agent's raw text response. @since T02 (Structured Agent Output Model)"),
|
|
124
|
-
harness: z.string().optional().describe("Execution harness for the agent invocation. Determines which execution engine processes the agent call: - HARNESS_UNSPECIFIED / HARNESS_NATIVE: Stigmer native engine (Python/LangGraph) - HARNESS_CURSOR: Cursor SDK engine (TypeScript/Cursor) The
|
|
124
|
+
harness: z.string().optional().describe("Execution harness for the agent invocation. Determines which execution engine processes the agent call: - HARNESS_UNSPECIFIED / HARNESS_NATIVE: Stigmer native engine (Python/LangGraph) - HARNESS_CURSOR: Cursor SDK engine (TypeScript/Cursor) The runner creates a Session with this harness before creating the AgentExecution. The harness is a session-level concern — it determines tool availability, state management, model access, and billing tier. When unspecified, defaults to HARNESS_NATIVE (the workflow surface's platform default). YAML Example: - code_review: call: agent with: agent: 'code-reviewer' harness: cursor message: 'Review this PR' Allowed values: HARNESS_NATIVE, HARNESS_CURSOR."),
|
|
125
125
|
workspace_entries: z.array(z.lazy(() => WorkspaceEntryInputSchema)).optional().describe("Workspace the child run's session operates on. Empty means no workspace."),
|
|
126
126
|
environment_refs: z.array(z.lazy(() => EnvironmentRefInputSchema)).optional().describe("References to Environment resources whose values are provided to the child runs this task creates. This is how a tool-using agent becomes runnable from a workflow: bind an org-shared environment holding the needed credentials, and the child runs receive its values at runtime. The agent and its default instance stay untouched."),
|
|
127
127
|
});
|
|
@@ -219,7 +219,7 @@ const HttpCallTaskConfigInputSchema = z.object({
|
|
|
219
219
|
endpoint: z.lazy(() => HttpEndpointInputSchema).describe("HTTP endpoint configuration."),
|
|
220
220
|
headers: z.record(z.string()).optional().describe("HTTP headers (optional). Values can contain expressions: 'Bearer ${TOKEN}'"),
|
|
221
221
|
body: z.record(z.unknown()).optional().describe("Request body (optional). Can be any JSON structure. Supports expressions in string values."),
|
|
222
|
-
timeout_seconds: z.number().optional().describe("Request timeout in seconds (
|
|
222
|
+
timeout_seconds: z.number().optional().describe("Request timeout in seconds. Max: 300 (5 minutes). Optional — unset (0) leaves the request bounded by the runner's activity timeout. NOTE: an explicit value is accepted but not yet applied by the runner; the activity timeout governs either way. Unset (0) is valid: proto3 implicit presence makes an omitted field indistinguishable from 0, so the range rule must not fire on it (#673)."),
|
|
223
223
|
});
|
|
224
224
|
type HttpCallTaskConfigInput = z.infer<typeof HttpCallTaskConfigInputSchema>;
|
|
225
225
|
|
|
@@ -266,10 +266,10 @@ const LlmCallTaskConfigInputSchema = z.object({
|
|
|
266
266
|
prompt: z.string().describe("User prompt / instruction sent to the LLM. Supports ${ } expression interpolation for injecting workflow context. Example: 'Classify this ticket: ${ $context.ticket.description }' Required field."),
|
|
267
267
|
response_schema: z.record(z.unknown()).optional().describe("JSON Schema for structured output. When set, the runner requests structured output from the provider (e.g., OpenAI's response_format, Anthropic's tool_use extraction) and validates the response against this schema. Uses the same google.protobuf.Struct + JSON Schema pattern as AgentCallOutputContract.schema for consistency across the workflow domain. When not set, the task output is the LLM's raw text response."),
|
|
268
268
|
temperature: z.number().optional().describe("Sampling temperature (0.0 to 2.0). Lower = more deterministic, higher = more creative. Range is 0.0-2.0 to accommodate all major providers (OpenAI supports up to 2.0; others clamp to their supported range at runtime). Optional — uses the provider's default when not set."),
|
|
269
|
-
max_tokens: z.number().optional().describe("Maximum tokens in the LLM response. Optional — uses the provider's default when not set."),
|
|
270
|
-
timeout: z.number().optional().describe("Timeout for the LLM call in seconds.
|
|
269
|
+
max_tokens: z.number().optional().describe("Maximum tokens in the LLM response. Optional — uses the provider's default when not set. Unset (0) is valid: proto3 implicit presence makes an omitted field indistinguishable from 0, so the range rule must not fire on it (#673)."),
|
|
270
|
+
timeout: z.number().optional().describe("Timeout for the LLM call in seconds. Max: 600 (10 minutes). Optional — unset (0) leaves the call bounded by the runner's activity timeout. NOTE: an explicit value is accepted but not yet applied by the runner; the activity timeout governs either way. Unset (0) is valid: proto3 implicit presence makes an omitted field indistinguishable from 0, so the range rule must not fire on it (#673)."),
|
|
271
271
|
on_invalid: z.string().optional().describe("Policy when the LLM response fails schema validation. Only meaningful when response_schema is set; ignored otherwise. Default: ON_INVALID_FAIL (task fails immediately). Allowed values: ON_INVALID_FAIL, ON_INVALID_RETRY, ON_INVALID_FALLBACK."),
|
|
272
|
-
max_retries: z.number().optional().describe("Maximum schema-validation retry attempts when on_invalid is ON_INVALID_RETRY. Each retry re-prompts the LLM with the validation errors and expected schema, giving it an opportunity to self-correct. Only meaningful when on_invalid is ON_INVALID_RETRY; ignored otherwise.
|
|
272
|
+
max_retries: z.number().optional().describe("Maximum schema-validation retry attempts when on_invalid is ON_INVALID_RETRY. Each retry re-prompts the LLM with the validation errors and expected schema, giving it an opportunity to self-correct. Only meaningful when on_invalid is ON_INVALID_RETRY; ignored otherwise. Valid range when set: 1-5. Unset (0) is valid: proto3 implicit presence makes an omitted field indistinguishable from 0, so the range rule must not fire on it (#673)."),
|
|
273
273
|
fallback_task: z.string().optional().describe("Target task to branch to when schema validation cannot be resolved. Used in two scenarios: 1. on_invalid is ON_INVALID_RETRY and all retries are exhausted 2. on_invalid is ON_INVALID_FALLBACK (immediate branch, no retry) Must reference a valid task name in the same workflow. When empty and retries are exhausted, the task fails."),
|
|
274
274
|
max_cost_micros: z.union([z.number(), z.string()]).optional().describe("Per-task cost cap in micro-USD (1 USD = 1,000,000 micros). When set, the runtime terminates this specific LLM call if its cost exceeds this limit, independent of the workflow-level budget. The runtime checks both: per-task limit first, then workflow remaining budget. Optional — when 0, no per-task cost limit is enforced. @since T05 (Workflow-Level Budget Primitives)"),
|
|
275
275
|
max_total_tokens: z.union([z.number(), z.string()]).optional().describe("Per-task token cap (input + output tokens combined). When set, the runtime terminates this specific LLM call if total tokens exceed this limit. Complements max_tokens (field 6), which limits only the output token count as a generation parameter. Optional — when 0, no per-task total token limit is enforced. @since T05 (Workflow-Level Budget Primitives)"),
|
|
@@ -68,6 +68,21 @@ afterAll(async () => {
|
|
|
68
68
|
|
|
69
69
|
const base = () => `http://127.0.0.1:${port}`;
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Every refusal must be a JSON-RPC error object with Content-Type
|
|
73
|
+
* application/json (oss#316 — strict MCP clients parse the body; text/plain
|
|
74
|
+
* surfaced as opaque content-type errors). Returns the error for
|
|
75
|
+
* code-specific assertions.
|
|
76
|
+
*/
|
|
77
|
+
async function expectJsonRpcError(res: Response): Promise<{ code: number; message: string }> {
|
|
78
|
+
expect(res.headers.get("content-type")).toBe("application/json");
|
|
79
|
+
const body = (await res.json()) as { jsonrpc: string; error: { code: number; message: string }; id: null };
|
|
80
|
+
expect(body.jsonrpc).toBe("2.0");
|
|
81
|
+
expect(body.id).toBeNull();
|
|
82
|
+
expect(typeof body.error.code).toBe("number");
|
|
83
|
+
return body.error;
|
|
84
|
+
}
|
|
85
|
+
|
|
71
86
|
describe("HTTP transport hardening + OAuth discovery", () => {
|
|
72
87
|
it("answers the /health probe without auth", async () => {
|
|
73
88
|
const res = await fetch(`${base()}/health`);
|
|
@@ -75,6 +90,16 @@ describe("HTTP transport hardening + OAuth discovery", () => {
|
|
|
75
90
|
expect(await res.json()).toEqual({ status: "ok" });
|
|
76
91
|
});
|
|
77
92
|
|
|
93
|
+
it("reports unready on /ready when the backend hop is down (no auth required)", async () => {
|
|
94
|
+
// The suite's backend address points at nothing — exactly the failure
|
|
95
|
+
// class /ready exists to expose while /health stays green (oss#316).
|
|
96
|
+
const res = await fetch(`${base()}/ready`);
|
|
97
|
+
expect(res.status).toBe(503);
|
|
98
|
+
const body = (await res.json()) as { status: string; reason?: string };
|
|
99
|
+
expect(body.status).toBe("unready");
|
|
100
|
+
expect(body.reason).toContain("backend health check failed");
|
|
101
|
+
});
|
|
102
|
+
|
|
78
103
|
it("serves RFC 9728 protected resource metadata", async () => {
|
|
79
104
|
const res = await fetch(`${base()}/.well-known/oauth-protected-resource`);
|
|
80
105
|
expect(res.status).toBe(200);
|
|
@@ -95,7 +120,7 @@ describe("HTTP transport hardening + OAuth discovery", () => {
|
|
|
95
120
|
expect(res.headers.get("access-control-allow-methods")).toContain("GET");
|
|
96
121
|
});
|
|
97
122
|
|
|
98
|
-
it("challenges token-less requests with WWW-Authenticate", async () => {
|
|
123
|
+
it("challenges token-less requests with WWW-Authenticate and a JSON-RPC body", async () => {
|
|
99
124
|
const res = await fetch(`${base()}/`, { method: "POST", body: "{}" });
|
|
100
125
|
expect(res.status).toBe(401);
|
|
101
126
|
const challenge = res.headers.get("www-authenticate") ?? "";
|
|
@@ -104,6 +129,9 @@ describe("HTTP transport hardening + OAuth discovery", () => {
|
|
|
104
129
|
'resource_metadata="https://mcp.stigmer.ai/.well-known/oauth-protected-resource"',
|
|
105
130
|
);
|
|
106
131
|
expect(challenge).toContain('scope="read write"');
|
|
132
|
+
const error = await expectJsonRpcError(res);
|
|
133
|
+
expect(error.code).toBe(-32000);
|
|
134
|
+
expect(error.message).toContain("missing or malformed Authorization");
|
|
107
135
|
});
|
|
108
136
|
|
|
109
137
|
it("rejects a malformed Authorization header as token-less", async () => {
|
|
@@ -115,16 +143,22 @@ describe("HTTP transport hardening + OAuth discovery", () => {
|
|
|
115
143
|
});
|
|
116
144
|
expect(res.status).toBe(401);
|
|
117
145
|
expect(res.headers.get("www-authenticate") ?? "").toContain('realm="stigmer"');
|
|
146
|
+
await expectJsonRpcError(res);
|
|
118
147
|
});
|
|
119
148
|
|
|
120
|
-
it("returns
|
|
149
|
+
it("returns the SDK's session-not-found shape (404, code -32001) for an unknown session", async () => {
|
|
150
|
+
// -32001 on a 404 is the streamable-HTTP recovery signal: on it a
|
|
151
|
+
// conformant client MUST open a new session with a fresh initialize —
|
|
152
|
+
// how clients survive the bridge's in-memory sessions dying on restart.
|
|
121
153
|
const res = await fetch(`${base()}/`, {
|
|
122
154
|
method: "POST",
|
|
123
155
|
headers: { authorization: "Bearer test-token", "mcp-session-id": "does-not-exist" },
|
|
124
156
|
body: "{}",
|
|
125
157
|
});
|
|
126
158
|
expect(res.status).toBe(404);
|
|
127
|
-
|
|
159
|
+
const error = await expectJsonRpcError(res);
|
|
160
|
+
expect(error.code).toBe(-32001);
|
|
161
|
+
expect(error.message).toContain("unknown or expired MCP session");
|
|
128
162
|
});
|
|
129
163
|
|
|
130
164
|
it("rejects a sessionless non-initialize POST", async () => {
|
|
@@ -134,7 +168,9 @@ describe("HTTP transport hardening + OAuth discovery", () => {
|
|
|
134
168
|
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/list" }),
|
|
135
169
|
});
|
|
136
170
|
expect(res.status).toBe(400);
|
|
137
|
-
|
|
171
|
+
const error = await expectJsonRpcError(res);
|
|
172
|
+
expect(error.code).toBe(-32000);
|
|
173
|
+
expect(error.message).toContain("an initialize request is required");
|
|
138
174
|
});
|
|
139
175
|
|
|
140
176
|
it("rejects a sessionless GET (no Mcp-Session-Id)", async () => {
|
|
@@ -143,7 +179,9 @@ describe("HTTP transport hardening + OAuth discovery", () => {
|
|
|
143
179
|
headers: { authorization: "Bearer test-token" },
|
|
144
180
|
});
|
|
145
181
|
expect(res.status).toBe(400);
|
|
146
|
-
|
|
182
|
+
const error = await expectJsonRpcError(res);
|
|
183
|
+
expect(error.code).toBe(-32000);
|
|
184
|
+
expect(error.message).toContain("Mcp-Session-Id header is required");
|
|
147
185
|
});
|
|
148
186
|
});
|
|
149
187
|
|
|
@@ -189,6 +227,8 @@ describe("HTTP route dispatch (the closed route table)", () => {
|
|
|
189
227
|
// except the send tool its attachment existed for.
|
|
190
228
|
const res = await initialize("/no-such-roster");
|
|
191
229
|
expect(res.status).toBe(404);
|
|
192
|
-
|
|
230
|
+
const error = await expectJsonRpcError(res);
|
|
231
|
+
expect(error.code).toBe(-32000);
|
|
232
|
+
expect(error.message).toContain("unknown MCP route: /no-such-roster");
|
|
193
233
|
});
|
|
194
234
|
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// Unit tests for the cached readiness check (oss#316). The backend RPC is
|
|
2
|
+
// injected, so caching, in-flight dedupe, and verdict propagation are pinned
|
|
3
|
+
// without a live gRPC server; the /ready route's wiring (including the real
|
|
4
|
+
// checkBackendHealth against a dead backend) is covered by
|
|
5
|
+
// http.integration.test.ts.
|
|
6
|
+
|
|
7
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
createReadinessCheck,
|
|
11
|
+
READINESS_CACHE_TTL_MS,
|
|
12
|
+
type ReadinessResult,
|
|
13
|
+
} from "./readiness";
|
|
14
|
+
|
|
15
|
+
const READY: ReadinessResult = { ready: true };
|
|
16
|
+
const UNREADY: ReadinessResult = { ready: false, reason: "backend health status: NOT_SERVING" };
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
vi.useFakeTimers();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
vi.useRealTimers();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe("createReadinessCheck", () => {
|
|
27
|
+
it("propagates the ready verdict", async () => {
|
|
28
|
+
const check = createReadinessCheck("addr", async () => READY);
|
|
29
|
+
await expect(check()).resolves.toEqual({ ready: true });
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("propagates the unready verdict with its reason", async () => {
|
|
33
|
+
const check = createReadinessCheck("addr", async () => UNREADY);
|
|
34
|
+
await expect(check()).resolves.toEqual(UNREADY);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("serves cached verdicts within the TTL without re-dialing", async () => {
|
|
38
|
+
const probe = vi.fn(async () => READY);
|
|
39
|
+
const check = createReadinessCheck("addr", probe);
|
|
40
|
+
await check();
|
|
41
|
+
vi.advanceTimersByTime(READINESS_CACHE_TTL_MS - 1);
|
|
42
|
+
await check();
|
|
43
|
+
expect(probe).toHaveBeenCalledTimes(1);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("re-checks after the TTL expires", async () => {
|
|
47
|
+
const probe = vi.fn(async () => READY);
|
|
48
|
+
const check = createReadinessCheck("addr", probe);
|
|
49
|
+
await check();
|
|
50
|
+
vi.advanceTimersByTime(READINESS_CACHE_TTL_MS + 1);
|
|
51
|
+
await check();
|
|
52
|
+
expect(probe).toHaveBeenCalledTimes(2);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("recovers: an unready verdict is replaced by a ready one after the TTL", async () => {
|
|
56
|
+
const probe = vi
|
|
57
|
+
.fn<() => Promise<ReadinessResult>>()
|
|
58
|
+
.mockResolvedValueOnce(UNREADY)
|
|
59
|
+
.mockResolvedValueOnce(READY);
|
|
60
|
+
const check = createReadinessCheck("addr", probe);
|
|
61
|
+
await expect(check()).resolves.toEqual(UNREADY);
|
|
62
|
+
vi.advanceTimersByTime(READINESS_CACHE_TTL_MS + 1);
|
|
63
|
+
await expect(check()).resolves.toEqual({ ready: true });
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("shares one in-flight RPC across concurrent callers", async () => {
|
|
67
|
+
let resolveProbe!: (r: ReadinessResult) => void;
|
|
68
|
+
const probe = vi.fn(
|
|
69
|
+
() => new Promise<ReadinessResult>((resolve) => (resolveProbe = resolve)),
|
|
70
|
+
);
|
|
71
|
+
const check = createReadinessCheck("addr", probe);
|
|
72
|
+
|
|
73
|
+
const first = check();
|
|
74
|
+
const second = check();
|
|
75
|
+
resolveProbe(READY);
|
|
76
|
+
|
|
77
|
+
await expect(first).resolves.toEqual({ ready: true });
|
|
78
|
+
await expect(second).resolves.toEqual({ ready: true });
|
|
79
|
+
expect(probe).toHaveBeenCalledTimes(1);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("passes the configured backend address to the probe", async () => {
|
|
83
|
+
const probe = vi.fn(async (addr: string) => {
|
|
84
|
+
expect(addr).toBe("backend:50051");
|
|
85
|
+
return READY;
|
|
86
|
+
});
|
|
87
|
+
await createReadinessCheck("backend:50051", probe)();
|
|
88
|
+
expect(probe).toHaveBeenCalledWith("backend:50051");
|
|
89
|
+
});
|
|
90
|
+
});
|
package/src/readiness.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Backend-hop readiness probe (stigmer/stigmer#316).
|
|
2
|
+
//
|
|
3
|
+
// /health reports process liveness only, which left a total backend-hop
|
|
4
|
+
// failure invisible: the bridge once spoke gRPC-web to a backend that only
|
|
5
|
+
// accepts native gRPC, every tool call failed for weeks, and all three
|
|
6
|
+
// Kubernetes probes stayed green. Readiness must therefore exercise the
|
|
7
|
+
// actual hop — transport, content-type, listener — with one cheap RPC.
|
|
8
|
+
//
|
|
9
|
+
// The probe RPC is grpc.health.v1.Health/Check: the one backend call both
|
|
10
|
+
// editions serve credential-free by design (the Go server sets it SERVING
|
|
11
|
+
// before its network listener opens; the cloud Java interceptors exempt
|
|
12
|
+
// "grpc.health.v1.Health" by name — "probes and tooling carry no bearer").
|
|
13
|
+
// The hosted bridge holds no startup credential (per-request Bearer
|
|
14
|
+
// passthrough only), so an authenticated probe is not an option.
|
|
15
|
+
//
|
|
16
|
+
// Only the READINESS probe should point here. Liveness and startup must stay
|
|
17
|
+
// on /health: readiness failure drains traffic (correct for a backend
|
|
18
|
+
// outage), while liveness/startup failures restart the pod — a restart loop
|
|
19
|
+
// that cannot fix a broken backend and destroys every live MCP session.
|
|
20
|
+
|
|
21
|
+
import { createClient } from "@connectrpc/connect";
|
|
22
|
+
import { Health, HealthCheckResponse_ServingStatus } from "@stigmer/protos/grpc/health/v1/health_pb";
|
|
23
|
+
import { transportForToken } from "./domains/client.js";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Per-check RPC bound. Deliberately below the probe's HTTP timeout in the
|
|
27
|
+
* deployment overlay (5 s) so a hung backend yields a clean 503 with a
|
|
28
|
+
* reason, never a probe-level timeout that hides it.
|
|
29
|
+
*/
|
|
30
|
+
export const READINESS_RPC_TIMEOUT_MS = 4_000;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* How long a verdict is served without re-dialing the backend. Bounds probe
|
|
34
|
+
* (and operator curl) traffic to at most one backend RPC per window without
|
|
35
|
+
* meaningfully delaying either transition: at the overlay's 10 s readiness
|
|
36
|
+
* period, every scheduled probe still lands on a fresh check.
|
|
37
|
+
*/
|
|
38
|
+
export const READINESS_CACHE_TTL_MS = 5_000;
|
|
39
|
+
|
|
40
|
+
export interface ReadinessResult {
|
|
41
|
+
ready: boolean;
|
|
42
|
+
/** Human-readable cause when not ready; surfaced in the 503 body. */
|
|
43
|
+
reason?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Checks the backend hop once; see {@link createReadinessCheck} for caching. */
|
|
47
|
+
export async function checkBackendHealth(serverAddress: string): Promise<ReadinessResult> {
|
|
48
|
+
const client = createClient(Health, transportForToken(serverAddress, ""));
|
|
49
|
+
try {
|
|
50
|
+
const res = await client.check({}, { timeoutMs: READINESS_RPC_TIMEOUT_MS });
|
|
51
|
+
if (res.status === HealthCheckResponse_ServingStatus.SERVING) {
|
|
52
|
+
return { ready: true };
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
ready: false,
|
|
56
|
+
reason: `backend health status: ${HealthCheckResponse_ServingStatus[res.status] ?? res.status}`,
|
|
57
|
+
};
|
|
58
|
+
} catch (err) {
|
|
59
|
+
return {
|
|
60
|
+
ready: false,
|
|
61
|
+
reason: `backend health check failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Build the cached readiness check used by the /ready route: verdicts are
|
|
68
|
+
* reused for {@link READINESS_CACHE_TTL_MS} and concurrent callers share one
|
|
69
|
+
* in-flight RPC, so probe pressure can never amplify into backend pressure.
|
|
70
|
+
*/
|
|
71
|
+
export function createReadinessCheck(
|
|
72
|
+
serverAddress: string,
|
|
73
|
+
check: (addr: string) => Promise<ReadinessResult> = checkBackendHealth,
|
|
74
|
+
): () => Promise<ReadinessResult> {
|
|
75
|
+
let cached: { result: ReadinessResult; at: number } | undefined;
|
|
76
|
+
let inFlight: Promise<ReadinessResult> | undefined;
|
|
77
|
+
|
|
78
|
+
return async () => {
|
|
79
|
+
if (cached !== undefined && Date.now() - cached.at < READINESS_CACHE_TTL_MS) {
|
|
80
|
+
return cached.result;
|
|
81
|
+
}
|
|
82
|
+
if (inFlight === undefined) {
|
|
83
|
+
inFlight = check(serverAddress)
|
|
84
|
+
.then((result) => {
|
|
85
|
+
cached = { result, at: Date.now() };
|
|
86
|
+
return result;
|
|
87
|
+
})
|
|
88
|
+
.finally(() => {
|
|
89
|
+
inFlight = undefined;
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return inFlight;
|
|
93
|
+
};
|
|
94
|
+
}
|