@stigmer/mcp-server 3.2.2 → 3.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.
- package/cli/mcp-server-stigmer.js +9 -9
- package/config.d.ts +12 -0
- package/config.d.ts.map +1 -1
- package/config.js +5 -0
- package/config.js.map +1 -1
- package/domains/records/calls.d.ts +48 -0
- package/domains/records/calls.d.ts.map +1 -0
- package/domains/records/calls.js +118 -0
- package/domains/records/calls.js.map +1 -0
- package/domains/records/errors.d.ts +24 -0
- package/domains/records/errors.d.ts.map +1 -0
- package/domains/records/errors.js +79 -0
- package/domains/records/errors.js.map +1 -0
- package/domains/records/tools.d.ts +7 -0
- package/domains/records/tools.d.ts.map +1 -0
- package/domains/records/tools.js +135 -0
- package/domains/records/tools.js.map +1 -0
- package/gen/agent.d.ts +56 -0
- package/gen/agent.d.ts.map +1 -1
- package/gen/agent.js +24 -1
- package/gen/agent.js.map +1 -1
- package/gen/workflow.d.ts +4 -4
- package/gen/workflow.js +1 -1
- package/gen/workflow.js.map +1 -1
- package/index.d.ts +2 -2
- package/index.d.ts.map +1 -1
- package/index.js +4 -4
- package/index.js.map +1 -1
- package/package.json +3 -3
- package/server.d.ts +31 -1
- package/server.d.ts.map +1 -1
- package/server.js +41 -3
- package/server.js.map +1 -1
- package/src/config.ts +19 -0
- package/src/domains/records/calls.ts +209 -0
- package/src/domains/records/errors.ts +98 -0
- package/src/domains/records/records.integration.test.ts +313 -0
- package/src/domains/records/tools.ts +206 -0
- package/src/gen/agent.ts +28 -1
- package/src/gen/workflow.ts +1 -1
- package/src/http.integration.test.ts +1 -0
- package/src/index.ts +12 -5
- package/src/server.ts +59 -5
package/src/server.ts
CHANGED
|
@@ -24,6 +24,7 @@ import { registerAgentTools } from "./domains/agents/tools.js";
|
|
|
24
24
|
import type { BackendTarget } from "./domains/client.js";
|
|
25
25
|
import { registerMcpServerResources } from "./domains/mcpservers/resources.js";
|
|
26
26
|
import { registerMcpServerTools } from "./domains/mcpservers/tools.js";
|
|
27
|
+
import { registerRecordTools } from "./domains/records/tools.js";
|
|
27
28
|
import { registerSearchTools } from "./domains/search/tools.js";
|
|
28
29
|
import { registerSkillResources } from "./domains/skills/resources.js";
|
|
29
30
|
import { registerSkillTools } from "./domains/skills/tools.js";
|
|
@@ -60,6 +61,22 @@ export function createServer(target: BackendTarget): McpServer {
|
|
|
60
61
|
return server;
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Build a records-only MCP server: the five record tools with the
|
|
66
|
+
* agent-facing argument surface, and nothing else (T05 R1). This is
|
|
67
|
+
* the roster the runner-synthesized datastore attachment connects to —
|
|
68
|
+
* a structural guarantee that an agent session never sees the
|
|
69
|
+
* management tools (apply/delete/…) its empty approval maps would make
|
|
70
|
+
* approval-free. Served on the /records HTTP route and as the stdio
|
|
71
|
+
* roster when STIGMER_MCP_ROSTER=records.
|
|
72
|
+
*/
|
|
73
|
+
export function createRecordsServer(target: BackendTarget): McpServer {
|
|
74
|
+
const server = new McpServer({ name: "mcp-server-stigmer-records", version: SERVER_VERSION });
|
|
75
|
+
const tools = registerRecordTools(server, target, "agent");
|
|
76
|
+
log.info("tools registered (records roster)", { count: tools.length, tools });
|
|
77
|
+
return server;
|
|
78
|
+
}
|
|
79
|
+
|
|
63
80
|
/**
|
|
64
81
|
* Wire up every domain's tools. Each domain returns the names it registered so
|
|
65
82
|
* the startup log's count and roster cannot drift from what is actually wired,
|
|
@@ -75,6 +92,10 @@ function registerTools(server: McpServer, target: BackendTarget): void {
|
|
|
75
92
|
...registerValidateWorkflowYamlTool(server, target),
|
|
76
93
|
...registerTaskKindTools(server, target),
|
|
77
94
|
...registerWorkflowExecutionTools(server, target),
|
|
95
|
+
// The record tools also serve external MCP clients — as direct
|
|
96
|
+
// principals with the org argument and honest annotations (the
|
|
97
|
+
// agent-facing variant lives on the records-only roster).
|
|
98
|
+
...registerRecordTools(server, target, "direct"),
|
|
78
99
|
];
|
|
79
100
|
log.info("tools registered", { count: tools.length, tools });
|
|
80
101
|
}
|
|
@@ -123,6 +144,25 @@ export async function serveStdio(server: McpServer, signal: AbortSignal): Promis
|
|
|
123
144
|
/** Builds a fresh, fully-registered server. One is created per MCP session. */
|
|
124
145
|
export type ServerFactory = () => McpServer;
|
|
125
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Builds the server for an inbound HTTP `initialize` request, selected
|
|
149
|
+
* by request path. Only the initialize request consults the path — an
|
|
150
|
+
* established session's transport already carries the server it was
|
|
151
|
+
* built with, so follow-up requests dispatch by Mcp-Session-Id alone.
|
|
152
|
+
*/
|
|
153
|
+
export type RouteServerFactory = (path: string) => McpServer;
|
|
154
|
+
|
|
155
|
+
/** HTTP route serving the records-only roster (T05 R1). */
|
|
156
|
+
export const RECORDS_ROUTE = "/records";
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* The standard HTTP route dispatch: the records-only roster on
|
|
160
|
+
* {@link RECORDS_ROUTE}, the full roster everywhere else.
|
|
161
|
+
*/
|
|
162
|
+
export function routedServerFactory(target: BackendTarget): RouteServerFactory {
|
|
163
|
+
return (path) => (path === RECORDS_ROUTE ? createRecordsServer(target) : createServer(target));
|
|
164
|
+
}
|
|
165
|
+
|
|
126
166
|
/**
|
|
127
167
|
* Serve over Streamable HTTP until `signal` aborts.
|
|
128
168
|
*
|
|
@@ -144,7 +184,11 @@ export type ServerFactory = () => McpServer;
|
|
|
144
184
|
* DNS-rebinding allow-lists are intentionally out of parity scope (the Go server
|
|
145
185
|
* has none).
|
|
146
186
|
*/
|
|
147
|
-
export async function serveHttp(
|
|
187
|
+
export async function serveHttp(
|
|
188
|
+
makeServer: RouteServerFactory,
|
|
189
|
+
cfg: Config,
|
|
190
|
+
signal: AbortSignal,
|
|
191
|
+
): Promise<void> {
|
|
148
192
|
const sessions = new Map<string, StreamableHTTPServerTransport>();
|
|
149
193
|
|
|
150
194
|
const httpServer = createHttpServer((req, res) => {
|
|
@@ -189,8 +233,8 @@ export async function serveBoth(target: BackendTarget, cfg: Config, signal: Abor
|
|
|
189
233
|
signal.addEventListener("abort", onParentAbort, { once: true });
|
|
190
234
|
|
|
191
235
|
const tasks = [
|
|
192
|
-
serveStdio(
|
|
193
|
-
serveHttp((
|
|
236
|
+
serveStdio(stdioServer(target, cfg), linked.signal),
|
|
237
|
+
serveHttp(routedServerFactory(target), cfg, linked.signal),
|
|
194
238
|
];
|
|
195
239
|
|
|
196
240
|
try {
|
|
@@ -215,7 +259,7 @@ async function routeRequest(
|
|
|
215
259
|
req: IncomingMessage & { auth?: AuthInfo },
|
|
216
260
|
res: ServerResponse,
|
|
217
261
|
sessions: Map<string, StreamableHTTPServerTransport>,
|
|
218
|
-
makeServer:
|
|
262
|
+
makeServer: RouteServerFactory,
|
|
219
263
|
cfg: Config,
|
|
220
264
|
): Promise<void> {
|
|
221
265
|
if (req.method === "GET" && req.url === "/health") {
|
|
@@ -247,6 +291,7 @@ async function routeRequest(
|
|
|
247
291
|
req.auth = { token, clientId: "stigmer-mcp-passthrough", scopes: [] };
|
|
248
292
|
}
|
|
249
293
|
|
|
294
|
+
const path = requestPath(req);
|
|
250
295
|
const sessionId = headerValue(req, "mcp-session-id");
|
|
251
296
|
|
|
252
297
|
// Established session → dispatch to its transport.
|
|
@@ -288,10 +333,19 @@ async function routeRequest(
|
|
|
288
333
|
if (transport.sessionId !== undefined) sessions.delete(transport.sessionId);
|
|
289
334
|
};
|
|
290
335
|
|
|
291
|
-
await makeServer().connect(transport);
|
|
336
|
+
await makeServer(path).connect(transport);
|
|
292
337
|
await transport.handleRequest(req, res, body);
|
|
293
338
|
}
|
|
294
339
|
|
|
340
|
+
/**
|
|
341
|
+
* The stdio server for the configured roster: the records-only roster
|
|
342
|
+
* when STIGMER_MCP_ROSTER=records (what the OSS runner-synthesized
|
|
343
|
+
* datastore attachment spawns), the full roster otherwise.
|
|
344
|
+
*/
|
|
345
|
+
export function stdioServer(target: BackendTarget, cfg: Config): McpServer {
|
|
346
|
+
return cfg.roster === "records" ? createRecordsServer(target) : createServer(target);
|
|
347
|
+
}
|
|
348
|
+
|
|
295
349
|
/** Return a single header value, collapsing the array form Node may produce. */
|
|
296
350
|
function headerValue(req: IncomingMessage, name: string): string | undefined {
|
|
297
351
|
const v = req.headers[name];
|