@longtable/mcp 0.1.47 → 0.1.48
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/server.js +155 -9
- package/package.json +7 -7
package/dist/server.js
CHANGED
|
@@ -11,7 +11,7 @@ import { classifyCheckpointTrigger } from "@longtable/checkpoints";
|
|
|
11
11
|
import { renderQuestionRecordInput } from "@longtable/provider-claude";
|
|
12
12
|
import { renderQuestionRecordPrompt } from "@longtable/provider-codex";
|
|
13
13
|
import { loadSetupOutput } from "@longtable/setup";
|
|
14
|
-
import { answerWorkspaceQuestion, clearWorkspaceQuestion, createOrUpdateProjectWorkspace, createWorkspaceQuestion, inspectProjectWorkspace, loadProjectContextFromDirectory, loadWorkspaceState, syncCurrentWorkspaceView } from "@longtable/cli";
|
|
14
|
+
import { answerWorkspaceQuestion, applyResearchSpecificationAuditUpdate, applyResearchSpecificationPatch, clearWorkspaceQuestion, createOrUpdateProjectWorkspace, createWorkspaceQuestion, diffResearchSpecifications, findUnincorporatedResearchEvidence, inspectProjectWorkspace, loadProjectContextFromDirectory, loadWorkspaceState, proposeResearchSpecificationPatch, readResearchSpecificationHistory, syncCurrentWorkspaceView } from "@longtable/cli";
|
|
15
15
|
import { buildFirstResearchShapeQuestion, firstResearchShapeAnswerConfirms, firstResearchShapeAnswerStatus } from "./first-research-shape.js";
|
|
16
16
|
import { buildResearchSpecificationQuestion, renderResearchSpecificationPreview, researchSpecificationAnswerConfirms, researchSpecificationAnswerNeedsFollowUp, researchSpecificationAnswerStatus } from "./research-specification.js";
|
|
17
17
|
const SERVER_NAME = "longtable-state";
|
|
@@ -27,6 +27,11 @@ const TOOL_NAMES = [
|
|
|
27
27
|
"summarize_interview",
|
|
28
28
|
"summarize_research_specification",
|
|
29
29
|
"read_research_specification",
|
|
30
|
+
"propose_research_spec_patch",
|
|
31
|
+
"apply_research_spec_patch",
|
|
32
|
+
"diff_research_specification",
|
|
33
|
+
"read_research_spec_history",
|
|
34
|
+
"find_unincorporated_evidence",
|
|
30
35
|
"cancel_interview",
|
|
31
36
|
"confirm_first_research_shape",
|
|
32
37
|
"confirm_research_specification",
|
|
@@ -83,6 +88,9 @@ const researchSpecificationSchema = z.object({
|
|
|
83
88
|
createdAt: z.string().optional(),
|
|
84
89
|
updatedAt: z.string().optional(),
|
|
85
90
|
sourceHookId: z.string().optional(),
|
|
91
|
+
latestRevisionId: z.string().optional(),
|
|
92
|
+
sourceEvidenceIds: z.array(z.string()).optional(),
|
|
93
|
+
sectionEvidence: z.record(z.string(), z.array(z.string())).optional(),
|
|
86
94
|
researchDirection: z.object({
|
|
87
95
|
question: z.string().optional(),
|
|
88
96
|
purpose: z.string().min(1),
|
|
@@ -129,6 +137,15 @@ const researchSpecificationSchema = z.object({
|
|
|
129
137
|
confidence: z.enum(["low", "medium", "high"]).default("medium"),
|
|
130
138
|
confirmedAt: z.string().optional()
|
|
131
139
|
});
|
|
140
|
+
const researchSpecificationPatchSourceSchema = z.enum([
|
|
141
|
+
"interview",
|
|
142
|
+
"panel",
|
|
143
|
+
"critic",
|
|
144
|
+
"reviewer",
|
|
145
|
+
"decision",
|
|
146
|
+
"manual",
|
|
147
|
+
"system"
|
|
148
|
+
]);
|
|
132
149
|
function textResult(structuredContent) {
|
|
133
150
|
return {
|
|
134
151
|
content: [
|
|
@@ -839,11 +856,6 @@ async function markResearchSpecificationConfirmation(context, specification, ans
|
|
|
839
856
|
status: researchSpecificationAnswerStatus(answer) === "deferred" ? "deferred" : "draft",
|
|
840
857
|
updatedAt: timestamp
|
|
841
858
|
};
|
|
842
|
-
state.researchSpecification = confirmedSpecification;
|
|
843
|
-
state.workingState = {
|
|
844
|
-
...state.workingState,
|
|
845
|
-
researchSpecification: confirmedSpecification
|
|
846
|
-
};
|
|
847
859
|
state.hooks = (state.hooks ?? []).map((hook) => {
|
|
848
860
|
if (hook.id !== specification.sourceHookId || !isInterviewHookRun(hook)) {
|
|
849
861
|
return hook;
|
|
@@ -861,19 +873,33 @@ async function markResearchSpecificationConfirmation(context, specification, ans
|
|
|
861
873
|
: hook.linkedDecisionRecordIds
|
|
862
874
|
};
|
|
863
875
|
});
|
|
876
|
+
const sourceEvidenceIds = (state.evidenceRecords ?? [])
|
|
877
|
+
.filter((record) => record.sourceHookId && record.sourceHookId === specification.sourceHookId)
|
|
878
|
+
.map((record) => record.id);
|
|
879
|
+
const audited = applyResearchSpecificationAuditUpdate(state, {
|
|
880
|
+
specification: confirmedSpecification,
|
|
881
|
+
timestamp,
|
|
882
|
+
source: "decision",
|
|
883
|
+
title: `Research Specification confirmation: ${confirmedSpecification.title}`,
|
|
884
|
+
rationale: `Research Specification confirmation answer: ${answer}`,
|
|
885
|
+
sourceEvidenceIds,
|
|
886
|
+
questionRecordId: questionId,
|
|
887
|
+
decisionRecordId: decisionId,
|
|
888
|
+
createDecisionRecord: false
|
|
889
|
+
});
|
|
864
890
|
const nextState = researchSpecificationAnswerConfirms(answer)
|
|
865
|
-
? resolveResearchSpecificationConfirmationObligation(state, confirmedSpecification, {
|
|
891
|
+
? resolveResearchSpecificationConfirmationObligation(audited.state, confirmedSpecification, {
|
|
866
892
|
questionId,
|
|
867
893
|
decisionId,
|
|
868
894
|
status: "satisfied"
|
|
869
895
|
})
|
|
870
896
|
: researchSpecificationAnswerNeedsFollowUp(answer)
|
|
871
|
-
? ensureResearchSpecificationConfirmationObligation(state, confirmedSpecification, {
|
|
897
|
+
? ensureResearchSpecificationConfirmationObligation(audited.state, confirmedSpecification, {
|
|
872
898
|
answer,
|
|
873
899
|
questionId,
|
|
874
900
|
decisionId
|
|
875
901
|
})
|
|
876
|
-
: resolveResearchSpecificationConfirmationObligation(state, confirmedSpecification, {
|
|
902
|
+
: resolveResearchSpecificationConfirmationObligation(audited.state, confirmedSpecification, {
|
|
877
903
|
questionId,
|
|
878
904
|
decisionId,
|
|
879
905
|
status: "cleared"
|
|
@@ -1219,6 +1245,126 @@ export function createLongTableMcpServer() {
|
|
|
1219
1245
|
return errorResult(error instanceof Error ? error.message : String(error));
|
|
1220
1246
|
}
|
|
1221
1247
|
});
|
|
1248
|
+
server.registerTool("propose_research_spec_patch", {
|
|
1249
|
+
title: "Propose Research Specification Patch",
|
|
1250
|
+
description: "Store a reviewable Research Specification patch without applying it.",
|
|
1251
|
+
inputSchema: cwdSchema.extend({
|
|
1252
|
+
specification: researchSpecificationSchema,
|
|
1253
|
+
source: researchSpecificationPatchSourceSchema.default("manual"),
|
|
1254
|
+
rationale: z.string().optional(),
|
|
1255
|
+
sourceEvidenceIds: z.array(z.string()).optional()
|
|
1256
|
+
})
|
|
1257
|
+
}, async ({ cwd: inputCwd, specification, source, rationale, sourceEvidenceIds }) => {
|
|
1258
|
+
try {
|
|
1259
|
+
const context = await requireContext(inputCwd);
|
|
1260
|
+
const result = await proposeResearchSpecificationPatch({
|
|
1261
|
+
context,
|
|
1262
|
+
specification: specification,
|
|
1263
|
+
source,
|
|
1264
|
+
rationale,
|
|
1265
|
+
sourceEvidenceIds
|
|
1266
|
+
});
|
|
1267
|
+
return textResult({
|
|
1268
|
+
patch: result.patch,
|
|
1269
|
+
changes: result.changes,
|
|
1270
|
+
nextAction: `apply_research_spec_patch patchId=${result.patch.id}`
|
|
1271
|
+
});
|
|
1272
|
+
}
|
|
1273
|
+
catch (error) {
|
|
1274
|
+
return errorResult(error instanceof Error ? error.message : String(error));
|
|
1275
|
+
}
|
|
1276
|
+
});
|
|
1277
|
+
server.registerTool("apply_research_spec_patch", {
|
|
1278
|
+
title: "Apply Research Specification Patch",
|
|
1279
|
+
description: "Automatically apply a proposed or inline Research Specification update and record a revision.",
|
|
1280
|
+
inputSchema: cwdSchema.extend({
|
|
1281
|
+
patchId: z.string().optional(),
|
|
1282
|
+
specification: researchSpecificationSchema.optional(),
|
|
1283
|
+
source: researchSpecificationPatchSourceSchema.default("manual"),
|
|
1284
|
+
rationale: z.string().optional(),
|
|
1285
|
+
sourceEvidenceIds: z.array(z.string()).optional(),
|
|
1286
|
+
questionRecordId: z.string().optional(),
|
|
1287
|
+
decisionRecordId: z.string().optional()
|
|
1288
|
+
})
|
|
1289
|
+
}, async ({ cwd: inputCwd, patchId, specification, source, rationale, sourceEvidenceIds, questionRecordId, decisionRecordId }) => {
|
|
1290
|
+
try {
|
|
1291
|
+
const context = await requireContext(inputCwd);
|
|
1292
|
+
const result = await applyResearchSpecificationPatch({
|
|
1293
|
+
context,
|
|
1294
|
+
patchId,
|
|
1295
|
+
specification: specification,
|
|
1296
|
+
source,
|
|
1297
|
+
rationale,
|
|
1298
|
+
sourceEvidenceIds,
|
|
1299
|
+
questionRecordId,
|
|
1300
|
+
decisionRecordId
|
|
1301
|
+
});
|
|
1302
|
+
return textResult({
|
|
1303
|
+
patch: result.patch,
|
|
1304
|
+
revision: result.revision,
|
|
1305
|
+
specification: result.specification,
|
|
1306
|
+
decision: result.decision,
|
|
1307
|
+
session: {
|
|
1308
|
+
currentGoal: result.session.currentGoal,
|
|
1309
|
+
researchSpecification: result.session.researchSpecification
|
|
1310
|
+
}
|
|
1311
|
+
});
|
|
1312
|
+
}
|
|
1313
|
+
catch (error) {
|
|
1314
|
+
return errorResult(error instanceof Error ? error.message : String(error));
|
|
1315
|
+
}
|
|
1316
|
+
});
|
|
1317
|
+
server.registerTool("diff_research_specification", {
|
|
1318
|
+
title: "Diff Research Specification",
|
|
1319
|
+
description: "Compare an inline Research Specification against the current workspace specification without writing state.",
|
|
1320
|
+
inputSchema: cwdSchema.extend({
|
|
1321
|
+
specification: researchSpecificationSchema
|
|
1322
|
+
}),
|
|
1323
|
+
annotations: { readOnlyHint: true }
|
|
1324
|
+
}, async ({ cwd: inputCwd, specification }) => {
|
|
1325
|
+
try {
|
|
1326
|
+
const context = await requireContext(inputCwd);
|
|
1327
|
+
const state = asInterviewState(await loadWorkspaceState(context));
|
|
1328
|
+
const current = state.researchSpecification ?? context.session.researchSpecification;
|
|
1329
|
+
return textResult({
|
|
1330
|
+
current,
|
|
1331
|
+
changes: diffResearchSpecifications(current, specification)
|
|
1332
|
+
});
|
|
1333
|
+
}
|
|
1334
|
+
catch (error) {
|
|
1335
|
+
return errorResult(error instanceof Error ? error.message : String(error));
|
|
1336
|
+
}
|
|
1337
|
+
});
|
|
1338
|
+
server.registerTool("read_research_spec_history", {
|
|
1339
|
+
title: "Read Research Specification History",
|
|
1340
|
+
description: "Read specification revisions, patches, and evidence records for audit or resume.",
|
|
1341
|
+
inputSchema: cwdSchema,
|
|
1342
|
+
annotations: { readOnlyHint: true }
|
|
1343
|
+
}, async ({ cwd: inputCwd }) => {
|
|
1344
|
+
try {
|
|
1345
|
+
const context = await requireContext(inputCwd);
|
|
1346
|
+
return textResult(await readResearchSpecificationHistory(context));
|
|
1347
|
+
}
|
|
1348
|
+
catch (error) {
|
|
1349
|
+
return errorResult(error instanceof Error ? error.message : String(error));
|
|
1350
|
+
}
|
|
1351
|
+
});
|
|
1352
|
+
server.registerTool("find_unincorporated_evidence", {
|
|
1353
|
+
title: "Find Unincorporated Research Evidence",
|
|
1354
|
+
description: "List interview, panel, critic, reviewer, or invocation evidence not yet incorporated into a Research Specification revision.",
|
|
1355
|
+
inputSchema: cwdSchema,
|
|
1356
|
+
annotations: { readOnlyHint: true }
|
|
1357
|
+
}, async ({ cwd: inputCwd }) => {
|
|
1358
|
+
try {
|
|
1359
|
+
const context = await requireContext(inputCwd);
|
|
1360
|
+
return textResult({
|
|
1361
|
+
evidenceRecords: await findUnincorporatedResearchEvidence(context)
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
catch (error) {
|
|
1365
|
+
return errorResult(error instanceof Error ? error.message : String(error));
|
|
1366
|
+
}
|
|
1367
|
+
});
|
|
1222
1368
|
server.registerTool("cancel_interview", {
|
|
1223
1369
|
title: "Cancel LongTable Interview",
|
|
1224
1370
|
description: "Explicitly cancel the active $longtable-interview hook without confirming a First Research Shape.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@longtable/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.48",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "LongTable MCP transport for workspace state and Researcher Checkpoints",
|
|
6
6
|
"type": "module",
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
"self-test": "node ./dist/server.js --self-test"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@longtable/checkpoints": "0.1.
|
|
30
|
-
"@longtable/cli": "0.1.
|
|
31
|
-
"@longtable/core": "0.1.
|
|
32
|
-
"@longtable/provider-claude": "0.1.
|
|
33
|
-
"@longtable/provider-codex": "0.1.
|
|
34
|
-
"@longtable/setup": "0.1.
|
|
29
|
+
"@longtable/checkpoints": "0.1.48",
|
|
30
|
+
"@longtable/cli": "0.1.48",
|
|
31
|
+
"@longtable/core": "0.1.48",
|
|
32
|
+
"@longtable/provider-claude": "0.1.48",
|
|
33
|
+
"@longtable/provider-codex": "0.1.48",
|
|
34
|
+
"@longtable/setup": "0.1.48",
|
|
35
35
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
36
36
|
"zod": "^4.0.0"
|
|
37
37
|
},
|