@coeat/mcp-server 0.1.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.
@@ -0,0 +1,7 @@
1
+ interface ApiResponse<T> {
2
+ data: T | null;
3
+ error: string | null;
4
+ status: number;
5
+ }
6
+ export declare const apiGet: <T>(path: string, params?: Record<string, string>) => Promise<ApiResponse<T>>;
7
+ export {};
@@ -0,0 +1,37 @@
1
+ import { getAccessToken } from './auth.js';
2
+ const getBaseUrl = () => {
3
+ const url = process.env.COEAT_API_URL;
4
+ if (!url) {
5
+ throw new Error('Missing COEAT_API_URL environment variable');
6
+ }
7
+ return url.replace(/\/$/, '');
8
+ };
9
+ export const apiGet = async (path, params) => {
10
+ const token = await getAccessToken();
11
+ const baseUrl = getBaseUrl();
12
+ const url = new URL(`${baseUrl}/api/v1${path}`);
13
+ if (params) {
14
+ for (const [key, value] of Object.entries(params)) {
15
+ if (value !== undefined && value !== '') {
16
+ url.searchParams.set(key, value);
17
+ }
18
+ }
19
+ }
20
+ const response = await fetch(url.toString(), {
21
+ headers: {
22
+ Authorization: `Bearer ${token}`,
23
+ 'Content-Type': 'application/json',
24
+ },
25
+ });
26
+ if (!response.ok) {
27
+ const body = await response.json().catch(() => ({ error: response.statusText }));
28
+ return {
29
+ data: null,
30
+ error: body.error ?? `HTTP ${response.status}`,
31
+ status: response.status,
32
+ };
33
+ }
34
+ const data = (await response.json());
35
+ return { data, error: null, status: response.status };
36
+ };
37
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,UAAU,GAAG,GAAW,EAAE;IAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IACtC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC,CAAC;AAQF,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,EAAK,IAAY,EAAE,MAA+B,EAA2B,EAAE;IACxG,MAAM,KAAK,GAAG,MAAM,cAAc,EAAE,CAAC;IACrC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,OAAO,UAAU,IAAI,EAAE,CAAC,CAAC;IAChD,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;gBACxC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;QAC3C,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,KAAK,EAAE;YAChC,cAAc,EAAE,kBAAkB;SACnC;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QACjF,OAAO;YACL,IAAI,EAAE,IAAI;YACV,KAAK,EAAG,IAA2B,CAAC,KAAK,IAAI,QAAQ,QAAQ,CAAC,MAAM,EAAE;YACtE,MAAM,EAAE,QAAQ,CAAC,MAAM;SACxB,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAM,CAAC;IAC1C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;AACxD,CAAC,CAAC"}
package/dist/auth.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Get a valid access token, signing in or refreshing as needed.
3
+ */
4
+ export declare const getAccessToken: () => Promise<string>;
package/dist/auth.js ADDED
@@ -0,0 +1,64 @@
1
+ import { createClient } from '@supabase/supabase-js';
2
+ let session = null;
3
+ let supabaseClient = null;
4
+ let authConfig = null;
5
+ const getConfig = () => {
6
+ if (authConfig)
7
+ return authConfig;
8
+ const supabaseUrl = process.env.COEAT_SUPABASE_URL;
9
+ const supabaseAnonKey = process.env.COEAT_SUPABASE_ANON_KEY;
10
+ const email = process.env.COEAT_EMAIL;
11
+ const password = process.env.COEAT_PASSWORD;
12
+ if (!supabaseUrl || !supabaseAnonKey || !email || !password) {
13
+ throw new Error('Missing required environment variables: COEAT_SUPABASE_URL, COEAT_SUPABASE_ANON_KEY, COEAT_EMAIL, COEAT_PASSWORD');
14
+ }
15
+ authConfig = { supabaseUrl, supabaseAnonKey, email, password };
16
+ return authConfig;
17
+ };
18
+ const signIn = async () => {
19
+ const config = getConfig();
20
+ supabaseClient = createClient(config.supabaseUrl, config.supabaseAnonKey);
21
+ const { data, error } = await supabaseClient.auth.signInWithPassword({
22
+ email: config.email,
23
+ password: config.password,
24
+ });
25
+ if (error || !data.session) {
26
+ throw new Error(`Authentication failed: ${error?.message ?? 'No session returned'}`);
27
+ }
28
+ session = data.session;
29
+ return session.access_token;
30
+ };
31
+ const isTokenExpired = () => {
32
+ if (!session)
33
+ return true;
34
+ // Refresh 60 seconds before expiry
35
+ const expiresAt = session.expires_at ?? 0;
36
+ return Date.now() / 1000 > expiresAt - 60;
37
+ };
38
+ const refreshToken = async () => {
39
+ if (!supabaseClient || !session?.refresh_token) {
40
+ return signIn();
41
+ }
42
+ const { data, error } = await supabaseClient.auth.refreshSession({
43
+ refresh_token: session.refresh_token,
44
+ });
45
+ if (error || !data.session) {
46
+ // If refresh fails, try full sign-in
47
+ return signIn();
48
+ }
49
+ session = data.session;
50
+ return session.access_token;
51
+ };
52
+ /**
53
+ * Get a valid access token, signing in or refreshing as needed.
54
+ */
55
+ export const getAccessToken = async () => {
56
+ if (!session) {
57
+ return signIn();
58
+ }
59
+ if (isTokenExpired()) {
60
+ return refreshToken();
61
+ }
62
+ return session.access_token;
63
+ };
64
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { apiGet } from './api-client.js';
5
+ import { registerProfileTools } from './tools/profile.js';
6
+ import { registerMealTools } from './tools/meals.js';
7
+ import { registerReportTools } from './tools/reports.js';
8
+ // --- Server Setup ---
9
+ const server = new McpServer({
10
+ name: 'coeat',
11
+ version: '0.1.0',
12
+ });
13
+ // --- Register Tools ---
14
+ registerProfileTools(server);
15
+ registerMealTools(server);
16
+ registerReportTools(server);
17
+ // --- Register Resources ---
18
+ const resourceHandler = (path) => async (uri) => {
19
+ const { data, error, status } = await apiGet(path);
20
+ if (error) {
21
+ throw new Error(`API request failed (${status}): ${error}`);
22
+ }
23
+ return { contents: [{ uri: uri.href, text: JSON.stringify(data, null, 2) }] };
24
+ };
25
+ server.resource('profile', 'coeat://profile', { description: 'User profile and nutrition targets', mimeType: 'application/json' }, resourceHandler('/profile'));
26
+ server.resource('meals-today', 'coeat://meals/today', { description: "Today's meals", mimeType: 'application/json' }, resourceHandler('/meals/today'));
27
+ server.resource('summary-today', 'coeat://summary/today', { description: "Today's nutrition summary", mimeType: 'application/json' }, resourceHandler('/daily-summary'));
28
+ server.resource('report-latest', 'coeat://reports/latest', { description: 'Latest weekly report', mimeType: 'application/json' }, resourceHandler('/reports/latest'));
29
+ // --- Start Server ---
30
+ const main = async () => {
31
+ const transport = new StdioServerTransport();
32
+ await server.connect(transport);
33
+ };
34
+ main().catch((err) => {
35
+ console.error('Failed to start MCP server:', err);
36
+ process.exit(1);
37
+ });
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AA2BzD,uBAAuB;AAEvB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,OAAO;IACb,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,yBAAyB;AAEzB,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7B,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAC1B,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAE5B,6BAA6B;AAE7B,MAAM,eAAe,GAAG,CAAI,IAAY,EAAE,EAAE,CAC1C,KAAK,EAAE,GAAQ,EAAE,EAAE;IACjB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAI,IAAI,CAAC,CAAC;IACtD,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,MAAM,KAAK,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAChF,CAAC,CAAC;AAEJ,MAAM,CAAC,QAAQ,CACb,SAAS,EACT,iBAAiB,EACjB,EAAE,WAAW,EAAE,oCAAoC,EAAE,QAAQ,EAAE,kBAAkB,EAAE,EACnF,eAAe,CAAsB,UAAU,CAAC,CACjD,CAAC;AAEF,MAAM,CAAC,QAAQ,CACb,aAAa,EACb,qBAAqB,EACrB,EAAE,WAAW,EAAE,eAAe,EAAE,QAAQ,EAAE,kBAAkB,EAAE,EAC9D,eAAe,CAAiB,cAAc,CAAC,CAChD,CAAC;AAEF,MAAM,CAAC,QAAQ,CACb,eAAe,EACf,uBAAuB,EACvB,EAAE,WAAW,EAAE,2BAA2B,EAAE,QAAQ,EAAE,kBAAkB,EAAE,EAC1E,eAAe,CAAc,gBAAgB,CAAC,CAC/C,CAAC;AAEF,MAAM,CAAC,QAAQ,CACb,eAAe,EACf,wBAAwB,EACxB,EAAE,WAAW,EAAE,sBAAsB,EAAE,QAAQ,EAAE,kBAAkB,EAAE,EACrE,eAAe,CAAa,iBAAiB,CAAC,CAC/C,CAAC;AAEF,uBAAuB;AAEvB,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;IACtB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC,CAAC;AAEF,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;IAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare const registerMealTools: (server: McpServer) => void;
@@ -0,0 +1,79 @@
1
+ import * as z from 'zod/v4';
2
+ import { apiGet } from '../api-client.js';
3
+ const formatMeal = (m, index) => `${index + 1}. ${m.name} - ${m.calories}kcal (P:${m.protein}g F:${m.fat}g C:${m.carbs}g) [${new Date(m.timestamp).toLocaleTimeString('ja-JP', { hour: '2-digit', minute: '2-digit' })}]`;
4
+ export const registerMealTools = (server) => {
5
+ server.tool('get_todays_meals', "Get today's meals", {}, async () => {
6
+ const { data, error } = await apiGet('/meals/today');
7
+ if (error || !data) {
8
+ return { content: [{ type: 'text', text: `Error: ${error ?? 'Unknown error'}` }] };
9
+ }
10
+ if (data.meals.length === 0) {
11
+ return { content: [{ type: 'text', text: `No meals logged today (${data.date}).` }] };
12
+ }
13
+ const totalCalories = data.meals.reduce((sum, m) => sum + m.calories, 0);
14
+ const lines = [
15
+ `Meals for ${data.date} (${data.meals.length} meals, ${totalCalories}kcal total):`,
16
+ '',
17
+ ...data.meals.map(formatMeal),
18
+ ];
19
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
20
+ });
21
+ server.tool('get_meals', 'Get meal history with optional filters', {
22
+ date: z.string().optional().describe('Single date (YYYY-MM-DD)'),
23
+ from: z.string().optional().describe('Start date (YYYY-MM-DD)'),
24
+ to: z.string().optional().describe('End date (YYYY-MM-DD)'),
25
+ limit: z.string().optional().describe('Max results as string (default "50", max "100")'),
26
+ }, async ({ date, from, to, limit }) => {
27
+ const params = {};
28
+ if (date)
29
+ params.date = date;
30
+ if (from)
31
+ params.from = from;
32
+ if (to)
33
+ params.to = to;
34
+ if (limit)
35
+ params.limit = limit;
36
+ const { data, error } = await apiGet('/meals', params);
37
+ if (error || !data) {
38
+ return { content: [{ type: 'text', text: `Error: ${error ?? 'Unknown error'}` }] };
39
+ }
40
+ if (data.meals.length === 0) {
41
+ return { content: [{ type: 'text', text: 'No meals found for the specified criteria.' }] };
42
+ }
43
+ const lines = [
44
+ `Found ${data.count} meal(s):`,
45
+ '',
46
+ ...data.meals.map(formatMeal),
47
+ ];
48
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
49
+ });
50
+ server.tool('get_daily_summary', 'Get daily nutrition summary with targets and achievement', {
51
+ date: z.string().optional().describe('Date (YYYY-MM-DD, default: today)'),
52
+ }, async ({ date }) => {
53
+ const params = {};
54
+ if (date)
55
+ params.date = date;
56
+ const { data, error } = await apiGet('/daily-summary', params);
57
+ if (error || !data) {
58
+ return { content: [{ type: 'text', text: `Error: ${error ?? 'Unknown error'}` }] };
59
+ }
60
+ const lines = [
61
+ `Daily Summary for ${data.date}:`,
62
+ `Meals logged: ${data.mealCount}`,
63
+ '',
64
+ 'Consumed / Target (Achievement):',
65
+ ` Calories: ${data.consumed.calories} / ${data.targets.calories}kcal (${data.achievement.calories}%)`,
66
+ ` Protein: ${data.consumed.protein} / ${data.targets.protein}g (${data.achievement.protein}%)`,
67
+ ` Fat: ${data.consumed.fat} / ${data.targets.fat}g (${data.achievement.fat}%)`,
68
+ ` Carbs: ${data.consumed.carbs} / ${data.targets.carbs}g (${data.achievement.carbs}%)`,
69
+ '',
70
+ 'Remaining:',
71
+ ` Calories: ${data.remaining.calories}kcal`,
72
+ ` Protein: ${data.remaining.protein}g`,
73
+ ` Fat: ${data.remaining.fat}g`,
74
+ ` Carbs: ${data.remaining.carbs}g`,
75
+ ];
76
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
77
+ });
78
+ };
79
+ //# sourceMappingURL=meals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meals.js","sourceRoot":"","sources":["../../src/tools/meals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare const registerProfileTools: (server: McpServer) => void;
@@ -0,0 +1,32 @@
1
+ import { apiGet } from '../api-client.js';
2
+ export const registerProfileTools = (server) => {
3
+ server.tool('get_profile', 'Get user profile and nutrition targets', {}, async () => {
4
+ const { data, error } = await apiGet('/profile');
5
+ if (error || !data) {
6
+ return { content: [{ type: 'text', text: `Error: ${error ?? 'Unknown error'}` }] };
7
+ }
8
+ const { profile, targets } = data;
9
+ const goalLabels = {
10
+ weight_loss: 'Weight Loss / 減量',
11
+ muscle_gain: 'Muscle Gain / 筋肉増量',
12
+ maintenance: 'Maintenance / 現状維持',
13
+ };
14
+ const text = [
15
+ `Name: ${profile.name}`,
16
+ `Age: ${profile.age}, Gender: ${profile.gender}`,
17
+ `Height: ${profile.height}cm, Weight: ${profile.weight}kg`,
18
+ `Goal: ${goalLabels[profile.goal] ?? profile.goal}`,
19
+ `Activity Level: ${profile.activityLevel}`,
20
+ `TDEE: ${profile.tdee}kcal`,
21
+ '',
22
+ 'Daily Targets:',
23
+ ` Calories: ${targets.calories}kcal`,
24
+ ` Protein: ${targets.protein}g`,
25
+ ` Fat: ${targets.fat}g`,
26
+ ` Carbs: ${targets.carbs}g`,
27
+ profile.coach ? `\nCoach: ${profile.coach.name}` : '',
28
+ ].join('\n');
29
+ return { content: [{ type: 'text', text }] };
30
+ });
31
+ };
32
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/tools/profile.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAwB1C,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,MAAiB,EAAE,EAAE;IACxD,MAAM,CAAC,IAAI,CACT,aAAa,EACb,wCAAwC,EACxC,EAAE,EACF,KAAK,IAAI,EAAE;QACT,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAkB,UAAU,CAAC,CAAC;QAElE,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YACnB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,KAAK,IAAI,eAAe,EAAE,EAAE,CAAC,EAAE,CAAC;QAC9F,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QAClC,MAAM,UAAU,GAA2B;YACzC,WAAW,EAAE,kBAAkB;YAC/B,WAAW,EAAE,oBAAoB;YACjC,WAAW,EAAE,oBAAoB;SAClC,CAAC;QAEF,MAAM,IAAI,GAAG;YACX,SAAS,OAAO,CAAC,IAAI,EAAE;YACvB,QAAQ,OAAO,CAAC,GAAG,aAAa,OAAO,CAAC,MAAM,EAAE;YAChD,WAAW,OAAO,CAAC,MAAM,eAAe,OAAO,CAAC,MAAM,IAAI;YAC1D,SAAS,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,EAAE;YACnD,mBAAmB,OAAO,CAAC,aAAa,EAAE;YAC1C,SAAS,OAAO,CAAC,IAAI,MAAM;YAC3B,EAAE;YACF,gBAAgB;YAChB,eAAe,OAAO,CAAC,QAAQ,MAAM;YACrC,cAAc,OAAO,CAAC,OAAO,GAAG;YAChC,UAAU,OAAO,CAAC,GAAG,GAAG;YACxB,YAAY,OAAO,CAAC,KAAK,GAAG;YAC5B,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE;SACtD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IACxD,CAAC,CACF,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare const registerReportTools: (server: McpServer) => void;
@@ -0,0 +1,59 @@
1
+ import * as z from 'zod/v4';
2
+ import { apiGet } from '../api-client.js';
3
+ const formatReport = (r) => {
4
+ const lines = [
5
+ `Weekly Report: ${r.weekStart} ~ ${r.weekEnd}`,
6
+ `Status: ${r.status}`,
7
+ '',
8
+ 'Summary:',
9
+ ` Total Calories: ${r.totalCalories}kcal`,
10
+ ` Protein: ${r.totalProtein}g, Fat: ${r.totalFat}g, Carbs: ${r.totalCarbs}g`,
11
+ ` Meals: ${r.mealCount}, Days Logged: ${r.daysLogged}/7`,
12
+ ` Calorie Goal Achievement: ${r.calorieGoalAchievement}%`,
13
+ ];
14
+ if (r.aiAnalysis?.aiInsights) {
15
+ const insights = r.aiAnalysis.aiInsights;
16
+ if (insights.praise?.length > 0) {
17
+ lines.push('', 'Praise:');
18
+ insights.praise.forEach((p) => lines.push(` - ${p}`));
19
+ }
20
+ if (insights.actionItems?.length > 0) {
21
+ lines.push('', 'Action Items:');
22
+ insights.actionItems.forEach((a) => lines.push(` - ${a.title}: ${a.description}`));
23
+ }
24
+ if (insights.coachMessage) {
25
+ lines.push('', `Coach Message: ${insights.coachMessage}`);
26
+ }
27
+ }
28
+ return lines.join('\n');
29
+ };
30
+ export const registerReportTools = (server) => {
31
+ server.tool('get_weekly_report', 'Get the latest weekly report', {}, async () => {
32
+ const { data, error } = await apiGet('/reports/latest');
33
+ if (error || !data) {
34
+ return { content: [{ type: 'text', text: `Error: ${error ?? 'No reports found'}` }] };
35
+ }
36
+ return { content: [{ type: 'text', text: formatReport(data.report) }] };
37
+ });
38
+ server.tool('get_weekly_reports', 'Get list of weekly reports', {
39
+ limit: z.string().optional().describe('Max results as string (default "10", max "50")'),
40
+ }, async ({ limit }) => {
41
+ const params = {};
42
+ if (limit)
43
+ params.limit = limit;
44
+ const { data, error } = await apiGet('/reports', params);
45
+ if (error || !data) {
46
+ return { content: [{ type: 'text', text: `Error: ${error ?? 'Unknown error'}` }] };
47
+ }
48
+ if (data.reports.length === 0) {
49
+ return { content: [{ type: 'text', text: 'No weekly reports found.' }] };
50
+ }
51
+ const lines = [
52
+ `${data.count} report(s):`,
53
+ '',
54
+ ...data.reports.map((r) => `- ${r.weekStart} ~ ${r.weekEnd}: ${r.totalCalories}kcal, ${r.mealCount} meals, ${r.calorieGoalAchievement}% achievement`),
55
+ ];
56
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
57
+ });
58
+ };
59
+ //# sourceMappingURL=reports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reports.js","sourceRoot":"","sources":["../../src/tools/reports.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@coeat/mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for CoEat nutrition data - access your meals, nutrition targets, and weekly reports from AI assistants",
5
+ "type": "module",
6
+ "bin": {
7
+ "coeat-mcp": "./dist/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsc --watch",
16
+ "start": "node dist/index.js",
17
+ "prepublishOnly": "tsc"
18
+ },
19
+ "keywords": [
20
+ "mcp",
21
+ "model-context-protocol",
22
+ "coeat",
23
+ "nutrition",
24
+ "calorie-tracking",
25
+ "ai"
26
+ ],
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/kazuki-masuda66/aidiet-next.git",
30
+ "directory": "packages/mcp-server"
31
+ },
32
+ "license": "MIT",
33
+ "dependencies": {
34
+ "@modelcontextprotocol/sdk": "^1.12.1",
35
+ "@supabase/supabase-js": "^2.89.0",
36
+ "zod": "^4.0.0"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^22.0.0",
40
+ "typescript": "^5.0.0"
41
+ },
42
+ "engines": {
43
+ "node": ">=18.0.0"
44
+ }
45
+ }