swift-patterns-mcp 1.0.2

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 (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +377 -0
  3. package/build/cli/auth.d.ts +3 -0
  4. package/build/cli/auth.d.ts.map +1 -0
  5. package/build/cli/auth.js +43 -0
  6. package/build/cli/auth.js.map +1 -0
  7. package/build/cli/setup.d.ts +2 -0
  8. package/build/cli/setup.d.ts.map +1 -0
  9. package/build/cli/setup.js +149 -0
  10. package/build/cli/setup.js.map +1 -0
  11. package/build/cli/source-manager.d.ts +3 -0
  12. package/build/cli/source-manager.d.ts.map +1 -0
  13. package/build/cli/source-manager.js +117 -0
  14. package/build/cli/source-manager.js.map +1 -0
  15. package/build/config/creators.d.ts +11 -0
  16. package/build/config/creators.d.ts.map +1 -0
  17. package/build/config/creators.js +32 -0
  18. package/build/config/creators.js.map +1 -0
  19. package/build/config/sources.d.ts +65 -0
  20. package/build/config/sources.d.ts.map +1 -0
  21. package/build/config/sources.js +184 -0
  22. package/build/config/sources.js.map +1 -0
  23. package/build/config/sources.test.d.ts +2 -0
  24. package/build/config/sources.test.d.ts.map +1 -0
  25. package/build/config/sources.test.js +195 -0
  26. package/build/config/sources.test.js.map +1 -0
  27. package/build/config/swift-keywords.d.ts +21 -0
  28. package/build/config/swift-keywords.d.ts.map +1 -0
  29. package/build/config/swift-keywords.js +67 -0
  30. package/build/config/swift-keywords.js.map +1 -0
  31. package/build/index.d.ts +3 -0
  32. package/build/index.d.ts.map +1 -0
  33. package/build/index.js +295 -0
  34. package/build/index.js.map +1 -0
  35. package/build/integration/mcp-client.test.d.ts +2 -0
  36. package/build/integration/mcp-client.test.d.ts.map +1 -0
  37. package/build/integration/mcp-client.test.js +82 -0
  38. package/build/integration/mcp-client.test.js.map +1 -0
  39. package/build/integration/response-quality.test.d.ts +2 -0
  40. package/build/integration/response-quality.test.d.ts.map +1 -0
  41. package/build/integration/response-quality.test.js +139 -0
  42. package/build/integration/response-quality.test.js.map +1 -0
  43. package/build/integration/test-client.d.ts +25 -0
  44. package/build/integration/test-client.d.ts.map +1 -0
  45. package/build/integration/test-client.js +93 -0
  46. package/build/integration/test-client.js.map +1 -0
  47. package/build/sources/free/rssPatternSource.d.ts +41 -0
  48. package/build/sources/free/rssPatternSource.d.ts.map +1 -0
  49. package/build/sources/free/rssPatternSource.js +122 -0
  50. package/build/sources/free/rssPatternSource.js.map +1 -0
  51. package/build/sources/free/rssPatternSource.test.d.ts +2 -0
  52. package/build/sources/free/rssPatternSource.test.d.ts.map +1 -0
  53. package/build/sources/free/rssPatternSource.test.js +92 -0
  54. package/build/sources/free/rssPatternSource.test.js.map +1 -0
  55. package/build/sources/free/sundell.d.ts +9 -0
  56. package/build/sources/free/sundell.d.ts.map +1 -0
  57. package/build/sources/free/sundell.js +31 -0
  58. package/build/sources/free/sundell.js.map +1 -0
  59. package/build/sources/free/sundell.test.d.ts +2 -0
  60. package/build/sources/free/sundell.test.d.ts.map +1 -0
  61. package/build/sources/free/sundell.test.js +63 -0
  62. package/build/sources/free/sundell.test.js.map +1 -0
  63. package/build/sources/free/vanderlee.d.ts +9 -0
  64. package/build/sources/free/vanderlee.d.ts.map +1 -0
  65. package/build/sources/free/vanderlee.js +71 -0
  66. package/build/sources/free/vanderlee.js.map +1 -0
  67. package/build/sources/free/vanderlee.test.d.ts +2 -0
  68. package/build/sources/free/vanderlee.test.d.ts.map +1 -0
  69. package/build/sources/free/vanderlee.test.js +73 -0
  70. package/build/sources/free/vanderlee.test.js.map +1 -0
  71. package/build/sources/premium/patreon-dl.d.ts +45 -0
  72. package/build/sources/premium/patreon-dl.d.ts.map +1 -0
  73. package/build/sources/premium/patreon-dl.js +189 -0
  74. package/build/sources/premium/patreon-dl.js.map +1 -0
  75. package/build/sources/premium/patreon-fetch.d.ts +3 -0
  76. package/build/sources/premium/patreon-fetch.d.ts.map +1 -0
  77. package/build/sources/premium/patreon-fetch.js +18 -0
  78. package/build/sources/premium/patreon-fetch.js.map +1 -0
  79. package/build/sources/premium/patreon-oauth.d.ts +24 -0
  80. package/build/sources/premium/patreon-oauth.d.ts.map +1 -0
  81. package/build/sources/premium/patreon-oauth.js +207 -0
  82. package/build/sources/premium/patreon-oauth.js.map +1 -0
  83. package/build/sources/premium/patreon-zip.d.ts +17 -0
  84. package/build/sources/premium/patreon-zip.d.ts.map +1 -0
  85. package/build/sources/premium/patreon-zip.js +128 -0
  86. package/build/sources/premium/patreon-zip.js.map +1 -0
  87. package/build/sources/premium/patreon.d.ts +48 -0
  88. package/build/sources/premium/patreon.d.ts.map +1 -0
  89. package/build/sources/premium/patreon.js +248 -0
  90. package/build/sources/premium/patreon.js.map +1 -0
  91. package/build/sources/premium/youtube.d.ts +14 -0
  92. package/build/sources/premium/youtube.d.ts.map +1 -0
  93. package/build/sources/premium/youtube.js +92 -0
  94. package/build/sources/premium/youtube.js.map +1 -0
  95. package/build/tools/extract-cookie.d.ts +2 -0
  96. package/build/tools/extract-cookie.d.ts.map +1 -0
  97. package/build/tools/extract-cookie.js +40 -0
  98. package/build/tools/extract-cookie.js.map +1 -0
  99. package/build/tools/handlers/enableSource.d.ts +3 -0
  100. package/build/tools/handlers/enableSource.d.ts.map +1 -0
  101. package/build/tools/handlers/enableSource.js +39 -0
  102. package/build/tools/handlers/enableSource.js.map +1 -0
  103. package/build/tools/handlers/getSwiftPattern.d.ts +3 -0
  104. package/build/tools/handlers/getSwiftPattern.d.ts.map +1 -0
  105. package/build/tools/handlers/getSwiftPattern.js +78 -0
  106. package/build/tools/handlers/getSwiftPattern.js.map +1 -0
  107. package/build/tools/handlers/handlers.test.d.ts +2 -0
  108. package/build/tools/handlers/handlers.test.d.ts.map +1 -0
  109. package/build/tools/handlers/handlers.test.js +189 -0
  110. package/build/tools/handlers/handlers.test.js.map +1 -0
  111. package/build/tools/handlers/listContentSources.d.ts +3 -0
  112. package/build/tools/handlers/listContentSources.d.ts.map +1 -0
  113. package/build/tools/handlers/listContentSources.js +38 -0
  114. package/build/tools/handlers/listContentSources.js.map +1 -0
  115. package/build/tools/handlers/searchSwiftContent.d.ts +3 -0
  116. package/build/tools/handlers/searchSwiftContent.d.ts.map +1 -0
  117. package/build/tools/handlers/searchSwiftContent.js +44 -0
  118. package/build/tools/handlers/searchSwiftContent.js.map +1 -0
  119. package/build/tools/index.d.ts +3 -0
  120. package/build/tools/index.d.ts.map +1 -0
  121. package/build/tools/index.js +14 -0
  122. package/build/tools/index.js.map +1 -0
  123. package/build/tools/registry.d.ts +14 -0
  124. package/build/tools/registry.d.ts.map +1 -0
  125. package/build/tools/registry.js +21 -0
  126. package/build/tools/registry.js.map +1 -0
  127. package/build/tools/registry.test.d.ts +2 -0
  128. package/build/tools/registry.test.d.ts.map +1 -0
  129. package/build/tools/registry.test.js +54 -0
  130. package/build/tools/registry.test.js.map +1 -0
  131. package/build/tools/types.d.ts +25 -0
  132. package/build/tools/types.d.ts.map +1 -0
  133. package/build/tools/types.js +3 -0
  134. package/build/tools/types.js.map +1 -0
  135. package/build/utils/cache.d.ts +17 -0
  136. package/build/utils/cache.d.ts.map +1 -0
  137. package/build/utils/cache.js +144 -0
  138. package/build/utils/cache.js.map +1 -0
  139. package/build/utils/errors.d.ts +19 -0
  140. package/build/utils/errors.d.ts.map +1 -0
  141. package/build/utils/errors.js +34 -0
  142. package/build/utils/errors.js.map +1 -0
  143. package/build/utils/paths.d.ts +27 -0
  144. package/build/utils/paths.d.ts.map +1 -0
  145. package/build/utils/paths.js +43 -0
  146. package/build/utils/paths.js.map +1 -0
  147. package/build/utils/search.d.ts +29 -0
  148. package/build/utils/search.d.ts.map +1 -0
  149. package/build/utils/search.js +165 -0
  150. package/build/utils/search.js.map +1 -0
  151. package/build/utils/search.test.d.ts +2 -0
  152. package/build/utils/search.test.d.ts.map +1 -0
  153. package/build/utils/search.test.js +199 -0
  154. package/build/utils/search.test.js.map +1 -0
  155. package/build/utils/swift-analysis.d.ts +27 -0
  156. package/build/utils/swift-analysis.d.ts.map +1 -0
  157. package/build/utils/swift-analysis.js +78 -0
  158. package/build/utils/swift-analysis.js.map +1 -0
  159. package/build/utils/swift-analysis.test.d.ts +2 -0
  160. package/build/utils/swift-analysis.test.d.ts.map +1 -0
  161. package/build/utils/swift-analysis.test.js +215 -0
  162. package/build/utils/swift-analysis.test.js.map +1 -0
  163. package/package.json +73 -0
@@ -0,0 +1,248 @@
1
+ // src/sources/premium/patreon.ts
2
+ import { loadTokens, getValidAccessToken } from './patreon-oauth.js';
3
+ import { getChannelVideos, searchVideos } from './youtube.js';
4
+ import { scanDownloadedContent } from './patreon-dl.js';
5
+ import { getByPatreonId } from '../../config/creators.js';
6
+ import { getPatreonCreatorsPath } from '../../utils/paths.js';
7
+ import { detectTopics, hasCodeContent, calculateRelevance } from '../../utils/swift-analysis.js';
8
+ import { BASE_TOPIC_KEYWORDS, BASE_QUALITY_SIGNALS, mergeKeywords, mergeQualitySignals } from '../../config/swift-keywords.js';
9
+ import fs from 'fs';
10
+ import path from 'path';
11
+ const PATREON_API = 'https://www.patreon.com/api/oauth2/v2';
12
+ // Patreon-specific keywords (extends base)
13
+ const patreonSpecificTopics = {
14
+ 'swiftui': ['@observable'], // Adds to base
15
+ 'architecture': ['clean architecture'], // Adds to base
16
+ };
17
+ const patreonSpecificSignals = {
18
+ 'swift': 10,
19
+ 'ios': 8,
20
+ 'pattern': 6,
21
+ 'best practice': 8,
22
+ };
23
+ const patreonTopicKeywords = mergeKeywords(BASE_TOPIC_KEYWORDS, patreonSpecificTopics);
24
+ const patreonQualitySignals = mergeQualitySignals(BASE_QUALITY_SIGNALS, patreonSpecificSignals);
25
+ // Patreon-specific scoring constants
26
+ const PATREON_CODE_BONUS = 15; // Higher bonus for code-heavy Patreon content
27
+ const PATREON_BASE_SCORE = 0; // Start at 0 for Patreon to rely on quality signals
28
+ function isSwiftRelated(name, summary) {
29
+ const text = `${name} ${summary || ''}`.toLowerCase();
30
+ const keywords = ['swift', 'swiftui', 'ios', 'apple', 'xcode', 'uikit', 'iphone', 'ipad'];
31
+ return keywords.some(k => text.includes(k));
32
+ }
33
+ export class PatreonSource {
34
+ clientId;
35
+ clientSecret;
36
+ enabledCreators = [];
37
+ constructor() {
38
+ this.clientId = process.env.PATREON_CLIENT_ID || '';
39
+ this.clientSecret = process.env.PATREON_CLIENT_SECRET || '';
40
+ this.loadEnabledCreators();
41
+ }
42
+ loadEnabledCreators() {
43
+ try {
44
+ const configPath = getPatreonCreatorsPath();
45
+ if (fs.existsSync(configPath)) {
46
+ const data = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
47
+ this.enabledCreators = data.enabledCreators || [];
48
+ }
49
+ }
50
+ catch {
51
+ this.enabledCreators = [];
52
+ }
53
+ }
54
+ saveEnabledCreators(creatorIds) {
55
+ this.enabledCreators = creatorIds;
56
+ const configPath = getPatreonCreatorsPath();
57
+ fs.mkdirSync(path.dirname(configPath), { recursive: true });
58
+ fs.writeFileSync(configPath, JSON.stringify({ enabledCreators: creatorIds }, null, 2));
59
+ }
60
+ async isConfigured() {
61
+ if (!this.clientId || !this.clientSecret)
62
+ return false;
63
+ const tokens = await loadTokens();
64
+ return tokens !== null;
65
+ }
66
+ /**
67
+ * Returns creators the user PAYS (patron memberships).
68
+ *
69
+ * IMPORTANT: This uses the identity endpoint with memberships.campaign include,
70
+ * NOT the /campaigns endpoint. The /campaigns endpoint only returns campaigns
71
+ * you OWN as a creator, not campaigns you subscribe to as a patron.
72
+ *
73
+ * Correct API: GET /identity?include=memberships.campaign
74
+ */
75
+ async getSubscribedCreators() {
76
+ const accessToken = await getValidAccessToken(this.clientId, this.clientSecret);
77
+ if (!accessToken)
78
+ return [];
79
+ try {
80
+ // Use identity endpoint with memberships to get campaigns user is subscribed to
81
+ // This is the ONLY correct way to get patron memberships
82
+ const url = `${PATREON_API}/identity?include=memberships.campaign&fields[user]=full_name,email&fields[member]=patron_status&fields[campaign]=creation_name,url,summary`;
83
+ console.log(`Fetching: ${url}`);
84
+ const response = await fetch(url, {
85
+ headers: { 'Authorization': `Bearer ${accessToken}` }
86
+ });
87
+ if (!response.ok) {
88
+ const errorBody = await response.text();
89
+ console.error(`Failed to fetch memberships: ${response.status}`);
90
+ console.error(`Response: ${errorBody}`);
91
+ return [];
92
+ }
93
+ const data = await response.json();
94
+ if (!data.included) {
95
+ console.error('No memberships data in response. User may not have any active patron memberships.');
96
+ return [];
97
+ }
98
+ console.log(`Memberships response: ${JSON.stringify(data, null, 2).slice(0, 500)}`);
99
+ // Extract active memberships and their campaigns
100
+ const members = data.included.filter((item) => item.type === 'member' &&
101
+ item.attributes?.patron_status === 'active_patron');
102
+ const campaigns = data.included.filter((item) => item.type === 'campaign');
103
+ // Get campaign IDs from active memberships
104
+ const activeCampaignIds = new Set(members
105
+ .map(m => m.relationships?.campaign?.data?.id)
106
+ .filter((id) => !!id));
107
+ // Return campaigns user is actively subscribed to
108
+ const creators = campaigns
109
+ .filter(c => activeCampaignIds.has(c.id))
110
+ .map(campaign => ({
111
+ id: campaign.id,
112
+ name: campaign.attributes.creation_name,
113
+ url: campaign.attributes.url,
114
+ isSwiftRelated: isSwiftRelated(campaign.attributes.creation_name, campaign.attributes.summary),
115
+ }));
116
+ if (creators.length === 0) {
117
+ console.warn('No active Patreon memberships found. ' +
118
+ 'You must be a paying patron of at least one creator to use Patreon with swift-mcp.');
119
+ }
120
+ return creators;
121
+ }
122
+ catch (error) {
123
+ console.error('Failed to fetch subscribed creators:', error);
124
+ return [];
125
+ }
126
+ }
127
+ async detectSwiftCreators() {
128
+ const creators = await this.getSubscribedCreators();
129
+ return creators.filter(c => c.isSwiftRelated);
130
+ }
131
+ async fetchPatterns(creatorId) {
132
+ const patterns = [];
133
+ const creatorsToFetch = creatorId
134
+ ? [creatorId]
135
+ : this.enabledCreators;
136
+ console.log(`Fetching patterns for ${creatorsToFetch.length} creators:`, creatorsToFetch);
137
+ // 1. Scan locally downloaded content (from patreon-dl)
138
+ const downloadedPosts = scanDownloadedContent();
139
+ console.log(`Found ${downloadedPosts.length} downloaded posts`);
140
+ for (const post of downloadedPosts) {
141
+ // Filter by creator if specified
142
+ const creator = creatorsToFetch.length > 0
143
+ ? getByPatreonId(creatorsToFetch.find(id => {
144
+ const c = getByPatreonId(id);
145
+ return c?.name === post.creator;
146
+ }) || '')
147
+ : null;
148
+ if (creatorsToFetch.length > 0 && !creator)
149
+ continue;
150
+ patterns.push(...this.downloadedPostToPatterns(post));
151
+ }
152
+ // 2. Fetch YouTube videos for additional metadata
153
+ for (const patreonId of creatorsToFetch) {
154
+ const creator = getByPatreonId(patreonId);
155
+ if (!creator?.youtubeChannelId) {
156
+ console.log(`No YouTube channel for creator ${patreonId}`);
157
+ continue;
158
+ }
159
+ try {
160
+ const videos = await getChannelVideos(creator.youtubeChannelId, 50);
161
+ console.log(`Found ${videos.length} videos for ${creator.name}`);
162
+ for (const video of videos) {
163
+ // Add video as pattern (skip if we already have downloaded content for this)
164
+ const hasDownloaded = patterns.some(p => p.url === video.patreonLink || p.title.includes(video.title));
165
+ if (!hasDownloaded) {
166
+ patterns.push(this.videoToPattern(video, creator.name));
167
+ }
168
+ }
169
+ }
170
+ catch (error) {
171
+ console.error(`Failed to fetch videos for ${creator.name}:`, error);
172
+ }
173
+ }
174
+ // Sort by date (newest first)
175
+ patterns.sort((a, b) => new Date(b.publishDate).getTime() - new Date(a.publishDate).getTime());
176
+ return patterns;
177
+ }
178
+ /**
179
+ * Convert downloaded post to patterns
180
+ */
181
+ downloadedPostToPatterns(post) {
182
+ const patterns = [];
183
+ for (const file of post.files) {
184
+ if (file.type === 'other')
185
+ continue;
186
+ const content = file.content || '';
187
+ const text = `${file.filename} ${content}`;
188
+ const topics = detectTopics(text, patreonTopicKeywords);
189
+ const hasCode = file.type === 'swift' || hasCodeContent(content);
190
+ const relevanceScore = calculateRelevance(text, hasCode, patreonQualitySignals, PATREON_BASE_SCORE, PATREON_CODE_BONUS);
191
+ patterns.push({
192
+ id: `dl-${post.postId}-${file.filename}`,
193
+ title: `${post.title} - ${file.filename}`,
194
+ url: `file://${file.filepath}`,
195
+ publishDate: post.publishDate || new Date().toISOString(),
196
+ excerpt: content.substring(0, 300),
197
+ content,
198
+ creator: post.creator,
199
+ topics,
200
+ relevanceScore,
201
+ hasCode,
202
+ });
203
+ }
204
+ return patterns;
205
+ }
206
+ videoToPattern(video, creatorName) {
207
+ const text = `${video.title} ${video.description}`;
208
+ const topics = detectTopics(text, patreonTopicKeywords);
209
+ const hasCode = hasCodeContent(video.description) || (video.codeLinks?.length ?? 0) > 0;
210
+ const relevanceScore = calculateRelevance(text, hasCode, patreonQualitySignals, PATREON_BASE_SCORE, PATREON_CODE_BONUS);
211
+ return {
212
+ id: `yt-${video.id}`,
213
+ title: video.title,
214
+ url: video.patreonLink || `https://youtube.com/watch?v=${video.id}`,
215
+ publishDate: video.publishedAt,
216
+ excerpt: video.description.substring(0, 300),
217
+ content: video.description,
218
+ creator: creatorName,
219
+ topics,
220
+ relevanceScore,
221
+ hasCode,
222
+ };
223
+ }
224
+ async searchPatterns(query) {
225
+ const patterns = [];
226
+ // Search YouTube for each enabled creator
227
+ for (const patreonId of this.enabledCreators) {
228
+ const creator = getByPatreonId(patreonId);
229
+ if (!creator?.youtubeChannelId)
230
+ continue;
231
+ try {
232
+ const videos = await searchVideos(query, creator.youtubeChannelId, 25);
233
+ for (const video of videos) {
234
+ patterns.push(this.videoToPattern(video, creator.name));
235
+ }
236
+ }
237
+ catch (error) {
238
+ console.error(`Search failed for ${creator.name}:`, error);
239
+ }
240
+ }
241
+ return patterns;
242
+ }
243
+ isAvailable() {
244
+ return !!(this.clientId && this.clientSecret);
245
+ }
246
+ }
247
+ export default PatreonSource;
248
+ //# sourceMappingURL=patreon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patreon.js","sourceRoot":"","sources":["../../../src/sources/premium/patreon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export interface Video {
2
+ id: string;
3
+ title: string;
4
+ description: string;
5
+ publishedAt: string;
6
+ channelId: string;
7
+ channelTitle: string;
8
+ tags?: string[];
9
+ patreonLink?: string;
10
+ codeLinks?: string[];
11
+ }
12
+ export declare function getChannelVideos(channelId: string, maxResults?: number): Promise<Video[]>;
13
+ export declare function searchVideos(query: string, channelId?: string, maxResults?: number): Promise<Video[]>;
14
+ //# sourceMappingURL=youtube.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"youtube.d.ts","sourceRoot":"","sources":["../../../src/sources/premium/youtube.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAYD,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,UAAU,SAAK,GACd,OAAO,CAAC,KAAK,EAAE,CAAC,CAgFlB;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,EAClB,UAAU,SAAK,GACd,OAAO,CAAC,KAAK,EAAE,CAAC,CAuClB"}
@@ -0,0 +1,92 @@
1
+ // src/sources/premium/youtube.ts
2
+ // YouTube Data API client
3
+ const API_BASE = 'https://www.googleapis.com/youtube/v3';
4
+ function extractPatreonLink(text) {
5
+ const match = text.match(/https?:\/\/(www\.)?patreon\.com\/[^\s\)]+/i);
6
+ return match?.[0];
7
+ }
8
+ function extractCodeLinks(text) {
9
+ const matches = text.match(/https?:\/\/(github\.com|gist\.github\.com)[^\s\)]+/gi);
10
+ return matches || [];
11
+ }
12
+ export async function getChannelVideos(channelId, maxResults = 50) {
13
+ const apiKey = process.env.YOUTUBE_API_KEY;
14
+ if (!apiKey) {
15
+ console.error('YOUTUBE_API_KEY not set');
16
+ return [];
17
+ }
18
+ try {
19
+ // Search for videos
20
+ const searchUrl = `${API_BASE}/search?key=${apiKey}&channelId=${channelId}&part=snippet&type=video&order=date&maxResults=${maxResults}`;
21
+ const searchRes = await fetch(searchUrl);
22
+ if (!searchRes.ok) {
23
+ console.error(`YouTube search failed: ${searchRes.status}`);
24
+ return [];
25
+ }
26
+ const searchData = await searchRes.json();
27
+ const videoIds = searchData.items.map(i => i.id.videoId).join(',');
28
+ if (!videoIds)
29
+ return [];
30
+ // Get full video details (includes tags)
31
+ const videosUrl = `${API_BASE}/videos?key=${apiKey}&id=${videoIds}&part=snippet`;
32
+ const videosRes = await fetch(videosUrl);
33
+ if (!videosRes.ok) {
34
+ // Fallback to search results
35
+ return searchData.items.map(i => ({
36
+ id: i.id.videoId,
37
+ title: i.snippet.title,
38
+ description: i.snippet.description,
39
+ publishedAt: i.snippet.publishedAt,
40
+ channelId: i.snippet.channelId,
41
+ channelTitle: i.snippet.channelTitle,
42
+ patreonLink: extractPatreonLink(i.snippet.description),
43
+ codeLinks: extractCodeLinks(i.snippet.description),
44
+ }));
45
+ }
46
+ const videosData = await videosRes.json();
47
+ return videosData.items.map(i => ({
48
+ id: i.id,
49
+ title: i.snippet.title,
50
+ description: i.snippet.description,
51
+ publishedAt: i.snippet.publishedAt,
52
+ channelId: i.snippet.channelId,
53
+ channelTitle: i.snippet.channelTitle,
54
+ tags: i.snippet.tags,
55
+ patreonLink: extractPatreonLink(i.snippet.description),
56
+ codeLinks: extractCodeLinks(i.snippet.description),
57
+ }));
58
+ }
59
+ catch (err) {
60
+ console.error('YouTube API error:', err);
61
+ return [];
62
+ }
63
+ }
64
+ export async function searchVideos(query, channelId, maxResults = 25) {
65
+ const apiKey = process.env.YOUTUBE_API_KEY;
66
+ if (!apiKey)
67
+ return [];
68
+ try {
69
+ let url = `${API_BASE}/search?key=${apiKey}&q=${encodeURIComponent(query)}&part=snippet&type=video&maxResults=${maxResults}`;
70
+ if (channelId) {
71
+ url += `&channelId=${channelId}`;
72
+ }
73
+ const res = await fetch(url);
74
+ if (!res.ok)
75
+ return [];
76
+ const data = await res.json();
77
+ return data.items.map(i => ({
78
+ id: i.id.videoId,
79
+ title: i.snippet.title,
80
+ description: i.snippet.description,
81
+ publishedAt: i.snippet.publishedAt,
82
+ channelId: i.snippet.channelId,
83
+ channelTitle: i.snippet.channelTitle,
84
+ patreonLink: extractPatreonLink(i.snippet.description),
85
+ codeLinks: extractCodeLinks(i.snippet.description),
86
+ }));
87
+ }
88
+ catch {
89
+ return [];
90
+ }
91
+ }
92
+ //# sourceMappingURL=youtube.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"youtube.js","sourceRoot":"","sources":["../../../src/sources/premium/youtube.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=extract-cookie.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-cookie.d.ts","sourceRoot":"","sources":["../../src/tools/extract-cookie.ts"],"names":[],"mappings":""}
@@ -0,0 +1,40 @@
1
+ import { chromium } from 'playwright';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ const PROFILE_DIR = path.join(process.cwd(), '.patreon-profile');
5
+ const COOKIE_FILE = '.patreon-session';
6
+ (async () => {
7
+ // Use persistent context - preserves login sessions across runs
8
+ const context = await chromium.launchPersistentContext(PROFILE_DIR, {
9
+ headless: false,
10
+ });
11
+ const page = context.pages()[0] || await context.newPage();
12
+ // Check if already logged in by looking for existing session cookie
13
+ const existingCookies = await context.cookies('https://www.patreon.com');
14
+ const existingSession = existingCookies.find(c => c.name === 'session_id');
15
+ if (existingSession) {
16
+ console.log('Found existing session from persistent profile!');
17
+ fs.writeFileSync(COOKIE_FILE, existingSession.value);
18
+ console.log('Saved session_id!');
19
+ await context.close();
20
+ return;
21
+ }
22
+ // No existing session, need to log in
23
+ await page.goto('https://www.patreon.com/login');
24
+ console.log('Please log in. Waiting for session cookie...');
25
+ // Poll for session cookie instead of waiting for Enter
26
+ let cookies = await context.cookies('https://www.patreon.com');
27
+ let sessionCookie = cookies.find(c => c.name === 'session_id');
28
+ while (!sessionCookie) {
29
+ await new Promise(resolve => setTimeout(resolve, 1000));
30
+ cookies = await context.cookies('https://www.patreon.com');
31
+ sessionCookie = cookies.find(c => c.name === 'session_id');
32
+ }
33
+ console.log('Login detected!');
34
+ // Debug: log all cookie names
35
+ console.log('Available cookies:', cookies.map(c => c.name).join(', '));
36
+ fs.writeFileSync(COOKIE_FILE, sessionCookie.value);
37
+ console.log('Saved session_id!');
38
+ await context.close();
39
+ })();
40
+ //# sourceMappingURL=extract-cookie.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-cookie.js","sourceRoot":"","sources":["../../src/tools/extract-cookie.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,kBAAkB,CAAC,CAAC;AACjE,MAAM,WAAW,GAAG,kBAAkB,CAAC;AAEvC,CAAC,KAAK,IAAI,EAAE;IACV,gEAAgE;IAChE,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,uBAAuB,CAAC,WAAW,EAAE;QAClE,QAAQ,EAAE,KAAK;KAChB,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IAE3D,oEAAoE;IACpE,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACzE,MAAM,eAAe,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;IAE3E,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;QAC/D,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACjC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO;IACT,CAAC;IAED,sCAAsC;IACtC,MAAM,IAAI,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAE5D,uDAAuD;IACvD,IAAI,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC/D,IAAI,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;IAE/D,OAAO,CAAC,aAAa,EAAE,CAAC;QACtB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QACxD,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;QAC3D,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;IAC7D,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAE/B,8BAA8B;IAC9B,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAEvE,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACjC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;AACxB,CAAC,CAAC,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ToolHandler } from '../types.js';
2
+ export declare const enableSourceHandler: ToolHandler;
3
+ //# sourceMappingURL=enableSource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enableSource.d.ts","sourceRoot":"","sources":["../../../src/tools/handlers/enableSource.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,eAAO,MAAM,mBAAmB,EAAE,WAwCjC,CAAC"}
@@ -0,0 +1,39 @@
1
+ // src/tools/handlers/enableSource.ts
2
+ export const enableSourceHandler = async (args, context) => {
3
+ const sourceId = args?.source;
4
+ const source = context.sourceManager.getSource(sourceId);
5
+ if (!source) {
6
+ return {
7
+ content: [{
8
+ type: "text",
9
+ text: `Unknown source: "${sourceId}"
10
+
11
+ Available sources:
12
+ ${context.sourceManager.getAllSources().map(s => `- ${s.id}: ${s.name}`).join('\n')}`,
13
+ }],
14
+ };
15
+ }
16
+ if (source.requiresAuth && !context.sourceManager.isSourceConfigured(sourceId)) {
17
+ return {
18
+ content: [{
19
+ type: "text",
20
+ text: `āš™ļø ${source.name} requires setup first.
21
+
22
+ Run: swift-mcp setup --${sourceId}
23
+
24
+ This will guide you through:
25
+ ${sourceId === 'patreon' ? '- Patreon OAuth authentication\n- Connecting your subscriptions' : '- Authentication setup'}`,
26
+ }],
27
+ };
28
+ }
29
+ context.sourceManager.enableSource(sourceId);
30
+ return {
31
+ content: [{
32
+ type: "text",
33
+ text: `āœ… ${source.name} enabled!
34
+
35
+ You can now use patterns from this source.`,
36
+ }],
37
+ };
38
+ };
39
+ //# sourceMappingURL=enableSource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enableSource.js","sourceRoot":"","sources":["../../../src/tools/handlers/enableSource.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAIrC,MAAM,CAAC,MAAM,mBAAmB,GAAgB,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;IACtE,MAAM,QAAQ,GAAG,IAAI,EAAE,MAAgB,CAAC;IACxC,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAEzD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,oBAAoB,QAAQ;;;EAGxC,OAAO,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;iBAC9E,CAAC;SACH,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/E,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,MAAM,MAAM,CAAC,IAAI;;yBAEN,QAAQ;;;EAG/B,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,iEAAiE,CAAC,CAAC,CAAC,wBAAwB,EAAE;iBAClH,CAAC;SACH,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAE7C,OAAO;QACL,OAAO,EAAE,CAAC;gBACR,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,KAAK,MAAM,CAAC,IAAI;;2CAEe;aACtC,CAAC;KACH,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ToolHandler } from '../types.js';
2
+ export declare const getSwiftPatternHandler: ToolHandler;
3
+ //# sourceMappingURL=getSwiftPattern.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSwiftPattern.d.ts","sourceRoot":"","sources":["../../../src/tools/handlers/getSwiftPattern.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK/C,eAAO,MAAM,sBAAsB,EAAE,WAkFpC,CAAC"}
@@ -0,0 +1,78 @@
1
+ // src/tools/handlers/getSwiftPattern.ts
2
+ import SundellSource from '../../sources/free/sundell.js';
3
+ import VanderLeeSource from '../../sources/free/vanderlee.js';
4
+ export const getSwiftPatternHandler = async (args, context) => {
5
+ const topic = args?.topic;
6
+ if (!topic) {
7
+ return {
8
+ content: [{
9
+ type: "text",
10
+ text: `Missing required argument: topic
11
+
12
+ Usage: get_swift_pattern({ topic: "swiftui" })
13
+
14
+ Example topics:
15
+ - swiftui, concurrency, testing, networking
16
+ - performance, architecture, protocols
17
+ - async-await, combine, coredata`,
18
+ }],
19
+ };
20
+ }
21
+ const source = args?.source || "all";
22
+ const minQuality = args?.minQuality || 60;
23
+ const results = [];
24
+ // Get from free sources
25
+ if (source === "all" || source === "sundell") {
26
+ const sundell = new SundellSource();
27
+ const patterns = await sundell.searchPatterns(topic);
28
+ results.push(...patterns.filter(p => p.relevanceScore >= minQuality));
29
+ }
30
+ if (source === "all" || source === "vanderlee") {
31
+ const vanderlee = new VanderLeeSource();
32
+ const patterns = await vanderlee.searchPatterns(topic);
33
+ results.push(...patterns.filter(p => p.relevanceScore >= minQuality));
34
+ }
35
+ if (results.length === 0) {
36
+ return {
37
+ content: [{
38
+ type: "text",
39
+ text: `No patterns found for "${topic}" with quality ≄ ${minQuality}.
40
+
41
+ Try:
42
+ - Broader search terms
43
+ - Lower minQuality
44
+ - Different topic
45
+
46
+ Available sources: Swift by Sundell, Antoine van der Lee
47
+ ${context.sourceManager.isSourceConfigured('patreon') ? '\nšŸ’” Enable Patreon for more premium content!' : ''}`,
48
+ }],
49
+ };
50
+ }
51
+ // Sort by relevance
52
+ results.sort((a, b) => b.relevanceScore - a.relevanceScore);
53
+ const formatted = results.slice(0, 10).map(p => `
54
+ ## ${p.title}
55
+ **Source**: ${p.id.split('-')[0]}
56
+ **Quality**: ${p.relevanceScore}/100
57
+ **Topics**: ${p.topics.join(', ')}
58
+ ${p.hasCode ? '**Has Code**: āœ…' : ''}
59
+
60
+ ${p.excerpt}...
61
+
62
+ **[Read full article](${p.url})**
63
+ `).join('\n---\n');
64
+ return {
65
+ content: [{
66
+ type: "text",
67
+ text: `# Swift Patterns: ${topic}
68
+
69
+ Found ${results.length} patterns from free sources:
70
+
71
+ ${formatted}
72
+
73
+ ${results.length > 10 ? `\n*Showing top 10 of ${results.length} results*` : ''}
74
+ `,
75
+ }],
76
+ };
77
+ };
78
+ //# sourceMappingURL=getSwiftPattern.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSwiftPattern.js","sourceRoot":"","sources":["../../../src/tools/handlers/getSwiftPattern.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=handlers.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.test.d.ts","sourceRoot":"","sources":["../../../src/tools/handlers/handlers.test.ts"],"names":[],"mappings":""}