mcp-osp-prompt 1.0.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/dialog/objc.js ADDED
@@ -0,0 +1,303 @@
1
+ import os from 'os';
2
+ import { execSync } from 'child_process';
3
+ import { escapeAppleScriptString, cleanAppleScriptString, validateTimeout } from './utils.js';
4
+ // ✅ UNIFIED: 导入统一的按钮管理常量
5
+ import { BASE_DIALOG_BUTTONS, getSafeButtons, validateDialogButtons } from './constants.js';
6
+
7
+ /**
8
+ * AppleScriptObjC-based dialog implementation for macOS
9
+ * Uses NSTextView for true multi-line text input with no external dependencies
10
+ */
11
+
12
+ // Default timeout for all dialogs (5 minutes)
13
+ const DEFAULT_TIMEOUT = 300000;
14
+
15
+ /**
16
+ * Execute AppleScript using a temporary file to handle multiline scripts properly
17
+ */
18
+ async function executeAppleScript(script, timeout = DEFAULT_TIMEOUT) {
19
+ const { writeFileSync, unlinkSync } = await import('fs');
20
+ const { tmpdir } = await import('os');
21
+ const path = await import('path');
22
+ const tempFile = path.join(tmpdir(), `dialog_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.applescript`);
23
+
24
+ try {
25
+ writeFileSync(tempFile, script, 'utf8');
26
+ const result = execSync(`osascript "${tempFile}"`, {
27
+ encoding: 'utf8',
28
+ timeout: validateTimeout(timeout)
29
+ });
30
+ unlinkSync(tempFile);
31
+ return result.trim();
32
+ } catch (err) {
33
+ try { unlinkSync(tempFile); } catch {}
34
+ throw err;
35
+ }
36
+ }
37
+
38
+ export async function showInputDialog({ title = '输入', message = '请输入内容:', defaultValue = '' }) {
39
+ // Handle automated testing mode
40
+ if (process.env.AUTOMATED_MODE === 'true') {
41
+ console.log(`🤖 [AUTOMATED] AppleScriptObjC showInputDialog: ${title}, returning: "${defaultValue}"`);
42
+ return defaultValue;
43
+ }
44
+
45
+ const platform = os.platform();
46
+ if (platform !== 'darwin') {
47
+ throw new Error('AppleScriptObjC dialogs are only supported on macOS');
48
+ }
49
+
50
+ try {
51
+ console.log('✨ [AppleScriptObjC] Showing multi-line capable input dialog...');
52
+
53
+ // For AppleScriptObjC, minimal escaping to avoid syntax errors
54
+ const safeTitle = title.replace(/"/g, '""');
55
+ const safeMessage = message.replace(/"/g, '""');
56
+ const safeDefault = defaultValue.replace(/"/g, '""');
57
+
58
+ // 修复版ObjC实现,确保NSTextView正确初始化
59
+ const script = `
60
+ use AppleScript version "2.4"
61
+ use scripting additions
62
+ use framework "Foundation"
63
+ use framework "AppKit"
64
+
65
+ -- Create NSAlert
66
+ set theAlert to current application's NSAlert's alloc()'s init()
67
+ theAlert's setMessageText:"` + safeTitle + `"
68
+ theAlert's setInformativeText:"` + safeMessage + `"
69
+ theAlert's addButtonWithTitle:"确认"
70
+
71
+ -- Create scroll view with frame
72
+ set theFrame to current application's NSMakeRect(0, 0, 400, 120)
73
+ set scrollView to current application's NSScrollView's alloc()'s initWithFrame:theFrame
74
+ scrollView's setHasVerticalScroller:true
75
+
76
+ -- Create text view with same frame
77
+ set textView to current application's NSTextView's alloc()'s initWithFrame:theFrame
78
+ textView's setString:"` + safeDefault + `"
79
+ textView's setEditable:true
80
+ textView's setSelectable:true
81
+ textView's setRichText:false
82
+
83
+ -- Set up the scroll view and text view
84
+ scrollView's setDocumentView:textView
85
+ theAlert's setAccessoryView:scrollView
86
+
87
+ -- Prepare text view for input by making it the initial first responder
88
+ textView's setEditable:true
89
+ textView's setSelectable:true
90
+ textView's setImportsGraphics:false
91
+ textView's setRichText:false
92
+
93
+ -- Force application to be active and in front
94
+ set theApp to current application's NSApplication's sharedApplication()
95
+ theApp's activateIgnoringOtherApps:true
96
+
97
+ -- Show modal dialog first, then handle focus
98
+ set response to theAlert's runModal()
99
+
100
+ -- After modal dialog closes, textView should have captured any input
101
+ -- No need to manage window focus manually as NSAlert handles this
102
+
103
+ -- Return result (only one button now)
104
+ set resultText to (textView's string()) as text
105
+ return resultText`;
106
+
107
+ const result = await executeAppleScript(script, DEFAULT_TIMEOUT);
108
+ return result;
109
+
110
+ } catch (err) {
111
+ // Enhanced error handling with more specific error messages
112
+ const errorMsg = err.message || 'Unknown error';
113
+ if (errorMsg.includes('timeout')) {
114
+ console.warn(`WARNING: AppleScriptObjC input dialog timed out after ${DEFAULT_TIMEOUT/1000} seconds. Returning default value.`);
115
+ } else if (errorMsg.includes('User canceled')) {
116
+ console.log(`INFO: User cancelled AppleScriptObjC input dialog.`);
117
+ } else {
118
+ console.warn(`WARNING: AppleScriptObjC input dialog failed: ${errorMsg}. Returning default value.`);
119
+ }
120
+ return defaultValue;
121
+ }
122
+ }
123
+
124
+ export async function showConfirmDialog({ title = '确认', message = '请选择:', buttons }) {
125
+ // ✅ UNIFIED: 使用统一的按钮管理系统
126
+ buttons = getSafeButtons(buttons);
127
+ console.log('🔧 [BUTTON-UNIFIED] AppleScriptObjC dialog using unified button management:', buttons);
128
+
129
+ if (process.env.AUTOMATED_MODE === 'true') {
130
+ // ✅ UNIFIED: 验证按钮包含"修改计划"选项,确保统一标准
131
+ if (!validateDialogButtons(buttons)) {
132
+ console.warn(`⚠️ [AUTOMATED] AppleScriptObjC dialog missing '修改计划' option:`, buttons);
133
+ }
134
+ console.log(`🤖 [AUTOMATED] AppleScriptObjC showConfirmDialog: ${title}, returning: "${buttons[0]}" (buttons: ${JSON.stringify(buttons)})`);
135
+ return buttons[0];
136
+ }
137
+
138
+ const platform = os.platform();
139
+ if (platform !== 'darwin') {
140
+ throw new Error('AppleScriptObjC dialogs are only supported on macOS');
141
+ }
142
+
143
+ try {
144
+ console.log('✨ [AppleScriptObjC] Showing confirmation dialog...');
145
+
146
+ // Use safe string processing
147
+ const safeTitle = cleanAppleScriptString(title) || 'Confirmation';
148
+ const safeMessage = cleanAppleScriptString(message);
149
+ const safeButtons = buttons.map(b => cleanAppleScriptString(b));
150
+
151
+ const buttonsList = safeButtons.map(b => `"${b}"`).join(', ');
152
+ const script = `set selectedButton to button returned of (display dialog "${safeMessage}" with title "${safeTitle}" buttons {${buttonsList}} default button "${safeButtons[0]}")`;
153
+
154
+ const result = await executeAppleScript(script, DEFAULT_TIMEOUT);
155
+
156
+ const selectedButton = result.trim();
157
+ console.log('✅ [AppleScriptObjC] User selected:', selectedButton);
158
+
159
+ // Map clean button back to original button
160
+ const cleanIndex = safeButtons.indexOf(selectedButton);
161
+ return cleanIndex >= 0 ? buttons[cleanIndex] : buttons[0];
162
+
163
+ } catch (error) {
164
+ const errorMsg = error.message || 'Unknown error';
165
+ if (errorMsg.includes('timeout')) {
166
+ console.warn(`WARNING: AppleScriptObjC confirm dialog timed out after ${DEFAULT_TIMEOUT/1000} seconds. Returning first button.`);
167
+ } else if (errorMsg.includes('User canceled')) {
168
+ console.log(`INFO: User cancelled AppleScriptObjC confirm dialog.`);
169
+ } else {
170
+ console.warn(`WARNING: AppleScriptObjC confirm dialog failed: ${errorMsg}. Returning first button.`);
171
+ }
172
+ return buttons[0];
173
+ }
174
+ }
175
+
176
+ export async function showSelectDialog({ title = '选择', message = '请选择', items = [] }) {
177
+ if (process.env.AUTOMATED_MODE === 'true') {
178
+ console.log(`🤖 [AUTOMATED] AppleScriptObjC showSelectDialog: ${title}, returning: "${items[0] || ''}"`);
179
+ return items[0] || '';
180
+ }
181
+
182
+ const platform = os.platform();
183
+ if (platform !== 'darwin') {
184
+ throw new Error('AppleScriptObjC dialogs are only supported on macOS');
185
+ }
186
+
187
+ if (!items.length) return '';
188
+
189
+ try {
190
+ console.log('✨ [AppleScriptObjC] Showing select dialog...');
191
+
192
+ // Use safe string processing
193
+ const safeTitle = cleanAppleScriptString(title);
194
+ const safeMessage = cleanAppleScriptString(message);
195
+ const safeItems = items.map(i => cleanAppleScriptString(i));
196
+ const listItems = safeItems.map(i => `"${i}"`).join(', ');
197
+
198
+ const script = `set theChoice to choose from list {${listItems}} with title "${safeTitle}" with prompt "${safeMessage}"
199
+ if theChoice is false then
200
+ return "false"
201
+ else
202
+ return theChoice as string
203
+ end if`;
204
+
205
+ const result = await executeAppleScript(script, DEFAULT_TIMEOUT);
206
+
207
+ const choice = result.trim();
208
+
209
+ // Map clean choice back to original item
210
+ if (choice && choice !== 'false') {
211
+ const cleanIndex = safeItems.indexOf(choice);
212
+ return cleanIndex >= 0 ? items[cleanIndex] : choice;
213
+ }
214
+
215
+ return '';
216
+
217
+ } catch (error) {
218
+ const errorMsg = error.message || 'Unknown error';
219
+ if (errorMsg.includes('timeout')) {
220
+ console.warn(`WARNING: AppleScriptObjC select dialog timed out after ${DEFAULT_TIMEOUT/1000} seconds.`);
221
+ } else if (errorMsg.includes('User canceled')) {
222
+ console.log('INFO: User cancelled AppleScriptObjC select dialog.');
223
+ } else {
224
+ console.warn(`WARNING: AppleScriptObjC select dialog failed: ${errorMsg}.`);
225
+ }
226
+
227
+ // Enhanced fallback to input dialog
228
+ console.log('🔄 Falling back to input dialog...');
229
+ return await showInputDialog({ title, message: `${message}\n输入选项:`, defaultValue: items[0] || '' });
230
+ }
231
+ }
232
+
233
+ export async function showPlanAdjustmentDialog({ title = '', message = '', currentPlan = '', options }) {
234
+ if (!title || !message) {
235
+ throw new Error('Title and message are required for plan adjustment dialog');
236
+ }
237
+
238
+ // ✅ UNIFIED: 使用统一的按钮管理系统
239
+ options = getSafeButtons(options);
240
+ console.log('🔧 [BUTTON-UNIFIED] AppleScriptObjC plan dialog using unified button management:', options);
241
+
242
+ if (process.env.AUTOMATED_MODE === 'true') {
243
+ // ✅ UNIFIED: 验证选项包含"修改计划"选项,确保统一标准
244
+ if (!validateDialogButtons(options)) {
245
+ console.warn(`⚠️ [AUTOMATED] AppleScriptObjC plan dialog missing '修改计划' option:`, options);
246
+ }
247
+ console.log(`🤖 [AUTOMATED] AppleScriptObjC showPlanAdjustmentDialog: ${title}, returning: "${options[0]}" (options: ${JSON.stringify(options)})`);
248
+ return options[0]; // Return first option
249
+ }
250
+
251
+ const platform = os.platform();
252
+ if (platform !== 'darwin') {
253
+ throw new Error('AppleScriptObjC dialogs are only supported on macOS');
254
+ }
255
+
256
+ // Enhanced message with current plan
257
+ let fullMessage = message;
258
+ if (currentPlan) {
259
+ fullMessage += `\n\n📝 当前计划:\n${currentPlan}`;
260
+ }
261
+
262
+ try {
263
+ console.log('✨ [AppleScriptObjC] Showing plan adjustment dialog...');
264
+
265
+ // Use safe string processing
266
+ const safeTitle = cleanAppleScriptString(title);
267
+ const safeMessage = escapeAppleScriptString(fullMessage);
268
+ const safeOptions = options.map(o => cleanAppleScriptString(o));
269
+ const buttonsList = safeOptions.map(b => `"${b}"`).join(', ');
270
+
271
+ // First show the choice dialog
272
+ const script = `set selectedButton to button returned of (display dialog "${safeMessage}" with title "${safeTitle}" buttons {${buttonsList}} default button "${safeOptions[0]}")`;
273
+ const result = await executeAppleScript(script, DEFAULT_TIMEOUT);
274
+
275
+ // If "修改计划" is selected, show input dialog using AppleScriptObjC NSTextView
276
+ if (result.includes('修改计划')) {
277
+ const inputValue = await showInputDialog({
278
+ title: '计划修改建议',
279
+ message: '请输入您的调整建议:\n\n💡 您可以描述具体的修改需求或建议\n📝 支持多行内容输入',
280
+ defaultValue: ''
281
+ });
282
+
283
+ return {
284
+ action: result,
285
+ input: inputValue
286
+ };
287
+ }
288
+
289
+ // Map safe result back to original option
290
+ const safeIndex = safeOptions.indexOf(result);
291
+ return safeIndex >= 0 ? options[safeIndex] : result;
292
+ } catch (error) {
293
+ const errorMsg = error.message || 'Unknown error';
294
+ if (errorMsg.includes('timeout')) {
295
+ console.warn(`WARNING: AppleScriptObjC plan adjustment dialog timed out after ${DEFAULT_TIMEOUT/1000} seconds. Returning first option.`);
296
+ } else if (errorMsg.includes('User canceled')) {
297
+ console.log('INFO: User cancelled AppleScriptObjC plan adjustment dialog.');
298
+ } else {
299
+ console.warn(`WARNING: AppleScriptObjC plan adjustment dialog failed: ${errorMsg}. Returning first option.`);
300
+ }
301
+ return options[0];
302
+ }
303
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Utilities for safe dialog string handling
3
+ */
4
+
5
+ /**
6
+ * Safely escape strings for AppleScript usage
7
+ * Enhanced to handle complex special characters including code blocks, multiple quotes, etc.
8
+ * Handles all special characters that could cause injection or syntax errors
9
+ */
10
+ export function escapeAppleScriptString(str) {
11
+ if (typeof str !== 'string') {
12
+ str = String(str);
13
+ }
14
+
15
+ // Truncate extremely long strings to prevent AppleScript crashes
16
+ if (str.length > 32000) {
17
+ str = str.substring(0, 32000) + '...[内容过长已截断]';
18
+ }
19
+
20
+ return str
21
+ // 🎯 **彻底解决方案第1步:移除和转换问题Unicode字符**
22
+ .replace(/[\u2028\u2029]/g, '\\n') // Line and paragraph separators
23
+
24
+ // 🔥 **关键修复:处理全角标点符号** - 这些字符经常导致AppleScript语法错误
25
+ .replace(/:/g, ':') // 全角冒号 → 半角冒号
26
+ .replace(/,/g, ',') // 全角逗号 → 半角逗号
27
+ .replace(/。/g, '.') // 全角句号 → 半角句号
28
+ .replace(/?/g, '?') // 全角问号 → 半角问号
29
+ .replace(/!/g, '!') // 全角感叹号 → 半角感叹号
30
+ .replace(/;/g, ';') // 全角分号 → 半角分号
31
+ .replace(/(/g, '(') // 全角左括号 → 半角左括号
32
+ .replace(/)/g, ')') // 全角右括号 → 半角右括号
33
+ .replace(/、/g, ',') // 顿号 → 逗号
34
+
35
+ // 移除所有emoji和特殊Unicode字符,包括圆圈编号
36
+ .replace(/[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]/gu, '')
37
+ // 移除圆圈编号字符 ①②③④⑤⑥⑦⑧⑨⑩ (U+2460-U+2469)
38
+ .replace(/[\u2460-\u2469]/g, (match) => {
39
+ const num = match.charCodeAt(0) - 0x2460 + 1;
40
+ return num + ''; // 转换为普通数字
41
+ })
42
+ // 移除其他圆圈/括号编号 (U+2474-U+249B)
43
+ .replace(/[\u2474-\u249B]/g, (match) => {
44
+ const code = match.charCodeAt(0);
45
+ if (code <= 0x247D) { // (1) to (10)
46
+ const num = code - 0x2474 + 1;
47
+ return '(' + num + ')';
48
+ }
49
+ return '';
50
+ })
51
+ // 移除其他装饰性Unicode字符
52
+ .replace(/[\u{1F900}-\u{1F9FF}]|[\u{2B00}-\u{2BFF}]|[\u{1F200}-\u{1F2FF}]/gu, '')
53
+
54
+ // 🎯 **彻底解决方案第2步:智能引号转换**
55
+ .replace(/[''`]/g, "'") // 将智能单引号和反引号转为普通单引号
56
+ .replace(/[""]/g, '"') // 将智能双引号转为普通双引号
57
+
58
+ // 🎯 **彻底解决方案第3步:关键字符转义(顺序很重要)**
59
+ // Step 1: Escape backslashes first to avoid double-escaping
60
+ .replace(/\\/g, '\\\\')
61
+
62
+ // Step 2: 🔥 **最关键修复**:双引号转义 - AppleScript字符串的核心需求
63
+ .replace(/"/g, '\\"')
64
+
65
+ // Step 3: 🔥 **单引号处理** - 在shell命令中,单引号会破坏 osascript -e '...' 语法结构
66
+ // 解决方案:将单引号直接移除,避免shell语法冲突
67
+ .replace(/'/g, '') // 直接移除单引号,避免任何shell语法问题
68
+
69
+ // Step 4: 处理换行符和控制字符 - 在osascript -e '...'中必须转义换行符
70
+ .replace(/\n/g, '\\n') // 转义换行符为\n,osascript -e需要
71
+ .replace(/\r/g, '') // 移除回车符
72
+ .replace(/\t/g, ' ') // 制表符转为2个空格
73
+
74
+ // Step 5: 🔥 **AppleScript安全处理** - 移除problematic字符,不需要shell转义
75
+ // 在osascript -e '...'中,AppleScript字符串在单引号内,shell不会解释内部字符
76
+ .replace(/\$/g, '$') // 保持美元符号,在AppleScript字符串中安全
77
+ .replace(/`/g, '') // 移除反引号避免问题
78
+ .replace(/!/g, '!') // 保持感叹号,在AppleScript字符串中安全
79
+ .replace(/[()]/g, '') // 🎯 关键修复:直接移除圆括号避免AppleScript转义问题
80
+ .replace(/[[\]]/g, '') // 移除方括号
81
+ .replace(/[{}]/g, '') // 移除花括号
82
+ .replace(/[|]/g, '|') // 保持管道符,在AppleScript字符串中安全
83
+ .replace(/[&]/g, '&') // 保持与号,在AppleScript字符串中安全
84
+ .replace(/[;]/g, ';') // 保持分号,在AppleScript字符串中安全
85
+ .replace(/[<>]/g, '') // 移除重定向符号
86
+ .replace(/\*/g, '*') // 保持星号,在AppleScript字符串中安全
87
+ .replace(/\?/g, '?') // 保持问号,在AppleScript字符串中安全
88
+
89
+ // Step 6: 移除其他控制字符
90
+ .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, '')
91
+
92
+ // Step 7: 简化markdown格式
93
+ .replace(/\*\*(.*?)\*\*/g, '$1') // Remove bold formatting
94
+ .replace(/\*(.*?)\*/g, '$1') // Remove italic formatting
95
+ .replace(/#{1,6}\s*/g, '') // Remove markdown headers
96
+
97
+ // Step 8: 清理多余空白
98
+ .replace(/\s+/g, ' ')
99
+ .trim();
100
+ }
101
+
102
+ /**
103
+ * Clean strings for AppleScript by removing problematic characters
104
+ * Used for titles and UI elements where special characters aren't needed
105
+ *
106
+ * This function now reuses escapeAppleScriptString to avoid code duplication
107
+ */
108
+ export function cleanAppleScriptString(str) {
109
+ // Reuse the main escaping logic to avoid code duplication
110
+ return escapeAppleScriptString(str);
111
+ }
112
+
113
+ /**
114
+ * Validate timeout value and return a safe default
115
+ */
116
+ export function validateTimeout(timeout, defaultTimeout = 300000) {
117
+ if (typeof timeout !== 'number' || timeout < 1000 || timeout > 600000) {
118
+ return defaultTimeout; // Default to 5 minutes, max 10 minutes
119
+ }
120
+ return timeout;
121
+ }
122
+
123
+ /**
124
+ * Create a safe AppleScript execution environment
125
+ */
126
+ export function createSafeAppleScript(template, variables = {}) {
127
+ // Validate and escape all variables
128
+ const safeVars = {};
129
+ for (const [key, value] of Object.entries(variables)) {
130
+ safeVars[key] = escapeAppleScriptString(value);
131
+ }
132
+
133
+ // Replace template variables safely
134
+ let script = template;
135
+ for (const [key, value] of Object.entries(safeVars)) {
136
+ script = script.replace(new RegExp(`\\$\\{${key}\\}`, 'g'), value);
137
+ }
138
+
139
+ return script;
140
+ }
package/fetcher.js ADDED
@@ -0,0 +1,56 @@
1
+ // fetcher.js - prompt获取接口层
2
+ import { getPrompt as getPromptFromManager, getLocalPromptInfo as getVersionFromManager, getLocalPromptInfo } from './prompt-manager.js';
3
+ import { detectPlatformFromPath, parseRemotePath, validatePlatformConfiguration } from './platform-utils.js';
4
+
5
+ // 主要接口:获取prompt内容
6
+ export async function getPrompt(fileName) {
7
+ return await getPromptFromManager(fileName);
8
+ }
9
+
10
+ // 批量获取prompts(优化功能)
11
+ export async function getPrompts(fileNames) {
12
+ const promises = fileNames.map(fileName => getPrompt(fileName));
13
+ return await Promise.all(promises);
14
+ }
15
+
16
+ // 检查prompt是否可用
17
+ export async function isPromptAvailable(fileName) {
18
+ try {
19
+ const content = await getPrompt(fileName);
20
+ return content && content.length > 0;
21
+ } catch (error) {
22
+ return false;
23
+ }
24
+ }
25
+
26
+ // 获取当前配置的平台类型
27
+ export function getCurrentPlatform() {
28
+ const promptPath = process.env.PROMPT_PATH;
29
+ return detectPlatformFromPath(promptPath);
30
+ }
31
+
32
+ // 获取平台配置信息
33
+ export function getPlatformInfo() {
34
+ const promptPath = process.env.PROMPT_PATH;
35
+ const platform = detectPlatformFromPath(promptPath);
36
+
37
+ if (platform === 'local') {
38
+ return { platform, path: promptPath };
39
+ }
40
+
41
+ try {
42
+ return { platform, ...parseRemotePath(promptPath) };
43
+ } catch (error) {
44
+ return { platform, error: error.message };
45
+ }
46
+ }
47
+
48
+ // 验证当前配置
49
+ export function validateCurrentConfiguration() {
50
+ try {
51
+ const platform = validatePlatformConfiguration(process.env.RESOURCE_PATH, process.env.GIT_TOKEN);
52
+ return { valid: true, platform };
53
+ } catch (error) {
54
+ return { valid: false, error: error.message };
55
+ }
56
+ }
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "mcp-osp-prompt",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for fetching and caching prompt templates from GitHub, GitLab, or local directories",
5
+ "main": "server.js",
6
+ "bin": {
7
+ "mcp-prompt-fetcher": "./server.js"
8
+ },
9
+ "type": "module",
10
+ "author": "OSP Team",
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/mcp-tools/mcp-prompt-fetcher.git"
15
+ },
16
+ "homepage": "https://github.com/mcp-tools/mcp-prompt-fetcher#readme",
17
+ "bugs": {
18
+ "url": "https://github.com/mcp-tools/mcp-prompt-fetcher/issues"
19
+ },
20
+ "keywords": [
21
+ "mcp",
22
+ "prompt",
23
+ "github",
24
+ "gitlab",
25
+ "cursor",
26
+ "ide",
27
+ "ai",
28
+ "development",
29
+ "automation"
30
+ ],
31
+ "engines": {
32
+ "node": ">=18.0.0"
33
+ },
34
+ "files": [
35
+ "*.js",
36
+ "dialog/*",
37
+ "README.md"
38
+ ],
39
+ "dependencies": {
40
+ "open": "^9.0.0"
41
+ },
42
+ "scripts": {
43
+ "test": "node test.js",
44
+ "test:all": "node test.js && node tests/test-simplified-config.js && node tests/test-code-deduplication.js",
45
+ "prepublishOnly": "npm run test:all && npm run audit:security",
46
+ "publish:dry": "npm pack --dry-run",
47
+ "audit:security": "node tests/test-security-audit.js"
48
+ }
49
+ }