@longtable/mcp 0.1.48 → 0.1.50

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/README.md CHANGED
@@ -15,7 +15,7 @@ longtable-state
15
15
  Run:
16
16
 
17
17
  ```bash
18
- npx -y @longtable/mcp@0.1.47
18
+ npx -y @longtable/mcp@0.1.50
19
19
  ```
20
20
 
21
21
  Self-test:
package/dist/server.js CHANGED
@@ -52,6 +52,18 @@ const questionOptionSchema = z.object({
52
52
  description: z.string().optional(),
53
53
  recommended: z.boolean().optional()
54
54
  });
55
+ const questionPromptTypeSchema = z.enum(["single_choice", "multi_choice", "free_text"]);
56
+ const questionAnswerInputSchema = z.union([
57
+ z.string().min(1),
58
+ z.array(z.string().min(1)).min(1),
59
+ z.object({
60
+ answer: z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]).optional(),
61
+ selectedValue: z.string().min(1).optional(),
62
+ selectedValues: z.array(z.string().min(1)).min(1).optional(),
63
+ otherText: z.string().min(1).optional(),
64
+ rationale: z.string().min(1).optional()
65
+ })
66
+ ]);
55
67
  const commitmentFamilySchema = z.enum([
56
68
  "scope",
57
69
  "construct",
@@ -728,6 +740,34 @@ function buildElicitationParams(record) {
728
740
  }]
729
741
  : [])
730
742
  ];
