latitude-mcp-server 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.
Files changed (51) hide show
  1. package/.releaserc.json +34 -0
  2. package/README.md +687 -0
  3. package/dist/cli/index.d.ts +7 -0
  4. package/dist/cli/index.js +43 -0
  5. package/dist/cli/latitude.cli.d.ts +10 -0
  6. package/dist/cli/latitude.cli.js +286 -0
  7. package/dist/controllers/latitude.controller.d.ts +115 -0
  8. package/dist/controllers/latitude.controller.js +287 -0
  9. package/dist/index.d.ts +6 -0
  10. package/dist/index.js +166 -0
  11. package/dist/resources/latitude.resource.d.ts +12 -0
  12. package/dist/resources/latitude.resource.js +145 -0
  13. package/dist/services/vendor.latitude.service.d.ts +49 -0
  14. package/dist/services/vendor.latitude.service.js +294 -0
  15. package/dist/tools/latitude.tool.d.ts +6 -0
  16. package/dist/tools/latitude.tool.js +517 -0
  17. package/dist/types/common.types.d.ts +20 -0
  18. package/dist/types/common.types.js +7 -0
  19. package/dist/types/latitude.types.d.ts +487 -0
  20. package/dist/types/latitude.types.js +311 -0
  21. package/dist/utils/cli.test.util.d.ts +34 -0
  22. package/dist/utils/cli.test.util.js +143 -0
  23. package/dist/utils/config.util.d.ts +43 -0
  24. package/dist/utils/config.util.js +145 -0
  25. package/dist/utils/config.util.test.d.ts +1 -0
  26. package/dist/utils/constants.util.d.ts +26 -0
  27. package/dist/utils/constants.util.js +29 -0
  28. package/dist/utils/error-handler.util.d.ts +54 -0
  29. package/dist/utils/error-handler.util.js +202 -0
  30. package/dist/utils/error-handler.util.test.d.ts +1 -0
  31. package/dist/utils/error.util.d.ts +73 -0
  32. package/dist/utils/error.util.js +174 -0
  33. package/dist/utils/error.util.test.d.ts +1 -0
  34. package/dist/utils/formatter.util.d.ts +36 -0
  35. package/dist/utils/formatter.util.js +116 -0
  36. package/dist/utils/jest.setup.d.ts +5 -0
  37. package/dist/utils/jest.setup.js +36 -0
  38. package/dist/utils/jq.util.d.ts +34 -0
  39. package/dist/utils/jq.util.js +87 -0
  40. package/dist/utils/logger.util.d.ts +78 -0
  41. package/dist/utils/logger.util.js +344 -0
  42. package/dist/utils/toon.util.d.ts +15 -0
  43. package/dist/utils/toon.util.js +65 -0
  44. package/dist/utils/transport.util.d.ts +49 -0
  45. package/dist/utils/transport.util.js +162 -0
  46. package/eslint.config.mjs +46 -0
  47. package/openapi.json +12592 -0
  48. package/package.json +118 -0
  49. package/scripts/ensure-executable.js +38 -0
  50. package/scripts/package.json +3 -0
  51. package/scripts/update-version.js +204 -0
