You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
MCP: let AI assistants read the contents of files stored in Twenty
#27993
Twenty's MCP server lets an outside AI assistant (Claude, ChatGPT, Cursor…) read and edit CRM data. Many teams keep their key documents in Twenty as files: contracts, proposals, reports, spreadsheets. These sit in the Files tab of a record or in a FILES field.
Today an assistant connected through MCP can see that these files exist, but it cannot open them. So it cannot answer simple questions such as:
"What is the notice period in the contract attached to Acme?"
"Which of our signed contracts contain an exclusivity clause, and what exactly does it say?"
"Summarise the latest proposal we sent to Globex."
This becomes even more useful with the email attachments work on the roadmap (twentyhq/core-team-issues#225, "Email Attachement", priority "P1 - Current focus"), which makes the attachments of synced emails available on the email records in Twenty. A large share of a team's documents arrive by email. Once those attachments are stored in Twenty, the same read tool would let an assistant answer "What price did Globex quote in the PDF they emailed last week?" without anyone saving the file by hand.
The upload side is already solved: create_file_upload and complete_file_upload let an assistant send a file to Twenty (follow-up of #25275). This ticket asks for the matching read side, which #25275 already suggested as an option ("a symmetric download_file({ fileId }) gated by DOWNLOAD_FILE… so agents can also read attachments they are allowed to see").
Current behavior
Tested over MCP on Twenty Cloud 2.46.0, signed in as an admin:
find_many_attachments works. For each file it returns the name, the extension and a file[].url link to /file/files-field/<fileId>?token=…, signed and valid for 24 hours.
No MCP tool returns the bytes or the text of a file. learn_tools on read_file, get_file, get_file_content or download_file returns them as not found.
code_interpreter can take files as input (files: [{ fileId }]), but it is not offered over MCP: execute_tool answers Tool "code_interpreter" is not available in this context. In the code it is on MCP_EXCLUDED_TOOL_NAMES. Even in the in-app AI chat it only opens files uploaded to the chat: downloadInputFiles reads with fileFolder: FileFolder.AgentChat, so files attached to records (files-field) cannot be passed to it.
The assistant is left with the signed URL. Many MCP clients cannot fetch arbitrary URLs: their sandbox blocks the host, or their fetch tool refuses long URLs. The ones that can fetch it get raw bytes with no text extraction. In our test, both routes failed.
One small inconsistency: the MCP server instructions (build-mcp-server-instructions.util.ts) tell the assistant to use an uploaded fileId "in code_interpreter.files", although code_interpreter is not available over MCP.
Expected behavior
A read-only MCP tool, for example read_file({ fileId }) or read_attachment({ attachmentId }), which:
Returns readable content, not just bytes. Text for each page of a PDF, text for Word and PowerPoint files, and a sheet-by-sheet text or CSV version for Excel files.
Starts with documents only. A first version could support PDF, Microsoft Office files (DOCX, XLSX, PPTX) and their close equivalents (OpenDocument ODT/ODS/ODP, plain text, CSV). Image and video files stay out of scope for now, and the tool returns a clear "file type not supported yet" message for them.
Still handles PDFs that contain images. Scanned PDFs, or PDFs with charts and pictures, are common. Pages without a text layer are run through OCR or returned as page images (MCP image content), so the assistant does not get blank pages back.
Follows the caller's permissions. It only works for files on records the signed-in user (or API key role) can read. It could have its own permission flag, alongside UPLOAD_FILE.
Handles large files. A size cap, plus paging (e.g. offset / maxCharacters, or a page range for PDFs), with the total length in the response so the assistant knows if there is more.
Example: the assistant calls find_many_attachments({ targetCompanyId: <Acme> }), finds "Master services agreement.pdf", then calls read_file({ fileId }) and gets back the text of pages 1 to 10 plus "totalPages": 24. It can then answer "The notice period is 90 days (clause 12.2)".
Images and videos could follow in a later version, once the document path works.
A different option would be to offer code_interpreter over MCP and let it open record files too. But it is a much broader tool (it runs code), and #20022 lists "decide a clearer policy for local runtime tools like code interpreter" as an open question. A narrow read-only tool seems simpler and safer.
Technical inputs
File access and signed URLs already exist (FileService, FileUrlService, FileStorageService). CodeInterpreterTool.downloadInputFiles already loads a file by fileId within a workspace, so the new tool can reuse that path.
Register the tool in ActionToolProvider next to create_file_upload / complete_file_upload, gated by a permission flag, and keep it out of MCP_EXCLUDED_TOOL_NAMES.
Text extraction could run server-side (e.g. pdf.js or pdf-parse for PDF, mammoth for DOCX, the existing XLSX handling for spreadsheets, an Office/OpenDocument text extractor for PPTX/ODT/ODS/ODP). Detect type from the stored MIME type, not the file name, and reject unsupported types up front.
For PDF pages with no text layer: OCR, or render the page to an image and return it as MCP image content.
Update the MCP server instructions to describe the read path, and drop the code_interpreter.files hint for MCP.
References: twentyhq/core-team-issues#225 (email attachments on synced emails), #25275 (MCP file upload, suggested a download tool), #20022 (policy for local runtime tools such as code interpreter), #27310 (read-only annotations on MCP read tools), #18113 (single MCP endpoint).
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Scope & Context
Twenty's MCP server lets an outside AI assistant (Claude, ChatGPT, Cursor…) read and edit CRM data. Many teams keep their key documents in Twenty as files: contracts, proposals, reports, spreadsheets. These sit in the Files tab of a record or in a FILES field.
Today an assistant connected through MCP can see that these files exist, but it cannot open them. So it cannot answer simple questions such as:
This becomes even more useful with the email attachments work on the roadmap (twentyhq/core-team-issues#225, "Email Attachement", priority "P1 - Current focus"), which makes the attachments of synced emails available on the email records in Twenty. A large share of a team's documents arrive by email. Once those attachments are stored in Twenty, the same read tool would let an assistant answer "What price did Globex quote in the PDF they emailed last week?" without anyone saving the file by hand.
The upload side is already solved:
create_file_uploadandcomplete_file_uploadlet an assistant send a file to Twenty (follow-up of #25275). This ticket asks for the matching read side, which #25275 already suggested as an option ("a symmetricdownload_file({ fileId })gated byDOWNLOAD_FILE… so agents can also read attachments they are allowed to see").Current behavior
Tested over MCP on Twenty Cloud 2.46.0, signed in as an admin:
find_many_attachmentsworks. For each file it returns the name, the extension and afile[].urllink to/file/files-field/<fileId>?token=…, signed and valid for 24 hours.learn_toolsonread_file,get_file,get_file_contentordownload_filereturns them as not found.code_interpretercan take files as input (files: [{ fileId }]), but it is not offered over MCP:execute_toolanswersTool "code_interpreter" is not available in this context. In the code it is onMCP_EXCLUDED_TOOL_NAMES. Even in the in-app AI chat it only opens files uploaded to the chat:downloadInputFilesreads withfileFolder: FileFolder.AgentChat, so files attached to records (files-field) cannot be passed to it.One small inconsistency: the MCP server instructions (
build-mcp-server-instructions.util.ts) tell the assistant to use an uploaded fileId "in code_interpreter.files", althoughcode_interpreteris not available over MCP.Expected behavior
A read-only MCP tool, for example
read_file({ fileId })orread_attachment({ attachmentId }), which:UPLOAD_FILE.offset/maxCharacters, or a page range for PDFs), with the total length in the response so the assistant knows if there is more.Example: the assistant calls
find_many_attachments({ targetCompanyId: <Acme> }), finds "Master services agreement.pdf", then callsread_file({ fileId })and gets back the text of pages 1 to 10 plus"totalPages": 24. It can then answer "The notice period is 90 days (clause 12.2)".Images and videos could follow in a later version, once the document path works.
A different option would be to offer
code_interpreterover MCP and let it open record files too. But it is a much broader tool (it runs code), and #20022 lists "decide a clearer policy for local runtime tools like code interpreter" as an open question. A narrow read-only tool seems simpler and safer.Technical inputs
FileService,FileUrlService,FileStorageService).CodeInterpreterTool.downloadInputFilesalready loads a file byfileIdwithin a workspace, so the new tool can reuse that path.ActionToolProvidernext tocreate_file_upload/complete_file_upload, gated by a permission flag, and keep it out ofMCP_EXCLUDED_TOOL_NAMES.code_interpreter.fileshint for MCP.References: twentyhq/core-team-issues#225 (email attachments on synced emails), #25275 (MCP file upload, suggested a download tool), #20022 (policy for local runtime tools such as code interpreter), #27310 (read-only annotations on MCP read tools), #18113 (single MCP endpoint).
All reactions