@smithery/cli 0.0.7 → 0.0.9
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smithery/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"private": false,
|
|
5
5
|
"homepage": "https://smithery.ai/",
|
|
6
6
|
"description": "A NPX command to install and list Model Context Protocols",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"format": "npx @biomejs/biome format --write"
|
|
26
26
|
},
|
|
27
27
|
"bin": {
|
|
28
|
-
"
|
|
28
|
+
"cli": "dist/index.js"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@iarna/toml": "^2.2.5",
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import { exec } from 'child_process';
|
|
2
|
-
import { promisify } from 'util';
|
|
3
|
-
import * as fs from 'fs';
|
|
4
|
-
import * as path from 'path';
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
6
|
-
import { dirname } from 'path';
|
|
7
|
-
import * as TOML from '@iarna/toml';
|
|
8
|
-
const execAsync = promisify(exec);
|
|
9
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
-
const __dirname = dirname(__filename);
|
|
11
|
-
const REPOS = [
|
|
12
|
-
{
|
|
13
|
-
url: 'https://github.com/modelcontextprotocol/servers.git',
|
|
14
|
-
branch: 'main',
|
|
15
|
-
packagePath: 'src',
|
|
16
|
-
runtime: 'mixed'
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
url: 'https://github.com/mcp-get/community-servers.git',
|
|
20
|
-
branch: 'main',
|
|
21
|
-
packagePath: 'src',
|
|
22
|
-
runtime: 'mixed'
|
|
23
|
-
}
|
|
24
|
-
];
|
|
25
|
-
async function cloneRepo(config, tempDir) {
|
|
26
|
-
const repoDir = path.join(tempDir, path.basename(config.url, '.git'));
|
|
27
|
-
console.log(`Cloning ${config.url} into ${repoDir}...`);
|
|
28
|
-
await execAsync(`git clone --depth 1 --branch ${config.branch} ${config.url} ${repoDir}`, { cwd: tempDir });
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
async function extractNodePackage(packageJsonPath, repoUrl, subPath) {
|
|
32
|
-
try {
|
|
33
|
-
const packageData = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
34
|
-
const repoPath = `${repoUrl}/blob/main/${subPath}`;
|
|
35
|
-
return {
|
|
36
|
-
name: packageData.name || '',
|
|
37
|
-
description: packageData.description || '',
|
|
38
|
-
vendor: packageData.author || '',
|
|
39
|
-
sourceUrl: repoPath,
|
|
40
|
-
homepage: packageData.homepage || '',
|
|
41
|
-
license: packageData.license || '',
|
|
42
|
-
runtime: 'node'
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
catch (error) {
|
|
46
|
-
console.error(`Error extracting Node package from ${packageJsonPath}:`, error);
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
async function extractPythonPackage(pyprojectPath, repoUrl, subPath) {
|
|
51
|
-
try {
|
|
52
|
-
const pyprojectContent = fs.readFileSync(pyprojectPath, 'utf8');
|
|
53
|
-
const pyproject = TOML.parse(pyprojectContent);
|
|
54
|
-
if (!pyproject.project) {
|
|
55
|
-
console.error(`No [project] section found in ${pyprojectPath}`);
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
const { project } = pyproject;
|
|
59
|
-
// Set vendor to Anthropic
|
|
60
|
-
const vendor = 'Anthropic, PBC (https://anthropic.com)';
|
|
61
|
-
// Set license to MIT
|
|
62
|
-
const license = 'MIT';
|
|
63
|
-
return {
|
|
64
|
-
name: project.name || '',
|
|
65
|
-
description: project.description || '',
|
|
66
|
-
vendor,
|
|
67
|
-
sourceUrl: `${repoUrl}/blob/main/${subPath}`,
|
|
68
|
-
homepage: project.homepage || project.repository || repoUrl,
|
|
69
|
-
license,
|
|
70
|
-
runtime: 'python'
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
console.error(`Error extracting Python package from ${pyprojectPath}:`, error);
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
export async function extractPackageInfo() {
|
|
79
|
-
const tempDir = path.join(__dirname, '../../temp');
|
|
80
|
-
const outputPath = path.join(__dirname, '../../packages/package-list.json');
|
|
81
|
-
const commitMsgPath = path.join(__dirname, '../../temp/commit-msg.txt');
|
|
82
|
-
console.log("Starting package extraction...");
|
|
83
|
-
try {
|
|
84
|
-
// Load existing packages
|
|
85
|
-
let existingPackages = [];
|
|
86
|
-
if (fs.existsSync(outputPath)) {
|
|
87
|
-
existingPackages = JSON.parse(fs.readFileSync(outputPath, 'utf8'));
|
|
88
|
-
}
|
|
89
|
-
// Create temp directory if it doesn't exist
|
|
90
|
-
if (!fs.existsSync(tempDir)) {
|
|
91
|
-
fs.mkdirSync(tempDir, { recursive: true });
|
|
92
|
-
}
|
|
93
|
-
// Initialize commit message
|
|
94
|
-
let commitMsg = "chore(packages): update MCP package list\n\nChanges:\n";
|
|
95
|
-
let changes = [];
|
|
96
|
-
// Process each repository
|
|
97
|
-
const newPackages = [];
|
|
98
|
-
for (const repo of REPOS) {
|
|
99
|
-
await cloneRepo(repo, tempDir);
|
|
100
|
-
const repoDir = path.join(tempDir, path.basename(repo.url, '.git'));
|
|
101
|
-
const packagePath = path.join(repoDir, repo.packagePath);
|
|
102
|
-
if (!fs.existsSync(packagePath))
|
|
103
|
-
continue;
|
|
104
|
-
const dirs = fs.readdirSync(packagePath);
|
|
105
|
-
for (const dir of dirs) {
|
|
106
|
-
const fullPath = path.join(packagePath, dir);
|
|
107
|
-
if (!fs.statSync(fullPath).isDirectory())
|
|
108
|
-
continue;
|
|
109
|
-
// Try to extract as Node.js package
|
|
110
|
-
const packageJsonPath = path.join(fullPath, 'package.json');
|
|
111
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
112
|
-
const nodePackage = await extractNodePackage(packageJsonPath, repo.url.replace('.git', ''), path.join(repo.packagePath, dir));
|
|
113
|
-
if (nodePackage) {
|
|
114
|
-
newPackages.push(nodePackage);
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
// Try to extract as Python package
|
|
119
|
-
const pyprojectPath = path.join(fullPath, 'pyproject.toml');
|
|
120
|
-
if (fs.existsSync(pyprojectPath)) {
|
|
121
|
-
const pythonPackage = await extractPythonPackage(pyprojectPath, repo.url.replace('.git', ''), path.join(repo.packagePath, dir));
|
|
122
|
-
if (pythonPackage) {
|
|
123
|
-
newPackages.push(pythonPackage);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
// Merge existing and new packages
|
|
129
|
-
const mergedPackages = [...existingPackages];
|
|
130
|
-
let hasChanges = false;
|
|
131
|
-
for (const newPkg of newPackages) {
|
|
132
|
-
const existingIndex = mergedPackages.findIndex(pkg => pkg.name === newPkg.name);
|
|
133
|
-
if (existingIndex >= 0) {
|
|
134
|
-
// Update existing package if there are changes
|
|
135
|
-
if (JSON.stringify(mergedPackages[existingIndex]) !== JSON.stringify(newPkg)) {
|
|
136
|
-
const oldPkg = mergedPackages[existingIndex];
|
|
137
|
-
mergedPackages[existingIndex] = newPkg;
|
|
138
|
-
hasChanges = true;
|
|
139
|
-
console.log(`Updated package: ${newPkg.name}`);
|
|
140
|
-
// Add detailed change information
|
|
141
|
-
const changeDetails = [];
|
|
142
|
-
if (oldPkg.description !== newPkg.description)
|
|
143
|
-
changeDetails.push('description');
|
|
144
|
-
if (oldPkg.vendor !== newPkg.vendor)
|
|
145
|
-
changeDetails.push('vendor');
|
|
146
|
-
if (oldPkg.license !== newPkg.license)
|
|
147
|
-
changeDetails.push('license');
|
|
148
|
-
if (oldPkg.homepage !== newPkg.homepage)
|
|
149
|
-
changeDetails.push('homepage');
|
|
150
|
-
if (oldPkg.sourceUrl !== newPkg.sourceUrl)
|
|
151
|
-
changeDetails.push('sourceUrl');
|
|
152
|
-
if (oldPkg.runtime !== newPkg.runtime)
|
|
153
|
-
changeDetails.push('runtime');
|
|
154
|
-
changes.push(`- Updated ${newPkg.name} (changed: ${changeDetails.join(', ')})`);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
// Add new package
|
|
159
|
-
mergedPackages.push(newPkg);
|
|
160
|
-
hasChanges = true;
|
|
161
|
-
console.log(`Added new package: ${newPkg.name} (${newPkg.runtime})`);
|
|
162
|
-
changes.push(`- Added new package: ${newPkg.name} (${newPkg.runtime})`);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
// Write updated packages to file if there are changes
|
|
166
|
-
if (hasChanges) {
|
|
167
|
-
fs.writeFileSync(outputPath, JSON.stringify(mergedPackages, null, 2));
|
|
168
|
-
console.log('Package list updated successfully');
|
|
169
|
-
// Write commit message with total number of changes
|
|
170
|
-
if (changes.length === 0) {
|
|
171
|
-
changes.push('- Initial package list creation');
|
|
172
|
-
}
|
|
173
|
-
commitMsg = `chore(packages): update MCP package list (${changes.length} packages)\n\nChanges:\n`;
|
|
174
|
-
commitMsg += changes.join('\n');
|
|
175
|
-
fs.writeFileSync(commitMsgPath, commitMsg);
|
|
176
|
-
console.log('Commit message generated');
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
console.log('No changes detected in package list');
|
|
180
|
-
}
|
|
181
|
-
// Cleanup (but keep commit-msg.txt if it exists)
|
|
182
|
-
const filesToKeep = new Set(['commit-msg.txt']);
|
|
183
|
-
for (const file of fs.readdirSync(tempDir)) {
|
|
184
|
-
if (!filesToKeep.has(file)) {
|
|
185
|
-
const filePath = path.join(tempDir, file);
|
|
186
|
-
fs.rmSync(filePath, { recursive: true, force: true });
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
console.log('Temporary files cleaned up');
|
|
190
|
-
return mergedPackages;
|
|
191
|
-
}
|
|
192
|
-
catch (error) {
|
|
193
|
-
console.error('Error:', error);
|
|
194
|
-
// Cleanup on error
|
|
195
|
-
if (fs.existsSync(tempDir)) {
|
|
196
|
-
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
197
|
-
}
|
|
198
|
-
throw error;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
// Run the function if this file is executed directly
|
|
202
|
-
if (import.meta.url === `file://${__filename}`) {
|
|
203
|
-
extractPackageInfo()
|
|
204
|
-
.then(() => console.log('Package extraction completed'))
|
|
205
|
-
.catch(error => {
|
|
206
|
-
console.error('Failed to extract packages:', error);
|
|
207
|
-
process.exit(1);
|
|
208
|
-
});
|
|
209
|
-
}
|
package/dist/helpers/index.js
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
export const packageHelpers = {
|
|
2
|
-
"@modelcontextprotocol/server-brave-search": {
|
|
3
|
-
requiredEnvVars: {
|
|
4
|
-
BRAVE_API_KEY: {
|
|
5
|
-
description: "API key for Brave Search",
|
|
6
|
-
required: true,
|
|
7
|
-
},
|
|
8
|
-
},
|
|
9
|
-
},
|
|
10
|
-
"@modelcontextprotocol/server-github": {
|
|
11
|
-
requiredEnvVars: {
|
|
12
|
-
GITHUB_PERSONAL_ACCESS_TOKEN: {
|
|
13
|
-
description: "Personal access token for GitHub API access",
|
|
14
|
-
required: true,
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
"@modelcontextprotocol/server-gitlab": {
|
|
19
|
-
requiredEnvVars: {
|
|
20
|
-
GITLAB_PERSONAL_ACCESS_TOKEN: {
|
|
21
|
-
description: "Personal access token for GitLab API access",
|
|
22
|
-
required: true,
|
|
23
|
-
},
|
|
24
|
-
GITLAB_API_URL: {
|
|
25
|
-
description: "GitLab API URL (optional, for self-hosted instances)",
|
|
26
|
-
required: false,
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
"@modelcontextprotocol/server-google-maps": {
|
|
31
|
-
requiredEnvVars: {
|
|
32
|
-
GOOGLE_MAPS_API_KEY: {
|
|
33
|
-
description: "API key for Google Maps services",
|
|
34
|
-
required: true,
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
"@modelcontextprotocol/server-slack": {
|
|
39
|
-
requiredEnvVars: {
|
|
40
|
-
SLACK_BOT_TOKEN: {
|
|
41
|
-
description: "Slack Bot User OAuth Token (starts with xoxb-)",
|
|
42
|
-
required: true,
|
|
43
|
-
},
|
|
44
|
-
SLACK_TEAM_ID: {
|
|
45
|
-
description: "Slack Team/Workspace ID",
|
|
46
|
-
required: true,
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
"@raygun.io/mcp-server-raygun": {
|
|
51
|
-
requiredEnvVars: {
|
|
52
|
-
RAYGUN_PAT_TOKEN: {
|
|
53
|
-
description: "Personal access token for Raygun API access",
|
|
54
|
-
required: true,
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
"@kagi/mcp-server-kagi": {
|
|
59
|
-
requiredEnvVars: {
|
|
60
|
-
KAGI_API_KEY: {
|
|
61
|
-
description: "API key for Kagi Search",
|
|
62
|
-
required: true,
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
"@exa/mcp-server": {
|
|
67
|
-
requiredEnvVars: {
|
|
68
|
-
EXA_API_KEY: {
|
|
69
|
-
description: "API key for Exa AI Search",
|
|
70
|
-
required: true,
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
"@search1api/mcp-server": {
|
|
75
|
-
requiredEnvVars: {
|
|
76
|
-
SEARCH1API_KEY: {
|
|
77
|
-
description: "API key for Search1API",
|
|
78
|
-
required: true,
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
"mcp-tinybird": {
|
|
83
|
-
requiredEnvVars: {
|
|
84
|
-
TB_API_URL: {
|
|
85
|
-
description: "API URL for Tinybird",
|
|
86
|
-
required: true,
|
|
87
|
-
},
|
|
88
|
-
TB_ADMIN_TOKEN: {
|
|
89
|
-
description: "Admin token for Tinybird",
|
|
90
|
-
required: true,
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
};
|