Puter MCP
Puter MCP enables AI tools to interact with Puter: manage files, websites, workers, and more
제작자가 쓴 설명(영어 원문)
Read tables, figures and dates out of a PDF, Word file, CSV or paste, with a verdict on the reading.
이 서버는 아직 쉬운 말로 된 요약을 쓰지 못했어요. 아래는 레지스트리에서 읽어 온 사실이에요.
쓰고 있는 AI 앱을 고른 다음 설정을 복사하세요.
검사 2/2 통과 · 내 컴퓨터에서 실행돼요
먼저: 어떤 AI를 쓰시나요?
쓰는 앱을 고르면 아래에 단계가 나옵니다.
Claude에 연결할 수 있지만 먼저 준비가 필요해요
truecopy 키가 필요해요 (제작자 사이트에서 가입, 비용이 들 수 있음) · 먼저 컴퓨터에 Node.js를 설치하세요 (한 번만) · 컴퓨터용 Claude 앱(Windows 또는 Mac)에서만 되고 웹이나 모바일은 안 돼요
SettingsDeveloperEdit Config
{
"mcpServers": {
"truecopy": {
"command": "npx",
"args": [
"-y",
"truecopy",
"mcp"
],
"env": {
"TRUECOPY_MCP_ROOT": "your-value"
}
}
}
}키는 앱 입력란에만 붙여 넣고, 채팅에 붙이거나 다른 사람에게 보내지 마세요
truecopy을 써서 나에게 무엇을 해 줄 수 있는지 알려 주고, 하나 해 봐✓ Claude가 truecopy을 쓰고 있다고 하거나 답에 truecopy 도구 이름이 나오면 연결된 거예요
메뉴 이름은 2026년 11월 11일에 Anthropic 도움말에서 확인 · 앱 버전에 따라 화면이 조금 다를 수 있어요
ChatGPT는 아직 truecopy에 연결할 수 없어요
truecopy는 내 컴퓨터에 설치해서 쓰지만 ChatGPT는 웹에서 도는 서버만 연결할 수 있어요
A · truecopy에 연결되는 앱 쓰기
Claude Code에 연결할 수 있지만 먼저 준비가 필요해요
truecopy 키가 필요해요 (제작자 사이트에서 가입, 비용이 들 수 있음) · 먼저 컴퓨터에 Node.js를 설치하세요 (한 번만)
Mac: Command+스페이스를 누르고 Terminal 입력 · Windows: PowerShell 열기
claude mcp add truecopy --env TRUECOPY_MCP_ROOT=your-value -- npx -y truecopy mcpEnter 전에 “your-value”를 내 키로 바꾸세요
키는 앱 입력란에만 붙여 넣고, 채팅에 붙이거나 다른 사람에게 보내지 마세요
truecopy이 목록에 있고 연결됨으로 보이면 돼요
truecopy을 써서 나에게 무엇을 해 줄 수 있는지 알려 주고, 하나 해 봐✓ Claude Code가 truecopy을 쓰고 있다고 하거나 답에 truecopy 도구 이름이 나오면 연결된 거예요
메뉴 이름은 2026년 11월 11일에 Anthropic 도움말에서 확인 · 앱 버전에 따라 화면이 조금 다를 수 있어요
Cursor에 연결할 수 있지만 먼저 준비가 필요해요
truecopy 키가 필요해요 (제작자 사이트에서 가입, 비용이 들 수 있음) · 먼저 컴퓨터에 Node.js를 설치하세요 (한 번만)
truecopy 설정에서 TRUECOPY_MCP_ROOT가 비어 있어요. 내 키를 넣고 저장하세요
키는 앱 입력란에만 붙여 넣고, 채팅에 붙이거나 다른 사람에게 보내지 마세요
truecopy을 써서 나에게 무엇을 해 줄 수 있는지 알려 주고, 하나 해 봐✓ Cursor가 truecopy을 쓰고 있다고 하거나 답에 truecopy 도구 이름이 나오면 연결된 거예요
메뉴 이름은 2026년 11월 11일에 Cursor 도움말에서 확인 · 앱 버전에 따라 화면이 조금 다를 수 있어요
VS Code에 연결할 수 있지만 먼저 준비가 필요해요
truecopy 키가 필요해요 (제작자 사이트에서 가입, 비용이 들 수 있음) · 먼저 컴퓨터에 Node.js를 설치하세요 (한 번만)
truecopy 설정에서 TRUECOPY_MCP_ROOT가 비어 있어요. 내 키를 넣고 저장하세요
키는 앱 입력란에만 붙여 넣고, 채팅에 붙이거나 다른 사람에게 보내지 마세요
truecopy을 써서 나에게 무엇을 해 줄 수 있는지 알려 주고, 하나 해 봐✓ VS Code가 truecopy을 쓰고 있다고 하거나 답에 truecopy 도구 이름이 나오면 연결된 거예요
메뉴 이름은 2026년 11월 11일에 VS Code 도움말에서 확인 · 앱 버전에 따라 화면이 조금 다를 수 있어요
Claude Code
claude mcp add truecopy --env TRUECOPY_MCP_ROOT=your-value -- npx -y truecopy mcpClaude Desktop (claude_desktop_config.json)
{
"mcpServers": {
"truecopy": {
"command": "npx",
"args": [
"-y",
"truecopy",
"mcp"
],
"env": {
"TRUECOPY_MCP_ROOT": "your-value"
}
}
}
}Cursor (~/.cursor/mcp.json)
{
"mcpServers": {
"truecopy": {
"command": "npx",
"args": [
"-y",
"truecopy",
"mcp"
],
"env": {
"TRUECOPY_MCP_ROOT": "your-value"
}
}
}
}VS Code (mcp.json)
{
"servers": {
"truecopy": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"truecopy",
"mcp"
],
"env": {
"TRUECOPY_MCP_ROOT": "your-value"
}
}
}
}TRUECOPY_MCP_ROOT env이 설정은 제작자의 레지스트리 정보로 만들었어요. README와 다르면 README를 따르세요.
npm: truecopy이 서버의 연결 방식과 각 앱의 공식 문서를 바탕으로 했어요. 2026년 11월 10일 확인.
내 컴퓨터에서 실행하는 앱
ClaudeGooseLM StudioMsty StudioCherry StudioCursorVS Code + GitHub CopilotVisual StudioWindsurf (Devin Desktop)ZedKiroClineContinueJetBrains AI AssistantClaude CodeCodex CLIGemini CLIOpenCodenodecodeWarpLibreChatRaycast
내 컴퓨터에서 실행돼요. 설치하면 AI 앱에 도구 목록이 나타나요.
누구나 볼 수 있는 정보를 점검했고, 코드는 읽지 않았어요. 해당하지 않는 항목은 개수에서 뺐어요. · 2026년 11월 11일 점검
레지스트리 이름이 GitHub 계정 truecopydev 기준으로 확인되었고, 이 계정이 저장소를 소유하고 있어요
코드 마지막 변경: 어제
아직 GitHub에서 이 저장소를 읽어 오지 않았어요
내 컴퓨터에서 실행되는 서버라 인터넷 엔드포인트가 없어요
내 컴퓨터에서 실행되며, 대신 로컬 설정을 사용해요
내 컴퓨터에서 실행돼요. 도구 목록은 인터넷 엔드포인트가 있는 서버에서만 읽을 수 있어요
질문하고, 팁을 나누고, 안 되는 점을 알려 주세요. "도움이 됨"이 많은 순서예요.
아직 리뷰가 없어요
레지스트리에서 이 카테고리의 활성 서버 전체와 비교했어요. 스타는 게시자가 저장소를 소유한 경우에만 세요.
해당하는 기본 점검 2개 중 2개를 통과했어요. 코드는 읽지 않았어요. 키나 토큰을 넣기 전에 서버가 어떤 권한을 요구하는지 확인하고, 꼭 필요한 권한만 있는 키를 쓰세요.
레지스트리에 필수 키가 나와 있지 않아요. 다만 처음 쓸 때 로그인을 요구하는 서버도 있어요.
내 컴퓨터에서 실행돼요. AI 앱이 필요할 때 실행하고, 데이터는 제작자의 서버를 거치지 않아요(서버 자체가 온라인 서비스를 호출하는 경우는 제외).
GitHub 저장소는 마지막으로 어제 변경됐고, 최신 버전(2.0.23)은 어제 레지스트리에 올라왔어요.
Claude Desktop, Claude Code, Cursor, VS Code처럼 MCP를 지원하는 앱에서 쓸 수 있어요. 내 컴퓨터에 Node.js도 있어야 해요.
같은 카테고리에는: Puter MCP, XcodeBuildMCP, XcodeBuildMCP
같은 카테고리에서 다른 제작자가 만든 서버예요. 스타 순으로 정렬했어요.
카드 보는 법:↓ 주간 다운로드i★ GitHub 스타i세 기둥: 리뷰 · 점검 · 사용 정도i업데이트 = 최신 버전을 레지스트리에 공개한 날i
Puter MCP enables AI tools to interact with Puter: manage files, websites, workers, and more
XcodeBuildMCP provides tools for Xcode project management, simulator management, and app utilities.
XcodeBuildMCP provides tools for Xcode project management, simulator management, and app utilities.
제작자의 저장소에서 쓰인 그대로 가져왔어요. PopNx MCP가 검토하거나 보증한 내용이 아니에요. HTML, 이미지, 스크립트는 제거했어요. 링크를 누르면 이 사이트를 벗어나요.
Extract tables from a PDF in TypeScript, and know when the extraction is wrong.
Turn a document into rows, and refuse the readings you cannot trust. A PDF, a Word or OpenDocument file, a paste, a CSV, an OCR page: one engine reads all of them.
A parser that returns a plausible-looking table from a document it misread is worse than one that returns nothing, because nobody checks a table that looks right. truecopy is the pipeline around whichever reader you write: the door bytes come through, the checks that catch a wrong reading, a way to see what it decided, and a conformance kit that goes red the day the reading stops being honest.
npx -y -p truecopy -p pdfjs-dist truecopy a-statement.pdf
No install, no project, no line of code. The engine is named on the line because it is an optional peer dependency and npm does not fetch one on its own: a project that only ever reads a paste or a CSV never downloads a PDF reader, and for those npx truecopy the-file.csv is the whole command. Left out on a PDF it says no-engine rather than guessing. It prints the cut it made, what each column holds, how often it is filled, and then, on its own, what it could not vouch for.
page 1 - cut at 68, 229, 356, 411, 490
what this reading cannot vouch for:
npm install truecopy
import { readTable } from 'truecopy';
const { rows, warnings, findings } = await readTable(file); // rows [['02/05/2026', 'CARTE AMAZON', '12,40'], …] // warnings ['column 3 of page 2 is filled on only 8% of its rows - the cut may have invented it'] // findings [{ code: 'thin-column', page: 2, column: 3, shareFilled: 0.08, message: '…' }]
No kindOf, no thresholds, no roles. If you only want the cells, destructure rows and go.
file is whatever was dropped. The cut does not care which ruler measured the page, so the same two lines read a PDF, a table pasted out of one, a CSV and a TSV:
| What was dropped | Where a column starts |
|---|---|
| a PDF | the item's x, in points |
| a table pasted with spaces | the character the field starts at |
| a file written with a delimiter | the field's index: a CSV lines nothing up |
| prose, or a file that quotes its fields | nowhere: the row comes back whole, and warnings says so |
That last line is the rule and not the exception. A quoted CSV field may hold the delimiter itself, so splitting on it anyway would shift every column after it. truecopy hands the rows back uncut instead, because half-parsing is the failure this library exists to prevent.
explainDocument names the ruler, so a cut is never a bare list of numbers: cut at 100, 290 on a page, cut at characters 7, 22 on a paste, cut on the delimiter on a CSV, where the columns _are_ the fields and their indices would tell you nothing.
The second field is why this is not just another extractor. An empty `warnings` is not a promise that the reading is right: it means nothing looked wrong from the shape of the page, which is a much smaller claim. Every warning is computed without knowing anything about your document: a page with no columns at all, a column that is almost always empty, pages cut differently from one another, a blank page in the middle.
findings is that same list with a code on it, plus the page and the column it is about. A person reads the sentence; a program branches on the code, and never on English that could be reworded tomorrow.
When the rows have to be trusted (when something downstream acts on them), the rest of this page is how.
A complete reader that runs, in one file and one command:
node example/read-a-statement.mjs
example/read-a-statement.mjs builds a real PDF, opens it, prints what the reading decided, and drives it through the contract. Nothing in it is stubbed, and it needs no document from you: it makes its own.
The first thing you need when a reading comes out wrong is not a better parser. It is knowing which of the three things broke: the document is odd, the cut into columns is wrong, or your rule is wrong. Each calls for a different fix.
import { openDocument, explainDocument } from 'truecopy';
const document = await openDocument(file);
console.log( explainDocument(document, { signature: { kindOf: (cell) => (isDate(cell) ? 'date' : isAmount(cell) ? 'amount' : 'text'), thresholds: { date: { share: 0.6, emptyIsAnomalyAbove: 0.7 }, amount: { share: 0.6 }, text: { share: 0.6 } } }, roles: [ { role: 'when', kind: 'date', minimum: 0.6, take: 'best' }, { role: 'money', kind: 'amount', minimum: 0.6, take: 'each' } ] }) );
truecopy - statement-2026-05.pdf pdf, 1 page(s), 6 row(s)
page 1 - cut at 100, 290
3 column(s), 6 row(s)
col kind filled role 0 date 83% when 1 text 100% - 2 amount 100% money
1 02/05/2026 | CARTE 28/04 AMAZON EU> | 12,40 2 03/05/2026 | VIR SEPA LOYER MAI | 750,00 3 05/05/2026 | CARTE 03/05 SNCF CONN> | 68,00 4 09/05/2026 | PRLV EDF | 91,32 5 12/05/2026 | CARTE 11/05 LE BOULAN> | 7,90 6 ! | TOTAL DES DEBITS | 929,62 <- column 0 (date) is empty
Text, not an image: it goes into a terminal, a CI log, a bug report, a test's expected value. It needs no canvas and no headless browser.
The usual way to read a table is to tune settings until one issuer's layout comes out right. It works, and it stops working at the second issuer: every new bank, every new format, every redesign is another block of settings that only its author understands.
truecopy learns the table from the table. A column full of dates is the date column, whatever its header says; a row that breaks what every other row does is a total, a balance, a footer.
import { findRowAnomalies } from 'truecopy/signature';
// Which rows fall outside the signature the table itself sets. const anomalies = findRowAnomalies(rows, signature);
It reads no label, so it survives an issuer you have never seen. A list of forbidden words only recognises yesterday's documents.
What reads no label is the judgement: which rows belong to the table, which column holds what. The cut is a different problem, and it is the one that still needs help.
Measured on a real bank statement whose header labels were deliberately hidden: the page-wide spread of x proposed twelve columns where the table had five, because it counts the letterhead, the address block and the footer as evidence of where a column starts. Cut on the rows that share the table's shape instead (the ones carrying a date and an amount), it proposed five, and three of the five roles were named from content alone.
`boundariesFromRecurrence` is the general answer, and readTable uses it: keep only the x that come back row after row, because a real column's left edge recurs and a word inside a description does not. On the statement above it took the cut from twelve columns to seven, and named the rest as thin. Where the page gives you something better to trust (a header row, a rule), boundariesFromAnchors takes it.
And whatever you do, keep the self-check. On that same statement the reading still came back wrong, and the only reason that was visible is that the sum of the rows did not match the balances the document itself declares.
That is the honest shape of this library. It does not promise to read an unknown layout correctly. It promises to tell you when it did not.
A value you cannot point at is a value nobody can check. Handed a list of figures, a person has to hunt through the document again; handed a place, they jump to it, and that difference is what makes a correction screen used or abandoned.
import { cellsOf, placesOf } from 'truecopy/layout';
const cells = cellsOf(page); // cells3 is what the fourth row holds const places = placesOf(page); // places3 is where to find it // { page: 1, x: 430, y: 700, width: 30 }
The two are laid out identically, so they are read together. A cell nothing fell into has no place: null, not a rectangle of nothing. ReviewableRow.where carries the same thing for the rows a person is asked to confirm.
No height, because none is known: a text item carries no height here, and inventing a line spacing would draw a rectangle the document never had.
That 1 234,50 and 1,234.50 are the same quantity, that (123,45) is negative and so is 123,45-, that 25/01 is a day before a month here and after it there: none of that says anything about banks or invoices. It says how the page was typeset, and it is the part everybody rewrites and everybody gets wrong once.
import { readNumber, findNumbers, readLeadingDate } from 'truecopy/notation';
readNumber('27800.50'); // 27800.5 - not 2 780 050 readNumber('(123,45)'); // -123.45 - the accounting negative readNumber("1'234.56"); // 1234.56
// Never starts a match inside another number: a date glued to a figure // reads as one figure, not as "026 300,00". findNumbers('30/05/2026 300,00', 2); // [{ value: 300, ... }]
readLeadingDate('25 janv. 2026 GROCERIES', { dateOrder: 'DMY', months }); // { date, length: 13 } - so the caller strips it and keeps the wording
It says null rather than guess. On figures somebody will act upon, a refusal costs a correction and a wrong reading costs a decision.
None of this needs a PDF. truecopy/notation takes strings, so an API field, an HTML scrape or a pasted email gets the same reading as a page, and pdfjs-dist is never loaded. It is the layer worth reaching for before writing a pattern of your own - because the pattern everybody writes instead has a defect nobody sees:
import { accentFree } from 'truecopy/notation';
// \w is [A-Za-z0-9_] in JavaScript, whatever the document is written in. /d[ée]tach\w+/.test('détaché'); // false - the suffix is an accented letter /d[ée]tach\p{L}*/u.test('détaché'); // true accentFree('Détaché'); // 'detache' - or fold first and compare plainly
Nothing fails there: the pattern compiles, runs, and returns a plausible fraction of the matches, which then reads as a fact about the documents rather than a defect in the rule.
try {
await openDocument(file); } catch (error) { if (error instanceof UnreadableDocument) { // 'empty' | 'too-big' | 'no-text' | 'too-slow' | 'no-engine' | 'not-opened' showInYourOwnWords(error.reason); } }
The reason is named so the sentence is not. A library that ships only English prose forces an application that speaks anything else to keep its own copy of the door.
no-engine and not-opened are kept apart on purpose, and the difference is not cosmetic: one says _install pdfjs-dist_, the other says _this file will not open, look for its password_. Told the wrong one, a person hunts for a lock that does not exist and an agent wr