9148c358d0
Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를 Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류. - 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로 자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거, 동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거. - 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming, Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business, Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로, 나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는 title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백). 원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지. - 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서. - 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는 지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지. - Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경. - 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
5.5 KiB
5.5 KiB
id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
| id | title | category | status | source_trust_level | verification_status | created_at | updated_at | tags | tech_stack | applied_in | aliases | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ai-mcp-integration-patterns | MCP — Model Context Protocol / Tool Server | Coding | draft | B | conceptual | 2026-05-09 | 2026-05-09 |
|
|
|
MCP (Model Context Protocol)
Anthropic 표준 — LLM 이 tool / resource / prompts 를 통일된 방식으로 사용. Claude Desktop, Cursor, Cline, IDE 통합 의 표준. JSON-RPC 기반, stdio / HTTP+SSE.
📖 핵심 개념
- Server: tool / resource / prompts 제공.
- Client: LLM 앱 (Claude Desktop, IDE).
- Tools: 함수 (action).
- Resources: 데이터 (file / db).
- Prompts: 재사용 prompt template.
💻 코드 패턴
MCP Server (TS, stdio)
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
ListResourcesRequestSchema,
ReadResourceRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
const server = new Server({ name: 'acme-tools', version: '1.0.0' }, { capabilities: { tools: {}, resources: {} } });
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'search_orders',
description: 'Search orders by customer email',
inputSchema: {
type: 'object',
properties: { email: { type: 'string' } },
required: ['email'],
},
},
],
}));
server.setRequestHandler(CallToolRequestSchema, async (req) => {
if (req.params.name === 'search_orders') {
const orders = await db.orders.findByEmail(req.params.arguments.email);
return { content: [{ type: 'text', text: JSON.stringify(orders) }] };
}
throw new Error('unknown tool');
});
const transport = new StdioServerTransport();
await server.connect(transport);
Run
node dist/server.js
Client config (Claude Desktop)
// ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"acme": {
"command": "node",
"args": ["/path/to/server.js"],
"env": { "DB_URL": "postgres://..." }
}
}
}
→ Claude 재시작 → tool 자동 인식.
Resources (data exposure)
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
resources: [
{ uri: 'acme://users', name: 'Users', mimeType: 'application/json' },
{ uri: 'acme://orders/recent', name: 'Recent orders', mimeType: 'application/json' },
],
}));
server.setRequestHandler(ReadResourceRequestSchema, async (req) => {
if (req.params.uri === 'acme://users') {
return { contents: [{ uri: req.params.uri, mimeType: 'application/json', text: JSON.stringify(await db.users.list()) }] };
}
throw new Error('not found');
});
Prompts (reusable template)
server.setRequestHandler(ListPromptsRequestSchema, async () => ({
prompts: [
{ name: 'analyze-customer', description: 'Summarize a customer', arguments: [{ name: 'email', required: true }] },
],
}));
server.setRequestHandler(GetPromptRequestSchema, async (req) => {
if (req.params.name === 'analyze-customer') {
return {
messages: [{
role: 'user',
content: { type: 'text', text: `Summarize ${req.params.arguments?.email}'s purchase history.` },
}],
};
}
});
HTTP + SSE transport
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
app.get('/sse', async (req, res) => {
const transport = new SSEServerTransport('/messages', res);
await server.connect(transport);
});
app.post('/messages', (req, res) => transport.handlePostMessage(req, res));
→ 멀티 client / cloud-deployed.
Auth (HTTP)
- OAuth: 사용자가 server 에 인증.
- Bearer: API key.
- TLS + CORS.
Capabilities
{ "tools": {}, "resources": { "subscribe": true }, "prompts": {}, "sampling": {} }
- Sampling: server 가 LLM 에 추가 호출 요청.
- Subscribe: resource 변경 알림.
Common MCP servers (커뮤니티)
- @modelcontextprotocol/server-filesystem
- @modelcontextprotocol/server-github
- @modelcontextprotocol/server-postgres
- 자체 = 회사 내 도구 wrap.
디버깅
# stdio 의 JSON-RPC trace
MCP_DEBUG=true node server.js
// Inspector
npx @modelcontextprotocol/inspector node server.js
🤔 의사결정 기준
| 사용 | 추천 |
|---|---|
| Claude Desktop / Cursor 통합 | MCP server |
| 회사 내 코딩 도우미 | MCP + private tools |
| Public API → AI tool | OpenAI tool / function calling |
| 프롬프트 템플릿 공유 | MCP prompts |
| Cloud-hosted multi-user | MCP HTTP+SSE |
| LangChain / LlamaIndex | tool wrapper (직접) |
❌ 안티패턴
- Tool description 빈약: LLM 이 못 고름.
- Tool 가 sensitive 작업 confirm 없이: HITL 필요.
- PII resource 그대로 expose: filter / mask.
- Tool error 그대로 throw: LLM 이 복구 못 함. content + isError.
- Sync long task: timeout. async + status.
- Auth 없는 prod HTTP: 누구나 호출.
- Schema 자주 변경: 등록된 tool descrip 깨짐.
🤖 LLM 활용 힌트
- 회사 도구 = MCP server 로 wrap → 모든 LLM 클라이언트 호환.
- Tool 명확 descrip + JSON schema 작게.
- Sensitive = HITL or audit.