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.
- package/.releaserc.json +34 -0
- package/README.md +687 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.js +43 -0
- package/dist/cli/latitude.cli.d.ts +10 -0
- package/dist/cli/latitude.cli.js +286 -0
- package/dist/controllers/latitude.controller.d.ts +115 -0
- package/dist/controllers/latitude.controller.js +287 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +166 -0
- package/dist/resources/latitude.resource.d.ts +12 -0
- package/dist/resources/latitude.resource.js +145 -0
- package/dist/services/vendor.latitude.service.d.ts +49 -0
- package/dist/services/vendor.latitude.service.js +294 -0
- package/dist/tools/latitude.tool.d.ts +6 -0
- package/dist/tools/latitude.tool.js +517 -0
- package/dist/types/common.types.d.ts +20 -0
- package/dist/types/common.types.js +7 -0
- package/dist/types/latitude.types.d.ts +487 -0
- package/dist/types/latitude.types.js +311 -0
- package/dist/utils/cli.test.util.d.ts +34 -0
- package/dist/utils/cli.test.util.js +143 -0
- package/dist/utils/config.util.d.ts +43 -0
- package/dist/utils/config.util.js +145 -0
- package/dist/utils/config.util.test.d.ts +1 -0
- package/dist/utils/constants.util.d.ts +26 -0
- package/dist/utils/constants.util.js +29 -0
- package/dist/utils/error-handler.util.d.ts +54 -0
- package/dist/utils/error-handler.util.js +202 -0
- package/dist/utils/error-handler.util.test.d.ts +1 -0
- package/dist/utils/error.util.d.ts +73 -0
- package/dist/utils/error.util.js +174 -0
- package/dist/utils/error.util.test.d.ts +1 -0
- package/dist/utils/formatter.util.d.ts +36 -0
- package/dist/utils/formatter.util.js +116 -0
- package/dist/utils/jest.setup.d.ts +5 -0
- package/dist/utils/jest.setup.js +36 -0
- package/dist/utils/jq.util.d.ts +34 -0
- package/dist/utils/jq.util.js +87 -0
- package/dist/utils/logger.util.d.ts +78 -0
- package/dist/utils/logger.util.js +344 -0
- package/dist/utils/toon.util.d.ts +15 -0
- package/dist/utils/toon.util.js +65 -0
- package/dist/utils/transport.util.d.ts +49 -0
- package/dist/utils/transport.util.js +162 -0
- package/eslint.config.mjs +46 -0
- package/openapi.json +12592 -0
- package/package.json +118 -0
- package/scripts/ensure-executable.js +38 -0
- package/scripts/package.json +3 -0
- 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,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
|
+
}
|