MCPcopy Create free account
hub / github.com/modelcontextprotocol/ext-apps / extractFormSchema

Function extractFormSchema

examples/pdf-server/server.ts:1138–1225  ·  view source on GitHub ↗
(
  pdfDoc: PDFDocumentProxy,
  fieldObjects: Record<string, PdfJsFieldObject[]> | null,
)

Source from the content-addressed store, hash-verified

1136}
1137
1138export async function extractFormSchema(
1139 pdfDoc: PDFDocumentProxy,
1140 fieldObjects: Record<string, PdfJsFieldObject[]> | null,
1141): Promise<{
1142 type: "object";
1143 properties: Record<string, PrimitiveSchemaDefinition>;
1144 required?: string[];
1145} | null> {
1146 if (!fieldObjects || Object.keys(fieldObjects).length === 0) {
1147 return null;
1148 }
1149
1150 const properties: Record<string, PrimitiveSchemaDefinition> = {};
1151 for (const [name, fields] of Object.entries(fieldObjects)) {
1152 // pdfjs returns the full field-tree array: for separated structures
1153 // (pdf-lib) the typed widget is at [1+] behind a container at [0]; for
1154 // merged/leaf entries (W-9, most authoring tools) it's at [0]. Pick the
1155 // first entry that actually has a field type.
1156 const field = fields.find((f) => f.type) ?? fields[0];
1157 if (!field.editable) continue;
1158
1159 switch (field.type) {
1160 case "text":
1161 properties[name] = { type: "string", title: name };
1162 break;
1163 case "checkbox":
1164 properties[name] = { type: "boolean", title: name };
1165 break;
1166 case "radiobutton": {
1167 const options = fields
1168 .map((f) => f.exportValues)
1169 .filter((v): v is string => !!v && v !== "Off");
1170 properties[name] =
1171 options.length > 0
1172 ? { type: "string", title: name, enum: options }
1173 : { type: "string", title: name };
1174 break;
1175 }
1176 case "combobox":
1177 case "listbox": {
1178 const items = field.items?.map((i) => i.exportValue).filter(Boolean);
1179 properties[name] =
1180 items && items.length > 0
1181 ? { type: "string", title: name, enum: items }
1182 : { type: "string", title: name };
1183 break;
1184 }
1185 // Skip "button" (push buttons) and unknown types
1186 }
1187 }
1188
1189 // Collect alternativeText labels from per-page annotations
1190 // (getFieldObjects doesn't include them)
1191 const fieldLabels = new Map<string, string>();
1192 try {
1193 for (let i = 1; i <= pdfDoc.numPages; i++) {
1194 const page = await pdfDoc.getPage(i);
1195 const annotations = await page.getAnnotations();

Callers 3

schemaForFunction · 0.90
server.test.tsFile · 0.90
probeFormFieldsFunction · 0.85

Calls

no outgoing calls

Tested by 1

schemaForFunction · 0.72

Used in the wild real call sites across dependent graphs

searching dependent graphs…