package/package.json ADDED
@@ -0,0 +1,118 @@
1
+ {
2
+ "name": "latitude-mcp-server",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for Latitude prompt management - manage prompts, versions, and run AI conversations",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "commonjs",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/yigitkonur/latitude-mcp-server.git"
11
+ },
12
+ "bin": {
13
+ "latitude-mcp": "./dist/index.js"
14
+ },
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "prepare": "npm run build && node scripts/ensure-executable.js",
18
+ "postinstall": "node scripts/ensure-executable.js",
19
+ "clean": "rm -rf dist coverage",
20
+ "test": "jest",
21
+ "test:coverage": "jest --coverage",
22
+ "lint": "eslint src --ext .ts --config eslint.config.mjs",
23
+ "update:deps": "npx npm-check-updates -u && npm install --legacy-peer-deps",
24
+ "format": "prettier --write 'src/**/*.ts' 'scripts/**/*.js'",
25
+ "cli": "npm run build && node dist/index.js",
26
+ "mcp:stdio": "npm run build && TRANSPORT_MODE=stdio node dist/index.js",
27
+ "mcp:http": "npm run build && TRANSPORT_MODE=http node dist/index.js",
28
+ "mcp:inspect": "npm run build && (TRANSPORT_MODE=http node dist/index.js &) && sleep 2 && npx @modelcontextprotocol/inspector http://localhost:3000/mcp",
29
+ "dev:stdio": "npm run build && npx @modelcontextprotocol/inspector -e TRANSPORT_MODE=stdio -e DEBUG=true node dist/index.js",
30
+ "dev:http": "npm run build && DEBUG=true TRANSPORT_MODE=http node dist/index.js"
31
+ },
32
+ "keywords": [
33
+ "mcp",
34
+ "model-context-protocol",
35
+ "latitude",
36
+ "prompt-management",
37
+ "ai",
38
+ "llm",
39
+ "typescript",
40
+ "claude",
41
+ "anthropic",
42
+ "prompts",
43
+ "version-control",
44
+ "mcp-server"
45
+ ],
46
+ "author": "Andi Ashari",
47
+ "license": "ISC",
48
+ "engines": {
49
+ "node": ">=18.0.0"
50
+ },
51
+ "devDependencies": {
52
+ "@eslint/js": "^9.39.1",
53
+ "@semantic-release/changelog": "^6.0.3",
54
+ "@semantic-release/exec": "^7.1.0",
55
+ "@semantic-release/git": "^10.0.1",
56
+ "@semantic-release/github": "^12.0.2",
57
+ "@semantic-release/npm": "^13.1.2",
58
+ "@types/cors": "^2.8.19",
59
+ "@types/express": "^5.0.5",
60
+ "@types/jest": "^30.0.0",
61
+ "@types/jmespath": "^0.15.2",
62
+ "@types/node": "^24.10.1",
63
+ "@typescript-eslint/eslint-plugin": "^8.48.0",
64
+ "@typescript-eslint/parser": "^8.48.0",
65
+ "eslint": "^9.39.1",
66
+ "eslint-config-prettier": "^10.1.8",
67
+ "eslint-plugin-prettier": "^5.5.4",
68
+ "jest": "^30.2.0",
69
+ "prettier": "^3.7.3",
70
+ "semantic-release": "^25.0.2",
71
+ "ts-jest": "^29.4.5",
72
+ "typescript": "^5.9.3",
73
+ "typescript-eslint": "^8.48.0"
74
+ },
75
+ "dependencies": {
76
+ "@modelcontextprotocol/sdk": "^1.23.0",
77
+ "@toon-format/toon": "^2.0.1",
78
+ "commander": "^14.0.2",
79
+ "cors": "^2.8.5",
80
+ "dotenv": "^17.2.3",
81
+ "express": "^5.1.0",
82
+ "jmespath": "^0.16.0",
83
+ "zod": "^4.1.13"
84
+ },
85
+ "publishConfig": {
86
+ "registry": "https://registry.npmjs.org/",
87
+ "access": "public"
88
+ },
89
+ "jest": {
90
+ "preset": "ts-jest",
91
+ "testEnvironment": "node",
92
+ "setupFilesAfterEnv": [
93
+ "<rootDir>/src/utils/jest.setup.ts"
94
+ ],
95
+ "testMatch": [
96
+ "**/src/**/*.test.ts"
97
+ ],
98
+ "collectCoverageFrom": [
99
+ "src/**/*.ts",
100
+ "!src/**/*.test.ts",
101
+ "!src/utils/jest.setup.ts"
102
+ ],
103
+ "transform": {
104
+ "^.+\\.tsx?$": [
105
+ "ts-jest",
106
+ {
107
+ "useESM": true
108
+ }
109
+ ]
110
+ },
111
+ "moduleNameMapper": {
112
+ "(.*)\\.(js|jsx)$": "$1"
113
+ },
114
+ "extensionsToTreatAsEsm": [
115
+ ".ts"
116
+ ]
117
+ }
118
+ }
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+
6
+ // Use dynamic import meta for ESM compatibility
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+ const rootDir = path.resolve(__dirname, '..');
10
+ const entryPoint = path.join(rootDir, 'dist', 'index.js');
11
+
12
+ try {
13
+ if (fs.existsSync(entryPoint)) {
14
+ // Ensure the file is executable (cross-platform)
15
+ const currentMode = fs.statSync(entryPoint).mode;
16
+ // Check if executable bits are set (user, group, or other)
17
+ // Mode constants differ slightly across platforms, checking broadly
18
+ const isExecutable =
19
+ currentMode & fs.constants.S_IXUSR ||
20
+ currentMode & fs.constants.S_IXGRP ||
21
+ currentMode & fs.constants.S_IXOTH;
22
+
23
+ if (!isExecutable) {
24
+ // Set permissions to 755 (rwxr-xr-x) if not executable
25
+ fs.chmodSync(entryPoint, 0o755);
26
+ console.log(
27
+ `Made ${path.relative(rootDir, entryPoint)} executable`,
28
+ );
29
+ } else {
30
+ // console.log(`${path.relative(rootDir, entryPoint)} is already executable`);
31
+ }
32
+ } else {
33
+ // console.warn(`${path.relative(rootDir, entryPoint)} not found, skipping chmod`);
34
+ }
35
+ } catch (err) {
36
+ // console.warn(`Failed to set executable permissions: ${err.message}`);
37
+ // We use '|| true' in package.json, so no need to exit here
38
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1,204 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Script to update version numbers across the project
5
+ * Usage: node scripts/update-version.js [version] [options]
6
+ * Options:
7
+ * --dry-run Show what changes would be made without applying them
8
+ * --verbose Show detailed logging information
9
+ *
10
+ * If no version is provided, it will use the version from package.json
11
+ */
12
+
13
+ import fs from 'fs';
14
+ import path from 'path';
15
+ import { fileURLToPath } from 'url';
16
+
17
+ // Get the directory name of the current module
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = path.dirname(__filename);
20
+ const rootDir = path.resolve(__dirname, '..');
21
+
22
+ // Parse command line arguments
23
+ const args = process.argv.slice(2);
24
+ const options = {
25
+ dryRun: args.includes('--dry-run'),
26
+ verbose: args.includes('--verbose'),
27
+ };
28
+
29
+ // Get the version (first non-flag argument)
30
+ let newVersion = args.find((arg) => !arg.startsWith('--'));
31
+
32
+ // Log helper function
33
+ const log = (message, verbose = false) => {
34
+ if (!verbose || options.verbose) {
35
+ console.log(message);
36
+ }
37
+ };
38
+
39
+ // File paths that may contain version information
40
+ const versionFiles = [
41
+ {
42
+ path: path.join(rootDir, 'package.json'),
43
+ pattern: /"version": "([^"]*)"/,
44
+ replacement: (match, currentVersion) =>
45
+ match.replace(currentVersion, newVersion),
46
+ },
47
+ {
48
+ path: path.join(rootDir, 'src', 'utils', 'constants.util.ts'),
49
+ pattern: /export const VERSION = ['"]([^'"]*)['"]/,
50
+ replacement: (match, currentVersion) =>
51
+ match.replace(currentVersion, newVersion),
52
+ },
53
+ // Also update the compiled JavaScript files if they exist
54
+ {
55
+ path: path.join(rootDir, 'dist', 'utils', 'constants.util.js'),
56
+ pattern: /exports.VERSION = ['"]([^'"]*)['"]/,
57
+ replacement: (match, currentVersion) =>
58
+ match.replace(currentVersion, newVersion),
59
+ optional: true, // Mark this file as optional
60
+ },
61
+ // Additional files can be added here with their patterns and replacement logic
62
+ ];
63
+
64
+ /**
65
+ * Read the version from package.json
66
+ * @returns {string} The version from package.json
67
+ */
68
+ function getPackageVersion() {
69
+ try {
70
+ const packageJsonPath = path.join(rootDir, 'package.json');
71
+ log(`Reading version from ${packageJsonPath}`, true);
72
+
73
+ const packageJson = JSON.parse(
74
+ fs.readFileSync(packageJsonPath, 'utf8'),
75
+ );
76
+
77
+ if (!packageJson.version) {
78
+ throw new Error('No version field found in package.json');
79
+ }
80
+
81
+ return packageJson.version;
82
+ } catch (error) {
83
+ console.error(`Error reading package.json: ${error.message}`);
84
+ process.exit(1);
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Validate the semantic version format
90
+ * @param {string} version - The version to validate
91
+ * @returns {boolean} True if valid, throws error if invalid
92
+ */
93
+ function validateVersion(version) {
94
+ // More comprehensive semver regex
95
+ const semverRegex =
96
+ /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
97
+
98
+ if (!semverRegex.test(version)) {
99
+ throw new Error(
100
+ `Invalid version format: ${version}\nPlease use semantic versioning format (e.g., 1.2.3, 1.2.3-beta.1, etc.)`,
101
+ );
102
+ }
103
+
104
+ return true;
105
+ }
106
+
107
+ /**
108
+ * Update version in a specific file
109
+ * @param {Object} fileConfig - Configuration for the file to update
110
+ */
111
+ function updateFileVersion(fileConfig) {
112
+ const {
113
+ path: filePath,
114
+ pattern,
115
+ replacement,
116
+ optional = false,
117
+ } = fileConfig;
118
+
119
+ try {
120
+ log(`Checking ${filePath}...`, true);
121
+
122
+ if (!fs.existsSync(filePath)) {
123
+ if (optional) {
124
+ log(`Optional file not found (skipping): ${filePath}`, true);
125
+ return;
126
+ }
127
+ console.warn(`Warning: File not found: ${filePath}`);
128
+ return;
129
+ }
130
+
131
+ // Read file content
132
+ const fileContent = fs.readFileSync(filePath, 'utf8');
133
+ const match = fileContent.match(pattern);
134
+
135
+ if (!match) {
136
+ console.warn(`Warning: Version pattern not found in ${filePath}`);
137
+ return;
138
+ }
139
+
140
+ const currentVersion = match[1];
141
+ if (currentVersion === newVersion) {
142
+ log(
143
+ `Version in ${path.basename(filePath)} is already ${newVersion}`,
144
+ true,
145
+ );
146
+ return;
147
+ }
148
+
149
+ // Create new content with the updated version
150
+ const updatedContent = fileContent.replace(pattern, replacement);
151
+
152
+ // Write the changes or log them in dry run mode
153
+ if (options.dryRun) {
154
+ log(
155
+ `Would update version in ${filePath} from ${currentVersion} to ${newVersion}`,
156
+ );
157
+ } else {
158
+ // Create a backup of the original file
159
+ fs.writeFileSync(`${filePath}.bak`, fileContent);
160
+ log(`Backup created: ${filePath}.bak`, true);
161
+
162
+ // Write the updated content
163
+ fs.writeFileSync(filePath, updatedContent);
164
+ log(
165
+ `Updated version in ${path.basename(filePath)} from ${currentVersion} to ${newVersion}`,
166
+ );
167
+ }
168
+ } catch (error) {
169
+ if (optional) {
170
+ log(`Error with optional file ${filePath}: ${error.message}`, true);
171
+ return;
172
+ }
173
+ console.error(`Error updating ${filePath}: ${error.message}`);
174
+ process.exit(1);
175
+ }
176
+ }
177
+
178
+ // Main execution
179
+ try {
180
+ // If no version specified, get from package.json
181
+ if (!newVersion) {
182
+ newVersion = getPackageVersion();
183
+ log(
184
+ `No version specified, using version from package.json: ${newVersion}`,
185
+ );
186
+ }
187
+
188
+ // Validate the version format
189
+ validateVersion(newVersion);
190
+
191
+ // Update all configured files
192
+ for (const fileConfig of versionFiles) {
193
+ updateFileVersion(fileConfig);
194
+ }
195
+
196
+ if (options.dryRun) {
197
+ log(`\nDry run completed. No files were modified.`);
198
+ } else {
199
+ log(`\nVersion successfully updated to ${newVersion}`);
200
+ }
201
+ } catch (error) {
202
+ console.error(`\nVersion update failed: ${error.message}`);
203
+ process.exit(1);
204
+ }