Skip to main content
Glama
data-mission

proof-print-dialog

by data-mission

PROOF

창문에 인쇄된 종이를 들어 보이는 손 — 거의 완전히 비어 있고, 중간쯤에 한 줄의 텍스트가 있다. 그 아래에는 용지가 가득 찬 프린터 트레이가 있다.

이미 인쇄해 버렸다. 그때서야 알게 된다.

PROOF는 인쇄 대화상자를 재창조한 것이다. 우표 크기의 미리보기와 막연한 기대 대신, 문서의 모든 페이지를 읽을 수 있는 크기로 보여 주고, 각 페이지가 실제로 렌더링된 레이아웃에서 잉크를 얼마나 쓰는지 측정하며, 종이를 태우기 전에 낭비가 될 용지를 표시해 준다 — 그리고 마지막 편집이 남긴 결과물이 아니라, 당신이 의도한 것을 인쇄한다.

Cursor Calgary 해커톤(2026년 8월)을 위해 제작되었으며, 그 주제는 지루하고 일상적인 애플리케이션 형식을 가져와 시각적으로든 기능적으로든 극적으로 개선하는 것이었다. 인쇄 대화상자는 1995년 이후로 의미 있게 바뀐 적이 없다. 누군가 마침내 손을 댔다면 이렇게 보일 것이다.


문제를 구체적으로

오늘날 대부분의 운영체제가 제공하는 인쇄 대화상자는 우표 크기 정도의 미리보기 창을 보여 준다. 그것이 12페이지가 넘는 문서에 대해 주어지는 전체 가시성이다. 그 크기에서는 한 페이지가 페이지 나눔으로 남겨진 단 하나의 고아 "약관이 적용됩니다." 줄인지, 다른 페이지가 자체 용지로 넘쳐 흐른 "— 계속 —" 표시만 있는지, 또 다른 페이지가 11포인트 세리프 활자로 "이 페이지는 의도적으로 비워 두었습니다"라고 쓰여 있는지 알 수 없다. 인쇄를 누른다. 모든 페이지가 나온다. 그중 몇 장은 콘텐츠가 아니라 장식품이다 — 그리고 그런 일이 일어나는 것을 보기도 전에 그 모든 종이와 토너 비용을 지불한 것이다.

PROOF가 막아내려는 실패 지점이 바로 이것이다: 이미 신뢰하고 있는 대화상자가, 당신이 내리라고 요구하는 결정을 내리기에 충분한 정보를 보여 주지 않는다.

PROOF에는 현실적인 데모 문서가 포함되어 있다 — 20여 개 단락으로 된 분기별 업무 보고서 "Q3_Operating_Review_FINAL_v4.docx"로, 목차, 경영진 요약, 실제 재무 표, 공급망 섹션, 인원 수치, 전망 섹션에 더해, 실제 문서에 쌓이는 바로 그런 종류의 정크 페이지 5장이 의도적으로 삽입되어 있다: 고아가 된 "약관" 바닥글, "— 계속 —" 나눔 잔재, 떠돌이 저작권 줄, "의도적으로 비워 둠" 공지, 그리고 외로운 페이지 번호 하나. 실제로 로드되어 페이지가 매겨진 이 문서는 15페이지에 달하며, PROOF의 자체 실시간 측정 — 손으로 입력한 수치가 아닌 — 은 그중 5페이지를 낭비로 표시하여 10페이지를 인쇄한다. 직접 proof/index.html을 열면 사이드바에 정확히 같은 숫자가 표시되는데, 그 숫자는 페이지가 로드될 때마다 새로 계산되며 여기에 기억된 값이 아니기 때문이다.


Related MCP server: MCP Mortgage Server

숫자가 실제로 만들어지는 방식

