@sophia-vibelog/mcp-server 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +47 -6
  2. package/dist/index.js +97 -0
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -22,11 +22,13 @@ Sophia 웹 대시보드 → 설정 → API 키 관리에서 새 키를 생성합
22
22
  ```json
23
23
  {
24
24
  "mcpServers": {
25
- "vibelog": {
26
- "command": "vibelog-mcp",
25
+ "sophia": {
26
+ "command": "npx",
27
+ "args": ["@sophia-vibelog/mcp-server"],
27
28
  "env": {
28
- "VIBELOG_API_KEY": "your-api-key-here",
29
- "VIBELOG_API_URL": "https://your-sophia-instance.com"
29
+ "SOPHIA_API_KEY": "your-api-key-here",
30
+ "SOPHIA_API_URL": "https://sophia-vibelog.site",
31
+ "ANTHROPIC_API_KEY": "your-anthropic-api-key"
30
32
  }
31
33
  }
32
34
  }
@@ -37,8 +39,9 @@ Sophia 웹 대시보드 → 설정 → API 키 관리에서 새 키를 생성합
37
39
 
38
40
  | 변수 | 필수 | 기본값 | 설명 |
39
41
  |------|------|--------|------|
40
- | `VIBELOG_API_KEY` | O | - | Sophia에서 발급받은 API 키 |
41
- | `VIBELOG_API_URL` | X | `http://localhost:3000` | Sophia 서버 URL |
42
+ | `SOPHIA_API_KEY` | O | - | Sophia에서 발급받은 API 키 |
43
+ | `SOPHIA_API_URL` | X | `http://localhost:3000` | Sophia 서버 URL |
44
+ | `ANTHROPIC_API_KEY` | △ | - | Claude API 키 (rate-prompt 사용 시 필요) |
42
45
 
43
46
  ## 사용법
44
47
 
@@ -60,6 +63,44 @@ AI 코딩 세션 로그를 Sophia에 발행합니다.
60
63
  - `title` (선택) — 로그 제목
61
64
  - `projectId` (선택) — 프로젝트 ID
62
65
 
66
+ #### `rate-prompt`
67
+
68
+ 사용자 질문의 품질을 평가하고 개선 방향을 제안합니다.
69
+
70
+ **사용법:**
71
+
72
+ 질문 끝에 `@@`를 붙이면 소피아가 질문 코칭을 제공합니다:
73
+
74
+ ```
75
+ 사용자: "에러가 난다@@"
76
+
77
+ → Claude의 답변
78
+ ...
79
+ ━━━━━━━━━━━━━━━━━━━━━━━
80
+ 💬 소피아의 질문 코칭
81
+
82
+ 좀 더 구체적으로 말씀해주시면
83
+ 훨씬 정확한 답변을 드릴 수 있어요!
84
+
85
+ 🎯 이 정보가 있으면 완벽해요
86
+ • 어느 페이지/기능에서 발생했나요?
87
+ • 어떤 에러 메시지가 보이나요?
88
+
89
+ ✨ 예를 들면 이렇게요
90
+ "○○ 페이지에서 △△ 버튼을 눌렀을 때
91
+ 'Type error: ...' 에러가 발생해요"
92
+ ━━━━━━━━━━━━━━━━━━━━━━━
93
+ ```
94
+
95
+ **매개변수:**
96
+ - `userMessage` (필수) — 평가할 사용자 메시지 (`@@`는 제거된 상태)
97
+ - `conversationContext` (선택) — 대화 맥락
98
+
99
+ **특징:**
100
+ - 👓 `@@` = 안경 쓰고 자세히 보기
101
+ - 💬 격려 중심 코칭 (점수/비판 없음)
102
+ - 📍 답변 맨 마지막에 표시 (긴 스크롤 고려)
103
+
63
104
  ## 개발
64
105
 