743
+ const decisionSchema = record.prompt.type === "multi_choice"
744
+ ? {
745
+ type: "array",
746
+ title: "Decisions",
747
+ items: {
748
+ anyOf: choices
749
+ },
750
+ minItems: record.prompt.required ? 1 : 0
751
+ }
752
+ : record.prompt.type === "free_text"
753
+ ? {
754
+ type: "string",
755
+ title: "Decision"
756
+ }
757
+ : {
758
+ type: "string",
759
+ title: "Decision",
760
+ oneOf: choices
761
+ };
762
+ const properties = {
763
+ answer: decisionSchema
764
+ };
765
+ if (record.prompt.allowOther && record.prompt.type !== "free_text") {
766
+ properties.otherText = {
767
+ type: "string",
768
+ title: record.prompt.otherLabel ?? "Other"
769
+ };
770
+ }
731
771
  return {
732
772
  mode: "form",
733
773
  message: [
@@ -737,14 +777,7 @@ function buildElicitationParams(record) {
737
777
  ].filter(Boolean).join("\n"),
738
778
  requestedSchema: {
739
779
  type: "object",
740
- properties: {
741
- answer: {
742
- type: "string",
743
- title: "Decision",
744
- oneOf: choices,
745
- default: choices[0]?.const
746
- }
747
- },
780
+ properties,
748
781
  required: ["answer"]
749
782
  }
750
783
  };
@@ -753,14 +786,32 @@ function acceptedAnswer(result) {
753
786
  if (result.action !== "accept") {
754
787
  return null;
755
788
  }
756
- const answer = result.content?.answer;
789
+ const content = result.content;
790
+ const answer = content?.answer ?? content?.answers ?? content?.selectedValues;
791
+ const otherText = typeof content?.otherText === "string" && content.otherText.trim().length > 0
792
+ ? content.otherText.trim()
793
+ : undefined;
757
794
  if (typeof answer !== "string" || answer.length === 0) {
795
+ if (Array.isArray(answer) && answer.every((entry) => typeof entry === "string" && entry.length > 0)) {
796
+ return {
797
+ answer: otherText ? { selectedValues: answer, otherText } : answer
798
+ };
799
+ }
758
800
  return null;
759
801
  }
760
802
  return {
761
- answer
803
+ answer: otherText ? { selectedValue: answer, otherText } : answer
762
804
  };
763
805
  }
806
+ function firstAcceptedAnswerValue(answer) {
807
+ if (typeof answer === "string") {
808
+ return answer;
809
+ }
810
+ if (Array.isArray(answer)) {
811
+ return answer[0] ?? "";
812
+ }
813
+ return answer.selectedValue ?? answer.selectedValues?.[0] ?? "";
814
+ }
764
815
  async function markFirstResearchShapeConfirmation(context, shape, answer, questionId, decisionId) {
765
816
  const state = asInterviewState(await loadWorkspaceState(context));
766
817
  const timestamp = new Date().toISOString();
@@ -1468,7 +1519,7 @@ export function createLongTableMcpServer() {
1468
1519
  surface: "mcp_elicitation"
1469
1520
  });
1470
1521
  const marked = await markQuestionTransport(context, created.question.id, "accepted");
1471
- const confirmation = await markFirstResearchShapeConfirmation(context, shape, accepted.answer, created.question.id, decided.decision.id);
1522
+ const confirmation = await markFirstResearchShapeConfirmation(context, shape, firstAcceptedAnswerValue(accepted.answer), created.question.id, decided.decision.id);
1472
1523
  return textResult({
1473
1524
  shape: confirmation.shape,
1474
1525
  question: marked ? { ...decided.question, transportStatus: marked.transportStatus } : decided.question,
@@ -1578,7 +1629,7 @@ export function createLongTableMcpServer() {
1578
1629
  surface: "mcp_elicitation"
1579
1630
  });
1580
1631
  const marked = await markQuestionTransport(context, created.question.id, "accepted");
1581
- const confirmation = await markResearchSpecificationConfirmation(context, specification, accepted.answer, created.question.id, decided.decision.id);
1632
+ const confirmation = await markResearchSpecificationConfirmation(context, specification, firstAcceptedAnswerValue(accepted.answer), created.question.id, decided.decision.id);
1582
1633
  return textResult({
1583
1634
  specification: confirmation.specification,
1584
1635
  preview: renderResearchSpecificationPreview(confirmation.specification),
@@ -1657,15 +1708,18 @@ export function createLongTableMcpServer() {
1657
1708
  prompt: z.string().min(1),
1658
1709
  title: z.string().optional(),
1659
1710
  question: z.string().optional(),
1711
+ type: questionPromptTypeSchema.optional(),
1660
1712
  checkpointKey: z.string().optional(),
1661
1713
  options: z.array(questionOptionSchema).optional(),
1714
+ allowOther: z.boolean().optional(),
1715
+ otherLabel: z.string().optional(),
1662
1716
  displayReason: z.string().optional(),
1663
1717
  provider: z.enum(["codex", "claude"]).optional(),
1664
1718
  required: z.boolean().optional(),
1665
1719
  commitmentFamily: commitmentFamilySchema.optional(),
1666
1720
  epistemicBasis: epistemicBasisSchema.optional()
1667
1721
  })
1668
- }, async ({ cwd: inputCwd, prompt, title, question, checkpointKey, options, displayReason, provider, required, commitmentFamily, epistemicBasis }) => {
1722
+ }, async ({ cwd: inputCwd, prompt, title, question, type, checkpointKey, options, allowOther, otherLabel, displayReason, provider, required, commitmentFamily, epistemicBasis }) => {
1669
1723
  try {
1670
1724
  const context = await requireContext(inputCwd);
1671
1725
  const result = await createWorkspaceQuestion({
@@ -1673,8 +1727,11 @@ export function createLongTableMcpServer() {
1673
1727
  prompt,
1674
1728
  title,
1675
1729
  question,
1730
+ type: type,
1676
1731
  checkpointKey,
1677
1732
  questionOptions: options,
1733
+ allowOther,
1734
+ otherLabel,
1678
1735
  displayReason,
1679
1736
  provider,
1680
1737
  required,
@@ -1697,8 +1754,11 @@ export function createLongTableMcpServer() {
1697
1754
  prompt: z.string().min(1),
1698
1755
  title: z.string().optional(),
1699
1756
  question: z.string().optional(),
1757
+ type: questionPromptTypeSchema.optional(),
1700
1758
  checkpointKey: z.string().optional(),
1701
1759
  options: z.array(questionOptionSchema).optional(),
1760
+ allowOther: z.boolean().optional(),
1761
+ otherLabel: z.string().optional(),
1702
1762
  displayReason: z.string().optional(),
1703
1763
  provider: z.enum(["codex", "claude"]).default("codex"),
1704
1764
  required: z.boolean().optional(),
@@ -1706,7 +1766,7 @@ export function createLongTableMcpServer() {
1706
1766
  epistemicBasis: epistemicBasisSchema.optional(),
1707
1767
  fallbackOnly: z.boolean().default(false).describe("Create and render the checkpoint without calling MCP elicitation.")
1708
1768
  })
1709
- }, async ({ cwd: inputCwd, prompt, title, question, checkpointKey, options, displayReason, provider, required, commitmentFamily, epistemicBasis, fallbackOnly }) => {
1769
+ }, async ({ cwd: inputCwd, prompt, title, question, type, checkpointKey, options, allowOther, otherLabel, displayReason, provider, required, commitmentFamily, epistemicBasis, fallbackOnly }) => {
1710
1770
  try {
1711
1771
  const context = await requireContext(inputCwd);
1712
1772
  const created = await createWorkspaceQuestion({
@@ -1714,8 +1774,11 @@ export function createLongTableMcpServer() {
1714
1774
  prompt,
1715
1775
  title,
1716
1776
  question,
1777
+ type: type,
1717
1778
  checkpointKey,
1718
1779
  questionOptions: options,
1780
+ allowOther,
1781
+ otherLabel,
1719
1782
  displayReason,
1720
1783
  provider,
1721
1784
  required,
@@ -1810,7 +1873,7 @@ export function createLongTableMcpServer() {
1810
1873
  description: "Answer a pending QuestionRecord and append a DecisionRecord.",
1811
1874
  inputSchema: cwdSchema.extend({
1812
1875
  questionId: z.string().optional(),
1813
- answer: z.string().min(1),
1876
+ answer: questionAnswerInputSchema,
1814
1877
  rationale: z.string().optional(),
1815
1878
  provider: z.enum(["codex", "claude"]).optional()
1816
1879
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@longtable/mcp",
3
- "version": "0.1.48",
3
+ "version": "0.1.50",
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.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",
29
+ "@longtable/checkpoints": "0.1.50",
30
+ "@longtable/cli": "0.1.50",
31
+ "@longtable/core": "0.1.50",
32
+ "@longtable/provider-claude": "0.1.50",
33
+ "@longtable/provider-codex": "0.1.50",
34
+ "@longtable/setup": "0.1.50",
35
35
  "@modelcontextprotocol/sdk": "^1.29.0",
36
36
  "zod": "^4.0.0"
37
37
  },