이 부분이 정확히 짚고 넘어가야 할 부분인데, 전체 아이디어가 작동하게 만드는 부분이기도 하다: PROOF가 보여 주는 모든 수치는 로드된 문서에서 계산된 것이지, 손으로 입력했거나 그럴듯해 보이도록 꾸민 것이 아니다 — 이는 번들된 데모 문서에도 그리고 아래에서 설명하는 것처럼 그 위에 놓는 어떤 파일에도 동일하게 적용된다.

  1. 페이지 매김은 가정이 아니라 측정이다. 문서의 HTML은 실제 콘텐츠 너비로 숨겨진 실제 DOM 요소에 배치되며, PROOF는 블록 레벨 자식 요소(제목, 문단, 표, 인용구)를 순회하면서 각각의 실제 렌더링 높이(getBoundingClientRect())를 누적하고, 다음 블록이 816×1056px 페이지 상자 — 96dpi에서 8.5"×11" 레터 용지, 대략 1인치 여백 — 를 넘치게 하면 새 페이지로 나눈다. 소스의 명시적 페이지 나눔 표시는 조기 나눔을 강제한다. 따라서 페이지 수는 누군가 고른 숫자가 아니라 레이아웃의 산출물이다.

  2. 잉크 범위는 실제 텍스트 기하 구조에서 측정된다. 완성된 각 페이지에 대해 PROOF는 모든 텍스트 노드를 순회하면서 브라우저 자체 레이아웃 엔진에 글리프가 차지하는 정확한 사각형(Range.getClientRects())을 요청한다 — 픽셀 단위 캔버스 스캔이 아니라, 브라우저가 이미 계산한 실제 기하 구조에 같은 아이디어를 적용한 것이다. 각 사각형의 면적은 명시된 글리프 밀도 상수(GLYPH_DENSITY = 0.16, 즉 일반 텍스트의 줄 상자 약 16%가 실제 잉크이며 글꼴 두께에 따라 증가)로 가중되며, 표/인용구 테두리 획도 잉크를 담으므로 그 위에 더해진다. 합계를 페이지의 콘텐츠 영역으로 나눈 것이 페이지의 잉크 범위 백분율이다.

  3. 캔버스 래스터화 경로도 존재하지만, 대표 수치는 아니다. PROOF에는 두 번째 독립적인 방법(inkOf())도 포함되어 있다: 페이지를 SVG로 직렬화하고 오프스크린 캔버스로 래스터화한 다음, 밝기-어두움으로 가중된 비흰색 픽셀을 센다. 코드는 이 방법을 명시적으로 "보조 의견, 대표 수치에 사용되지 않음"으로 표시해 둔다 — 소스를 읽는다면 알아 둘 가치가 있는데, 두 방법 중 더 직관적이지만 화면에 표시되는 것을 구동하는 방법은 아니기 때문이다.

  4. 낮은 잉크만으로는 낭비가 아니다. 2.0% 잉크 범위(WASTE_THRESHOLD) 미만은 필요 조건이지 충분 조건이 아니다. 페이지는 또한 인식된 페이지 매김 장식품( "의도적으로 비워 둠" 공지, "— 계속 —" 표시, 저작권 줄, 외로운 페이지 번호)이거나 구조적 요소(h1,h2,h3,table,ul,ol,svg,img,blockquote)가 전혀 없고 텍스트가 120자 미만일 때만 표시된다. 이것이 제목 페이지나 목차가 단지 듬성듬성하다는 이유로 잘못 표시되지 않게 하는 것이다 — 번들 데모에서 제목 페이지는 2.06% 잉크, 목차는 1.0%로 측정되며, 둘 다 기술적으로 얇지만 각각 제목이 있으므로 둘 다 인쇄된다.

  5. 표시만이 아니라 이유. 표시된 페이지의 실제 텍스트는 실제 문서에 쌓이는 종류의 장식품 — "의도적으로 비워 둠" 공지, "— 계속 —" 표시, 저작권 줄, 외로운 페이지 번호, 또는 명확한 범주가 없는 짧은 끝줄 — 과 패턴 매칭되므로, 각 낭비 페이지에 표시되는 이유는 특정 데모를 위해 작성된 캡션이 아니라 그 페이지가 실제로 말하는 내용에서 파생된다.