65
106
  ```bash
package/dist/index.js CHANGED
@@ -2,8 +2,13 @@
2
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
  import { z } from "zod";
5
+ import Anthropic from "@anthropic-ai/sdk";
5
6
  const SOPHIA_API_URL = process.env.SOPHIA_API_URL || "http://localhost:3000";
6
7
  const SOPHIA_API_KEY = process.env.SOPHIA_API_KEY || "";
8
+ const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "";
9
+ const anthropic = ANTHROPIC_API_KEY
10
+ ? new Anthropic({ apiKey: ANTHROPIC_API_KEY })
11
+ : null;
7
12
  const server = new McpServer({
8
13
  name: "sophia-mcp",
9
14
  version: "0.1.0",
@@ -74,6 +79,98 @@ server.tool("publish-log", "VibeLog에 AI 코딩 세션 로그를 발행합니
74
79
  };
75
80
  }
76
81
  });
82
+ server.tool("rate-prompt", "사용자의 질문 품질을 평가하고 개선 제안을 제공합니다. 질문 끝에 @@가 붙어있을 때만 사용하세요.", {
83
+ userMessage: z.string().describe("평가할 사용자 메시지 (@@는 제거된 상태)"),
84
+ conversationContext: z
85
+ .string()
86
+ .optional()
87
+ .describe("대화 맥락 (선택사항)"),
88
+ }, async ({ userMessage, conversationContext }) => {
89
+ if (!anthropic) {
90
+ return {
91
+ content: [
92
+ {
93
+ type: "text",
94
+ text: "ANTHROPIC_API_KEY가 설정되지 않았습니다. 환경변수에 API 키를 설정해주세요.",
95
+ },
96
+ ],
97
+ isError: true,
98
+ };
99
+ }
100
+ try {
101
+ const prompt = `당신은 '소피아'로, 사용자의 질문을 더 나아지도록 돕는 친절한 코치입니다.
102
+
103
+ 사용자의 질문을 분석하고, 격려하면서 개선 포인트를 제안해주세요.
104
+ 절대 점수를 매기거나 비판하지 마세요. 파트너처럼 함께 더 나은 질문을 만들어가는 느낌으로.
105
+
106
+ 평가 기준:
107
+ - 위치: 어디서 발생했는지 명확한가?
108
+ - 동작: 무엇을 했는지 명확한가?
109
+ - 증상: 무슨 일이 일어났는지 명확한가?
110
+ - 에러 메시지: 구체적인 에러가 있는가?
111
+ - 예상 vs 실제: 원래 어떻게 되어야 하는지 설명했는가?
112
+
113
+ 사용자 질문:
114
+ "${userMessage}"
115
+
116
+ ${conversationContext ? `대화 맥락:\n${conversationContext}` : ""}
117
+
118
+ 출력 형식 (반드시 JSON):
119
+ {
120
+ "encouragement": "격려 메시지 (예: '좀 더 구체적으로 말씀해주시면 훨씬 정확한 답변을 드릴 수 있어요!')",
121
+ "strengths": ["이미 좋은 점1", "이미 좋은 점2"] (없으면 빈 배열),
122
+ "improvements": ["필요한 정보1", "필요한 정보2"] (예: "어느 페이지/기능에서 발생했나요?"),
123
+ "example": "구체적인 질문 예시 (한 문장)"
124
+ }`;
125
+ const response = await anthropic.messages.create({
126
+ model: "claude-3-5-sonnet-20241022",
127
+ max_tokens: 1024,
128
+ messages: [{ role: "user", content: prompt }],
129
+ });
130
+ const textContent = response.content.find((c) => c.type === "text");
131
+ if (!textContent || textContent.type !== "text") {
132
+ throw new Error("No text content in response");
133
+ }
134
+ const result = JSON.parse(textContent.text);
135
+ // 피드백 포맷팅
136
+ let feedback = `\n━━━━━━━━━━━━━━━━━━━━━━━\n`;
137
+ feedback += `💬 소피아의 질문 코칭\n\n`;
138
+ feedback += `${result.encouragement}\n`;
139
+ if (result.strengths.length > 0) {
140
+ feedback += `\n✨ 이미 좋은 점 / 이 질문이 좋은 이유\n`;
141
+ result.strengths.forEach((s) => {
142
+ feedback += ` • ${s}\n`;
143
+ });
144
+ }
145
+ if (result.improvements.length > 0) {
146
+ const header = result.strengths.length > 0
147
+ ? `\n💡 한 가지만 더하면 완벽\n`
148
+ : `\n🎯 이것만 더 알려주세요\n`;
149
+ feedback += header;
150
+ result.improvements.forEach((i) => {
151
+ feedback += ` • ${i}\n`;
152
+ });
153
+ }
154
+ if (result.example) {
155
+ feedback += `\n✨ 예를 들면 이렇게요\n "${result.example}"\n`;
156
+ }
157
+ feedback += `\n━━━━━━━━━━━━━━━━━━━━━━━\n`;
158
+ return {
159
+ content: [{ type: "text", text: feedback }],
160
+ };
161
+ }
162
+ catch (e) {
163
+ return {
164
+ content: [
165
+ {
166
+ type: "text",
167
+ text: `프롬프트 평가 실패: ${e instanceof Error ? e.message : "알 수 없는 오류"}`,
168
+ },
169
+ ],
170
+ isError: true,
171
+ };
172
+ }
173
+ });
77
174
  async function main() {
78
175
  const transport = new StdioServerTransport();
79
176
  await server.connect(transport);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sophia-vibelog/mcp-server",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Sophia (VibeLog) MCP Server — Claude Code에서 AI 코딩 세션 로그를 자동 발행합니다",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -30,6 +30,7 @@
30
30
  "lint": "echo 'no lint configured'"
31
31
  },
32
32
  "dependencies": {
33
+ "@anthropic-ai/sdk": "^0.74.0",
33
34
  "@modelcontextprotocol/sdk": "^1.26.0",
34
35
  "zod": "^4.3.6"
35
36
  },