[G1-Sync] Manual knowledge update
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
---
|
||||
id: ai-mcp-integration-patterns
|
||||
title: MCP — Model Context Protocol / Tool Server
|
||||
category: Coding
|
||||
status: draft
|
||||
source_trust_level: B
|
||||
verification_status: conceptual
|
||||
created_at: 2026-05-09
|
||||
updated_at: 2026-05-09
|
||||
tags: [ai, mcp, llm, vibe-coding]
|
||||
tech_stack: { language: "TS / MCP SDK", applicable_to: ["Backend"] }
|
||||
applied_in: []
|
||||
aliases: [MCP, Model Context Protocol, Anthropic, tool server, resource, prompts]
|
||||
---
|
||||
|
||||
# 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)
|
||||
```ts
|
||||
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
|
||||
```bash
|
||||
node dist/server.js
|
||||
```
|
||||
|
||||
### Client config (Claude Desktop)
|
||||
```json
|
||||
// ~/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)
|
||||
```ts
|
||||
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)
|
||||
```ts
|
||||
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
|
||||
```ts
|
||||
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
|
||||
```json
|
||||
{ "tools": {}, "resources": { "subscribe": true }, "prompts": {}, "sampling": {} }
|
||||
```
|
||||
|
||||
- Sampling: server 가 LLM 에 추가 호출 요청.
|
||||
- Subscribe: resource 변경 알림.
|
||||
|
||||
### Common MCP servers (커뮤니티)
|
||||
- @modelcontextprotocol/server-filesystem
|
||||
- @modelcontextprotocol/server-github
|
||||
- @modelcontextprotocol/server-postgres
|
||||
- 자체 = 회사 내 도구 wrap.
|
||||
|
||||
### 디버깅
|
||||
```bash
|
||||
# stdio 의 JSON-RPC trace
|
||||
MCP_DEBUG=true node server.js
|
||||
```
|
||||
|
||||
```ts
|
||||
// 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.
|
||||
|
||||
## 🔗 관련 문서
|
||||
- [[AI_Function_Calling_Deep]]
|
||||
- [[AI_Agentic_Patterns]]
|
||||
- [[Backend_Webhook_Patterns]]
|
||||
Reference in New Issue
Block a user