신뢰에 중요하므로 분명히 말한다: 어떤 이유로 레이아웃 기반 측정이 실행될 수 없다면, PROOF는 조용히 아무것도 보여 주지 않거나 조용히 무언가를 지어내지 않는다 — 공개된 결정론적 추정(estimateInk(): 문자 수, 제목 수, 표 셀 수에 대한 명시된 공식)으로 폴백하며, 코드에 정확히 그렇게 — 추정이지 측정이 아님 — 문서화되어 있다. UI의 상태 줄은 지금 보고 있는 숫자를 어느 쪽이 만들었는지 알려 준다measured · N glyph runs across N pages 또는 estimated · layout measurement unavailable로 표시되므로, 측정으로 제시된 추측을 보는 일은 결코 없다. 시트별 세부 패널의 자체 "method" 판독값도 이와 일치하여, 해당 특정 시트에 대해 measured · glyph-run geometry 또는 estimated · block model로 표시된다.

그 아래의 모든 것 — 어떤 페이지가 표시되는지, 절약된 용지 수, 평균 잉크 백분율, 시트를 열 때 표시되는 페이지별 이유, 비용 수치 — 은 현재 로드된 문서에 대해 이 파이프라인이 실행된 결과에서 파생된다. 화면의 어떤 것도 계산으로 꾸민 하드코딩 결과가 아니다.


실제로 보게 되는 것

  • 먼저 판정. 들어간 페이지, 나온 페이지, 삭제된 시트 수와 평균 잉크 백분율이 설정 패널에 묻히지 않고 사이드바의 핵심 통계로 명시된다.

  • 시트 벽. 작업의 모든 페이지가 라이브 썸네일로 표시된다 — 실제 렌더링된 페이지를 CSS transform: scale()로 축소한 것이지, 플레이스홀더 그래픽이나 처음부터 다시 그린 축소판이 아니다 — 낭비 페이지에는 눈에 띄는 도장이 찍히고 페이지별 잉크 게이지가 표시된다.

  • 중첩 공개. 아무 시트나 클릭하면 자체 설명으로 열린다: 어떻게 분류되었는지, 2.0% 임계값에 대한 측정된 잉크 범위, 그리고 표시된 페이지의 경우 — 어떤 특정 종류의 장식품이며 왜 그것을 버려도 인쇄하려던 것이 바뀌지 않는지. 이것이 디자인의 척추다: 문서 → 페이지 → 표시된 시트 하나 → 이유, 각 수준이 다음 수준을 드러낸다. 같은 패널에서 그 시트 하나를 개별적으로 복원하거나 버릴 수 있다.

  • 다른 파일도 실제로 검증. 사이드바에는 진짜 드롭 존이 있다: 자신의 .html, .txt, 또는 .md 파일을 끌어다 놓으면(또는 클릭하여 선택) PROOF가 위에서 설명한 것과 정확히 같은 파이프라인으로 문서를 페이지 매김하고 측정한다 — 이것은 두 번째 데모 모드가 아니라 번들 문서가 통과하는 것과 같은 load() 함수다.

  • 진짜 인쇄 버튼. "Print"는 화면의 작업을 반영하는 숨겨진 인쇄 루트에 대해 브라우저의 실제 window.print()를 호출한다. 버려진/낭비 페이지는 @media print 아래에서 display:none을 가지므로, 인쇄하지 않기로 결정한 용지는 실제로 인쇄되지 않는다. "어쨌든 전부 인쇄"라는 명시적 탈출구도 있으며, 인쇄 CSS는 앱 크롬을 숨겨서 문서 자체만 프린터로 나가게 한다.

  • 전후 비교. 1995년 대화상자는 프레젠테이션 데크(proof/deck.html)에 정직하게 렌더링되어, PROOF가 대신 보여 주는 것과 나란히 놓이므로 대비가 암시적으로만이 아니라 명시적으로 진술된다.

