@hasna/mcps 0.0.13 → 0.0.14
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/bin/index.js +371 -3
- package/bin/mcp.js +271 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +376 -6
- package/dist/lib/provider-profile-seeds.d.ts +2 -0
- package/dist/lib/provider-profiles.d.ts +14 -0
- package/dist/mcp/index.js +271 -0
- package/dist/types.d.ts +82 -2
- package/package.json +2 -2
package/bin/index.js
CHANGED
|
@@ -11944,6 +11944,85 @@ var init_config2 = __esm(() => {
|
|
|
11944
11944
|
DB_PATH = process.env.HASNA_MCPS_DB_PATH ?? process.env.MCPS_DB_PATH ?? join5(MCPS_DIR, "registry.db");
|
|
11945
11945
|
});
|
|
11946
11946
|
|
|
11947
|
+
// src/lib/provider-profile-seeds.ts
|
|
11948
|
+
var DEFAULT_PROVIDER_PROFILE_SEEDS;
|
|
11949
|
+
var init_provider_profile_seeds = __esm(() => {
|
|
11950
|
+
DEFAULT_PROVIDER_PROFILE_SEEDS = [
|
|
11951
|
+
{
|
|
11952
|
+
id: "notion",
|
|
11953
|
+
displayName: "Notion",
|
|
11954
|
+
description: "Connect a Notion workspace so agents can search, read, create, and update workspace content.",
|
|
11955
|
+
endpoint: "https://mcp.notion.com/mcp",
|
|
11956
|
+
transport: "streamable-http",
|
|
11957
|
+
fallbackEndpoints: [
|
|
11958
|
+
{
|
|
11959
|
+
transport: "sse",
|
|
11960
|
+
url: "https://mcp.notion.com/sse",
|
|
11961
|
+
notes: "Fallback for clients that do not support Streamable HTTP."
|
|
11962
|
+
}
|
|
11963
|
+
],
|
|
11964
|
+
authType: "oauth2",
|
|
11965
|
+
authMetadata: {
|
|
11966
|
+
oauthVersion: "2.0",
|
|
11967
|
+
pkce: true,
|
|
11968
|
+
dynamicClientRegistration: true,
|
|
11969
|
+
bearerToken: "none",
|
|
11970
|
+
notes: "Remote Notion MCP uses OAuth with PKCE. Bearer-token authentication is only appropriate for self-hosted/local fallback deployments."
|
|
11971
|
+
},
|
|
11972
|
+
tokenMode: "workspace",
|
|
11973
|
+
installFallback: {
|
|
11974
|
+
command: "npx",
|
|
11975
|
+
args: ["-y", "mcp-remote", "https://mcp.notion.com/sse", "--transport", "sse-only"],
|
|
11976
|
+
packageName: "mcp-remote",
|
|
11977
|
+
url: "https://mcp.notion.com/sse"
|
|
11978
|
+
},
|
|
11979
|
+
docsUrl: "https://developers.notion.com/guides/mcp/build-mcp-client",
|
|
11980
|
+
safety: {
|
|
11981
|
+
requiresApproval: true,
|
|
11982
|
+
dataClasses: ["workspace_content", "pages", "databases", "comments"],
|
|
11983
|
+
notes: "Connected agents operate with the authorizing user's workspace access. Human confirmation is recommended for write-capable workflows."
|
|
11984
|
+
},
|
|
11985
|
+
provenance: {
|
|
11986
|
+
source: "curated",
|
|
11987
|
+
sourceUrl: "https://developers.notion.com/guides/mcp/build-mcp-client",
|
|
11988
|
+
verifiedAt: "2026-05-10"
|
|
11989
|
+
}
|
|
11990
|
+
},
|
|
11991
|
+
{
|
|
11992
|
+
id: "linear",
|
|
11993
|
+
displayName: "Linear",
|
|
11994
|
+
description: "Connect Linear so agents can find, create, and update issues, projects, comments, and related workspace objects.",
|
|
11995
|
+
endpoint: "https://mcp.linear.app/mcp",
|
|
11996
|
+
transport: "streamable-http",
|
|
11997
|
+
authType: "oauth2",
|
|
11998
|
+
authMetadata: {
|
|
11999
|
+
oauthVersion: "2.1",
|
|
12000
|
+
dynamicClientRegistration: true,
|
|
12001
|
+
bearerToken: "optional",
|
|
12002
|
+
notes: "Linear supports interactive OAuth 2.1 with dynamic client registration and optional Authorization: Bearer tokens for OAuth tokens or API keys."
|
|
12003
|
+
},
|
|
12004
|
+
tokenMode: "workspace",
|
|
12005
|
+
installFallback: {
|
|
12006
|
+
command: "npx",
|
|
12007
|
+
args: ["-y", "mcp-remote", "https://mcp.linear.app/mcp"],
|
|
12008
|
+
packageName: "mcp-remote",
|
|
12009
|
+
url: "https://mcp.linear.app/mcp"
|
|
12010
|
+
},
|
|
12011
|
+
docsUrl: "https://linear.app/docs/mcp",
|
|
12012
|
+
safety: {
|
|
12013
|
+
requiresApproval: true,
|
|
12014
|
+
dataClasses: ["issues", "projects", "comments", "teams", "users"],
|
|
12015
|
+
notes: "Linear tools can create and update workspace objects, so write actions should be policy-gated by the platform."
|
|
12016
|
+
},
|
|
12017
|
+
provenance: {
|
|
12018
|
+
source: "curated",
|
|
12019
|
+
sourceUrl: "https://linear.app/docs/mcp",
|
|
12020
|
+
verifiedAt: "2026-05-10"
|
|
12021
|
+
}
|
|
12022
|
+
}
|
|
12023
|
+
];
|
|
12024
|
+
});
|
|
12025
|
+
|
|
11947
12026
|
// src/lib/db.ts
|
|
11948
12027
|
import { mkdirSync as mkdirSync5 } from "fs";
|
|
11949
12028
|
function getDb() {
|
|
@@ -12029,6 +12108,50 @@ function getDb() {
|
|
|
12029
12108
|
('github-mcp-topic', 'GitHub MCP Topic', 'github-topic', 'https://api.github.com/search/repositories', 'GitHub repositories tagged with mcp-server topic')
|
|
12030
12109
|
`);
|
|
12031
12110
|
}
|
|
12111
|
+
db.exec(`
|
|
12112
|
+
CREATE TABLE IF NOT EXISTS provider_profiles (
|
|
12113
|
+
id TEXT PRIMARY KEY,
|
|
12114
|
+
display_name TEXT NOT NULL,
|
|
12115
|
+
description TEXT,
|
|
12116
|
+
endpoint TEXT,
|
|
12117
|
+
transport TEXT NOT NULL,
|
|
12118
|
+
fallback_endpoints TEXT NOT NULL DEFAULT '[]',
|
|
12119
|
+
auth_type TEXT NOT NULL,
|
|
12120
|
+
auth_metadata TEXT NOT NULL DEFAULT '{}',
|
|
12121
|
+
scopes TEXT NOT NULL DEFAULT '[]',
|
|
12122
|
+
token_mode TEXT NOT NULL DEFAULT 'none',
|
|
12123
|
+
install_fallback TEXT NOT NULL DEFAULT '{}',
|
|
12124
|
+
docs_url TEXT,
|
|
12125
|
+
safety TEXT NOT NULL DEFAULT '{}',
|
|
12126
|
+
provenance TEXT NOT NULL DEFAULT '{"source":"manual"}',
|
|
12127
|
+
enabled INTEGER NOT NULL DEFAULT 1,
|
|
12128
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
12129
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
12130
|
+
)
|
|
12131
|
+
`);
|
|
12132
|
+
try {
|
|
12133
|
+
db.exec("ALTER TABLE provider_profiles ADD COLUMN fallback_endpoints TEXT NOT NULL DEFAULT '[]'");
|
|
12134
|
+
} catch {}
|
|
12135
|
+
try {
|
|
12136
|
+
db.exec("ALTER TABLE provider_profiles ADD COLUMN auth_metadata TEXT NOT NULL DEFAULT '{}'");
|
|
12137
|
+
} catch {}
|
|
12138
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_provider_profiles_enabled ON provider_profiles(enabled)");
|
|
12139
|
+
const providerProfileCount = db.query("SELECT COUNT(*) as c FROM provider_profiles").get().c;
|
|
12140
|
+
if (providerProfileCount === 0) {
|
|
12141
|
+
const insertProviderProfile = db.prepare(`
|
|
12142
|
+
INSERT OR IGNORE INTO provider_profiles (
|
|
12143
|
+
id, display_name, description, endpoint, transport, fallback_endpoints,
|
|
12144
|
+
auth_type, auth_metadata, scopes, token_mode, install_fallback,
|
|
12145
|
+
docs_url, safety, provenance, enabled
|
|
12146
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
12147
|
+
`);
|
|
12148
|
+
const run = db.transaction(() => {
|
|
12149
|
+
for (const profile of DEFAULT_PROVIDER_PROFILE_SEEDS) {
|
|
12150
|
+
insertProviderProfile.run(profile.id, profile.displayName, profile.description ?? null, profile.endpoint ?? null, profile.transport, JSON.stringify(profile.fallbackEndpoints ?? []), profile.authType, JSON.stringify(profile.authMetadata ?? {}), JSON.stringify(profile.scopes ?? []), profile.tokenMode ?? "none", JSON.stringify(profile.installFallback ?? null), profile.docsUrl ?? null, JSON.stringify(profile.safety ?? {}), JSON.stringify(profile.provenance), profile.enabled === false ? 0 : 1);
|
|
12151
|
+
}
|
|
12152
|
+
});
|
|
12153
|
+
run();
|
|
12154
|
+
}
|
|
12032
12155
|
db.exec(`
|
|
12033
12156
|
CREATE TABLE IF NOT EXISTS feedback (
|
|
12034
12157
|
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
@@ -12059,6 +12182,7 @@ var db = null, _adapter = null;
|
|
|
12059
12182
|
var init_db = __esm(() => {
|
|
12060
12183
|
init_dist();
|
|
12061
12184
|
init_config2();
|
|
12185
|
+
init_provider_profile_seeds();
|
|
12062
12186
|
});
|
|
12063
12187
|
|
|
12064
12188
|
// node_modules/ajv/dist/compile/codegen/code.js
|
|
@@ -19288,12 +19412,12 @@ var init_sources = __esm(() => {
|
|
|
19288
19412
|
var require_package = __commonJS((exports, module) => {
|
|
19289
19413
|
module.exports = {
|
|
19290
19414
|
name: "@hasna/mcps",
|
|
19291
|
-
version: "0.0.
|
|
19415
|
+
version: "0.0.14",
|
|
19292
19416
|
description: "Meta-MCP registry & CLI \u2014 discover, manage, and proxy MCP servers",
|
|
19293
19417
|
type: "module",
|
|
19294
19418
|
repository: {
|
|
19295
19419
|
type: "git",
|
|
19296
|
-
url: "https://github.com/hasna/mcps.git"
|
|
19420
|
+
url: "git+https://github.com/hasna/mcps.git"
|
|
19297
19421
|
},
|
|
19298
19422
|
main: "dist/index.js",
|
|
19299
19423
|
types: "dist/index.d.ts",
|
|
@@ -36767,6 +36891,104 @@ async function runFleetInstall(options = {}, dependencies = {}) {
|
|
|
36767
36891
|
}));
|
|
36768
36892
|
}
|
|
36769
36893
|
|
|
36894
|
+
// src/lib/provider-profiles.ts
|
|
36895
|
+
init_db();
|
|
36896
|
+
init_provider_profile_seeds();
|
|
36897
|
+
var TRANSPORTS = new Set(["stdio", "sse", "streamable-http"]);
|
|
36898
|
+
var AUTH_TYPES = new Set(["none", "oauth2", "api_key", "bearer_token", "custom"]);
|
|
36899
|
+
var TOKEN_MODES = new Set(["none", "user", "workspace", "service"]);
|
|
36900
|
+
var BEARER_TOKEN_MODES = new Set(["none", "optional", "required"]);
|
|
36901
|
+
var PROVENANCE_SOURCES = new Set(["curated", "official-registry", "npm", "github", "manual"]);
|
|
36902
|
+
function safeJsonParse2(value, fallback) {
|
|
36903
|
+
if (typeof value !== "string")
|
|
36904
|
+
return fallback;
|
|
36905
|
+
try {
|
|
36906
|
+
return JSON.parse(value);
|
|
36907
|
+
} catch {
|
|
36908
|
+
return fallback;
|
|
36909
|
+
}
|
|
36910
|
+
}
|
|
36911
|
+
function normalizeId(id) {
|
|
36912
|
+
const normalized = id.trim().toLowerCase();
|
|
36913
|
+
if (!/^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$/.test(normalized)) {
|
|
36914
|
+
throw new Error("Provider profile id must be lowercase kebab-case");
|
|
36915
|
+
}
|
|
36916
|
+
return normalized;
|
|
36917
|
+
}
|
|
36918
|
+
function parseRow3(row) {
|
|
36919
|
+
const installFallback = safeJsonParse2(row.install_fallback, null);
|
|
36920
|
+
return {
|
|
36921
|
+
id: row.id,
|
|
36922
|
+
displayName: row.display_name,
|
|
36923
|
+
description: row.description || null,
|
|
36924
|
+
endpoint: row.endpoint || null,
|
|
36925
|
+
transport: row.transport,
|
|
36926
|
+
fallbackEndpoints: safeJsonParse2(row.fallback_endpoints, []),
|
|
36927
|
+
authType: row.auth_type,
|
|
36928
|
+
authMetadata: safeJsonParse2(row.auth_metadata, {}),
|
|
36929
|
+
scopes: safeJsonParse2(row.scopes, []),
|
|
36930
|
+
tokenMode: row.token_mode,
|
|
36931
|
+
installFallback,
|
|
36932
|
+
docsUrl: row.docs_url || null,
|
|
36933
|
+
safety: safeJsonParse2(row.safety, {}),
|
|
36934
|
+
provenance: safeJsonParse2(row.provenance, { source: "manual" }),
|
|
36935
|
+
enabled: row.enabled === 1 || row.enabled === true,
|
|
36936
|
+
created_at: row.created_at,
|
|
36937
|
+
updated_at: row.updated_at
|
|
36938
|
+
};
|
|
36939
|
+
}
|
|
36940
|
+
function listProviderProfiles(options = {}) {
|
|
36941
|
+
const db2 = getDb();
|
|
36942
|
+
const sql = options.enabledOnly ? "SELECT * FROM provider_profiles WHERE enabled = 1 ORDER BY display_name" : "SELECT * FROM provider_profiles ORDER BY display_name";
|
|
36943
|
+
return db2.prepare(sql).all().map(parseRow3);
|
|
36944
|
+
}
|
|
36945
|
+
function searchProviderProfiles(query, options = {}) {
|
|
36946
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
36947
|
+
if (!normalizedQuery)
|
|
36948
|
+
return listProviderProfiles(options);
|
|
36949
|
+
return listProviderProfiles(options).filter((profile) => {
|
|
36950
|
+
const searchable = [
|
|
36951
|
+
profile.id,
|
|
36952
|
+
profile.displayName,
|
|
36953
|
+
profile.description ?? "",
|
|
36954
|
+
profile.endpoint ?? "",
|
|
36955
|
+
profile.docsUrl ?? "",
|
|
36956
|
+
profile.provenance.sourceUrl ?? "",
|
|
36957
|
+
profile.provenance.packageName ?? ""
|
|
36958
|
+
].join(`
|
|
36959
|
+
`).toLowerCase();
|
|
36960
|
+
return searchable.includes(normalizedQuery);
|
|
36961
|
+
});
|
|
36962
|
+
}
|
|
36963
|
+
function getProviderProfile(id) {
|
|
36964
|
+
const db2 = getDb();
|
|
36965
|
+
const row = db2.prepare("SELECT * FROM provider_profiles WHERE id = ?").get(normalizeId(id));
|
|
36966
|
+
return row ? parseRow3(row) : null;
|
|
36967
|
+
}
|
|
36968
|
+
function installProviderProfile(id, options = {}) {
|
|
36969
|
+
const profile = getProviderProfile(id);
|
|
36970
|
+
if (!profile)
|
|
36971
|
+
throw new Error(`Provider profile "${id}" not found`);
|
|
36972
|
+
if (!profile.enabled)
|
|
36973
|
+
throw new Error(`Provider profile "${id}" is disabled`);
|
|
36974
|
+
const fallback = profile.installFallback;
|
|
36975
|
+
const useFallback = options.useFallback || !profile.endpoint;
|
|
36976
|
+
const command = useFallback ? fallback?.command : fallback?.command ?? "npx";
|
|
36977
|
+
const args = useFallback ? fallback?.args ?? [] : fallback?.args ?? [];
|
|
36978
|
+
if (!command) {
|
|
36979
|
+
throw new Error(`Provider profile "${id}" does not define an install fallback command`);
|
|
36980
|
+
}
|
|
36981
|
+
return addServer({
|
|
36982
|
+
name: options.name ?? profile.displayName,
|
|
36983
|
+
description: profile.description ?? undefined,
|
|
36984
|
+
command,
|
|
36985
|
+
args,
|
|
36986
|
+
transport: useFallback ? "stdio" : profile.transport,
|
|
36987
|
+
url: useFallback ? fallback?.url : profile.endpoint ?? undefined,
|
|
36988
|
+
source: "provider-profile"
|
|
36989
|
+
});
|
|
36990
|
+
}
|
|
36991
|
+
|
|
36770
36992
|
// src/cli/index.tsx
|
|
36771
36993
|
import * as readline from "readline";
|
|
36772
36994
|
|
|
@@ -38186,6 +38408,55 @@ function buildMcpTools() {
|
|
|
38186
38408
|
limit: typeof limit === "number" ? limit : undefined
|
|
38187
38409
|
}))
|
|
38188
38410
|
},
|
|
38411
|
+
{
|
|
38412
|
+
name: "list_provider_profiles",
|
|
38413
|
+
description: "List curated provider profiles for hosted/common MCP integrations such as Notion and Linear.",
|
|
38414
|
+
paramsSchema: {
|
|
38415
|
+
enabled_only: exports_external2.boolean().optional().describe("Only include enabled provider profiles")
|
|
38416
|
+
},
|
|
38417
|
+
run: ({ enabled_only }) => jsonContent(listProviderProfiles({ enabledOnly: enabled_only === true }))
|
|
38418
|
+
},
|
|
38419
|
+
{
|
|
38420
|
+
name: "search_provider_profiles",
|
|
38421
|
+
description: "Search curated provider profiles separately from raw MCP registry/source search.",
|
|
38422
|
+
paramsSchema: {
|
|
38423
|
+
query: exports_external2.string().describe("Search query such as 'notion', 'linear', or an endpoint URL"),
|
|
38424
|
+
enabled_only: exports_external2.boolean().optional().describe("Only include enabled provider profiles")
|
|
38425
|
+
},
|
|
38426
|
+
run: ({ query, enabled_only }) => jsonContent(searchProviderProfiles(String(query), { enabledOnly: enabled_only === true }))
|
|
38427
|
+
},
|
|
38428
|
+
{
|
|
38429
|
+
name: "get_provider_profile",
|
|
38430
|
+
description: "Get one curated provider profile by ID.",
|
|
38431
|
+
paramsSchema: {
|
|
38432
|
+
id: exports_external2.string().describe("Provider profile ID")
|
|
38433
|
+
},
|
|
38434
|
+
run: ({ id }) => {
|
|
38435
|
+
const profile = getProviderProfile(String(id));
|
|
38436
|
+
if (!profile)
|
|
38437
|
+
return errorContent(`Provider profile "${String(id)}" not found.`);
|
|
38438
|
+
return jsonContent(profile);
|
|
38439
|
+
}
|
|
38440
|
+
},
|
|
38441
|
+
{
|
|
38442
|
+
name: "install_provider_profile",
|
|
38443
|
+
description: "Register a curated provider profile as an MCP server.",
|
|
38444
|
+
paramsSchema: {
|
|
38445
|
+
id: exports_external2.string().describe("Provider profile ID"),
|
|
38446
|
+
name: exports_external2.string().optional().describe("Override registered server name"),
|
|
38447
|
+
use_fallback: exports_external2.boolean().optional().describe("Install the stdio fallback command instead of the direct remote transport")
|
|
38448
|
+
},
|
|
38449
|
+
run: ({ id, name, use_fallback }) => {
|
|
38450
|
+
try {
|
|
38451
|
+
return jsonContent(redactServerEnv(installProviderProfile(String(id), {
|
|
38452
|
+
name: typeof name === "string" ? name : undefined,
|
|
38453
|
+
useFallback: use_fallback === true
|
|
38454
|
+
})));
|
|
38455
|
+
} catch (err) {
|
|
38456
|
+
return errorContent(err.message);
|
|
38457
|
+
}
|
|
38458
|
+
}
|
|
38459
|
+
},
|
|
38189
38460
|
{
|
|
38190
38461
|
name: "list_sources",
|
|
38191
38462
|
description: "List all configured search sources for finding MCP servers",
|
|
@@ -40266,6 +40537,24 @@ var MACHINE_PLATFORMS = ["linux", "darwin", "unknown"];
|
|
|
40266
40537
|
var MACHINE_ARCHES = ["arm64", "x64", "unknown"];
|
|
40267
40538
|
var MACHINE_INSTALLERS = ["auto", "bun", "npm"];
|
|
40268
40539
|
var FLEET_INSTALL_MODES = ["missing", "missing-or-outdated", "all"];
|
|
40540
|
+
function printProviderProfile(profile) {
|
|
40541
|
+
const status = profile.enabled ? chalk2.green("enabled") : chalk2.red("disabled");
|
|
40542
|
+
console.log(` ${chalk2.bold(profile.displayName)} ${chalk2.dim(`[${profile.id}]`)} \u2014 ${chalk2.dim(profile.transport)} \u2014 ${status}`);
|
|
40543
|
+
if (profile.description)
|
|
40544
|
+
console.log(` ${chalk2.dim(profile.description)}`);
|
|
40545
|
+
if (profile.endpoint)
|
|
40546
|
+
console.log(` ${chalk2.cyan(profile.endpoint)}`);
|
|
40547
|
+
if (profile.authMetadata.bearerToken === "optional") {
|
|
40548
|
+
console.log(` ${chalk2.dim("Auth: OAuth with optional bearer token/API key support")}`);
|
|
40549
|
+
} else if (profile.authMetadata.pkce || profile.authMetadata.dynamicClientRegistration) {
|
|
40550
|
+
const parts = [
|
|
40551
|
+
profile.authMetadata.oauthVersion ? `OAuth ${profile.authMetadata.oauthVersion}` : "OAuth",
|
|
40552
|
+
profile.authMetadata.pkce ? "PKCE" : null,
|
|
40553
|
+
profile.authMetadata.dynamicClientRegistration ? "dynamic client registration" : null
|
|
40554
|
+
].filter(Boolean);
|
|
40555
|
+
console.log(` ${chalk2.dim(`Auth: ${parts.join(", ")}`)}`);
|
|
40556
|
+
}
|
|
40557
|
+
}
|
|
40269
40558
|
function printJson(value) {
|
|
40270
40559
|
console.log(JSON.stringify(value, null, 2));
|
|
40271
40560
|
}
|
|
@@ -40438,6 +40727,85 @@ ${results.length} result(s). Use \`mcps add --from-registry <id>\` to install.`)
|
|
|
40438
40727
|
closeDb();
|
|
40439
40728
|
}
|
|
40440
40729
|
});
|
|
40730
|
+
var providersCmd = program2.command("providers").description("Discover and install curated MCP provider profiles");
|
|
40731
|
+
providersCmd.command("list").description("List curated provider profiles").option("--json", "Output as JSON").option("--enabled-only", "Only include enabled profiles").action((opts) => {
|
|
40732
|
+
const profiles = listProviderProfiles({ enabledOnly: opts.enabledOnly === true });
|
|
40733
|
+
if (opts.json) {
|
|
40734
|
+
printJson(profiles);
|
|
40735
|
+
closeDb();
|
|
40736
|
+
return;
|
|
40737
|
+
}
|
|
40738
|
+
if (profiles.length === 0) {
|
|
40739
|
+
console.log(chalk2.dim("No curated provider profiles available."));
|
|
40740
|
+
closeDb();
|
|
40741
|
+
return;
|
|
40742
|
+
}
|
|
40743
|
+
for (const profile of profiles)
|
|
40744
|
+
printProviderProfile(profile);
|
|
40745
|
+
closeDb();
|
|
40746
|
+
});
|
|
40747
|
+
providersCmd.command("search").argument("<query>", "Search query").description("Search curated provider profiles").option("--json", "Output as JSON").option("--enabled-only", "Only include enabled profiles").action((query, opts) => {
|
|
40748
|
+
const profiles = searchProviderProfiles(query, { enabledOnly: opts.enabledOnly === true });
|
|
40749
|
+
if (opts.json) {
|
|
40750
|
+
printJson(profiles);
|
|
40751
|
+
closeDb();
|
|
40752
|
+
return;
|
|
40753
|
+
}
|
|
40754
|
+
if (profiles.length === 0) {
|
|
40755
|
+
console.log(chalk2.dim("No curated provider profiles found."));
|
|
40756
|
+
closeDb();
|
|
40757
|
+
return;
|
|
40758
|
+
}
|
|
40759
|
+
for (const profile of profiles)
|
|
40760
|
+
printProviderProfile(profile);
|
|
40761
|
+
console.log(chalk2.dim(`
|
|
40762
|
+
${profiles.length} provider profile(s). Use \`mcps providers install <id>\` to register one.`));
|
|
40763
|
+
closeDb();
|
|
40764
|
+
});
|
|
40765
|
+
providersCmd.command("info").argument("<id>", "Provider profile ID").description("Show a curated provider profile").option("--json", "Output as JSON").action((id, opts) => {
|
|
40766
|
+
const profile = getProviderProfile(id);
|
|
40767
|
+
if (!profile) {
|
|
40768
|
+
console.error(chalk2.red(`Provider profile "${id}" not found.`));
|
|
40769
|
+
closeDb();
|
|
40770
|
+
process.exit(1);
|
|
40771
|
+
}
|
|
40772
|
+
if (opts.json) {
|
|
40773
|
+
printJson(profile);
|
|
40774
|
+
closeDb();
|
|
40775
|
+
return;
|
|
40776
|
+
}
|
|
40777
|
+
printProviderProfile(profile);
|
|
40778
|
+
if (profile.fallbackEndpoints.length > 0) {
|
|
40779
|
+
console.log(chalk2.bold(" Fallback endpoints:"));
|
|
40780
|
+
for (const fallback of profile.fallbackEndpoints) {
|
|
40781
|
+
console.log(` ${fallback.transport}: ${chalk2.cyan(fallback.url)}`);
|
|
40782
|
+
}
|
|
40783
|
+
}
|
|
40784
|
+
if (profile.docsUrl)
|
|
40785
|
+
console.log(` Docs: ${chalk2.cyan(profile.docsUrl)}`);
|
|
40786
|
+
closeDb();
|
|
40787
|
+
});
|
|
40788
|
+
providersCmd.command("install").argument("<id>", "Provider profile ID").description("Register a curated provider profile as an MCP server").option("--name <name>", "Override registered server name").option("--fallback", "Install the stdio fallback command instead of direct remote transport").option("--json", "Output as JSON").action((id, opts) => {
|
|
40789
|
+
try {
|
|
40790
|
+
const server = installProviderProfile(id, {
|
|
40791
|
+
name: opts.name,
|
|
40792
|
+
useFallback: opts.fallback === true
|
|
40793
|
+
});
|
|
40794
|
+
if (opts.json) {
|
|
40795
|
+
printJson(server);
|
|
40796
|
+
} else {
|
|
40797
|
+
console.log(chalk2.green(`Installed provider profile: ${server.name} [${server.id}]`));
|
|
40798
|
+
console.log(chalk2.dim(` Transport: ${server.transport}`));
|
|
40799
|
+
if (server.url)
|
|
40800
|
+
console.log(chalk2.dim(` URL: ${server.url}`));
|
|
40801
|
+
}
|
|
40802
|
+
closeDb();
|
|
40803
|
+
} catch (err) {
|
|
40804
|
+
console.error(chalk2.red(`Failed to install provider profile: ${err.message}`));
|
|
40805
|
+
closeDb();
|
|
40806
|
+
process.exit(1);
|
|
40807
|
+
}
|
|
40808
|
+
});
|
|
40441
40809
|
async function promptReadline(rl, question) {
|
|
40442
40810
|
return new Promise((resolve2) => rl.question(question, resolve2));
|
|
40443
40811
|
}
|
|
@@ -40816,7 +41184,7 @@ ${server.name} [${server.id}]`));
|
|
|
40816
41184
|
closeDb();
|
|
40817
41185
|
});
|
|
40818
41186
|
program2.command("completion").argument("<shell>", "Shell type: bash, zsh, fish").description("Generate shell completion script").action((shell) => {
|
|
40819
|
-
const commands = ["list", "search", "find", "add", "remove", "enable", "disable", "info", "status", "tools", "call", "doctor", "install", "machines", "fleet", "export", "import", "env", "sources", "clone", "update-server", "serve", "update", "mcp", "completion"];
|
|
41187
|
+
const commands = ["list", "search", "providers", "find", "add", "remove", "enable", "disable", "info", "status", "tools", "call", "doctor", "install", "machines", "fleet", "export", "import", "env", "sources", "clone", "update-server", "serve", "update", "mcp", "completion"];
|
|
40820
41188
|
if (shell === "bash") {
|
|
40821
41189
|
console.log(`# Add to ~/.bashrc: eval "$(mcps completion bash)"
|
|
40822
41190
|
_mcps_complete() {
|