Agent BrainsAgent Brains

Document structuring with MCP

Start one document-structuring job, poll the existing task, and interpret the result.

Document structuring with MCP

Use this guide when an MCP agent imports a document into the Knowledge Base. Structuring and vectorization are separate operations: a successful structuring task does not prove vectorization is complete, and agents should not vectorize the whole workspace after every import.

These contracts were checked against public-gateway develop at bfa1675 (version 0.5.1). This is source verification, not confirmation that every environment has deployed that version.

MCP results currently contain JSON serialized in a text content block. The examples below show the decoded JSON.

Tools

ToolRequired argumentsOptional argumentsResult
get-categoriesnonecategoryId to inspect a subtreeAvailable Knowledge Base categories
create-structuring-tasksource: nonempty stringcategoryId: nonempty string{ "taskId": "..." }
get-structuring-tasktaskId: nonempty stringnoneStatus and processing result for the same task

The authenticated workspace comes from the MCP API key. Do not add tenantId, internal SDS credentials, or internal routes to tool arguments.

Before starting

source must be a URL or storage reference accessible to the processing service. Do not pass a local filesystem path, a file's contents, or a base64 attachment payload as if it were a source URL. Missing or inaccessible sources need to be corrected.

Choose exactly one path:

Known category

Retrieve available categories with get-categories, or reuse a relevant result already obtained. Match the intended category and pass its actual returned ID as categoryId. A category name or policy name is not a category ID.

{"name":"get-categories","arguments":{}}

After selecting an actual returned category ID:

{"name":"create-structuring-task","arguments":{"source":"https://example.com/manual.pdf","categoryId":"507f1f77bcf86cd799439012"}}

Unknown category

If no matching category is established, pass only source and omit categoryId entirely. This starts pre-parsing and stores the processed document in the general category.

Do not guess an ID, create a category, require category selection just to start this flow, or hard-code a general-category ID.

{"name":"create-structuring-task","arguments":{"source":"https://example.com/manual.pdf"}}

The gateway chooses the processing flow from the presence of categoryId. Do not add mode, preParsing, policyId, or tenantId.

Start once and save taskId

Both paths enqueue background work and immediately return a job identifier in taskId, not jobId. This is not the final document or entity ID.

{"taskId":"example-task-id"}

Never call create-structuring-task again to check progress. A repeated creation can enqueue duplicate processing. If creation times out without returning an ID, report the uncertain outcome instead of blindly submitting again.

Poll the same task

Wait 30 seconds by default, then call get-structuring-task with the saved taskId.

{"name":"get-structuring-task","arguments":{"taskId":"example-task-id"}}

Repeat this status call at the selected interval while work remains in progress. Another positive interval can be selected by the user or agent runtime. The interval is a client-side scheduling choice, not a server guarantee or a pollInterval argument. Use the runtime's timer, wait, or scheduler; do not issue a tight loop.

Use a finite waiting budget. If it expires, retain taskId and report the last observed state as pending or unconfirmed. A client timeout does not prove server-side failure. If the runtime cannot wait or schedule follow-ups, return taskId and explain how to check it later.

Interpret the result

FieldMeaning
taskIdThe task being checked
stateTask execution state, passed through from the task service as a string
applicationStatusProcessing outcome, such as SUCCESS or FAILURE, or null when unavailable
entityIdResulting entity ID when supplied by processing, otherwise null
resultOriginal processing result, or null
progressCurrently always null in the gateway; do not promise percentages or an ETA

Decision logic:

  • Confirmed success: state === "SUCCESS" and applicationStatus === "SUCCESS". Stop polling. If entityId is present, use get-entity with {"id":"<returned-entity-id>"} when the user needs the processed content.
  • Failure: applicationStatus === "FAILURE" or the task reports a terminal failure/cancellation, such as FAILURE or REVOKED. Stop polling and report the relevant returned error without exposing credentials or internal secrets.
  • Still running: for a nonterminal state such as PENDING, wait and check the same task again. A missing result is not itself an error. Example state names are not an exhaustive enum.
  • Finished but inconclusive: state === "SUCCESS" without confirmed application success is not enough to claim the document was processed. Surface the returned outcome; if it is missing or unrecognized, report that completion is unconfirmed instead of polling forever or inventing a result.

Successful result example:

{
  "taskId": "example-task-id",
  "state": "SUCCESS",
  "progress": null,
  "result": {"status":"SUCCESS","result":{"data":{"id":"507f1f77bcf86cd799439013"}}},
  "applicationStatus": "SUCCESS",
  "entityId": "507f1f77bcf86cd799439013"
}

Important failure example: the task executor finished normally, but document processing failed. Treat this as failure, not success.

{
  "taskId": "example-task-id",
  "state": "SUCCESS",
  "progress": null,
  "result": {"status":"FAILURE","error":"Document type unsupported"},
  "applicationStatus": "FAILURE",
  "entityId": null
}

On a temporary status-read failure, retry the status read within the runtime's retry/wait budget. On an authentication error or missing task, stop and resolve that issue rather than creating a replacement task.

On this page