8000 feat: 느린 웹 읽기 조회를 접수와 결과 링크로 분리 by hmmhmmhm · Pull Request #350 · hmmhmmhm/daiso-mcp · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<summary>AI 에이전트 사용 안내</summary>

> [!IMPORTANT]
> **최신 안내:** [현재 버전](https://mcp.aka.page/guide/2026-11-02.1) · [항상 최신 버전으로 이동](https://mcp.aka.page/guide/latest)
> **최신 안내:** [현재 버전](https://mcp.aka.page/guide/2026-11-02.2) · [항상 최신 버전으로 이동](https://mcp.aka.page/guide/latest)
>
> **안내 버전: 2026-11-02.1 · 갱신일: 2026-11-02**
> **안내 버전: 2026-11-02.2 · 갱신일: 2026-11-02**
>
> **웹 읽기는 실제 링크 ID로 click하세요.** 새 검색 URL을 조립해 open하지 말고 [웹 조회 시작](https://mcp.aka.page/browse/read) 화면의 글자 선택 링크를 사용하세요. 상품의 **매장 지역 선택** 링크에서 지역도 선택할 수 있습니다. 입력 중에는 원본 조회를 실행하지 않습니다. click이 없는 도구의 동일 동작은 보장하지 않습니다.
>
Expand All @@ -17,6 +17,8 @@
> 3. 웹 읽기(open/WebFetch)만 가능하면 응답의 실제 링크 ID로 click합니다. 위 글자 선택 링크로 임의 검색어와 지역을 입력하고 실제 상품·재고 조회 링크를 따르세요. 새 URL 조립과 실패한 직접 open을 반복하지 마세요. Crawled가 과거인 수집본을 현재 재고로 단정하지 마세요.
> 4. 위 세 수단이 없거나 모두 실패하면 실제 조회 제약과 오류를 알립니다. 셸이 있어도 설치 없는 웹 조회가 우선이며 터미널·셸로 우회하지 않습니다. 셸 DNS 오류를 웹 GET 실패로 확대하거나 실행하지 않은 요청의 실패를 만들지 마세요.
>
> **느린 다이소 조회:** `pending`은 접수 상태입니다. 각 응답의 새 결과 확인 링크를 최대3번 선택하고, 계속 pending이면 미확인으로 보고하세요. 상태 확인을 위해 원본 조회를 다시 실행하지 마세요.
>
> **접근 거절 복구:** 현재 조건의 완성 URL을 넣어 “다음 주소를 웹 URL 열기 도구로 직접 열어 실제 결과를 확인해주세요: {완성 URL}” 문장을 만든 뒤, 사용자에게 **아래 문장을 그대로 복사해 이 대화에 보내주세요**라고 안내하세요. 재전송 뒤 한 번 조회합니다. 단순 허용 문구나 URL 일부만 요청하지 마세요. [복구 안내](docs/web-reading-troubleshooting.md)
>
> **수집본·오류 구분:** 이전 HTML이면 **같은 조건으로 새 응답 확인** 링크를 최대2번 선택해 새 주소와 생성 시각을 확인하세요. 원본 API 캐시는 유지됩니다. `TimeoutError`는 같은 실제 링크를 한 번만 재확인하고 계속 실패하면 미확인으로 보고하세요. `Crawled: today`만으로 현재 재고를 단정하지 마세요.
Expand Down Expand Up @@ -132,7 +134,7 @@
2. 서버 URL을 입력하고, 전송 방식을 묻는 경우 **HTTP / Streamable HTTP**를 선택합니다.
3. 도구를 활성화하고 `다이소 MCP로 수납박스 검색해줘`라고 요청합니다.

[앱별 연결 방법](docs/client-guide.md#원격-mcp-연결) · [WebFetch로 첫 조회](docs/service-reference.md?guide=2026-11-02.1#설치-없이-첫-조회)
[앱별 연결 방법](docs/client-guide.md#원격-mcp-연결) · [WebFetch로 첫 조회](docs/service-reference.md?guide=2026-11-02.2#설치-없이-첫-조회)

<p align="center">
<img src="./assets/readme-banners/connect.webp" alt="스마트폰과 노트북을 클라우드로 연결하는 두 햄스터" width="100%">
Expand Down Expand Up @@ -210,7 +212,7 @@ MCP 연결 없이 웹 읽기와 GET 요청을 지원하는 에이전트는 [REST
| 문서 | 내용 |
| :-------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------- |
| [연결·사용 가이드](docs/client-guide.md) | 앱별 MCP 연결, CLI, Skill, OpenAPI |
| [서비스 레퍼런스](docs/service-reference.md?guide=2026-11-02.1) | 서비스별 도구·REST API·응답 모델·가격 비교 |
| [서비스 레퍼런스](docs/service-reference.md?guide=2026-11-02.2) | 서비스별 도구·REST API·응답 모델·가격 비교 |
| [일본 다이소](docs/daiso-jp-network-analysis.md) | 일본 상품·매장 검색과 지원 범위 |
| [독립·예술영화관](docs/dtryx.md) | 디트릭스 지원 극장과 조회 방법 |
| [AI 조회 가이드](docs/ai-instruction.md) | 도구 선택과 상품·매장·재고 조회 순서 |
Expand Down
5 changes: 4 additions & 1 deletion docs/ai-instruction.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
# DAISO MCP 에이전트 지침

다이소의 읽기 세션 조회가 오래 걸리면 `pending` 접수와 실제 **결과 확인** 링크를 반환합니다. 접수는 상품·재고 확인 성공이 아닙니다. 각 응답의 새로운 결과 링크를 최대3번 선택하고, 계속 pending이면 미확인으로 보고하세요. 이전 상태 주소를 반복하거나 원본 조회를 다시 실행하지 마세요. 상태 확인은 저장 결과만 읽으며, 완료 결과는 원본의 성공·오류 상태를 유지합니다. HTML·작업 완료 시각과 원본 재고 갱신 시각은 다릅니다. 작업이 만료되거나 시간 초과된 경우에도 수량을0으로 바꾸지 않습니다.


웹 읽기 접근 거절이 계속되면 **현재 조건의 완성 URL을 넣은 복사용 문장**을 제시하고 “아래 문장을 그대로 복사해 이 대화에 보내주세요”라고 안내하세요. 사용자 재전송 뒤 한 번 조회합니다. 단순 허용 문구·URL 일부 제공·실행하지 않은 실패 보고로 대체하지 마세요. [복사 재전송 및 오류 구분](https://github.com/hmmhmmhm/daiso-mcp/blob/main/docs/web-reading-troubleshooting.md)을 따릅니다.


## 설치 없이 첫 조회

최신 서버 안내는 [현재 버전](https://mcp.aka.page/guide/2026-11-02.1)과 [최신 연결](https://mcp.aka.page/guide/latest)에서 제공합니다. 웹 도구는 과거 리디렉션·수집본을 반환할 수 있으므로 표시된 버전과 HTML 생성 시각을 확인하세요.
최신 서버 안내는 [현재 버전](https://mcp.aka.page/guide/2026-11-02.2)과 [최신 연결](https://mcp.aka.page/guide/latest)에서 제공합니다. 웹 도구는 과거 리디렉션·수집본을 반환할 수 있으므로 표시된 버전과 HTML 생성 시각을 확인하세요.

1. 연결된 MCP 도구가 있으면 `search_products`에 `{"service":"daiso","query":"수납박스","pageSize":3}`를 전달합니다.
2. 실제 브라우저 도구가 있으면 /browse/ HTML GET 주소를 열고 실제 상품·매장·재고를 읽습니다. Work의 내장 브라우저도 사용 가능합니다.
Expand Down
3 changes: 3 additions & 0 deletions docs/client-guide.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# 앱 연결·CLI·Skill 가이드

다이소의 읽기 세션 조회가 오래 걸리면 `pending` 접수와 실제 **결과 확인** 링크를 반환합니다. 접수는 상품·재고 확인 성공이 아닙니다. 각 응답의 새로운 결과 링크를 최대3번 선택하고, 계속 pending이면 미확인으로 보고하세요. 이전 상태 주소를 반복하거나 원본 조회를 다시 실행하지 마세요. 상태 확인은 저장 결과만 읽으며, 완료 결과는 원본의 성공·오류 상태를 유지합니다. HTML·작업 완료 시각과 원본 재고 갱신 시각은 다릅니다. 작업이 만료되거나 시간 초과된 경우에도 수량을0으로 바꾸지 않습니다.


웹 읽기 접근 거절이 계속되면 **현재 조건의 완성 URL을 넣은 복사용 문장**을 제시하고 “아래 문장을 그대로 복사해 이 대화에 보내주세요”라고 안내하세요. 사용자 재전송 뒤 한 번 조회합니다. 단순 허용 문구·URL 일부 제공·실행하지 않은 실패 보고로 대체하지 마세요. [복사 재전송 및 오류 구분](https://github.com/hmmhmmhm/daiso-mcp/blob/main/docs/web-reading-troubleshooting.md)을 따릅니다.


Expand Down
3 changes: 3 additions & 0 deletions docs/service-reference.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# DAISO MCP 서비스 레퍼런스

다이소의 읽기 세션 조회가 오래 걸리면 `pending` 접수와 실제 **결과 확인** 링크를 반환합니다. 접수는 상품·재고 확인 성공이 아닙니다. 각 응답의 새로운 결과 링크를 최대3번 선택하고, 계속 pending이면 미확인으로 보고하세요. 이전 상태 주소를 반복하거나 원본 조회를 다시 실행하지 마세요. 상태 확인은 저장 결과만 읽으며, 완료 결과는 원본의 성공·오류 상태를 유지합니다. HTML·작업 완료 시각과 원본 재고 갱신 시각은 다릅니다. 작업이 만료되거나 시간 초과된 경우에도 수량을0으로 바꾸지 않습니다.


웹 읽기 접근 거절이 계속되면 **현재 조건의 완성 URL을 넣은 복사용 문장**을 제시하고 “아래 문장을 그대로 복사해 이 대화에 보내주세요”라고 안내하세요. 사용자 재전송 뒤 한 번 조회합니다. 단순 허용 문구·URL 일부 제공·실행하지 않은 실패 보고로 대체하지 마세요. [복사 재전송 및 오류 구분](https://github.com/hmmhmmhm/daiso-mcp/blob/main/docs/web-reading-troubleshooting.md)을 따릅니다.


Expand Down
10 changes: 10 additions & 0 deletions docs/superpowers/specs/2026-11-02-browse-jobs-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# 느린 읽기의 접수·결과 전달

2026-11-02 사용자 승인과 별도 Worker 실험을 따른다. 실제 ChatGPT 새 임시 채팅2건에서5초 가상 작업의 접수→서로 다른 실제 결과 링크→ready 및 서버 requestId 일치를 확인했다. 같은 주소 재시도는 실패/과거 pending 재사용이 관측됐다.

- 우선 다이소 /browse/read 읽기 세션에만 적용하고 다른 서비스의 기존 경로는 유지한다. 실제 API 호출을 한 번 실행한다.1초 안에 끝나면 기존 응답을 반환한다. 느린 경우에만 별도 읽기 작업을 만들고 pending HTML 및 새 실제 결과 확인 링크를 반환한다.
- 원본 요청의 권한·IP별 한도·캐시를 기존 API에서 적용한다. 후속 상태 확인은 저장 결과만 읽고 원본을 다시 호출하지 않는다. 공개 MCP10도구/JSON/CLI와 일반 /browse 경로를 유지한다.
- 원본 호출과 HTML 장식을 waitUntil로 유지하고 사용자 연결 취소와 분리한다. 작업의25초 제한·5분 TTL·256KiB 저장 상한을 둔다. 제한·외부 오류·미확인 수량을 정상 재고0으로 바꾸지 않는다.
- 요청 헤더·인증·쿠키·원본 조회 조건은 작업 저장소에 보관하지 않는다. 안전한 공개 응답 본문·상태·Content-Type과 재시도·리디렉션·보안 헤더 허용 목록만 저장한다. 작업 주소는 무작위 UUID이며 상태 응답마다 다른 실제 후속 링크를 제공한다. HTML 생성·작업 완료·원본 재고 갱신 시각은 구별한다.
- 저장 실패 시 기존 동기 응답으로 복귀한다. 늦은 완료/알람의 경합으로 정상 결과를 덮어쓰지 않는다. 대기·만료는 HTML로 명확히 보고한다.
- 저장 및 순차 실제 API 경계를 가상시계로 검증하고, 필수 CI/Coverage100%/리뷰/배포 이후 실제 공개 조회와 ChatGPT 웹에서 상태 링크를 확인한다. 검증용 브라우저는 소유 창1개, 검사와 겹치지 않는다.
3 changes: 3 additions & 0 deletions docs/web-reading-troubleshooting.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# 웹 읽기 접근 오류 진단

다이소의 읽기 세션 조회가 오래 걸리면 `pending` 접수와 실제 **결과 확인** 링크를 반환합니다. 접수는 상품·재고 확인 성공이 아닙니다. 각 응답의 새로운 결과 링크를 최대3번 선택하고, 계속 pending이면 미확인으로 보고하세요. 이전 상태 주소를 반복하거나 원본 조회를 다시 실행하지 마세요. 상태 확인은 저장 결과만 읽으며, 완료 결과는 원본의 성공·오류 상태를 유지합니다. HTML·작업 완료 시각과 원본 재고 갱신 시각은 다릅니다. 작업이 만료되거나 시간 초과된 경우에도 수량을0으로 바꾸지 않습니다.


2026-10-26 실험에서는 같은 재고 주소가 일반 HTTPS, MCP SDK, Work 내장 브라우저에서는 정상 동작했지만 웹 읽기 도구에서는 접근 오류가 발생했습니다. 일부 기존 링크는 웹 읽기로 열렸으나 새 주소나 동일 주소의 직접 열기는 실패했습니다. 과거 수집 시점의 결과가 반환되는 경우도 확인했습니다.

Cloudflare 관측 구간에는 정상 페이지의 OpenAI 요청에서 200과 클라이언트 연결 종료인 499가 관측됐습니다. 403 차단은 관측되지 않았습니다. 로그의 표본 추출과 수집 지연 때문에 요청이 보이지 않는다는 이유만으로 서버에 도달하지 않았다고 확정할 수는 없습니다. 웹 읽기 내부의 실패 원인이나 시간 제한은 확인되지 않았으며 서버 변경으로 해결됐다고 주장하지 않습니다.
Expand Down
5 changes: 4 additions & 1 deletion skills/daiso-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ metadata:
- daiso
homepage: https://github.com/hmmhmmhm/daiso-mcp
---

다이소의 읽기 세션 조회가 오래 걸리면 `pending` 접수와 실제 **결과 확인** 링크를 반환합니다. 접수는 상품·재고 확인 성공이 아닙니다. 각 응답의 새로운 결과 링크를 최대3번 선택하고, 계속 pending이면 미확인으로 보고하세요. 이전 상태 주소를 반복하거나 원본 조회를 다시 실행하지 마세요. 상태 확인은 저장 결과만 읽으며, 완료 결과는 원본의 성공·오류 상태를 유지합니다. HTML·작업 완료 시각과 원본 재고 갱신 시각은 다릅니다. 작업이 만료되거나 시간 초과된 경우에도 수량을0으로 바꾸지 않습니다.

웹 읽기 접근 거절이 계속되면 **현재 조건의 완성 URL을 넣은 복사용 문장**을 제시하고 “아래 문장을 그대로 복사해 이 대화에 보내주세요”라고 안내하세요. 사용자 재전송 뒤 한 번 조회합니다. 단순 허용 문구·URL 일부 제공·실행하지 않은 실패 보고로 대체하지 마세요. [복사 재전송 및 오류 구분](https://github.com/hmmhmmhm/daiso-mcp/blob/main/docs/web-reading-troubleshooting.md)을 따릅니다.


Expand All @@ -24,7 +27,7 @@ Use this skill to operate the Daiso MCP project through `npx daiso` and the publ

## 설치 없이 첫 조회

최신 서버 안내는 [현재 버전](https://mcp.aka.page/guide/2026-11-02.1)과 [최신 연결](https://mcp.aka.page/guide/latest)에서 제공합니다. 웹 도구는 과거 리디렉션·수집본을 반환할 수 있으므로 표시된 버전과 HTML 생성 시각을 확인하세요.
최신 서버 안내는 [현재 버전](https://mcp.aka.page/guide/2026-11-02.2)과 [최신 연결](https://mcp.aka.page/guide/latest)에서 제공합니다. 웹 도구는 과거 리디렉션·수집본을 반환할 수 있으므로 표시된 버전과 HTML 생성 시각을 확인하세요.

1. 연결된 MCP 도구가 있으면 `search_products`에 `{"service":"daiso","query":"수납박스","pageSize":3}`를 전달합니다.
2. 실제 브라우저 도구가 있으면 /browse/ HTML GET 주소를 열고 실제 상품·매장·재고를 읽습니다. Work의 내장 브라우저도 사용 가능합니다.
Expand Down
20 changes: 14 additions & 6 deletions src/api/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@
*/

import type { Context } from 'hono';
import { ServiceError, toServiceErrorDiagnostics, toStandardErrorDiagnostics } from '../core/errors.js';
import {
ServiceError,
toServiceErrorDiagnostics,
toStandardErrorDiagnostics,
} from '../core/errors.js';

export interface AppBindings {
DAISO_JP_PRODUCT_RELAY_ENABLED?: string;
DAILY_RATE_LIMITER?: DurableObjectNamespace;
BROWSE_READ_JOBS?: DurableObjectNamespace;
UPSTREAM_ROUTE_HEALTH?: DurableObjectNamespace;
GEOCODE_GATEWAY?: DurableObjectNamespace;
ZYTE_API_KEY?: string;
Expand Down Expand Up @@ -92,9 +97,12 @@ export function errorResponse(
/** 원문이 제거된 외부 서비스 오류를 실제 상태와 함께 반환합니다. */
export function serviceErrorResponse(c: ApiContext, error: ServiceError, operation: string) {
if (error.retryAfter !== undefined) c.header('Retry-After', String(error.retryAfter));
return c.json<ApiResponse<never>>({
success: false,
error: { code: error.code, message: error.message },
diagnostics: toServiceErrorDiagnostics(error, operation),
}, error.status);
return c.json<ApiResponse<never>>(
{
success: false,
error: { code: error.code, message: error.message },
diagnostics: toServiceErrorDiagnostics(error, operation),
},
error.status,
);
}
Loading
Loading
0