rewind-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.
- package/README.md +140 -0
- package/dist/client.d.ts +21 -0
- package/dist/client.js +62 -0
- package/dist/client.js.map +1 -0
- package/dist/consent.d.ts +10 -0
- package/dist/consent.js +148 -0
- package/dist/consent.js.map +1 -0
- package/dist/github-auth.d.ts +21 -0
- package/dist/github-auth.js +60 -0
- package/dist/github-auth.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts.d.ts +2 -0
- package/dist/prompts.js +93 -0
- package/dist/prompts.js.map +1 -0
- package/dist/resources.d.ts +3 -0
- package/dist/resources.js +80 -0
- package/dist/resources.js.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.js +59 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/collecting.d.ts +3 -0
- package/dist/tools/collecting.js +92 -0
- package/dist/tools/collecting.js.map +1 -0
- package/dist/tools/cross-domain.d.ts +3 -0
- package/dist/tools/cross-domain.js +114 -0
- package/dist/tools/cross-domain.js.map +1 -0
- package/dist/tools/helpers.d.ts +32 -0
- package/dist/tools/helpers.js +69 -0
- package/dist/tools/helpers.js.map +1 -0
- package/dist/tools/listening.d.ts +3 -0
- package/dist/tools/listening.js +176 -0
- package/dist/tools/listening.js.map +1 -0
- package/dist/tools/reading.d.ts +3 -0
- package/dist/tools/reading.js +85 -0
- package/dist/tools/reading.js.map +1 -0
- package/dist/tools/running.d.ts +3 -0
- package/dist/tools/running.js +135 -0
- package/dist/tools/running.js.map +1 -0
- package/dist/tools/watching.d.ts +3 -0
- package/dist/tools/watching.js +138 -0
- package/dist/tools/watching.js.map +1 -0
- package/dist/worker.d.ts +20 -0
- package/dist/worker.js +173 -0
- package/dist/worker.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { withErrorHandling, formatDate, timeAgo, fmt, READ_ONLY_ANNOTATIONS, dateFilterParams, } from './helpers.js';
|
|
3
|
+
export function registerListeningTools(server, client) {
|
|
4
|
+
// get_now_playing
|
|
5
|
+
server.tool('get_now_playing', 'Get the track currently playing on Last.fm. Returns the song, artist, and album if something is playing.', {}, READ_ONLY_ANNOTATIONS, async () => withErrorHandling(async () => {
|
|
6
|
+
const data = await client.get('/listening/now-playing');
|
|
7
|
+
if (!data.is_playing || !data.track) {
|
|
8
|
+
return 'Nothing playing right now.';
|
|
9
|
+
}
|
|
10
|
+
const artist = data.artist?.name ?? 'Unknown Artist';
|
|
11
|
+
const album = data.album?.name ? ` (from ${data.album.name})` : '';
|
|
12
|
+
return `Now playing: "${data.track.name}" by ${artist}${album}`;
|
|
13
|
+
}));
|
|
14
|
+
// get_recent_listens
|
|
15
|
+
server.tool('get_recent_listens', 'Get recently scrobbled tracks from Last.fm. Returns a list of recent plays with artist, album, and time. Supports date filtering.', {
|
|
16
|
+
limit: z
|
|
17
|
+
.number()
|
|
18
|
+
.min(1)
|
|
19
|
+
.max(50)
|
|
20
|
+
.default(10)
|
|
21
|
+
.describe('Number of recent tracks to return (default 10, max 50)'),
|
|
22
|
+
...dateFilterParams,
|
|
23
|
+
}, READ_ONLY_ANNOTATIONS, async ({ limit, date, from, to }) => withErrorHandling(async () => {
|
|
24
|
+
const data = await client.get('/listening/recent', { limit, date, from, to });
|
|
25
|
+
if (!data.data.length)
|
|
26
|
+
return 'No recent listens found.';
|
|
27
|
+
const lines = ['Recent listens:'];
|
|
28
|
+
for (const [i, s] of data.data.entries()) {
|
|
29
|
+
const album = s.album?.name ? ` -- ${s.album.name}` : '';
|
|
30
|
+
lines.push(`${i + 1}. "${s.track.name}" by ${s.artist.name}${album} (${timeAgo(s.scrobbled_at)})`);
|
|
31
|
+
}
|
|
32
|
+
return lines.join('\n');
|
|
33
|
+
}));
|
|
34
|
+
// get_listening_stats
|
|
35
|
+
server.tool('get_listening_stats', 'Get overall listening statistics from Last.fm including total scrobbles, unique artists, albums, tracks, and daily average. Supports date filtering for period-specific stats.', { ...dateFilterParams }, READ_ONLY_ANNOTATIONS, async ({ date, from, to }) => withErrorHandling(async () => {
|
|
36
|
+
const data = await client.get('/listening/stats', { date, from, to });
|
|
37
|
+
return [
|
|
38
|
+
'Listening Stats:',
|
|
39
|
+
`- Total scrobbles: ${fmt(data.total_scrobbles)}`,
|
|
40
|
+
`- Unique artists: ${fmt(data.unique_artists)}`,
|
|
41
|
+
`- Unique albums: ${fmt(data.unique_albums)}`,
|
|
42
|
+
`- Unique tracks: ${fmt(data.unique_tracks)}`,
|
|
43
|
+
`- Average per day: ${data.scrobbles_per_day.toFixed(1)}`,
|
|
44
|
+
`- Years tracking: ${data.years_tracking}`,
|
|
45
|
+
].join('\n');
|
|
46
|
+
}));
|
|
47
|
+
// get_top_artists
|
|
48
|
+
server.tool('get_top_artists', 'Get top listened-to artists from Last.fm for a given time period. Returns ranked list with play counts.', {
|
|
49
|
+
period: z
|
|
50
|
+
.enum(['7day', '1month', '3month', '6month', '12month', 'overall'])
|
|
51
|
+
.default('1month')
|
|
52
|
+
.describe('Time period for rankings'),
|
|
53
|
+
limit: z
|
|
54
|
+
.number()
|
|
55
|
+
.min(1)
|
|
56
|
+
.max(50)
|
|
57
|
+
.default(10)
|
|
58
|
+
.describe('Number of artists to return'),
|
|
59
|
+
page: z.number().min(1).default(1).describe('Page number for pagination'),
|
|
60
|
+
}, READ_ONLY_ANNOTATIONS, async ({ period, limit, page }) => withErrorHandling(async () => {
|
|
61
|
+
const data = await client.get('/listening/top/artists', { period, limit, page });
|
|
62
|
+
if (!data.data.length)
|
|
63
|
+
return `No top artists for period: ${period}`;
|
|
64
|
+
const lines = [`Top Artists (${period}):`];
|
|
65
|
+
for (const a of data.data) {
|
|
66
|
+
lines.push(`${a.rank}. ${a.name} -- ${fmt(a.playcount)} plays`);
|
|
67
|
+
}
|
|
68
|
+
return lines.join('\n');
|
|
69
|
+
}));
|
|
70
|
+
// get_top_albums
|
|
71
|
+
server.tool('get_top_albums', 'Get top listened-to albums from Last.fm for a given time period. Returns ranked list with play counts.', {
|
|
72
|
+
period: z
|
|
73
|
+
.enum(['7day', '1month', '3month', '6month', '12month', 'overall'])
|
|
74
|
+
.default('1month')
|
|
75
|
+
.describe('Time period for rankings'),
|
|
76
|
+
limit: z
|
|
77
|
+
.number()
|
|
78
|
+
.min(1)
|
|
79
|
+
.max(50)
|
|
80
|
+
.default(10)
|
|
81
|
+
.describe('Number of albums to return'),
|
|
82
|
+
page: z.number().min(1).default(1).describe('Page number for pagination'),
|
|
83
|
+
}, READ_ONLY_ANNOTATIONS, async ({ period, limit, page }) => withErrorHandling(async () => {
|
|
84
|
+
const data = await client.get('/listening/top/albums', { period, limit, page });
|
|
85
|
+
if (!data.data.length)
|
|
86
|
+
return `No top albums for period: ${period}`;
|
|
87
|
+
const lines = [`Top Albums (${period}):`];
|
|
88
|
+
for (const a of data.data) {
|
|
89
|
+
lines.push(`${a.rank}. ${a.name} by ${a.detail} -- ${fmt(a.playcount)} plays`);
|
|
90
|
+
}
|
|
91
|
+
return lines.join('\n');
|
|
92
|
+
}));
|
|
93
|
+
// get_top_tracks
|
|
94
|
+
server.tool('get_top_tracks', 'Get top listened-to tracks from Last.fm for a given time period. Returns ranked list with play counts.', {
|
|
95
|
+
period: z
|
|
96
|
+
.enum(['7day', '1month', '3month', '6month', '12month', 'overall'])
|
|
97
|
+
.default('1month')
|
|
98
|
+
.describe('Time period for rankings'),
|
|
99
|
+
limit: z
|
|
100
|
+
.number()
|
|
101
|
+
.min(1)
|
|
102
|
+
.max(50)
|
|
103
|
+
.default(10)
|
|
104
|
+
.describe('Number of tracks to return'),
|
|
105
|
+
page: z.number().min(1).default(1).describe('Page number for pagination'),
|
|
106
|
+
}, READ_ONLY_ANNOTATIONS, async ({ period, limit, page }) => withErrorHandling(async () => {
|
|
107
|
+
const data = await client.get('/listening/top/tracks', { period, limit, page });
|
|
108
|
+
if (!data.data.length)
|
|
109
|
+
return `No top tracks for period: ${period}`;
|
|
110
|
+
const lines = [`Top Tracks (${period}):`];
|
|
111
|
+
for (const t of data.data) {
|
|
112
|
+
lines.push(`${t.rank}. "${t.name}" by ${t.detail} -- ${fmt(t.playcount)} plays`);
|
|
113
|
+
}
|
|
114
|
+
return lines.join('\n');
|
|
115
|
+
}));
|
|
116
|
+
// get_listening_streaks
|
|
117
|
+
server.tool('get_listening_streaks', 'Get listening streak data from Last.fm -- current consecutive days with scrobbles and the longest streak ever.', {}, READ_ONLY_ANNOTATIONS, async () => withErrorHandling(async () => {
|
|
118
|
+
const data = await client.get('/listening/streaks');
|
|
119
|
+
return [
|
|
120
|
+
'Listening Streaks:',
|
|
121
|
+
'',
|
|
122
|
+
`Current streak: ${data.current.days} days (${fmt(data.current.total_scrobbles)} scrobbles)`,
|
|
123
|
+
data.current.start_date
|
|
124
|
+
? ` Started: ${formatDate(data.current.start_date)}`
|
|
125
|
+
: '',
|
|
126
|
+
'',
|
|
127
|
+
`Longest streak: ${data.longest.days} days (${fmt(data.longest.total_scrobbles)} scrobbles)`,
|
|
128
|
+
data.longest.start_date
|
|
129
|
+
? ` ${formatDate(data.longest.start_date)} -- ${formatDate(data.longest.end_date)}`
|
|
130
|
+
: '',
|
|
131
|
+
]
|
|
132
|
+
.filter(Boolean)
|
|
133
|
+
.join('\n');
|
|
134
|
+
}));
|
|
135
|
+
// get_artist_details
|
|
136
|
+
server.tool('get_artist_details', 'Get detailed information about a specific artist by ID, including play count, top albums, and top tracks.', { id: z.number().describe('Artist ID') }, READ_ONLY_ANNOTATIONS, async ({ id }) => withErrorHandling(async () => {
|
|
137
|
+
const data = await client.get(`/listening/artists/${id}`);
|
|
138
|
+
const lines = [
|
|
139
|
+
`${data.name}`,
|
|
140
|
+
`Total plays: ${fmt(data.playcount)}`,
|
|
141
|
+
data.genre ? `Genre: ${data.genre}` : null,
|
|
142
|
+
'',
|
|
143
|
+
].filter((l) => l !== null);
|
|
144
|
+
if (data.top_albums.length) {
|
|
145
|
+
lines.push('Top Albums:');
|
|
146
|
+
for (const a of data.top_albums.slice(0, 5)) {
|
|
147
|
+
lines.push(` - ${a.name} (${fmt(a.playcount)} plays)`);
|
|
148
|
+
}
|
|
149
|
+
lines.push('');
|
|
150
|
+
}
|
|
151
|
+
if (data.top_tracks.length) {
|
|
152
|
+
lines.push('Top Tracks:');
|
|
153
|
+
for (const t of data.top_tracks.slice(0, 5)) {
|
|
154
|
+
lines.push(` - "${t.name}" (${fmt(t.scrobble_count)} plays)`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return lines.join('\n');
|
|
158
|
+
}));
|
|
159
|
+
// get_album_details
|
|
160
|
+
server.tool('get_album_details', 'Get detailed information about a specific album by ID, including artist, play count, and track listing.', { id: z.number().describe('Album ID') }, READ_ONLY_ANNOTATIONS, async ({ id }) => withErrorHandling(async () => {
|
|
161
|
+
const data = await client.get(`/listening/albums/${id}`);
|
|
162
|
+
const lines = [
|
|
163
|
+
`${data.name} by ${data.artist.name}`,
|
|
164
|
+
`Total plays: ${fmt(data.playcount)}`,
|
|
165
|
+
'',
|
|
166
|
+
];
|
|
167
|
+
if (data.tracks.length) {
|
|
168
|
+
lines.push('Tracks:');
|
|
169
|
+
for (const [i, t] of data.tracks.entries()) {
|
|
170
|
+
lines.push(` ${i + 1}. "${t.name}" (${fmt(t.scrobble_count)} plays)`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return lines.join('\n');
|
|
174
|
+
}));
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=listening.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listening.js","sourceRoot":"","sources":["../../src/tools/listening.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { withErrorHandling, formatDate, timeAgo, fmt, READ_ONLY_ANNOTATIONS, dateFilterParams, } from './helpers.js';
|
|
3
|
+
export function registerReadingTools(server, client) {
|
|
4
|
+
// get_recent_reads
|
|
5
|
+
server.tool('get_recent_reads', 'Get recently saved articles from Instapaper. Returns article titles, authors, domains, reading time, and status.', {
|
|
6
|
+
limit: z
|
|
7
|
+
.number()
|
|
8
|
+
.min(1)
|
|
9
|
+
.max(50)
|
|
10
|
+
.default(10)
|
|
11
|
+
.describe('Number of recent articles to return'),
|
|
12
|
+
...dateFilterParams,
|
|
13
|
+
}, READ_ONLY_ANNOTATIONS, async ({ limit, date, from, to }) => withErrorHandling(async () => {
|
|
14
|
+
const { data } = await client.get('/reading/recent', { limit, date, from, to });
|
|
15
|
+
if (!data.length)
|
|
16
|
+
return 'No recent articles found.';
|
|
17
|
+
const lines = ['Recent reads:'];
|
|
18
|
+
for (const [i, a] of data.entries()) {
|
|
19
|
+
const author = a.author ? ` by ${a.author}` : '';
|
|
20
|
+
const domain = a.domain ? ` (${a.domain})` : '';
|
|
21
|
+
const readTime = a.estimated_read_min
|
|
22
|
+
? ` -- ${a.estimated_read_min} min read`
|
|
23
|
+
: '';
|
|
24
|
+
const status = a.status === 'reading'
|
|
25
|
+
? ` [${Math.round(a.progress * 100)}%]`
|
|
26
|
+
: a.status === 'archived'
|
|
27
|
+
? ' [finished]'
|
|
28
|
+
: '';
|
|
29
|
+
lines.push(`${i + 1}. ${a.title}${author}${domain}${readTime}${status} (${timeAgo(a.saved_at)})`);
|
|
30
|
+
}
|
|
31
|
+
return lines.join('\n');
|
|
32
|
+
}));
|
|
33
|
+
// get_reading_highlights
|
|
34
|
+
server.tool('get_reading_highlights', 'Get saved highlights from Instapaper articles. Returns the highlighted text, optional notes, and the source article.', {
|
|
35
|
+
limit: z
|
|
36
|
+
.number()
|
|
37
|
+
.min(1)
|
|
38
|
+
.max(50)
|
|
39
|
+
.default(10)
|
|
40
|
+
.describe('Number of highlights to return'),
|
|
41
|
+
page: z.number().min(1).default(1).describe('Page number'),
|
|
42
|
+
}, READ_ONLY_ANNOTATIONS, async ({ limit, page }) => withErrorHandling(async () => {
|
|
43
|
+
const data = await client.get('/reading/highlights', { limit, page });
|
|
44
|
+
if (!data.data.length)
|
|
45
|
+
return 'No highlights found.';
|
|
46
|
+
const lines = [`Highlights (${fmt(data.pagination.total)} total):`];
|
|
47
|
+
for (const h of data.data) {
|
|
48
|
+
const source = h.article.author
|
|
49
|
+
? `${h.article.title} by ${h.article.author}`
|
|
50
|
+
: h.article.title;
|
|
51
|
+
lines.push('');
|
|
52
|
+
lines.push(`"${h.text}"`);
|
|
53
|
+
if (h.note)
|
|
54
|
+
lines.push(` Note: ${h.note}`);
|
|
55
|
+
lines.push(` -- ${source} (${formatDate(h.created_at)})`);
|
|
56
|
+
}
|
|
57
|
+
return lines.join('\n');
|
|
58
|
+
}));
|
|
59
|
+
// get_random_highlight
|
|
60
|
+
server.tool('get_random_highlight', 'Get a single random highlight from saved Instapaper articles. Great for daily inspiration or reflection.', {}, READ_ONLY_ANNOTATIONS, async () => withErrorHandling(async () => {
|
|
61
|
+
const data = await client.get('/reading/highlights/random');
|
|
62
|
+
const source = data.article.author
|
|
63
|
+
? `${data.article.title} by ${data.article.author}`
|
|
64
|
+
: data.article.title;
|
|
65
|
+
const lines = [`"${data.text}"`];
|
|
66
|
+
if (data.note)
|
|
67
|
+
lines.push(`Note: ${data.note}`);
|
|
68
|
+
lines.push(`-- ${source}`);
|
|
69
|
+
return lines.join('\n');
|
|
70
|
+
}));
|
|
71
|
+
// get_reading_stats
|
|
72
|
+
server.tool('get_reading_stats', 'Get overall reading statistics from Instapaper including total articles, finished count, currently reading, highlights, and word count.', {}, READ_ONLY_ANNOTATIONS, async () => withErrorHandling(async () => {
|
|
73
|
+
const data = await client.get('/reading/stats');
|
|
74
|
+
return [
|
|
75
|
+
'Reading Stats:',
|
|
76
|
+
`- Total articles: ${fmt(data.total_articles)}`,
|
|
77
|
+
`- Finished: ${fmt(data.finished_count)}`,
|
|
78
|
+
`- Currently reading: ${data.currently_reading_count}`,
|
|
79
|
+
`- Total highlights: ${fmt(data.total_highlights)}`,
|
|
80
|
+
`- Total words read: ${fmt(data.total_word_count)}`,
|
|
81
|
+
`- Average read time: ${Math.round(data.avg_estimated_read_min)} min`,
|
|
82
|
+
].join('\n');
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=reading.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reading.js","sourceRoot":"","sources":["../../src/tools/reading.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { withErrorHandling, formatDate, timeAgo, fmt, READ_ONLY_ANNOTATIONS, } from './helpers.js';
|
|
3
|
+
export function registerRunningTools(server, client) {
|
|
4
|
+
// get_running_stats
|
|
5
|
+
server.tool('get_running_stats', 'Get overall running statistics from Strava including total runs, distance, elevation, duration, average pace, and Eddington number.', {}, READ_ONLY_ANNOTATIONS, async () => withErrorHandling(async () => {
|
|
6
|
+
const { data } = await client.get('/running/stats');
|
|
7
|
+
return [
|
|
8
|
+
'Running Stats:',
|
|
9
|
+
`- Total runs: ${fmt(data.total_runs)}`,
|
|
10
|
+
`- Total distance: ${fmt(Math.round(data.total_distance_mi))} mi`,
|
|
11
|
+
`- Total elevation: ${fmt(Math.round(data.total_elevation_ft))} ft`,
|
|
12
|
+
`- Total time: ${data.total_duration}`,
|
|
13
|
+
data.avg_pace ? `- Average pace: ${data.avg_pace}` : null,
|
|
14
|
+
`- Years active: ${data.years_active}`,
|
|
15
|
+
data.first_run
|
|
16
|
+
? `- Running since: ${formatDate(data.first_run)}`
|
|
17
|
+
: null,
|
|
18
|
+
`- Eddington number: ${data.eddington_number}`,
|
|
19
|
+
]
|
|
20
|
+
.filter((l) => l !== null)
|
|
21
|
+
.join('\n');
|
|
22
|
+
}));
|
|
23
|
+
// get_recent_runs
|
|
24
|
+
server.tool('get_recent_runs', 'Get recent running activities from Strava. Returns a list of runs with ID, distance, pace, duration, and location. Use the ID with get_activity_details or get_activity_splits for more info.', {
|
|
25
|
+
limit: z
|
|
26
|
+
.number()
|
|
27
|
+
.min(1)
|
|
28
|
+
.max(50)
|
|
29
|
+
.default(10)
|
|
30
|
+
.describe('Number of recent runs to return'),
|
|
31
|
+
date: z
|
|
32
|
+
.string()
|
|
33
|
+
.optional()
|
|
34
|
+
.describe('Optional: filter to a specific date (YYYY-MM-DD)'),
|
|
35
|
+
from: z
|
|
36
|
+
.string()
|
|
37
|
+
.optional()
|
|
38
|
+
.describe('Optional: start of date range (ISO 8601)'),
|
|
39
|
+
to: z
|
|
40
|
+
.string()
|
|
41
|
+
.optional()
|
|
42
|
+
.describe('Optional: end of date range (ISO 8601)'),
|
|
43
|
+
}, READ_ONLY_ANNOTATIONS, async ({ limit, date, from, to }) => withErrorHandling(async () => {
|
|
44
|
+
const { data } = await client.get('/running/recent', { limit, date, from, to });
|
|
45
|
+
if (!data.length)
|
|
46
|
+
return 'No recent runs found.';
|
|
47
|
+
const lines = ['Recent runs:'];
|
|
48
|
+
for (const [i, r] of data.entries()) {
|
|
49
|
+
const location = r.city && r.state ? ` in ${r.city}, ${r.state}` : '';
|
|
50
|
+
const race = r.is_race ? ' [RACE]' : '';
|
|
51
|
+
lines.push(`${i + 1}. [ID: ${r.id}] ${r.name}${race} -- ${r.distance_mi.toFixed(1)} mi, ${r.pace}/mi, ${r.duration}${location} (${timeAgo(r.date)})`);
|
|
52
|
+
}
|
|
53
|
+
return lines.join('\n');
|
|
54
|
+
}));
|
|
55
|
+
// get_personal_records
|
|
56
|
+
server.tool('get_personal_records', 'Get personal running records (PRs) from Strava -- fastest times at standard distances like mile, 5K, 10K, half marathon, marathon.', {}, READ_ONLY_ANNOTATIONS, async () => withErrorHandling(async () => {
|
|
57
|
+
const { data } = await client.get('/running/prs');
|
|
58
|
+
if (!data.length)
|
|
59
|
+
return 'No personal records found.';
|
|
60
|
+
const lines = ['Personal Records:'];
|
|
61
|
+
for (const pr of data) {
|
|
62
|
+
lines.push(`- ${pr.distance_label}: ${pr.time} (${pr.pace}/mi) -- ${pr.activity_name} [ID: ${pr.activity_id}], ${formatDate(pr.date)}`);
|
|
63
|
+
}
|
|
64
|
+
return lines.join('\n');
|
|
65
|
+
}));
|
|
66
|
+
// get_running_streaks
|
|
67
|
+
server.tool('get_running_streaks', 'Get running streak data from Strava -- current consecutive days with runs and the longest streak ever.', {}, READ_ONLY_ANNOTATIONS, async () => withErrorHandling(async () => {
|
|
68
|
+
const { data } = await client.get('/running/streaks');
|
|
69
|
+
return [
|
|
70
|
+
'Running Streaks:',
|
|
71
|
+
'',
|
|
72
|
+
`Current streak: ${data.current.days} days`,
|
|
73
|
+
data.current.start
|
|
74
|
+
? ` ${formatDate(data.current.start)} -- ${formatDate(data.current.end)}`
|
|
75
|
+
: '',
|
|
76
|
+
'',
|
|
77
|
+
`Longest streak: ${data.longest.days} days`,
|
|
78
|
+
data.longest.start
|
|
79
|
+
? ` ${formatDate(data.longest.start)} -- ${formatDate(data.longest.end)}`
|
|
80
|
+
: '',
|
|
81
|
+
]
|
|
82
|
+
.filter(Boolean)
|
|
83
|
+
.join('\n');
|
|
84
|
+
}));
|
|
85
|
+
// get_activity_details
|
|
86
|
+
server.tool('get_activity_details', 'Get detailed information about a specific running activity by ID, including distance, pace, heart rate, elevation, and calories. Get the ID from get_recent_runs.', {
|
|
87
|
+
id: z
|
|
88
|
+
.number()
|
|
89
|
+
.describe('Activity ID (from get_recent_runs or get_personal_records)'),
|
|
90
|
+
}, READ_ONLY_ANNOTATIONS, async ({ id }) => withErrorHandling(async () => {
|
|
91
|
+
const data = await client.get(`/running/activities/${id}`);
|
|
92
|
+
const lines = [
|
|
93
|
+
`${data.name}${data.is_race ? ' [RACE]' : ''}`,
|
|
94
|
+
`Date: ${formatDate(data.date)}`,
|
|
95
|
+
`Distance: ${data.distance_mi.toFixed(2)} mi`,
|
|
96
|
+
`Duration: ${data.duration}`,
|
|
97
|
+
`Pace: ${data.pace}/mi`,
|
|
98
|
+
`Elevation: ${fmt(Math.round(data.elevation_ft))} ft`,
|
|
99
|
+
`Type: ${data.workout_type}`,
|
|
100
|
+
];
|
|
101
|
+
if (data.city && data.state) {
|
|
102
|
+
lines.push(`Location: ${data.city}, ${data.state}`);
|
|
103
|
+
}
|
|
104
|
+
if (data.heartrate_avg) {
|
|
105
|
+
lines.push(`Heart rate: ${Math.round(data.heartrate_avg)} avg / ${data.heartrate_max ?? '?'} max bpm`);
|
|
106
|
+
}
|
|
107
|
+
if (data.cadence)
|
|
108
|
+
lines.push(`Cadence: ${Math.round(data.cadence)} spm`);
|
|
109
|
+
if (data.calories)
|
|
110
|
+
lines.push(`Calories: ${fmt(data.calories)}`);
|
|
111
|
+
if (data.strava_url)
|
|
112
|
+
lines.push(`Strava: ${data.strava_url}`);
|
|
113
|
+
return lines.join('\n');
|
|
114
|
+
}));
|
|
115
|
+
// get_activity_splits
|
|
116
|
+
server.tool('get_activity_splits', 'Get per-mile splits for a running activity. Shows pace, elevation, and heart rate for each mile. Get the activity ID from get_recent_runs.', {
|
|
117
|
+
id: z
|
|
118
|
+
.number()
|
|
119
|
+
.describe('Activity ID (from get_recent_runs or get_personal_records)'),
|
|
120
|
+
}, READ_ONLY_ANNOTATIONS, async ({ id }) => withErrorHandling(async () => {
|
|
121
|
+
const { data } = await client.get(`/running/activities/${id}/splits`);
|
|
122
|
+
if (!data.length)
|
|
123
|
+
return 'No splits found for this activity.';
|
|
124
|
+
const lines = [`Mile splits for activity ${id}:`];
|
|
125
|
+
for (const s of data) {
|
|
126
|
+
const hr = s.heartrate ? ` | ${Math.round(s.heartrate)} bpm` : '';
|
|
127
|
+
const elev = s.elevation_ft !== 0
|
|
128
|
+
? ` | ${s.elevation_ft > 0 ? '+' : ''}${Math.round(s.elevation_ft)} ft`
|
|
129
|
+
: '';
|
|
130
|
+
lines.push(` Mile ${s.split}: ${s.pace}${elev}${hr}`);
|
|
131
|
+
}
|
|
132
|
+
return lines.join('\n');
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=running.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"running.js","sourceRoot":"","sources":["../../src/tools/running.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { withErrorHandling, formatDate, timeAgo, fmt, READ_ONLY_ANNOTATIONS, dateFilterParams, } from './helpers.js';
|
|
3
|
+
export function registerWatchingTools(server, client) {
|
|
4
|
+
// get_recent_watches
|
|
5
|
+
server.tool('get_recent_watches', 'Get recently watched movies and TV shows from Plex and Letterboxd. Returns titles, ratings, and watch dates.', {
|
|
6
|
+
limit: z
|
|
7
|
+
.number()
|
|
8
|
+
.min(1)
|
|
9
|
+
.max(50)
|
|
10
|
+
.default(10)
|
|
11
|
+
.describe('Number of recent watches to return'),
|
|
12
|
+
...dateFilterParams,
|
|
13
|
+
}, READ_ONLY_ANNOTATIONS, async ({ limit, date, from, to }) => withErrorHandling(async () => {
|
|
14
|
+
const { data } = await client.get('/watching/recent', { limit, date, from, to });
|
|
15
|
+
if (!data.length)
|
|
16
|
+
return 'No recent watches found.';
|
|
17
|
+
const lines = ['Recent watches:'];
|
|
18
|
+
for (const [i, w] of data.entries()) {
|
|
19
|
+
const year = w.movie.year ? ` (${w.movie.year})` : '';
|
|
20
|
+
const director = w.movie.director ? ` dir. ${w.movie.director}` : '';
|
|
21
|
+
const rating = w.user_rating !== null ? ` -- ${w.user_rating}/10` : '';
|
|
22
|
+
const rewatch = w.rewatch ? ' [rewatch]' : '';
|
|
23
|
+
lines.push(`${i + 1}. ${w.movie.title}${year}${director}${rating}${rewatch} (${timeAgo(w.watched_at)})`);
|
|
24
|
+
}
|
|
25
|
+
return lines.join('\n');
|
|
26
|
+
}));
|
|
27
|
+
// get_movie_details
|
|
28
|
+
server.tool('get_movie_details', 'Get detailed information about a specific movie by ID, including director, genres, rating, summary, and watch history.', { id: z.number().describe('Movie ID') }, READ_ONLY_ANNOTATIONS, async ({ id }) => withErrorHandling(async () => {
|
|
29
|
+
const data = await client.get(`/watching/movies/${id}`);
|
|
30
|
+
const lines = [
|
|
31
|
+
`${data.title}${data.year ? ` (${data.year})` : ''}`,
|
|
32
|
+
data.tagline ? `"${data.tagline}"` : null,
|
|
33
|
+
'',
|
|
34
|
+
data.directors.length
|
|
35
|
+
? `Director${data.directors.length > 1 ? 's' : ''}: ${data.directors.join(', ')}`
|
|
36
|
+
: null,
|
|
37
|
+
data.genres.length ? `Genres: ${data.genres.join(', ')}` : null,
|
|
38
|
+
data.duration_min ? `Runtime: ${data.duration_min} min` : null,
|
|
39
|
+
data.rating ? `Rated: ${data.rating}` : null,
|
|
40
|
+
data.tmdb_rating ? `TMDB: ${data.tmdb_rating}/10` : null,
|
|
41
|
+
data.summary ? `\n${data.summary}` : null,
|
|
42
|
+
].filter((l) => l !== null);
|
|
43
|
+
if (data.watch_history.length) {
|
|
44
|
+
lines.push('', 'Watch History:');
|
|
45
|
+
for (const w of data.watch_history) {
|
|
46
|
+
const rating = w.user_rating !== null ? ` -- rated ${w.user_rating}/10` : '';
|
|
47
|
+
const rewatch = w.rewatch ? ' [rewatch]' : '';
|
|
48
|
+
const source = w.source ? ` via ${w.source}` : '';
|
|
49
|
+
lines.push(` - ${formatDate(w.watched_at)}${rating}${rewatch}${source}`);
|
|
50
|
+
if (w.review) {
|
|
51
|
+
lines.push(` Review: ${w.review.slice(0, 200)}${w.review.length > 200 ? '...' : ''}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return lines.join('\n');
|
|
56
|
+
}));
|
|
57
|
+
// get_watching_stats
|
|
58
|
+
server.tool('get_watching_stats', 'Get overall watching statistics including total movies, watch time, movies this year, top genre, top director, TV show counts, and episode counts. Supports date filtering.', { ...dateFilterParams }, READ_ONLY_ANNOTATIONS, async ({ date, from, to }) => withErrorHandling(async () => {
|
|
59
|
+
const { data } = await client.get('/watching/stats', { date, from, to });
|
|
60
|
+
return [
|
|
61
|
+
'Watching Stats:',
|
|
62
|
+
'',
|
|
63
|
+
'Movies:',
|
|
64
|
+
`- Total movies: ${fmt(data.total_movies)}`,
|
|
65
|
+
`- Total watch time: ${fmt(Math.round(data.total_watch_time_hours))} hours`,
|
|
66
|
+
`- Movies this year: ${data.movies_this_year}`,
|
|
67
|
+
`- Average per month: ${data.avg_per_month.toFixed(1)}`,
|
|
68
|
+
data.top_genre ? `- Top genre: ${data.top_genre}` : null,
|
|
69
|
+
data.top_director ? `- Top director: ${data.top_director}` : null,
|
|
70
|
+
data.top_decade ? `- Top decade: ${data.top_decade}s` : null,
|
|
71
|
+
'',
|
|
72
|
+
'TV Shows:',
|
|
73
|
+
`- Total shows: ${fmt(data.total_shows)}`,
|
|
74
|
+
`- Total episodes: ${fmt(data.total_episodes_watched)}`,
|
|
75
|
+
`- Episodes this year: ${data.episodes_this_year}`,
|
|
76
|
+
]
|
|
77
|
+
.filter((l) => l !== null)
|
|
78
|
+
.join('\n');
|
|
79
|
+
}));
|
|
80
|
+
// browse_movies
|
|
81
|
+
server.tool('browse_movies', 'Browse the movie collection with filters for genre, decade, director, and year. Supports sorting and pagination.', {
|
|
82
|
+
genre: z
|
|
83
|
+
.string()
|
|
84
|
+
.optional()
|
|
85
|
+
.describe("Optional: filter by genre (e.g. 'Horror', 'Comedy', 'Drama')"),
|
|
86
|
+
decade: z
|
|
87
|
+
.string()
|
|
88
|
+
.optional()
|
|
89
|
+
.describe("Optional: filter by decade (e.g. '1990', '2000')"),
|
|
90
|
+
director: z
|
|
91
|
+
.string()
|
|
92
|
+
.optional()
|
|
93
|
+
.describe('Optional: filter by director name'),
|
|
94
|
+
year: z.string().optional().describe('Optional: filter by release year'),
|
|
95
|
+
sort: z
|
|
96
|
+
.string()
|
|
97
|
+
.optional()
|
|
98
|
+
.describe('Optional: sort by field (default: watched_at). Options: watched_at, title, year, rating'),
|
|
99
|
+
order: z
|
|
100
|
+
.enum(['asc', 'desc'])
|
|
101
|
+
.optional()
|
|
102
|
+
.describe('Optional: sort order (default: desc)'),
|
|
103
|
+
limit: z
|
|
104
|
+
.number()
|
|
105
|
+
.min(1)
|
|
106
|
+
.max(50)
|
|
107
|
+
.default(10)
|
|
108
|
+
.describe('Number of movies to return'),
|
|
109
|
+
page: z.number().min(1).default(1).describe('Page number'),
|
|
110
|
+
}, READ_ONLY_ANNOTATIONS, async ({ genre, decade, director, year, sort, order, limit, page }) => withErrorHandling(async () => {
|
|
111
|
+
const data = await client.get('/watching/movies', {
|
|
112
|
+
genre,
|
|
113
|
+
decade,
|
|
114
|
+
director,
|
|
115
|
+
year,
|
|
116
|
+
sort,
|
|
117
|
+
order,
|
|
118
|
+
limit,
|
|
119
|
+
page,
|
|
120
|
+
});
|
|
121
|
+
if (!data.data.length)
|
|
122
|
+
return 'No movies found matching those filters.';
|
|
123
|
+
const filters = [genre, decade, director, year].filter(Boolean);
|
|
124
|
+
const header = filters.length
|
|
125
|
+
? `Movies (filtered: ${filters.join(', ')})`
|
|
126
|
+
: `Movies (page ${data.pagination.page} of ${data.pagination.total_pages})`;
|
|
127
|
+
const lines = [`${header} -- ${fmt(data.pagination.total)} total:`];
|
|
128
|
+
for (const [i, m] of data.data.entries()) {
|
|
129
|
+
const num = (data.pagination.page - 1) * data.pagination.limit + i + 1;
|
|
130
|
+
const yr = m.year ? ` (${m.year})` : '';
|
|
131
|
+
const dir = m.director ? ` dir. ${m.director}` : '';
|
|
132
|
+
const rating = m.tmdb_rating ? ` -- ${m.tmdb_rating}/10` : '';
|
|
133
|
+
lines.push(`${num}. [ID: ${m.id}] ${m.title}${yr}${dir}${rating}`);
|
|
134
|
+
}
|
|
135
|
+
return lines.join('\n');
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=watching.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watching.js","sourceRoot":"","sources":["../../src/tools/watching.ts"],"names":[],"mappings":"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"}
|
package/dist/worker.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudflare Worker entry point for remote MCP access (Claude iOS, claude.ai).
|
|
3
|
+
* Deployed at mcp.rewind.rest.
|
|
4
|
+
*
|
|
5
|
+
* Uses @cloudflare/workers-oauth-provider for OAuth 2.1 with GitHub as the
|
|
6
|
+
* upstream identity provider. The OAuth layer is only for the remote transport;
|
|
7
|
+
* local stdio transport (Claude Desktop, Claude Code) uses REWIND_API_KEY directly.
|
|
8
|
+
*/
|
|
9
|
+
import { OAuthProvider } from '@cloudflare/workers-oauth-provider';
|
|
10
|
+
interface Env {
|
|
11
|
+
OAUTH_KV: KVNamespace;
|
|
12
|
+
REWIND_API_URL: string;
|
|
13
|
+
REWIND_API_KEY: string;
|
|
14
|
+
GITHUB_CLIENT_ID: string;
|
|
15
|
+
GITHUB_CLIENT_SECRET: string;
|
|
16
|
+
/** JSON map of GitHub user ID -> Rewind user_id, e.g. {"12345": 1} */
|
|
17
|
+
USER_ALLOWLIST: string;
|
|
18
|
+
}
|
|
19
|
+
declare const provider: OAuthProvider<Env>;
|
|
20
|
+
export default provider;
|