플랫폼

데스크톱과 모바일 모두 하나가 다른 하나에서 축소된 것이 아니라 일급 레이아웃으로 설계되었다 — 시트 벽, 핵심 통계 행, 중첩 상세 보기 모두 전화기 폭까지 전용 브레이크포인트가 있다.


MCP 서버 — 사람이 개입하지 않고 문서 검증

웹 페이지는 PROOF의 한 표면이다. 그 아래에서 PROOF는 AI 에이전트가 직접 사용할 수 있도록 설계되었다: MCP 서버가 웹 UI가 사용하는 것과 같은 문서 모델을 노출하므로, 코딩 에이전트, 문서 파이프라인, 또는 Claude 자신이 단 한 장의 용지가 움직이기 전에 작업을 검증할 수 있다 — 스크린샷도, 미리보기 창을 읽는 사람도 없이.

서버는 proof/mcp/에 있으며 웹 앱이 측정하는 것과 정확히 같은 15페이지 문서를 반영한다 — 같은 파일명(Q3_Operating_Review_FINAL_v4.docx), 같은 5개의 낭비 페이지(4, 6, 9, 11, 13)와 같은 이유, 그리고 index.html 자체가 사용하는 같은 비용 상수(cost_per_sheet_usd: 0.012, cost_per_ink_point_usd: 0.0009)를 사용하므로, ink_cost 호출은 UI가 화면에 표시하는 것과 같은 금액을 인용한다(여기서 평균 잉크 2.97%와 $0.0603 절약, UI에서는 "2.9%"와 "$0.06"으로 반올림). 숨기기보다 명시적으로 진술된 한 가지: 서버의 document.js에 있는 잉크 백분율은 실제 브라우저 측정에서 미러링된 캡처 값이지 서버 자체가 다시 계산한 것이 아니다 — index.htmlRange.getClientRects() 글리프 기하 구조 방법에 대한 휴대용 Node 등가물이 없기 때문이다. 그 API는 실제 레이아웃 엔진에만 존재하므로, 서버는 독립적으로 다시 파생하는 척하지 않고 숫자를 "method": "measured_in_browser_layout"으로 공개한다. 서버가 전달된 임의의 문서를 측정하도록 연결하는 것 — 웹 UI의 드롭 존이 이미 하는 것과 같은 방식 — 이 자연스러운 다음 단계다.

노출된 네 가지 도구는 라이브 스모크 테스트 실행(node proof/mcp/smoke_test.mjs)으로 검증되었다:

도구

기능

proof

문서를 측정하고 각 페이지의 잉크 범위와 채움 백분율을 반환한다.

waste_report

표시된 시트만 반환하며, 각각이 낭비인 구체적인 이유를 함께 반환한다.

drop_pages

표시된 시트를 제거한다 — 실제로 인쇄될 작업을 반환한다. 페이지는 제거되며 다시 흐르지 않는다.

ink_cost

시작 시점 대비 현재 작업의 용지, 잉크 범위, 모델링된 비용.

연결하려면 Claude Desktop, Claude Code, 또는 MCP 호환 클라이언트에서 클라이언트를 서버 디렉토리로 지정한다:

cd proof/mcp
npm install

그런 다음 클라이언트의 설정에서 MCP 서버(stdio 전송)로 추가한다. 예를 들어 Claude Desktop의 claude_desktop_config.json의 경우:

{
  "mcpServers": {
    "proof": {
      "command": "node",
      "args": ["/absolute/path/to/proof/mcp/server.js"]
    }
  }
}

네트워크 홉이 없고 배포할 것도 없다. 서버는 로컬 stdio 프로세스로, 로컬 도구용으로 실행하는 다른 MCP 서버와 똑같다. 이는 프로젝트 전체에 걸친 의도적인 제약이었으며(아래 "백엔드 없음" 참조) 에이전트 계층까지 확장된 것이다. 즉, 데모 중에 실패할 수 있는 호스팅 의존성 없이 에이전트 기능을 제공한다.

