@sophia-vibelog/mcp-server 0.2.2 → 0.3.1

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 (2) hide show
  1. package/dist/index.js +26 -47
  2. package/package.json +1 -2
package/dist/index.js CHANGED
@@ -2,16 +2,11 @@
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";
6
5
  const SOPHIA_API_URL = process.env.SOPHIA_API_URL || "http://localhost:3000";
7
6
  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;
12
7
  const server = new McpServer({
13
8
  name: "sophia-mcp",
14
- version: "0.1.0",
9
+ version: "0.3.0",
15
10
  });
16
11
  server.tool("publish-log", "VibeLog에 AI 코딩 세션 로그를 발행합니다. 세션 로그 텍스트를 전달하면 AI가 분석하고 소피아가 조언을 남깁니다.", {
17
12
  rawSessionLog: z.string().describe("AI 코딩 세션의 전체 로그 텍스트"),
@@ -79,65 +74,49 @@ server.tool("publish-log", "VibeLog에 AI 코딩 세션 로그를 발행합니
79
74
  };
80
75
  }
81
76
  });
82
- server.tool("rate-prompt", "사용자의 질문 품질을 평가하고 개선 제안을 제공합니다. 질문 끝에 @@가 붙어있을 때만 사용하세요.", {
77
+ server.tool("rate-prompt", "사용자의 질문 품질을 평가하고 개선 제안을 제공합니다. 질문 끝에 @@가 붙어있을 때만 사용하세요. 중요: 이 도구의 출력은 반드시 응답의 가장 마지막에, 원본 포맷 그대로(━━━ 테두리, 들여쓰기, 이모지 포함) 표시하세요. 재가공, 요약, 마크다운 변환을 하지 마세요.", {
83
78
  userMessage: z.string().describe("평가할 사용자 메시지 (@@는 제거된 상태)"),
84
79
  conversationContext: z
85
80
  .string()
86
81
  .optional()
87
82
  .describe("대화 맥락 (선택사항)"),
88
83
  }, async ({ userMessage, conversationContext }) => {
89
- if (!anthropic) {
84
+ if (!SOPHIA_API_KEY) {
90
85
  return {
91
86
  content: [
92
87
  {
93
88
  type: "text",
94
- text: "ANTHROPIC_API_KEY가 설정되지 않았습니다. 환경변수에 API 키를 설정해주세요.",
89
+ text: "SOPHIA_API_KEY가 설정되지 않았습니다. VibeLog 설정에서 API 키를 생성한 후 환경변수에 설정해주세요.",
95
90
  },
96
91
  ],
97
92
  isError: true,
98
93
  };
99
94
  }
100
95
  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-sonnet-4-5-20250929",
127
- max_tokens: 1024,
128
- messages: [{ role: "user", content: prompt }],
96
+ const response = await fetch(`${SOPHIA_API_URL}/api/rate-prompt`, {
97
+ method: "POST",
98
+ headers: {
99
+ "Content-Type": "application/json",
100
+ Authorization: `Bearer ${SOPHIA_API_KEY}`,
101
+ },
102
+ body: JSON.stringify({
103
+ userMessage,
104
+ conversationContext: conversationContext || undefined,
105
+ }),
129
106
  });
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
- // 마크다운 코드블록 제거 (```json ... ``` → raw JSON)
135
- let rawJson = textContent.text.trim();
136
- const codeBlockMatch = rawJson.match(/```(?:json)?\s*([\s\S]*?)```/);
137
- if (codeBlockMatch) {
138
- rawJson = codeBlockMatch[1].trim();
107
+ if (!response.ok) {
108
+ const error = await response.json().catch(() => ({}));
109
+ return {
110
+ content: [
111
+ {
112
+ type: "text",
113
+ text: `프롬프트 평가 실패 (${response.status}): ${error.error || "알 수 없는 오류"}`,
114
+ },
115
+ ],
116
+ isError: true,
117
+ };
139
118
  }
140
- const result = JSON.parse(rawJson);
119
+ const result = await response.json();
141
120
  // 피드백 포맷팅
142
121
  let feedback = `\n━━━━━━━━━━━━━━━━━━━━━━━\n`;
143
122
  feedback += `💬 소피아의 질문 코칭\n\n`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sophia-vibelog/mcp-server",
3
- "version": "0.2.2",
3
+ "version": "0.3.1",
4
4
  "description": "Sophia (VibeLog) MCP Server — Claude Code에서 AI 코딩 세션 로그를 자동 발행합니다",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -30,7 +30,6 @@
30
30
  "lint": "echo 'no lint configured'"
31
31
  },
32
32
  "dependencies": {
33
- "@anthropic-ai/sdk": "^0.74.0",
34
33
  "@modelcontextprotocol/sdk": "^1.26.0",
35
34
  "zod": "^4.3.6"
36
35
  },