@brainervirus/workit-mcp 1.0.9 → 1.0.11
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 +359 -222
- package/package.json +2 -2
- package/src/server.ts +51 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit shared MCP transport for the eight task and policy operation families",
|
|
6
6
|
"keywords": [
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"build": "bun scripts/build.ts"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@brainervirus/workit-core": "^1.0.
|
|
45
|
+
"@brainervirus/workit-core": "^1.0.11",
|
|
46
46
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
47
47
|
"zod": "4.5.4"
|
|
48
48
|
},
|
package/src/server.ts
CHANGED
|
@@ -133,6 +133,46 @@ const toolInputSchema = (family: OperationFamily) => {
|
|
|
133
133
|
return { type: "object" as const, ...schema };
|
|
134
134
|
};
|
|
135
135
|
|
|
136
|
+
const schemaBranches = (schema: Record<string, unknown>): unknown[] =>
|
|
137
|
+
Array.isArray(schema.oneOf)
|
|
138
|
+
? schema.oneOf
|
|
139
|
+
: Array.isArray(schema.anyOf)
|
|
140
|
+
? schema.anyOf
|
|
141
|
+
: [schema];
|
|
142
|
+
|
|
143
|
+
const readOnlyBranches = (family: OperationFamily): unknown[] =>
|
|
144
|
+
schemaBranches(boundedOperationJsonSchema(family) as Record<string, unknown>).filter((branch) => {
|
|
145
|
+
const action = (branch as { properties?: { action?: { const?: unknown } } }).properties?.action
|
|
146
|
+
?.const;
|
|
147
|
+
return typeof action === "string" && READ_ONLY_ACTIONS.has(action);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
/** Attested callers (host sessions that can mutate) see the full family union;
|
|
151
|
+
* unattested MCP callers see only read-only actions, and families with no
|
|
152
|
+
* read-only action are not advertised as callable tools at all. */
|
|
153
|
+
export const advertisedToolSchemas = (
|
|
154
|
+
attested: boolean,
|
|
155
|
+
): { name: string; description: string; inputSchema: Record<string, unknown> }[] => {
|
|
156
|
+
if (attested)
|
|
157
|
+
return OPERATION_FAMILIES.map((family) => ({
|
|
158
|
+
name: `workit_${family}`,
|
|
159
|
+
description: operationDescription(family),
|
|
160
|
+
inputSchema: toolInputSchema(family),
|
|
161
|
+
}));
|
|
162
|
+
return OPERATION_FAMILIES.flatMap((family) => {
|
|
163
|
+
const branches = readOnlyBranches(family);
|
|
164
|
+
if (!branches.length) return [];
|
|
165
|
+
const schema = boundedOperationJsonSchema(family) as Record<string, unknown>;
|
|
166
|
+
return [
|
|
167
|
+
{
|
|
168
|
+
name: `workit_${family}`,
|
|
169
|
+
description: `${operationDescription(family)} Unattested MCP callers can only run read-only actions; mutating operations require an attested host session.`,
|
|
170
|
+
inputSchema: { type: "object" as const, ...schema, oneOf: branches },
|
|
171
|
+
},
|
|
172
|
+
];
|
|
173
|
+
});
|
|
174
|
+
};
|
|
175
|
+
|
|
136
176
|
const sanitizeFailure = (result: Result<unknown>, workspaceRoot?: string): Result<unknown> => {
|
|
137
177
|
if (result.ok) return result;
|
|
138
178
|
const sanitize = (value: unknown): unknown => {
|
|
@@ -198,13 +238,16 @@ export function createMcpServer(host: McpHost, contextProvider: NativeContextPro
|
|
|
198
238
|
{ capabilities: { tools: {}, resources: {} } },
|
|
199
239
|
);
|
|
200
240
|
|
|
201
|
-
server.setRequestHandler(ListToolsRequestSchema, async () =>
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
|
|
241
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
242
|
+
let attested = false;
|
|
243
|
+
try {
|
|
244
|
+
const context = await contextProvider.current();
|
|
245
|
+
attested = context.callerAttested === true;
|
|
246
|
+
} catch {
|
|
247
|
+
attested = false;
|
|
248
|
+
}
|
|
249
|
+
return { tools: advertisedToolSchemas(attested) };
|
|
250
|
+
});
|
|
208
251
|
|
|
209
252
|
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
|
210
253
|
resources: CONTEXT_KINDS.map((kind) => ({
|
|
@@ -338,7 +381,7 @@ export function createMcpServer(host: McpHost, contextProvider: NativeContextPro
|
|
|
338
381
|
}
|
|
339
382
|
const parsed = parseOperation(family, request.params.arguments);
|
|
340
383
|
if (!parsed.ok) return resultForClient(parsed, workspaceRoot);
|
|
341
|
-
if (context.callerAttested
|
|
384
|
+
if (context.callerAttested !== true && requiresCallerIdentity(parsed.data))
|
|
342
385
|
return resultForClient(
|
|
343
386
|
{
|
|
344
387
|
ok: false,
|