서버가 전체 클라이언트를 연결하지 않고도 실제로 end to end로 작동하는지 확인하려면 포함된 스모크 테스트를 실행하면 된다. 이 테스트는 server.js를 실제 자식 프로세스로 stdio 위에서 실행하고, MCP 핸드셰이크를 수행하며, 네 가지 도구를 모두 나열하고 각각을 호출한다:

cd proof/mcp
node smoke_test.mjs

전체 연결 방법(Cursor 전용 구성 포함)은 proof/mcp/README.md에 있다.


실행 방법

이 제품은 정적 HTML/CSS/JS다. 빌드 단계도, 번들러도, 서버도 없다.

open proof/index.html

또는 Finder/Explorer에서 proof/index.html을 더블클릭하면 된다. 그것이 설치 절차의 전부다. npm install도, dev 서버도, 이 저장소의 node_modules에 대한 의존성도 전혀 없으며, 외부 폰트나 CDN 스크립트, 네트워크 이미지도 없다.

이 페이지는 proof/sample-document.js와 짝을 이룬다. 이 파일은 전체 15페이지 데모 보고서(window.SAMPLE_DOC)를 제공하며, 두 파일을 proof/에 함께 두면 일반 <script src> 태그를 통해 자동으로 로드된다. 해당 파일이 없어도 index.html은 깨지지 않는다. 페이지 자체에 내장된 더 작은 자체 포함 데모 문서(FALLBACK)로 폴백하므로 앱이 빈 화면을 보여주는 일은 없고, 단지 더 짧은 문서만 표시된다. 어느 쪽이든 잉크 측정은 파일을 직접 열든(file://) 서빙하든 동일하게 작동한다. 파이프라인의 어떤 것도 교차 출처 네트워크 접근에 의존하지 않기 때문이다.

어떤 이유로든 HTTP로 서빙하고 싶다면(일부 브라우저 확장 프로그램이나 더 엄격한 로컬 보안 정책이 file:// 페이지를 방해할 수 있음) 아무 정적 파일 서버나 사용하면 된다. 예:

npx serve proof

스크린샷 및 캡처 하네스

_brainstorming/ 디렉터리에는 이 프로젝트의 작업 노트가 있으며, 여기에는 해커톤 제출용으로 특정 스크롤 위치와 뷰포트 크기(데스크톱 및 휴대폰)에서 페이지의 프레임 정확한 스크린샷을 찍는 데 사용되는 작은 Playwright 스크립트인 capture.mjs가 포함되어 있다. 이 스크립트는 이 저장소의 루트 package.json에 선언된 playwright devDependency가 필요하다:

npm install
node _brainstorming/capture.mjs proof/index.html --out shots

이것은 개발 도구일 뿐 제품의 일부가 아니다. PROOF 자체는 이 중 어떤 것도 필요로 하지 않는다.


의도적인 백엔드 없음

PROOF에는 제품 자체를 위한 서버도, 데이터베이스도, 배포 단계도 없다. 번들된 데모 "데이터"는 정적 콘텐츠로 제공되는 손수 제작한 현실적인 분기별 보고서(sample-document.js, 파일이 없을 경우 더 작은 내장 폴백 포함)이므로, 여기서 계산되는 모든 숫자(페이지 수, 잉크 커버리지, 낭비 플래그, 비용)는 페이지가 로드되는 순간 실제 콘텐츠에 대한 실제 산술 연산이며, 데모 중에 다운되거나 느리거나 없을 수 있는 백엔드에 대한 fetch가 아니다. 또한 사용자가 파일을 드롭하면 동일한 파이프라인을 통해 실제로 수용한다. MCP 서버는 브라우저 밖에서 실행되는 유일한 프로세스이며, 호스팅된 프로세스가 아닌 로컬 stdio 프로세스이므로 웹 백엔드의 배포 위험을 전혀 지니지 않는다.

인쇄 대화상자를 선택한 이유

디자인 과정에서 약 12개의 다른 "지루한 형식" 후보가 검토되었고 각각 별개의 명시된 이유로 기각되었다. 구독 관리자, 패키지 추적기, 공과금 청구서는 정직하게 재창조하려면 합법적인 출처가 없는 데이터(은행 잔액, 통신사의 실제 추적 상태, 계량기 판독값)를 발명해야 하므로 제외되었다. 취소 플로우와 CAPTCHA는 실제 정보를 추가하지 않아 제외되었다. 브라우저 탭 관리자와 항공사 좌석 배치도는 기존 제품(OneTab/Arc, SeatGuru)이 이미 잘 서비스하고 있어 제외되었다. 쿠키 배너는 의도한 레이어드 스크롤 기반 전개를 담기에는 캔버스가 너무 작았고, 초기의 처방전 용량 개념은 즉시 이해 가능성 테스트를 통과하지 못해 삭제되었다. 인쇄 대화상자는 이 모든 기준을 동시에 통과한 유일한 후보였다. 즉시 알아볼 수 있고, 현재 대화상자가 숨기고 있는 실제 정보를 추가하며, 화면의 모든 극적인 숫자(페이지 수, 빈 페이지 감지, 잉크 커버리지)는 브라우저가 실제 문서에서 아무것도 위조하지 않고 실시간으로 실제로 계산할 수 있는 것이다. 기각된 후보와 각 단계의 근거를 포함한 전체 결정 기록은 _brainstorming/SPEC.md에 있다.


저장소 구조

proof/
  index.html          the product — open this
  sample-document.js   the 15-page demo report loaded into the product
  deck.html            a short, seven-slide product presentation, same art direction
  docs.html             the full feature-by-feature reference, verified against live output
  mcp/
    server.js           the MCP server entrypoint (stdio transport)
    document.js          MCP server's document model — mirrors index.html's live document
    smoke_test.mjs        end-to-end check: spawns the server, calls all four tools
    package.json          MCP server package (@modelcontextprotocol/sdk, zod)
    README.md             MCP-specific install/connect instructions
_brainstorming/
  SPEC.md             the full design/decision record for this project
  capture.mjs          Playwright screenshot harness used for the submission
  ...                  earlier design drafts and research notes, kept for the record
shots/                desktop + mobile submission screenshots of proof/index.html
shots-deck/           submission screenshots of proof/deck.html

proof/deck.html은 짧고 독립적인 제품 프레젠테이션 페이지다. index.html과 같은 방식으로 열면 되며, 인쇄 대화상자가 왜 문제인지, PROOF가 잉크 커버리지를 어떻게 측정하는지(측정 방식 vs. 래스터화 방식), 그리고 낮은 잉크에도 유지되는 분류기의 논리를 제품 자체와 동일한 시각적 언어로 일곱 개의 슬라이드에 걸쳐 설명한다. proof/docs.html은 더 깊이 있는 스크롤 가능한 참조 문서로, MCP 서버를 포함한 모든 기능이 현재 코드를 기준으로 실제 검증된 실시간 숫자와 함께 문서화되어 있다.

Cursor Calgary 해커톤(2026년 8월)을 위해 제작되었다.

F
license - not found
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Provides comprehensive print production and color management tools (Pantone lookup, CMYK/RGB conversion, ink estimation, preflight checks, etc.) that work 100% offline without API keys.
    10
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to parse and analyze mortgage documents (Loan Estimates & Closing Disclosures), converting them into structured MISMO-compliant JSON and checking for TRID compliance violations.
    2
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables deterministic visual and structural analysis of PDF and DOCX documents, extracting measurable evidence such as blur, OCR confidence, and image anomalies for auditable forensic workflows.
    1
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables creating professional documents (invoices, contracts, certificates, proposals, reports) via the DocuQueue API, with tools for template management, filling, previewing, and PDF generation.
    1
    MIT

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/data-mission/proof-print-dialog'

If you have feedback or need assistance with the MCP directory API, please join our Discord server