# TypeScript 런북 — 실행/테스트/Inspector
이 문서는 TypeScript 구현체를 실제로 실행하고, MCP Inspector로 `fs.search_by_time` 도구를 검증하는 방법을 정리합니다.
---
## 0. v0 환경변수 설정(필수)
v0 정책은 [PRD-v0-Policy.md](PRD-v0-Policy.md)에 따라 **허용 루트(allowed roots)를 환경변수로 공급**하는 방식을 고정합니다.
- `ALLOW_ROOTS` (필수): 하나 이상의 루트 경로 목록(`;` 또는 `,`로 구분)
- `DEFAULT_ROOT` (선택): `root` 생략 시 사용할 기본 루트
### 0.1 PowerShell(pwsh) 예시
```powershell
# 예: 단일 루트
$env:ALLOW_ROOTS = "D:\\1.playground_ai\\file_search_mcp"
$env:DEFAULT_ROOT = "D:\\1.playground_ai\\file_search_mcp"
# 예: 여러 루트(세미콜론 구분)
# $env:ALLOW_ROOTS = "D:\\work\\a;D:\\work\\b"
```
### 0.2 입력 시간 형식(v0 주의)
`fs.search_by_time`의 `from/to`는 v0에서 **ISO 8601 date-time 문자열만** 허용합니다(예: `2025-12-15T00:00:00Z`, `2025-12-15T09:00:00+09:00`).
---
## 1. 실행 모드 선택
TypeScript SDK는 대표적으로 다음 2가지 전송을 권장합니다.
- **stdio**: 로컬에서 호스트가 서버 프로세스를 spawn하는 형태
- **Streamable HTTP**: 원격/서버형 배포에 적합(권장)
둘 다 제공하면 개발(로컬)과 운영(서버)을 분리하기 쉽습니다.
---
## 2. stdio 서버 실행
### 2.1 최소 엔트리 예시
```ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = new McpServer({ name: 'file-time-search', version: '1.0.0' });
// TODO: server.registerTool('fs.search_by_time', ...)
const transport = new StdioServerTransport();
await server.connect(transport);
// 중요: stdio 서버에서 stdout 로깅 금지
console.error('MCP server running on stdio');
```
### 2.2 개발 실행
```bash
npm run dev:stdio
```
### 2.3 프로덕션 실행
```bash
npm run build
npm run start:stdio
```
---
## 3. Streamable HTTP 서버 실행
### 3.1 Express 기반 엔트리(요지)
Streamable HTTP는 MCP 스펙(2025-11-25)의 권장 전송입니다.
SDK는 `createMcpExpressApp()`를 제공하며, 로컬 서버에서 문제가 되는 DNS rebinding 공격에 대한 기본 방어를 포함합니다.
```ts
import { randomUUID } from 'node:crypto';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { createMcpExpressApp } from '@modelcontextprotocol/sdk/server/express.js';
const app = createMcpExpressApp();
const transports: Record<string, StreamableHTTPServerTransport> = {};
const server = new McpServer({ name: 'file-time-search', version: '1.0.0' }, { capabilities: { logging: {} } });
// TODO: server.registerTool('fs.search_by_time', ...)
const isInitializeRequest = (body: unknown): boolean =>
typeof body === 'object' && body !== null && 'method' in body && (body as any).method === 'initialize';
app.post('/mcp', async (req, res) => {
const sessionId = req.headers['mcp-session-id'] as string | undefined;
let transport: StreamableHTTPServerTransport | undefined = sessionId ? transports[sessionId] : undefined;
if (!transport) {
if (!isInitializeRequest(req.body)) {
res.status(400).json({ jsonrpc: '2.0', error: { code: -32000, message: 'Bad Request' }, id: null });
return;
}
transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => randomUUID(),
onsessioninitialized: sid => {
transports[sid] = transport!;
}
});
transport.onclose = () => {
const sid = transport!.sessionId;
if (sid) delete transports[sid];
};
await server.connect(transport);
}
await transport.handleRequest(req, res, req.body);
});
app.listen(3000, () => {
console.log('MCP Streamable HTTP listening on http://127.0.0.1:3000/mcp');
});
```
> HTTP 서버에서는 stdout 로깅이 전송을 깨지지 않지만, 운영에서는 structured logger 사용을 권장합니다.
### 3.2 필요한 의존성
```bash
npm install express
npm install -D @types/express
```
(선택) CORS가 필요하면 별도 설정을 추가하세요.
### 3.3 실행
```bash
npm run dev:http
# 또는
npm run build
npm run start:http
```
---
## 4. MCP Inspector로 테스트
MCP Inspector는 서버의 tools/resources/prompts를 인터랙티브하게 확인/호출할 수 있는 개발자 도구입니다.
문서: https://modelcontextprotocol.io/docs/tools/inspector
### 4.1 로컬 stdio 서버 검사(권장)
1) 먼저 빌드
```bash
npm run build
```
2) Inspector 실행 (로컬 JS 엔트리를 직접 실행)
```bash
npx -y @modelcontextprotocol/inspector node dist/stdio.js
```
Inspector UI에서:
- Tools 탭 → `tools/list`로 `fs.search_by_time` 노출 확인
- `tools/call`로 입력을 바꿔가며 케이스 테스트
- Notifications/Logs에서 stderr 로그 확인
### 4.2 Streamable HTTP 서버 검사
- 서버를 먼저 띄운 뒤(예: `http://127.0.0.1:3000/mcp`)
- Inspector의 connection pane에서 **Streamable HTTP** 전송을 선택해 URL을 입력합니다.
---
## 5. 최소 검증 시나리오
[PRD-TestPlan.md](PRD-TestPlan.md)의 시나리오를 Inspector로 그대로 재현하면 됩니다.
특히 아래는 “초기에 반드시” 확인 권장:
- `timeField=modified` / `created` 각각 동작
- `from/to` 경계 포함 여부
- `glob`/`recursive` 조합
- `limit` + `cursor` 페이지네이션
- 권한 없는 폴더/깨진 링크/긴 경로에서의 안전한 실패(`isError` 정책)
---
## 6. 배포 메모(최소)
- npm 패키지로 배포 시:
- `dist/*.js`가 포함되도록 `files` 필드/`npmignore` 설정
- 실행형으로 만들면 `bin` 엔트리와 shebang(예: `#!/usr/bin/env node`) 고려
- 단일 실행 파일 배포가 목표라면 [PRD-Distribution-Review.md](PRD-Distribution-Review.md)의 권장안을 참고