@hasna/mcps 0.0.11 → 0.0.13
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 +772 -611
- package/bin/mcp.js +21599 -21430
- package/dist/index.d.ts +1 -0
- package/dist/index.js +24 -0
- package/dist/lib/version.d.ts +1 -0
- package/dist/mcp/index.d.ts +4 -0
- package/dist/mcp/index.js +35019 -0
- package/dist/mcp/server.d.ts +10 -0
- package/dist/mcp/tools.d.ts +14 -0
- package/package.json +10 -2
package/bin/index.js
CHANGED
|
@@ -19288,15 +19288,23 @@ var init_sources = __esm(() => {
|
|
|
19288
19288
|
var require_package = __commonJS((exports, module) => {
|
|
19289
19289
|
module.exports = {
|
|
19290
19290
|
name: "@hasna/mcps",
|
|
19291
|
-
version: "0.0.
|
|
19291
|
+
version: "0.0.13",
|
|
19292
19292
|
description: "Meta-MCP registry & CLI \u2014 discover, manage, and proxy MCP servers",
|
|
19293
19293
|
type: "module",
|
|
19294
|
+
repository: {
|
|
19295
|
+
type: "git",
|
|
19296
|
+
url: "https://github.com/hasna/mcps.git"
|
|
19297
|
+
},
|
|
19294
19298
|
main: "dist/index.js",
|
|
19295
19299
|
types: "dist/index.d.ts",
|
|
19296
19300
|
exports: {
|
|
19297
19301
|
".": {
|
|
19298
19302
|
import: "./dist/index.js",
|
|
19299
19303
|
types: "./dist/index.d.ts"
|
|
19304
|
+
},
|
|
19305
|
+
"./mcp": {
|
|
19306
|
+
import: "./dist/mcp/index.js",
|
|
19307
|
+
types: "./dist/mcp/index.d.ts"
|
|
19300
19308
|
}
|
|
19301
19309
|
},
|
|
19302
19310
|
bin: {
|
|
@@ -19311,7 +19319,7 @@ var require_package = __commonJS((exports, module) => {
|
|
|
19311
19319
|
"README.md"
|
|
19312
19320
|
],
|
|
19313
19321
|
scripts: {
|
|
19314
|
-
build: "bun run build:dashboard && bun build ./src/cli/index.tsx --outdir ./bin --target bun --external ink --external react --external chalk && bun build ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun run scripts/fix-shebangs.ts && bun build ./src/index.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist",
|
|
19322
|
+
build: "bun run build:dashboard && bun build ./src/cli/index.tsx --outdir ./bin --target bun --external ink --external react --external chalk && bun build ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun run scripts/fix-shebangs.ts && bun build ./src/index.ts --outdir ./dist --target bun && bun build ./src/mcp/index.ts --outdir ./dist/mcp --target bun && tsc --emitDeclarationOnly --declaration --outDir dist",
|
|
19315
19323
|
"build:dashboard": "cd dashboard && bun install && bun run build",
|
|
19316
19324
|
dev: "bun run src/cli/index.tsx",
|
|
19317
19325
|
"dev:mcp": "bun run src/mcp/index.ts",
|
|
@@ -21011,8 +21019,6 @@ import React10 from "react";
|
|
|
21011
21019
|
import { render } from "ink";
|
|
21012
21020
|
import chalk2 from "chalk";
|
|
21013
21021
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
21014
|
-
import { join as join12, dirname as dirname5 } from "path";
|
|
21015
|
-
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
21016
21022
|
|
|
21017
21023
|
// src/lib/registry.ts
|
|
21018
21024
|
init_db();
|
|
@@ -36764,6 +36770,68 @@ async function runFleetInstall(options = {}, dependencies = {}) {
|
|
|
36764
36770
|
// src/cli/index.tsx
|
|
36765
36771
|
import * as readline from "readline";
|
|
36766
36772
|
|
|
36773
|
+
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
36774
|
+
import process3 from "process";
|
|
36775
|
+
class StdioServerTransport {
|
|
36776
|
+
constructor(_stdin = process3.stdin, _stdout = process3.stdout) {
|
|
36777
|
+
this._stdin = _stdin;
|
|
36778
|
+
this._stdout = _stdout;
|
|
36779
|
+
this._readBuffer = new ReadBuffer;
|
|
36780
|
+
this._started = false;
|
|
36781
|
+
this._ondata = (chunk) => {
|
|
36782
|
+
this._readBuffer.append(chunk);
|
|
36783
|
+
this.processReadBuffer();
|
|
36784
|
+
};
|
|
36785
|
+
this._onerror = (error2) => {
|
|
36786
|
+
this.onerror?.(error2);
|
|
36787
|
+
};
|
|
36788
|
+
}
|
|
36789
|
+
async start() {
|
|
36790
|
+
if (this._started) {
|
|
36791
|
+
throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");
|
|
36792
|
+
}
|
|
36793
|
+
this._started = true;
|
|
36794
|
+
this._stdin.on("data", this._ondata);
|
|
36795
|
+
this._stdin.on("error", this._onerror);
|
|
36796
|
+
}
|
|
36797
|
+
processReadBuffer() {
|
|
36798
|
+
while (true) {
|
|
36799
|
+
try {
|
|
36800
|
+
const message = this._readBuffer.readMessage();
|
|
36801
|
+
if (message === null) {
|
|
36802
|
+
break;
|
|
36803
|
+
}
|
|
36804
|
+
this.onmessage?.(message);
|
|
36805
|
+
} catch (error2) {
|
|
36806
|
+
this.onerror?.(error2);
|
|
36807
|
+
}
|
|
36808
|
+
}
|
|
36809
|
+
}
|
|
36810
|
+
async close() {
|
|
36811
|
+
this._stdin.off("data", this._ondata);
|
|
36812
|
+
this._stdin.off("error", this._onerror);
|
|
36813
|
+
const remainingDataListeners = this._stdin.listenerCount("data");
|
|
36814
|
+
if (remainingDataListeners === 0) {
|
|
36815
|
+
this._stdin.pause();
|
|
36816
|
+
}
|
|
36817
|
+
this._readBuffer.clear();
|
|
36818
|
+
this.onclose?.();
|
|
36819
|
+
}
|
|
36820
|
+
send(message) {
|
|
36821
|
+
return new Promise((resolve) => {
|
|
36822
|
+
const json = serializeMessage(message);
|
|
36823
|
+
if (this._stdout.write(json)) {
|
|
36824
|
+
resolve();
|
|
36825
|
+
} else {
|
|
36826
|
+
this._stdout.once("drain", resolve);
|
|
36827
|
+
}
|
|
36828
|
+
});
|
|
36829
|
+
}
|
|
36830
|
+
}
|
|
36831
|
+
|
|
36832
|
+
// src/mcp/server.ts
|
|
36833
|
+
init_dist();
|
|
36834
|
+
|
|
36767
36835
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/server.js
|
|
36768
36836
|
class ExperimentalServerTasks {
|
|
36769
36837
|
constructor(_server) {
|
|
@@ -37925,535 +37993,634 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
37925
37993
|
}
|
|
37926
37994
|
};
|
|
37927
37995
|
|
|
37928
|
-
//
|
|
37929
|
-
import
|
|
37930
|
-
|
|
37931
|
-
|
|
37932
|
-
|
|
37933
|
-
|
|
37934
|
-
|
|
37935
|
-
|
|
37936
|
-
|
|
37937
|
-
|
|
37938
|
-
|
|
37939
|
-
|
|
37940
|
-
|
|
37941
|
-
|
|
37942
|
-
|
|
37943
|
-
|
|
37944
|
-
|
|
37945
|
-
|
|
37946
|
-
|
|
37947
|
-
}
|
|
37948
|
-
this._started = true;
|
|
37949
|
-
this._stdin.on("data", this._ondata);
|
|
37950
|
-
this._stdin.on("error", this._onerror);
|
|
37951
|
-
}
|
|
37952
|
-
processReadBuffer() {
|
|
37953
|
-
while (true) {
|
|
37954
|
-
try {
|
|
37955
|
-
const message = this._readBuffer.readMessage();
|
|
37956
|
-
if (message === null) {
|
|
37957
|
-
break;
|
|
37958
|
-
}
|
|
37959
|
-
this.onmessage?.(message);
|
|
37960
|
-
} catch (error2) {
|
|
37961
|
-
this.onerror?.(error2);
|
|
37962
|
-
}
|
|
37963
|
-
}
|
|
37964
|
-
}
|
|
37965
|
-
async close() {
|
|
37966
|
-
this._stdin.off("data", this._ondata);
|
|
37967
|
-
this._stdin.off("error", this._onerror);
|
|
37968
|
-
const remainingDataListeners = this._stdin.listenerCount("data");
|
|
37969
|
-
if (remainingDataListeners === 0) {
|
|
37970
|
-
this._stdin.pause();
|
|
37971
|
-
}
|
|
37972
|
-
this._readBuffer.clear();
|
|
37973
|
-
this.onclose?.();
|
|
37974
|
-
}
|
|
37975
|
-
send(message) {
|
|
37976
|
-
return new Promise((resolve) => {
|
|
37977
|
-
const json = serializeMessage(message);
|
|
37978
|
-
if (this._stdout.write(json)) {
|
|
37979
|
-
resolve();
|
|
37980
|
-
} else {
|
|
37981
|
-
this._stdout.once("drain", resolve);
|
|
37982
|
-
}
|
|
37983
|
-
});
|
|
37996
|
+
// src/lib/version.ts
|
|
37997
|
+
import { existsSync as existsSync9, readFileSync as readFileSync5 } from "fs";
|
|
37998
|
+
import { dirname as dirname3, join as join10 } from "path";
|
|
37999
|
+
import { fileURLToPath } from "url";
|
|
38000
|
+
var FALLBACK_VERSION = "0.0.1";
|
|
38001
|
+
function readPackageVersion(moduleUrl, fallback = FALLBACK_VERSION) {
|
|
38002
|
+
const baseDir = dirname3(fileURLToPath(moduleUrl));
|
|
38003
|
+
const candidates = [
|
|
38004
|
+
join10(baseDir, "..", "..", "package.json"),
|
|
38005
|
+
join10(baseDir, "..", "package.json"),
|
|
38006
|
+
join10(baseDir, "package.json")
|
|
38007
|
+
];
|
|
38008
|
+
for (const candidate of candidates) {
|
|
38009
|
+
if (!existsSync9(candidate))
|
|
38010
|
+
continue;
|
|
38011
|
+
try {
|
|
38012
|
+
const pkg = JSON.parse(readFileSync5(candidate, "utf-8"));
|
|
38013
|
+
if (pkg.version)
|
|
38014
|
+
return pkg.version;
|
|
38015
|
+
} catch {}
|
|
37984
38016
|
}
|
|
38017
|
+
return fallback;
|
|
37985
38018
|
}
|
|
37986
38019
|
|
|
37987
|
-
// src/mcp/
|
|
37988
|
-
init_dist();
|
|
37989
|
-
import { readFileSync as readFileSync5 } from "fs";
|
|
37990
|
-
import { join as join10, dirname as dirname3 } from "path";
|
|
37991
|
-
import { fileURLToPath } from "url";
|
|
38020
|
+
// src/mcp/tools.ts
|
|
37992
38021
|
init_sources();
|
|
37993
38022
|
init_config2();
|
|
37994
38023
|
init_db();
|
|
38024
|
+
var VERSION = readPackageVersion(import.meta.url);
|
|
38025
|
+
var mcpsAgents = new Map;
|
|
37995
38026
|
function redactServerEnv(server) {
|
|
37996
38027
|
return { ...server, env: {} };
|
|
37997
38028
|
}
|
|
37998
|
-
|
|
37999
|
-
|
|
38000
|
-
|
|
38001
|
-
|
|
38002
|
-
|
|
38003
|
-
|
|
38004
|
-
|
|
38005
|
-
}
|
|
38006
|
-
}
|
|
38007
|
-
|
|
38008
|
-
|
|
38009
|
-
|
|
38010
|
-
|
|
38011
|
-
|
|
38012
|
-
|
|
38013
|
-
|
|
38014
|
-
|
|
38015
|
-
|
|
38016
|
-
|
|
38017
|
-
|
|
38018
|
-
|
|
38019
|
-
|
|
38020
|
-
|
|
38021
|
-
|
|
38022
|
-
|
|
38023
|
-
|
|
38024
|
-
|
|
38025
|
-
|
|
38026
|
-
|
|
38027
|
-
|
|
38028
|
-
|
|
38029
|
-
|
|
38030
|
-
|
|
38031
|
-
|
|
38032
|
-
},
|
|
38033
|
-
|
|
38034
|
-
|
|
38035
|
-
|
|
38036
|
-
|
|
38037
|
-
|
|
38038
|
-
|
|
38039
|
-
|
|
38040
|
-
|
|
38041
|
-
|
|
38042
|
-
|
|
38043
|
-
|
|
38044
|
-
|
|
38045
|
-
|
|
38046
|
-
|
|
38047
|
-
|
|
38048
|
-
|
|
38049
|
-
|
|
38050
|
-
|
|
38051
|
-
|
|
38052
|
-
|
|
38053
|
-
|
|
38054
|
-
|
|
38055
|
-
|
|
38056
|
-
|
|
38057
|
-
|
|
38058
|
-
|
|
38059
|
-
|
|
38060
|
-
|
|
38061
|
-
|
|
38062
|
-
|
|
38063
|
-
|
|
38064
|
-
}
|
|
38065
|
-
|
|
38066
|
-
|
|
38067
|
-
|
|
38068
|
-
|
|
38069
|
-
|
|
38070
|
-
|
|
38071
|
-
}
|
|
38029
|
+
function textContent(text) {
|
|
38030
|
+
return { content: [{ type: "text", text }] };
|
|
38031
|
+
}
|
|
38032
|
+
function jsonContent(value) {
|
|
38033
|
+
return textContent(JSON.stringify(value, null, 2));
|
|
38034
|
+
}
|
|
38035
|
+
function errorContent(text) {
|
|
38036
|
+
return { ...textContent(text), isError: true };
|
|
38037
|
+
}
|
|
38038
|
+
function buildMcpTools() {
|
|
38039
|
+
const definitions = [
|
|
38040
|
+
{
|
|
38041
|
+
name: "list_servers",
|
|
38042
|
+
description: "List all registered MCP servers",
|
|
38043
|
+
paramsSchema: {},
|
|
38044
|
+
run: () => jsonContent(listServers().map(redactServerEnv))
|
|
38045
|
+
},
|
|
38046
|
+
{
|
|
38047
|
+
name: "search_registry",
|
|
38048
|
+
description: "Search the official MCP registry for servers",
|
|
38049
|
+
paramsSchema: { query: exports_external2.string().describe("Search query") },
|
|
38050
|
+
run: async ({ query }) => jsonContent(await searchRegistry(String(query)))
|
|
38051
|
+
},
|
|
38052
|
+
{
|
|
38053
|
+
name: "add_server",
|
|
38054
|
+
description: "Register a new MCP server",
|
|
38055
|
+
paramsSchema: {
|
|
38056
|
+
command: exports_external2.string().describe("Command to run the server (e.g., npx, bunx, node)"),
|
|
38057
|
+
args: exports_external2.array(exports_external2.string()).optional().describe("Arguments for the command"),
|
|
38058
|
+
name: exports_external2.string().optional().describe("Display name"),
|
|
38059
|
+
description: exports_external2.string().optional().describe("Description"),
|
|
38060
|
+
transport: exports_external2.enum(["stdio", "sse", "streamable-http"]).optional().describe("Transport type"),
|
|
38061
|
+
url: exports_external2.string().optional().describe("URL for remote transports"),
|
|
38062
|
+
env: exports_external2.record(exports_external2.string()).optional().describe("Environment variables")
|
|
38063
|
+
},
|
|
38064
|
+
run: ({ command, args, name, description, transport, url: url2, env }) => jsonContent(addServer({
|
|
38065
|
+
command: String(command),
|
|
38066
|
+
args: Array.isArray(args) ? args.map(String) : [],
|
|
38067
|
+
name: typeof name === "string" ? name : undefined,
|
|
38068
|
+
description: typeof description === "string" ? description : undefined,
|
|
38069
|
+
transport,
|
|
38070
|
+
url: typeof url2 === "string" ? url2 : undefined,
|
|
38071
|
+
env: isRecordOfStrings(env) ? env : {}
|
|
38072
|
+
}))
|
|
38073
|
+
},
|
|
38074
|
+
{
|
|
38075
|
+
name: "install_from_registry",
|
|
38076
|
+
description: "Install an MCP server from the official registry",
|
|
38077
|
+
paramsSchema: { id: exports_external2.string().describe("Registry server ID") },
|
|
38078
|
+
run: async ({ id }) => jsonContent(await installFromRegistry(String(id)))
|
|
38079
|
+
},
|
|
38080
|
+
{
|
|
38081
|
+
name: "remove_server",
|
|
38082
|
+
description: "Remove a registered MCP server",
|
|
38083
|
+
paramsSchema: { id: exports_external2.string().describe("Server ID to remove") },
|
|
38084
|
+
run: ({ id }) => {
|
|
38085
|
+
const existing = getServer(String(id));
|
|
38086
|
+
if (!existing)
|
|
38087
|
+
return errorContent(`Server "${String(id)}" not found.`);
|
|
38088
|
+
removeServer(String(id));
|
|
38089
|
+
return textContent(`Removed server: ${existing.name} [${String(id)}]`);
|
|
38090
|
+
}
|
|
38091
|
+
},
|
|
38092
|
+
{
|
|
38093
|
+
name: "enable_server",
|
|
38094
|
+
description: "Enable a registered MCP server",
|
|
38095
|
+
paramsSchema: { id: exports_external2.string().describe("Server ID to enable") },
|
|
38096
|
+
run: ({ id }) => {
|
|
38097
|
+
const existing = getServer(String(id));
|
|
38098
|
+
if (!existing)
|
|
38099
|
+
return errorContent(`Server "${String(id)}" not found.`);
|
|
38100
|
+
return jsonContent(enableServer(String(id)));
|
|
38101
|
+
}
|
|
38102
|
+
},
|
|
38103
|
+
{
|
|
38104
|
+
name: "disable_server",
|
|
38105
|
+
description: "Disable a registered MCP server",
|
|
38106
|
+
paramsSchema: { id: exports_external2.string().describe("Server ID to disable") },
|
|
38107
|
+
run: ({ id }) => {
|
|
38108
|
+
const existing = getServer(String(id));
|
|
38109
|
+
if (!existing)
|
|
38110
|
+
return errorContent(`Server "${String(id)}" not found.`);
|
|
38111
|
+
return jsonContent(disableServer(String(id)));
|
|
38112
|
+
}
|
|
38113
|
+
},
|
|
38114
|
+
{
|
|
38115
|
+
name: "update_server",
|
|
38116
|
+
description: "Update fields of a registered MCP server",
|
|
38117
|
+
paramsSchema: {
|
|
38118
|
+
id: exports_external2.string().describe("Server ID to update"),
|
|
38119
|
+
name: exports_external2.string().optional().describe("New display name"),
|
|
38120
|
+
description: exports_external2.string().optional().describe("New description"),
|
|
38121
|
+
command: exports_external2.string().optional().describe("New command"),
|
|
38122
|
+
args: exports_external2.array(exports_external2.string()).optional().describe("New args list"),
|
|
38123
|
+
transport: exports_external2.enum(["stdio", "sse", "streamable-http"]).optional().describe("New transport type"),
|
|
38124
|
+
url: exports_external2.string().optional().describe("New URL for remote transports")
|
|
38125
|
+
},
|
|
38126
|
+
run: ({ id, name, description, command, args, transport, url: url2 }) => {
|
|
38127
|
+
const serverId = String(id);
|
|
38128
|
+
const existing = getServer(serverId);
|
|
38129
|
+
if (!existing)
|
|
38130
|
+
return errorContent(`Server "${serverId}" not found.`);
|
|
38131
|
+
const fields = {};
|
|
38132
|
+
if (typeof name === "string")
|
|
38133
|
+
fields.name = name;
|
|
38134
|
+
if (typeof description === "string")
|
|
38135
|
+
fields.description = description;
|
|
38136
|
+
if (typeof command === "string")
|
|
38137
|
+
fields.command = command;
|
|
38138
|
+
if (Array.isArray(args))
|
|
38139
|
+
fields.args = args.map(String);
|
|
38140
|
+
if (transport === "stdio" || transport === "sse" || transport === "streamable-http")
|
|
38141
|
+
fields.transport = transport;
|
|
38142
|
+
if (typeof url2 === "string")
|
|
38143
|
+
fields.url = url2;
|
|
38144
|
+
return jsonContent(redactServerEnv(updateServer(serverId, fields)));
|
|
38145
|
+
}
|
|
38146
|
+
},
|
|
38147
|
+
{
|
|
38148
|
+
name: "list_tools",
|
|
38149
|
+
description: "List all cached tools across registered servers without connecting. Optionally filter by server_id.",
|
|
38150
|
+
paramsSchema: { server_id: exports_external2.string().optional().describe("Server ID to filter by (optional)") },
|
|
38151
|
+
run: ({ server_id }) => {
|
|
38152
|
+
if (typeof server_id === "string" && server_id) {
|
|
38153
|
+
const toolsForServer = getCachedTools(server_id);
|
|
38154
|
+
return jsonContent(toolsForServer.map((tool) => ({ ...tool, server_id })));
|
|
38155
|
+
}
|
|
38156
|
+
const allTools = [];
|
|
38157
|
+
for (const server of listServers()) {
|
|
38158
|
+
for (const tool of getCachedTools(server.id)) {
|
|
38159
|
+
allTools.push({ server_id: server.id, ...tool });
|
|
38160
|
+
}
|
|
38161
|
+
}
|
|
38162
|
+
return jsonContent(allTools);
|
|
38163
|
+
}
|
|
38164
|
+
},
|
|
38165
|
+
{
|
|
38166
|
+
name: "get_server_info",
|
|
38167
|
+
description: "Get detailed information about a registered MCP server",
|
|
38168
|
+
paramsSchema: { id: exports_external2.string().describe("Server ID") },
|
|
38169
|
+
run: ({ id }) => {
|
|
38170
|
+
const entry = getServer(String(id));
|
|
38171
|
+
if (!entry)
|
|
38172
|
+
return errorContent(`Server "${String(id)}" not found.`);
|
|
38173
|
+
return jsonContent(redactServerEnv(entry));
|
|
38174
|
+
}
|
|
38175
|
+
},
|
|
38176
|
+
{
|
|
38177
|
+
name: "find_mcp_servers",
|
|
38178
|
+
description: "Search for MCP servers across configured sources (official registry, npm, GitHub topics, awesome lists). Use list_sources to see available source IDs.",
|
|
38179
|
+
paramsSchema: {
|
|
38180
|
+
query: exports_external2.string().describe("Search query (e.g., 'filesystem', 'postgres', 'browser')"),
|
|
38181
|
+
sources: exports_external2.array(exports_external2.string()).optional().describe("Source IDs to search (default: all enabled). Use list_sources to get IDs."),
|
|
38182
|
+
limit: exports_external2.number().optional().describe("Max results per source (default: 20)")
|
|
38183
|
+
},
|
|
38184
|
+
run: async ({ query, sources, limit }) => jsonContent(await findServers(String(query), {
|
|
38185
|
+
sources: Array.isArray(sources) ? sources.map(String) : undefined,
|
|
38186
|
+
limit: typeof limit === "number" ? limit : undefined
|
|
38187
|
+
}))
|
|
38188
|
+
},
|
|
38189
|
+
{
|
|
38190
|
+
name: "list_sources",
|
|
38191
|
+
description: "List all configured search sources for finding MCP servers",
|
|
38192
|
+
paramsSchema: {},
|
|
38193
|
+
run: () => jsonContent(listSources())
|
|
38194
|
+
},
|
|
38195
|
+
{
|
|
38196
|
+
name: "add_source",
|
|
38197
|
+
description: "Add a new search source for finding MCP servers",
|
|
38198
|
+
paramsSchema: {
|
|
38199
|
+
name: exports_external2.string().describe("Source name"),
|
|
38200
|
+
type: exports_external2.enum(["mcp-registry", "awesome-list", "npm-search", "github-topic"]).describe("Source type"),
|
|
38201
|
+
url: exports_external2.string().describe("Source URL endpoint"),
|
|
38202
|
+
description: exports_external2.string().optional().describe("Description")
|
|
38203
|
+
},
|
|
38204
|
+
run: ({ name, type, url: url2, description }) => jsonContent(addSource({
|
|
38205
|
+
name: String(name),
|
|
38206
|
+
type,
|
|
38207
|
+
url: String(url2),
|
|
38208
|
+
description: typeof description === "string" ? description : undefined
|
|
38209
|
+
}))
|
|
38210
|
+
},
|
|
38211
|
+
{
|
|
38212
|
+
name: "remove_source",
|
|
38213
|
+
description: "Remove a search source by ID",
|
|
38214
|
+
paramsSchema: { id: exports_external2.string().describe("Source ID to remove") },
|
|
38215
|
+
run: ({ id }) => {
|
|
38216
|
+
const sourceId = String(id);
|
|
38217
|
+
const existing = getSource(sourceId);
|
|
38218
|
+
if (!existing)
|
|
38219
|
+
return errorContent(`Source "${sourceId}" not found.`);
|
|
38220
|
+
removeSource(sourceId);
|
|
38221
|
+
return textContent(`Removed source: ${existing.name} [${sourceId}]`);
|
|
38222
|
+
}
|
|
38223
|
+
},
|
|
38224
|
+
{
|
|
38225
|
+
name: "enable_source_finder",
|
|
38226
|
+
description: "Enable a search source",
|
|
38227
|
+
paramsSchema: { id: exports_external2.string().describe("Source ID to enable") },
|
|
38228
|
+
run: ({ id }) => {
|
|
38229
|
+
const sourceId = String(id);
|
|
38230
|
+
const existing = getSource(sourceId);
|
|
38231
|
+
if (!existing)
|
|
38232
|
+
return errorContent(`Source "${sourceId}" not found.`);
|
|
38233
|
+
enableSource(sourceId);
|
|
38234
|
+
return textContent(`Enabled source: ${existing.name}`);
|
|
38235
|
+
}
|
|
38236
|
+
},
|
|
38237
|
+
{
|
|
38238
|
+
name: "disable_source_finder",
|
|
38239
|
+
description: "Disable a search source",
|
|
38240
|
+
paramsSchema: { id: exports_external2.string().describe("Source ID to disable") },
|
|
38241
|
+
run: ({ id }) => {
|
|
38242
|
+
const sourceId = String(id);
|
|
38243
|
+
const existing = getSource(sourceId);
|
|
38244
|
+
if (!existing)
|
|
38245
|
+
return errorContent(`Source "${sourceId}" not found.`);
|
|
38246
|
+
disableSource(sourceId);
|
|
38247
|
+
return textContent(`Disabled source: ${existing.name}`);
|
|
38248
|
+
}
|
|
38249
|
+
},
|
|
38250
|
+
{
|
|
38251
|
+
name: "install_to_agents",
|
|
38252
|
+
description: "Install a registered MCP server into Claude Code, Codex, and/or Gemini",
|
|
38253
|
+
paramsSchema: {
|
|
38254
|
+
id: exports_external2.string().describe("Server ID to install (from list_servers)"),
|
|
38255
|
+
targets: exports_external2.array(exports_external2.enum(["claude", "codex", "gemini"])).optional().describe("Target agents to install into (default: all)")
|
|
38256
|
+
},
|
|
38257
|
+
run: ({ id, targets }) => {
|
|
38258
|
+
const serverId = String(id);
|
|
38259
|
+
const entry = getServer(serverId);
|
|
38260
|
+
if (!entry)
|
|
38261
|
+
return errorContent(`Server "${serverId}" not found.`);
|
|
38262
|
+
const agentTargets = Array.isArray(targets) ? targets : undefined;
|
|
38263
|
+
return jsonContent(installToAgents(entry, agentTargets ?? ["claude", "codex", "gemini"]));
|
|
38264
|
+
}
|
|
38265
|
+
},
|
|
38266
|
+
{
|
|
38267
|
+
name: "list_awesome_servers",
|
|
38268
|
+
description: "List all MCP servers from the curated punkpeye/awesome-mcp-servers GitHub list",
|
|
38269
|
+
paramsSchema: {},
|
|
38270
|
+
run: async () => jsonContent(await listAwesomeServers())
|
|
38271
|
+
},
|
|
38272
|
+
{
|
|
38273
|
+
name: "connect_and_list_tools",
|
|
38274
|
+
description: "Connect to all enabled MCP servers and list their available tools",
|
|
38275
|
+
paramsSchema: {},
|
|
38276
|
+
run: async () => {
|
|
38277
|
+
let liveTools = [];
|
|
38278
|
+
try {
|
|
38279
|
+
await connectAllEnabled();
|
|
38280
|
+
liveTools = listAllTools();
|
|
38281
|
+
} finally {
|
|
38282
|
+
await disconnectAll().catch(() => {
|
|
38283
|
+
return;
|
|
38284
|
+
});
|
|
38285
|
+
}
|
|
38286
|
+
return jsonContent(liveTools);
|
|
38287
|
+
}
|
|
38288
|
+
},
|
|
38289
|
+
{
|
|
38290
|
+
name: "call_upstream_tool",
|
|
38291
|
+
description: `Call a tool on a connected upstream MCP server. Tool name format: server_id${TOOL_PREFIX_SEPARATOR}tool_name`,
|
|
38292
|
+
paramsSchema: {
|
|
38293
|
+
tool_name: exports_external2.string().describe(`Prefixed tool name (server_id${TOOL_PREFIX_SEPARATOR}tool_name)`),
|
|
38294
|
+
arguments: exports_external2.record(exports_external2.unknown()).optional().describe("Tool arguments as key-value pairs")
|
|
38295
|
+
},
|
|
38296
|
+
run: async ({ tool_name, arguments: args }) => {
|
|
38297
|
+
try {
|
|
38298
|
+
const toolName = String(tool_name);
|
|
38299
|
+
const sepIdx = toolName.indexOf(TOOL_PREFIX_SEPARATOR);
|
|
38300
|
+
if (sepIdx === -1)
|
|
38301
|
+
return errorContent(`Error: Invalid tool name "${toolName}"`);
|
|
38302
|
+
const serverId = toolName.slice(0, sepIdx);
|
|
38303
|
+
const entry = getServer(serverId);
|
|
38304
|
+
if (!entry)
|
|
38305
|
+
return errorContent(`Error: Server "${serverId}" not found.`);
|
|
38306
|
+
if (!entry.enabled)
|
|
38307
|
+
return errorContent(`Error: Server "${serverId}" is disabled.`);
|
|
38308
|
+
await connectToServer(entry);
|
|
38309
|
+
const result = await callTool(toolName, readRecord(args));
|
|
38310
|
+
return { content: result.content };
|
|
38311
|
+
} catch (error2) {
|
|
38312
|
+
return errorContent(`Error: ${error2.message}`);
|
|
38313
|
+
}
|
|
38314
|
+
}
|
|
38315
|
+
},
|
|
38316
|
+
{
|
|
38317
|
+
name: "diagnose_server",
|
|
38318
|
+
description: "Run health checks on a registered MCP server",
|
|
38319
|
+
paramsSchema: { id: exports_external2.string().describe("Server ID") },
|
|
38320
|
+
run: async ({ id }) => {
|
|
38321
|
+
const serverId = String(id);
|
|
38322
|
+
const entry = getServer(serverId);
|
|
38323
|
+
if (!entry)
|
|
38324
|
+
return errorContent(`Server "${serverId}" not found.`);
|
|
38325
|
+
return jsonContent(await diagnoseServer(entry));
|
|
38326
|
+
}
|
|
38327
|
+
},
|
|
38328
|
+
{
|
|
38329
|
+
name: "list_machines",
|
|
38330
|
+
description: "List registered fleet machines",
|
|
38331
|
+
paramsSchema: {
|
|
38332
|
+
enabled_only: exports_external2.boolean().optional().describe("When true, only return enabled machines")
|
|
38333
|
+
},
|
|
38334
|
+
run: ({ enabled_only }) => jsonContent(listMachines().filter((machine) => enabled_only === true ? machine.enabled : true))
|
|
38335
|
+
},
|
|
38336
|
+
{
|
|
38337
|
+
name: "add_machine",
|
|
38338
|
+
description: "Register a machine for fleet health checks and installs",
|
|
38339
|
+
paramsSchema: {
|
|
38340
|
+
host: exports_external2.string().describe("Hostname or SSH target"),
|
|
38341
|
+
id: exports_external2.string().optional().describe("Stable machine ID"),
|
|
38342
|
+
name: exports_external2.string().optional().describe("Display name"),
|
|
38343
|
+
username: exports_external2.string().optional().describe("SSH username"),
|
|
38344
|
+
port: exports_external2.number().int().min(1).max(65535).optional().describe("SSH port"),
|
|
38345
|
+
platform: exports_external2.enum(["linux", "darwin", "unknown"]).optional().describe("Machine platform"),
|
|
38346
|
+
arch: exports_external2.enum(["arm64", "x64", "unknown"]).optional().describe("Machine architecture"),
|
|
38347
|
+
bun_path: exports_external2.string().optional().describe("Explicit path to bun on the remote machine"),
|
|
38348
|
+
npm_path: exports_external2.string().optional().describe("Explicit path to npm on the remote machine"),
|
|
38349
|
+
installer: exports_external2.enum(["auto", "bun", "npm"]).optional().describe("Preferred installer"),
|
|
38350
|
+
ssh_key_path: exports_external2.string().optional().describe("SSH private key path"),
|
|
38351
|
+
enabled: exports_external2.boolean().optional().describe("Whether the machine should be enabled")
|
|
38352
|
+
},
|
|
38353
|
+
run: ({ host, id, name, username, port, platform: platform2, arch, bun_path, npm_path, installer, ssh_key_path, enabled }) => jsonContent(addMachine({
|
|
38354
|
+
host: String(host),
|
|
38355
|
+
id: typeof id === "string" ? id : undefined,
|
|
38356
|
+
name: typeof name === "string" ? name : undefined,
|
|
38357
|
+
username: typeof username === "string" ? username : undefined,
|
|
38358
|
+
port: typeof port === "number" ? port : undefined,
|
|
38359
|
+
platform: platform2,
|
|
38360
|
+
arch,
|
|
38361
|
+
bun_path: typeof bun_path === "string" ? bun_path : undefined,
|
|
38362
|
+
npm_path: typeof npm_path === "string" ? npm_path : undefined,
|
|
38363
|
+
installer,
|
|
38364
|
+
ssh_key_path: typeof ssh_key_path === "string" ? ssh_key_path : undefined,
|
|
38365
|
+
enabled: typeof enabled === "boolean" ? enabled : undefined
|
|
38366
|
+
}))
|
|
38367
|
+
},
|
|
38368
|
+
{
|
|
38369
|
+
name: "remove_machine",
|
|
38370
|
+
description: "Remove a registered machine",
|
|
38371
|
+
paramsSchema: { id: exports_external2.string().describe("Machine ID to remove") },
|
|
38372
|
+
run: ({ id }) => {
|
|
38373
|
+
const machineId = String(id);
|
|
38374
|
+
const machine = getMachine(machineId);
|
|
38375
|
+
if (!machine)
|
|
38376
|
+
return errorContent(`Machine "${machineId}" not found.`);
|
|
38377
|
+
removeMachine(machineId);
|
|
38378
|
+
return jsonContent({ removed: true, machine });
|
|
38379
|
+
}
|
|
38380
|
+
},
|
|
38381
|
+
{
|
|
38382
|
+
name: "seed_default_machines",
|
|
38383
|
+
description: "Seed the standard spark/apple machine inventory",
|
|
38384
|
+
paramsSchema: {},
|
|
38385
|
+
run: () => jsonContent(seedDefaultMachines())
|
|
38386
|
+
},
|
|
38387
|
+
{
|
|
38388
|
+
name: "list_hasna_mcp_catalog",
|
|
38389
|
+
description: "List the discovered @hasna MCP package catalog",
|
|
38390
|
+
paramsSchema: {
|
|
38391
|
+
packages: exports_external2.array(exports_external2.string()).optional().describe("Optional package-name filter"),
|
|
38392
|
+
refresh: exports_external2.boolean().optional().describe("Refresh npm metadata instead of using cache")
|
|
38393
|
+
},
|
|
38394
|
+
run: async ({ packages, refresh }) => {
|
|
38395
|
+
const catalog = await listHasnaMcpCatalog({ refresh: refresh === true });
|
|
38396
|
+
const filtered = Array.isArray(packages) && packages.length > 0 ? catalog.filter((entry) => packages.map(String).includes(entry.name)) : catalog;
|
|
38397
|
+
return jsonContent(filtered);
|
|
38398
|
+
}
|
|
38399
|
+
},
|
|
38400
|
+
{
|
|
38401
|
+
name: "fleet_health",
|
|
38402
|
+
description: "Run fleet-wide MCP health checks across registered machines",
|
|
38403
|
+
paramsSchema: {
|
|
38404
|
+
machine_ids: exports_external2.array(exports_external2.string()).optional().describe("Optional machine IDs to check"),
|
|
38405
|
+
packages: exports_external2.array(exports_external2.string()).optional().describe("Optional @hasna package-name filter"),
|
|
38406
|
+
refresh_catalog: exports_external2.boolean().optional().describe("Refresh npm metadata before checking"),
|
|
38407
|
+
timeout_ms: exports_external2.number().int().min(1000).optional().describe("Remote timeout in milliseconds")
|
|
38408
|
+
},
|
|
38409
|
+
run: async ({ machine_ids, packages, refresh_catalog, timeout_ms }) => jsonContent(await runFleetHealthCheck({
|
|
38410
|
+
machineIds: Array.isArray(machine_ids) ? machine_ids.map(String) : undefined,
|
|
38411
|
+
packages: Array.isArray(packages) ? packages.map(String) : undefined,
|
|
38412
|
+
refreshCatalog: refresh_catalog === true,
|
|
38413
|
+
timeoutMs: typeof timeout_ms === "number" ? timeout_ms : undefined
|
|
38414
|
+
}))
|
|
38415
|
+
},
|
|
38416
|
+
{
|
|
38417
|
+
name: "fleet_install",
|
|
38418
|
+
description: "Batch-install missing or outdated @hasna MCP packages across machines",
|
|
38419
|
+
paramsSchema: {
|
|
38420
|
+
machine_ids: exports_external2.array(exports_external2.string()).optional().describe("Optional machine IDs to target"),
|
|
38421
|
+
packages: exports_external2.array(exports_external2.string()).optional().describe("Optional @hasna package-name filter"),
|
|
38422
|
+
mode: exports_external2.enum(["missing", "missing-or-outdated", "all"]).optional().describe("Install selection mode"),
|
|
38423
|
+
installer: exports_external2.enum(["auto", "bun", "npm"]).optional().describe("Override installer"),
|
|
38424
|
+
refresh_catalog: exports_external2.boolean().optional().describe("Refresh npm metadata before installing"),
|
|
38425
|
+
timeout_ms: exports_external2.number().int().min(1000).optional().describe("Remote timeout in milliseconds")
|
|
38426
|
+
},
|
|
38427
|
+
run: async ({ machine_ids, packages, mode, installer, refresh_catalog, timeout_ms }) => jsonContent(await runFleetInstall({
|
|
38428
|
+
machineIds: Array.isArray(machine_ids) ? machine_ids.map(String) : undefined,
|
|
38429
|
+
packages: Array.isArray(packages) ? packages.map(String) : undefined,
|
|
38430
|
+
mode: mode === "missing" || mode === "missing-or-outdated" || mode === "all" ? mode : undefined,
|
|
38431
|
+
installer: installer === "auto" || installer === "bun" || installer === "npm" ? installer : undefined,
|
|
38432
|
+
refreshCatalog: refresh_catalog === true,
|
|
38433
|
+
timeoutMs: typeof timeout_ms === "number" ? timeout_ms : undefined
|
|
38434
|
+
}))
|
|
38435
|
+
},
|
|
38436
|
+
{
|
|
38437
|
+
name: "send_feedback",
|
|
38438
|
+
description: "Send feedback about this service",
|
|
38439
|
+
paramsSchema: {
|
|
38440
|
+
message: exports_external2.string().describe("Feedback message"),
|
|
38441
|
+
email: exports_external2.string().optional().describe("Contact email (optional)"),
|
|
38442
|
+
category: exports_external2.enum(["bug", "feature", "general"]).optional().describe("Feedback category")
|
|
38443
|
+
},
|
|
38444
|
+
run: ({ message, email: email2, category }) => {
|
|
38445
|
+
const adapter = getAdapter();
|
|
38446
|
+
adapter.run("INSERT INTO feedback (message, email, category, version) VALUES (?, ?, ?, ?)", String(message), typeof email2 === "string" ? email2 : null, typeof category === "string" ? category : "general", VERSION);
|
|
38447
|
+
return textContent("Feedback saved. Thank you!");
|
|
38448
|
+
}
|
|
38449
|
+
},
|
|
38450
|
+
{
|
|
38451
|
+
name: "register_agent",
|
|
38452
|
+
description: "Register an agent session. Returns agent_id. Auto-triggers a heartbeat.",
|
|
38453
|
+
paramsSchema: {
|
|
38454
|
+
name: exports_external2.string(),
|
|
38455
|
+
session_id: exports_external2.string().optional()
|
|
38456
|
+
},
|
|
38457
|
+
run: ({ name, session_id }) => {
|
|
38458
|
+
const agentName = String(name);
|
|
38459
|
+
const existing = [...mcpsAgents.values()].find((agent2) => agent2.name === agentName);
|
|
38460
|
+
if (existing) {
|
|
38461
|
+
existing.last_seen_at = new Date().toISOString();
|
|
38462
|
+
if (typeof session_id === "string")
|
|
38463
|
+
existing.session_id = session_id;
|
|
38464
|
+
return jsonContent(existing);
|
|
38465
|
+
}
|
|
38466
|
+
const id = Math.random().toString(36).slice(2, 10);
|
|
38467
|
+
const agent = {
|
|
38468
|
+
id,
|
|
38469
|
+
name: agentName,
|
|
38470
|
+
session_id: typeof session_id === "string" ? session_id : undefined,
|
|
38471
|
+
last_seen_at: new Date().toISOString()
|
|
38472
|
+
};
|
|
38473
|
+
mcpsAgents.set(id, agent);
|
|
38474
|
+
return jsonContent(agent);
|
|
38475
|
+
}
|
|
38476
|
+
},
|
|
38477
|
+
{
|
|
38478
|
+
name: "heartbeat",
|
|
38479
|
+
description: "Update last_seen_at to signal agent is active.",
|
|
38480
|
+
paramsSchema: { agent_id: exports_external2.string() },
|
|
38481
|
+
run: ({ agent_id }) => {
|
|
38482
|
+
const agentId = String(agent_id);
|
|
38483
|
+
const agent = mcpsAgents.get(agentId);
|
|
38484
|
+
if (!agent)
|
|
38485
|
+
return errorContent(`Agent not found: ${agentId}`);
|
|
38486
|
+
agent.last_seen_at = new Date().toISOString();
|
|
38487
|
+
return jsonContent({ agent_id: agent.id, last_seen_at: agent.last_seen_at });
|
|
38488
|
+
}
|
|
38489
|
+
},
|
|
38490
|
+
{
|
|
38491
|
+
name: "set_focus",
|
|
38492
|
+
description: "Set active project context for this agent session.",
|
|
38493
|
+
paramsSchema: {
|
|
38494
|
+
agent_id: exports_external2.string(),
|
|
38495
|
+
project_id: exports_external2.string().optional()
|
|
38496
|
+
},
|
|
38497
|
+
run: ({ agent_id, project_id }) => {
|
|
38498
|
+
const agentId = String(agent_id);
|
|
38499
|
+
const agent = mcpsAgents.get(agentId);
|
|
38500
|
+
if (!agent)
|
|
38501
|
+
return errorContent(`Agent not found: ${agentId}`);
|
|
38502
|
+
agent.project_id = typeof project_id === "string" ? project_id : undefined;
|
|
38503
|
+
return jsonContent({ agent_id: agent.id, project_id: agent.project_id ?? null });
|
|
38504
|
+
}
|
|
38505
|
+
},
|
|
38506
|
+
{
|
|
38507
|
+
name: "list_agents",
|
|
38508
|
+
description: "List all registered agents.",
|
|
38509
|
+
paramsSchema: {},
|
|
38510
|
+
run: () => jsonContent([...mcpsAgents.values()])
|
|
38511
|
+
}
|
|
38512
|
+
];
|
|
38513
|
+
return definitions.map((definition) => ({
|
|
38514
|
+
...definition,
|
|
38515
|
+
inputSchema: zodRawShapeToJsonSchema(definition.paramsSchema)
|
|
38516
|
+
}));
|
|
38517
|
+
}
|
|
38518
|
+
var tools = buildMcpTools();
|
|
38519
|
+
function registerMcpTools(server, toolDefinitions = buildMcpTools()) {
|
|
38520
|
+
for (const tool of toolDefinitions) {
|
|
38521
|
+
server.tool(tool.name, tool.description, tool.paramsSchema ?? {}, async (input) => tool.run(readRecord(input)));
|
|
38072
38522
|
}
|
|
38073
|
-
|
|
38074
|
-
|
|
38075
|
-
|
|
38076
|
-
};
|
|
38077
|
-
|
|
38078
|
-
|
|
38079
|
-
|
|
38080
|
-
|
|
38081
|
-
|
|
38082
|
-
content: [{ type: "text", text: `Server "${id}" not found.` }],
|
|
38083
|
-
isError: true
|
|
38084
|
-
};
|
|
38523
|
+
return toolDefinitions;
|
|
38524
|
+
}
|
|
38525
|
+
function zodRawShapeToJsonSchema(shape) {
|
|
38526
|
+
const properties = {};
|
|
38527
|
+
const required2 = [];
|
|
38528
|
+
for (const [key, schema] of Object.entries(shape)) {
|
|
38529
|
+
properties[key] = zodSchemaToJsonSchema(schema);
|
|
38530
|
+
if (!isOptionalSchema(schema))
|
|
38531
|
+
required2.push(key);
|
|
38085
38532
|
}
|
|
38086
|
-
const entry = disableServer(id);
|
|
38087
38533
|
return {
|
|
38088
|
-
|
|
38534
|
+
type: "object",
|
|
38535
|
+
properties,
|
|
38536
|
+
...required2.length > 0 ? { required: required2 } : {},
|
|
38537
|
+
additionalProperties: false
|
|
38089
38538
|
};
|
|
38090
|
-
}
|
|
38091
|
-
|
|
38092
|
-
|
|
38093
|
-
|
|
38094
|
-
description:
|
|
38095
|
-
|
|
38096
|
-
|
|
38097
|
-
transport: exports_external2.enum(["stdio", "sse", "streamable-http"]).optional().describe("New transport type"),
|
|
38098
|
-
url: exports_external2.string().optional().describe("New URL for remote transports")
|
|
38099
|
-
}, async ({ id, name, description, command, args, transport, url: url2 }) => {
|
|
38100
|
-
const existing = getServer(id);
|
|
38101
|
-
if (!existing) {
|
|
38102
|
-
return {
|
|
38103
|
-
content: [{ type: "text", text: `Server "${id}" not found.` }],
|
|
38104
|
-
isError: true
|
|
38105
|
-
};
|
|
38539
|
+
}
|
|
38540
|
+
function zodSchemaToJsonSchema(schema) {
|
|
38541
|
+
const def = schema._def;
|
|
38542
|
+
const typeName = String(def?.typeName ?? "");
|
|
38543
|
+
const description = schema.description ? { description: schema.description } : {};
|
|
38544
|
+
if (typeName === exports_external2.ZodFirstPartyTypeKind.ZodOptional || typeName === exports_external2.ZodFirstPartyTypeKind.ZodDefault) {
|
|
38545
|
+
return { ...asJsonSchemaObject(zodSchemaToJsonSchema(def.innerType)), ...description };
|
|
38106
38546
|
}
|
|
38107
|
-
|
|
38108
|
-
|
|
38109
|
-
fields.name = name;
|
|
38110
|
-
if (description !== undefined)
|
|
38111
|
-
fields.description = description;
|
|
38112
|
-
if (command !== undefined)
|
|
38113
|
-
fields.command = command;
|
|
38114
|
-
if (args !== undefined)
|
|
38115
|
-
fields.args = args;
|
|
38116
|
-
if (transport !== undefined)
|
|
38117
|
-
fields.transport = transport;
|
|
38118
|
-
if (url2 !== undefined)
|
|
38119
|
-
fields.url = url2;
|
|
38120
|
-
const updated = updateServer(id, fields);
|
|
38121
|
-
return {
|
|
38122
|
-
content: [{ type: "text", text: JSON.stringify(redactServerEnv(updated), null, 2) }]
|
|
38123
|
-
};
|
|
38124
|
-
});
|
|
38125
|
-
server.tool("list_tools", "List all cached tools across registered servers without connecting. Optionally filter by server_id.", { server_id: exports_external2.string().optional().describe("Server ID to filter by (optional)") }, async ({ server_id }) => {
|
|
38126
|
-
if (server_id) {
|
|
38127
|
-
const tools = getCachedTools(server_id);
|
|
38128
|
-
return {
|
|
38129
|
-
content: [{ type: "text", text: JSON.stringify(tools.map((t) => ({ ...t, server_id })), null, 2) }]
|
|
38130
|
-
};
|
|
38547
|
+
if (typeName === exports_external2.ZodFirstPartyTypeKind.ZodNullable) {
|
|
38548
|
+
return { ...asJsonSchemaObject(zodSchemaToJsonSchema(def.innerType)), nullable: true, ...description };
|
|
38131
38549
|
}
|
|
38132
|
-
|
|
38133
|
-
|
|
38134
|
-
for (const s of servers) {
|
|
38135
|
-
const tools = getCachedTools(s.id);
|
|
38136
|
-
for (const t of tools) {
|
|
38137
|
-
allTools.push({ server_id: s.id, ...t });
|
|
38138
|
-
}
|
|
38550
|
+
if (typeName === exports_external2.ZodFirstPartyTypeKind.ZodString) {
|
|
38551
|
+
return { type: "string", ...description };
|
|
38139
38552
|
}
|
|
38140
|
-
|
|
38141
|
-
|
|
38142
|
-
};
|
|
38143
|
-
});
|
|
38144
|
-
server.tool("get_server_info", "Get detailed information about a registered MCP server", { id: exports_external2.string().describe("Server ID") }, async ({ id }) => {
|
|
38145
|
-
const entry = getServer(id);
|
|
38146
|
-
if (!entry) {
|
|
38147
|
-
return {
|
|
38148
|
-
content: [{ type: "text", text: `Server "${id}" not found.` }],
|
|
38149
|
-
isError: true
|
|
38150
|
-
};
|
|
38553
|
+
if (typeName === exports_external2.ZodFirstPartyTypeKind.ZodBoolean) {
|
|
38554
|
+
return { type: "boolean", ...description };
|
|
38151
38555
|
}
|
|
38152
|
-
|
|
38153
|
-
|
|
38154
|
-
};
|
|
38155
|
-
});
|
|
38156
|
-
server.tool("find_mcp_servers", "Search for MCP servers across configured sources (official registry, npm, GitHub topics, awesome lists). Use list_sources to see available source IDs.", {
|
|
38157
|
-
query: exports_external2.string().describe("Search query (e.g. 'filesystem', 'postgres', 'browser')"),
|
|
38158
|
-
sources: exports_external2.array(exports_external2.string()).optional().describe("Source IDs to search (default: all enabled). Use list_sources to get IDs."),
|
|
38159
|
-
limit: exports_external2.number().optional().describe("Max results per source (default: 20)")
|
|
38160
|
-
}, async ({ query, sources, limit }) => {
|
|
38161
|
-
const results = await findServers(query, { sources, limit });
|
|
38162
|
-
return {
|
|
38163
|
-
content: [{ type: "text", text: JSON.stringify(results, null, 2) }]
|
|
38164
|
-
};
|
|
38165
|
-
});
|
|
38166
|
-
server.tool("list_sources", "List all configured search sources for finding MCP servers", {}, async () => {
|
|
38167
|
-
const sources = listSources();
|
|
38168
|
-
return {
|
|
38169
|
-
content: [{ type: "text", text: JSON.stringify(sources, null, 2) }]
|
|
38170
|
-
};
|
|
38171
|
-
});
|
|
38172
|
-
server.tool("add_source", "Add a new search source for finding MCP servers", {
|
|
38173
|
-
name: exports_external2.string().describe("Source name"),
|
|
38174
|
-
type: exports_external2.enum(["mcp-registry", "awesome-list", "npm-search", "github-topic"]).describe("Source type"),
|
|
38175
|
-
url: exports_external2.string().describe("Source URL endpoint"),
|
|
38176
|
-
description: exports_external2.string().optional().describe("Description")
|
|
38177
|
-
}, async ({ name, type, url: url2, description }) => {
|
|
38178
|
-
const source = addSource({ name, type, url: url2, description });
|
|
38179
|
-
return {
|
|
38180
|
-
content: [{ type: "text", text: JSON.stringify(source, null, 2) }]
|
|
38181
|
-
};
|
|
38182
|
-
});
|
|
38183
|
-
server.tool("remove_source", "Remove a search source by ID", { id: exports_external2.string().describe("Source ID to remove") }, async ({ id }) => {
|
|
38184
|
-
const existing = getSource(id);
|
|
38185
|
-
if (!existing) {
|
|
38186
|
-
return {
|
|
38187
|
-
content: [{ type: "text", text: `Source "${id}" not found.` }],
|
|
38188
|
-
isError: true
|
|
38189
|
-
};
|
|
38556
|
+
if (typeName === exports_external2.ZodFirstPartyTypeKind.ZodUnknown || typeName === exports_external2.ZodFirstPartyTypeKind.ZodAny) {
|
|
38557
|
+
return Object.keys(description).length > 0 ? description : true;
|
|
38190
38558
|
}
|
|
38191
|
-
|
|
38192
|
-
|
|
38193
|
-
|
|
38194
|
-
|
|
38195
|
-
|
|
38196
|
-
server.tool("enable_source_finder", "Enable a search source", { id: exports_external2.string().describe("Source ID to enable") }, async ({ id }) => {
|
|
38197
|
-
const existing = getSource(id);
|
|
38198
|
-
if (!existing) {
|
|
38199
|
-
return {
|
|
38200
|
-
content: [{ type: "text", text: `Source "${id}" not found.` }],
|
|
38201
|
-
isError: true
|
|
38559
|
+
if (typeName === exports_external2.ZodFirstPartyTypeKind.ZodNumber) {
|
|
38560
|
+
const checks4 = Array.isArray(def.checks) ? def.checks : [];
|
|
38561
|
+
const schemaJson = {
|
|
38562
|
+
type: checks4.some((check2) => check2.kind === "int") ? "integer" : "number",
|
|
38563
|
+
...description
|
|
38202
38564
|
};
|
|
38565
|
+
for (const check2 of checks4) {
|
|
38566
|
+
if (check2.kind === "min")
|
|
38567
|
+
schemaJson.minimum = check2.value;
|
|
38568
|
+
if (check2.kind === "max")
|
|
38569
|
+
schemaJson.maximum = check2.value;
|
|
38570
|
+
}
|
|
38571
|
+
return schemaJson;
|
|
38203
38572
|
}
|
|
38204
|
-
|
|
38205
|
-
|
|
38206
|
-
content: [{ type: "text", text: `Enabled source: ${existing.name}` }]
|
|
38207
|
-
};
|
|
38208
|
-
});
|
|
38209
|
-
server.tool("disable_source_finder", "Disable a search source", { id: exports_external2.string().describe("Source ID to disable") }, async ({ id }) => {
|
|
38210
|
-
const existing = getSource(id);
|
|
38211
|
-
if (!existing) {
|
|
38212
|
-
return {
|
|
38213
|
-
content: [{ type: "text", text: `Source "${id}" not found.` }],
|
|
38214
|
-
isError: true
|
|
38215
|
-
};
|
|
38573
|
+
if (typeName === exports_external2.ZodFirstPartyTypeKind.ZodEnum) {
|
|
38574
|
+
return { type: "string", enum: def.values, ...description };
|
|
38216
38575
|
}
|
|
38217
|
-
|
|
38218
|
-
|
|
38219
|
-
content: [{ type: "text", text: `Disabled source: ${existing.name}` }]
|
|
38220
|
-
};
|
|
38221
|
-
});
|
|
38222
|
-
server.tool("install_to_agents", "Install a registered MCP server into Claude Code, Codex, and/or Gemini", {
|
|
38223
|
-
id: exports_external2.string().describe("Server ID to install (from list_servers)"),
|
|
38224
|
-
targets: exports_external2.array(exports_external2.enum(["claude", "codex", "gemini"])).optional().describe("Target agents to install into (default: all)")
|
|
38225
|
-
}, async ({ id, targets }) => {
|
|
38226
|
-
const entry = getServer(id);
|
|
38227
|
-
if (!entry) {
|
|
38228
|
-
return {
|
|
38229
|
-
content: [{ type: "text", text: `Server "${id}" not found.` }],
|
|
38230
|
-
isError: true
|
|
38231
|
-
};
|
|
38576
|
+
if (typeName === exports_external2.ZodFirstPartyTypeKind.ZodArray) {
|
|
38577
|
+
return { type: "array", items: zodSchemaToJsonSchema(def.type), ...description };
|
|
38232
38578
|
}
|
|
38233
|
-
|
|
38234
|
-
|
|
38235
|
-
|
|
38236
|
-
content: [{ type: "text", text: JSON.stringify(results, null, 2) }]
|
|
38237
|
-
};
|
|
38238
|
-
});
|
|
38239
|
-
server.tool("list_awesome_servers", "List all MCP servers from the curated punkpeye/awesome-mcp-servers GitHub list", {}, async () => {
|
|
38240
|
-
const results = await listAwesomeServers();
|
|
38241
|
-
return {
|
|
38242
|
-
content: [{ type: "text", text: JSON.stringify(results, null, 2) }]
|
|
38243
|
-
};
|
|
38244
|
-
});
|
|
38245
|
-
server.tool("connect_and_list_tools", "Connect to all enabled MCP servers and list their available tools", {}, async () => {
|
|
38246
|
-
let tools = [];
|
|
38247
|
-
try {
|
|
38248
|
-
await connectAllEnabled();
|
|
38249
|
-
tools = listAllTools();
|
|
38250
|
-
} finally {
|
|
38251
|
-
await disconnectAll().catch(() => {
|
|
38252
|
-
return;
|
|
38253
|
-
});
|
|
38579
|
+
if (typeName === exports_external2.ZodFirstPartyTypeKind.ZodRecord) {
|
|
38580
|
+
const valueType = def.valueType ? zodSchemaToJsonSchema(def.valueType) : true;
|
|
38581
|
+
return { type: "object", additionalProperties: valueType, ...description };
|
|
38254
38582
|
}
|
|
38255
|
-
|
|
38256
|
-
|
|
38257
|
-
|
|
38258
|
-
});
|
|
38259
|
-
server.tool("call_upstream_tool", `Call a tool on a connected upstream MCP server. Tool name format: server_id${TOOL_PREFIX_SEPARATOR}tool_name`, {
|
|
38260
|
-
tool_name: exports_external2.string().describe(`Prefixed tool name (server_id${TOOL_PREFIX_SEPARATOR}tool_name)`),
|
|
38261
|
-
arguments: exports_external2.record(exports_external2.unknown()).optional().describe("Tool arguments as key-value pairs")
|
|
38262
|
-
}, async ({ tool_name, arguments: args }) => {
|
|
38263
|
-
try {
|
|
38264
|
-
const sepIdx = tool_name.indexOf(TOOL_PREFIX_SEPARATOR);
|
|
38265
|
-
if (sepIdx === -1) {
|
|
38266
|
-
return {
|
|
38267
|
-
content: [{ type: "text", text: `Error: Invalid tool name "${tool_name}"` }],
|
|
38268
|
-
isError: true
|
|
38269
|
-
};
|
|
38270
|
-
}
|
|
38271
|
-
const serverId = tool_name.slice(0, sepIdx);
|
|
38272
|
-
const entry = getServer(serverId);
|
|
38273
|
-
if (!entry) {
|
|
38274
|
-
return {
|
|
38275
|
-
content: [{ type: "text", text: `Error: Server "${serverId}" not found.` }],
|
|
38276
|
-
isError: true
|
|
38277
|
-
};
|
|
38278
|
-
}
|
|
38279
|
-
if (!entry.enabled) {
|
|
38280
|
-
return {
|
|
38281
|
-
content: [{ type: "text", text: `Error: Server "${serverId}" is disabled.` }],
|
|
38282
|
-
isError: true
|
|
38283
|
-
};
|
|
38284
|
-
}
|
|
38285
|
-
await connectToServer(entry);
|
|
38286
|
-
const result = await callTool(tool_name, args || {});
|
|
38287
|
-
return { content: result.content };
|
|
38288
|
-
} catch (err) {
|
|
38289
|
-
return {
|
|
38290
|
-
content: [{ type: "text", text: `Error: ${err.message}` }],
|
|
38291
|
-
isError: true
|
|
38292
|
-
};
|
|
38583
|
+
if (typeName === exports_external2.ZodFirstPartyTypeKind.ZodObject) {
|
|
38584
|
+
const objectShape = typeof def.shape === "function" ? def.shape() : def.shape;
|
|
38585
|
+
return { ...zodRawShapeToJsonSchema(objectShape ?? {}), ...description };
|
|
38293
38586
|
}
|
|
38294
|
-
}
|
|
38295
|
-
|
|
38296
|
-
|
|
38297
|
-
|
|
38298
|
-
|
|
38299
|
-
|
|
38300
|
-
|
|
38301
|
-
|
|
38302
|
-
|
|
38303
|
-
|
|
38304
|
-
|
|
38305
|
-
|
|
38306
|
-
|
|
38307
|
-
|
|
38308
|
-
|
|
38309
|
-
|
|
38310
|
-
|
|
38311
|
-
|
|
38312
|
-
|
|
38313
|
-
|
|
38314
|
-
|
|
38315
|
-
|
|
38316
|
-
|
|
38317
|
-
|
|
38318
|
-
|
|
38319
|
-
npm_path: exports_external2.string().optional().describe("Explicit path to npm on the remote machine"),
|
|
38320
|
-
installer: exports_external2.enum(["auto", "bun", "npm"]).optional().describe("Preferred installer"),
|
|
38321
|
-
ssh_key_path: exports_external2.string().optional().describe("SSH private key path"),
|
|
38322
|
-
enabled: exports_external2.boolean().optional().describe("Whether the machine should be enabled")
|
|
38323
|
-
}, async ({ host, id, name, username, port, platform: platform2, arch, bun_path, npm_path, installer, ssh_key_path, enabled }) => {
|
|
38324
|
-
const machine = addMachine({
|
|
38325
|
-
host,
|
|
38326
|
-
id,
|
|
38327
|
-
name,
|
|
38328
|
-
username,
|
|
38329
|
-
port,
|
|
38330
|
-
platform: platform2,
|
|
38331
|
-
arch,
|
|
38332
|
-
bun_path,
|
|
38333
|
-
npm_path,
|
|
38334
|
-
installer,
|
|
38335
|
-
ssh_key_path,
|
|
38336
|
-
enabled
|
|
38587
|
+
return Object.keys(description).length > 0 ? description : {};
|
|
38588
|
+
}
|
|
38589
|
+
function asJsonSchemaObject(schema) {
|
|
38590
|
+
return typeof schema === "boolean" ? {} : schema;
|
|
38591
|
+
}
|
|
38592
|
+
function isOptionalSchema(schema) {
|
|
38593
|
+
const def = schema._def;
|
|
38594
|
+
const typeName = String(def?.typeName ?? "");
|
|
38595
|
+
return typeName === exports_external2.ZodFirstPartyTypeKind.ZodOptional || typeName === exports_external2.ZodFirstPartyTypeKind.ZodDefault;
|
|
38596
|
+
}
|
|
38597
|
+
function readRecord(value) {
|
|
38598
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
38599
|
+
}
|
|
38600
|
+
function isRecordOfStrings(value) {
|
|
38601
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
38602
|
+
return false;
|
|
38603
|
+
return Object.values(value).every((item) => typeof item === "string");
|
|
38604
|
+
}
|
|
38605
|
+
|
|
38606
|
+
// src/mcp/server.ts
|
|
38607
|
+
var VERSION2 = readPackageVersion(import.meta.url);
|
|
38608
|
+
function createMcpServer(options = {}) {
|
|
38609
|
+
const server = new McpServer({
|
|
38610
|
+
name: options.name ?? "mcps",
|
|
38611
|
+
version: options.version ?? VERSION2
|
|
38337
38612
|
});
|
|
38338
|
-
|
|
38339
|
-
|
|
38340
|
-
|
|
38341
|
-
});
|
|
38342
|
-
server.tool("remove_machine", "Remove a registered machine", { id: exports_external2.string().describe("Machine ID to remove") }, async ({ id }) => {
|
|
38343
|
-
const machine = getMachine(id);
|
|
38344
|
-
if (!machine) {
|
|
38345
|
-
return {
|
|
38346
|
-
content: [{ type: "text", text: `Machine "${id}" not found.` }],
|
|
38347
|
-
isError: true
|
|
38348
|
-
};
|
|
38613
|
+
registerMcpTools(server, options.tools);
|
|
38614
|
+
if (options.cloudTools !== false) {
|
|
38615
|
+
registerCloudTools(server, "mcps");
|
|
38349
38616
|
}
|
|
38350
|
-
|
|
38351
|
-
|
|
38352
|
-
|
|
38353
|
-
|
|
38354
|
-
});
|
|
38355
|
-
server.tool("seed_default_machines", "Seed the standard spark/apple machine inventory", {}, async () => {
|
|
38356
|
-
const machines = seedDefaultMachines();
|
|
38357
|
-
return {
|
|
38358
|
-
content: [{ type: "text", text: JSON.stringify(machines, null, 2) }]
|
|
38359
|
-
};
|
|
38360
|
-
});
|
|
38361
|
-
server.tool("list_hasna_mcp_catalog", "List the discovered @hasna MCP package catalog", {
|
|
38362
|
-
packages: exports_external2.array(exports_external2.string()).optional().describe("Optional package-name filter"),
|
|
38363
|
-
refresh: exports_external2.boolean().optional().describe("Refresh npm metadata instead of using cache")
|
|
38364
|
-
}, async ({ packages, refresh }) => {
|
|
38365
|
-
const catalog = await listHasnaMcpCatalog({ refresh });
|
|
38366
|
-
const filtered = packages?.length ? catalog.filter((entry) => packages.includes(entry.name)) : catalog;
|
|
38367
|
-
return {
|
|
38368
|
-
content: [{ type: "text", text: JSON.stringify(filtered, null, 2) }]
|
|
38369
|
-
};
|
|
38370
|
-
});
|
|
38371
|
-
server.tool("fleet_health", "Run fleet-wide MCP health checks across registered machines", {
|
|
38372
|
-
machine_ids: exports_external2.array(exports_external2.string()).optional().describe("Optional machine IDs to check"),
|
|
38373
|
-
packages: exports_external2.array(exports_external2.string()).optional().describe("Optional @hasna package-name filter"),
|
|
38374
|
-
refresh_catalog: exports_external2.boolean().optional().describe("Refresh npm metadata before checking"),
|
|
38375
|
-
timeout_ms: exports_external2.number().int().min(1000).optional().describe("Remote timeout in milliseconds")
|
|
38376
|
-
}, async ({ machine_ids, packages, refresh_catalog, timeout_ms }) => {
|
|
38377
|
-
const reports = await runFleetHealthCheck({
|
|
38378
|
-
machineIds: machine_ids,
|
|
38379
|
-
packages,
|
|
38380
|
-
refreshCatalog: refresh_catalog,
|
|
38381
|
-
timeoutMs: timeout_ms
|
|
38382
|
-
});
|
|
38383
|
-
return {
|
|
38384
|
-
content: [{ type: "text", text: JSON.stringify(reports, null, 2) }]
|
|
38385
|
-
};
|
|
38386
|
-
});
|
|
38387
|
-
server.tool("fleet_install", "Batch-install missing or outdated @hasna MCP packages across machines", {
|
|
38388
|
-
machine_ids: exports_external2.array(exports_external2.string()).optional().describe("Optional machine IDs to target"),
|
|
38389
|
-
packages: exports_external2.array(exports_external2.string()).optional().describe("Optional @hasna package-name filter"),
|
|
38390
|
-
mode: exports_external2.enum(["missing", "missing-or-outdated", "all"]).optional().describe("Install selection mode"),
|
|
38391
|
-
installer: exports_external2.enum(["auto", "bun", "npm"]).optional().describe("Override installer"),
|
|
38392
|
-
refresh_catalog: exports_external2.boolean().optional().describe("Refresh npm metadata before installing"),
|
|
38393
|
-
timeout_ms: exports_external2.number().int().min(1000).optional().describe("Remote timeout in milliseconds")
|
|
38394
|
-
}, async ({ machine_ids, packages, mode, installer, refresh_catalog, timeout_ms }) => {
|
|
38395
|
-
const reports = await runFleetInstall({
|
|
38396
|
-
machineIds: machine_ids,
|
|
38397
|
-
packages,
|
|
38398
|
-
mode,
|
|
38399
|
-
installer,
|
|
38400
|
-
refreshCatalog: refresh_catalog,
|
|
38401
|
-
timeoutMs: timeout_ms
|
|
38402
|
-
});
|
|
38403
|
-
return {
|
|
38404
|
-
content: [{ type: "text", text: JSON.stringify(reports, null, 2) }]
|
|
38405
|
-
};
|
|
38406
|
-
});
|
|
38407
|
-
server.tool("send_feedback", "Send feedback about this service", {
|
|
38408
|
-
message: exports_external2.string().describe("Feedback message"),
|
|
38409
|
-
email: exports_external2.string().optional().describe("Contact email (optional)"),
|
|
38410
|
-
category: exports_external2.enum(["bug", "feature", "general"]).optional().describe("Feedback category")
|
|
38411
|
-
}, async (params) => {
|
|
38412
|
-
const adapter = getAdapter();
|
|
38413
|
-
adapter.run("INSERT INTO feedback (message, email, category, version) VALUES (?, ?, ?, ?)", params.message, params.email || null, params.category || "general", VERSION);
|
|
38414
|
-
return { content: [{ type: "text", text: "Feedback saved. Thank you!" }] };
|
|
38415
|
-
});
|
|
38416
|
-
server.tool("register_agent", "Register an agent session. Returns agent_id. Auto-triggers a heartbeat.", {
|
|
38417
|
-
name: exports_external2.string(),
|
|
38418
|
-
session_id: exports_external2.string().optional()
|
|
38419
|
-
}, async (params) => {
|
|
38420
|
-
const existing = [..._mcpsAgents.values()].find((a) => a.name === params.name);
|
|
38421
|
-
if (existing) {
|
|
38422
|
-
existing.last_seen_at = new Date().toISOString();
|
|
38423
|
-
if (params.session_id)
|
|
38424
|
-
existing.session_id = params.session_id;
|
|
38425
|
-
return { content: [{ type: "text", text: JSON.stringify(existing) }] };
|
|
38426
|
-
}
|
|
38427
|
-
const id = Math.random().toString(36).slice(2, 10);
|
|
38428
|
-
const ag = { id, name: params.name, session_id: params.session_id, last_seen_at: new Date().toISOString() };
|
|
38429
|
-
_mcpsAgents.set(id, ag);
|
|
38430
|
-
return { content: [{ type: "text", text: JSON.stringify(ag) }] };
|
|
38431
|
-
});
|
|
38432
|
-
server.tool("heartbeat", "Update last_seen_at to signal agent is active.", {
|
|
38433
|
-
agent_id: exports_external2.string()
|
|
38434
|
-
}, async (params) => {
|
|
38435
|
-
const ag = _mcpsAgents.get(params.agent_id);
|
|
38436
|
-
if (!ag)
|
|
38437
|
-
return { content: [{ type: "text", text: `Agent not found: ${params.agent_id}` }], isError: true };
|
|
38438
|
-
ag.last_seen_at = new Date().toISOString();
|
|
38439
|
-
return { content: [{ type: "text", text: JSON.stringify({ agent_id: ag.id, last_seen_at: ag.last_seen_at }) }] };
|
|
38440
|
-
});
|
|
38441
|
-
server.tool("set_focus", "Set active project context for this agent session.", {
|
|
38442
|
-
agent_id: exports_external2.string(),
|
|
38443
|
-
project_id: exports_external2.string().optional()
|
|
38444
|
-
}, async (params) => {
|
|
38445
|
-
const ag = _mcpsAgents.get(params.agent_id);
|
|
38446
|
-
if (!ag)
|
|
38447
|
-
return { content: [{ type: "text", text: `Agent not found: ${params.agent_id}` }], isError: true };
|
|
38448
|
-
ag.project_id = params.project_id;
|
|
38449
|
-
return { content: [{ type: "text", text: JSON.stringify({ agent_id: ag.id, project_id: ag.project_id ?? null }) }] };
|
|
38450
|
-
});
|
|
38451
|
-
server.tool("list_agents", "List all registered agents.", {}, async () => {
|
|
38452
|
-
return { content: [{ type: "text", text: JSON.stringify([..._mcpsAgents.values()]) }] };
|
|
38453
|
-
});
|
|
38617
|
+
return server;
|
|
38618
|
+
}
|
|
38619
|
+
|
|
38620
|
+
// src/mcp/index.ts
|
|
38454
38621
|
async function startMcpServer() {
|
|
38622
|
+
const server = createMcpServer();
|
|
38455
38623
|
const transport = new StdioServerTransport;
|
|
38456
|
-
registerCloudTools(server, "mcps");
|
|
38457
38624
|
await server.connect(transport);
|
|
38458
38625
|
}
|
|
38459
38626
|
var isDirectRun = import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith("/mcp/index.ts") || process.argv[1]?.endsWith("/bin/mcp.js");
|
|
@@ -38465,13 +38632,13 @@ if (isDirectRun) {
|
|
|
38465
38632
|
}
|
|
38466
38633
|
|
|
38467
38634
|
// src/server/serve.ts
|
|
38468
|
-
import { existsSync as
|
|
38635
|
+
import { existsSync as existsSync10 } from "fs";
|
|
38469
38636
|
import { join as join11, dirname as dirname4, extname, resolve, relative as relative2, sep } from "path";
|
|
38470
38637
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
38471
38638
|
init_sources();
|
|
38472
38639
|
init_db();
|
|
38473
|
-
function redactServer(
|
|
38474
|
-
return { ...
|
|
38640
|
+
function redactServer(server) {
|
|
38641
|
+
return { ...server, env: {} };
|
|
38475
38642
|
}
|
|
38476
38643
|
function resolveDashboardDir() {
|
|
38477
38644
|
const candidates = [];
|
|
@@ -38487,7 +38654,7 @@ function resolveDashboardDir() {
|
|
|
38487
38654
|
}
|
|
38488
38655
|
candidates.push(join11(process.cwd(), "dashboard", "dist"));
|
|
38489
38656
|
for (const candidate of candidates) {
|
|
38490
|
-
if (
|
|
38657
|
+
if (existsSync10(candidate))
|
|
38491
38658
|
return candidate;
|
|
38492
38659
|
}
|
|
38493
38660
|
return join11(process.cwd(), "dashboard", "dist");
|
|
@@ -38578,7 +38745,7 @@ function getAllServersWithToolCount() {
|
|
|
38578
38745
|
}));
|
|
38579
38746
|
}
|
|
38580
38747
|
function serveStaticFile(filePath) {
|
|
38581
|
-
if (!
|
|
38748
|
+
if (!existsSync10(filePath))
|
|
38582
38749
|
return null;
|
|
38583
38750
|
const ext = extname(filePath);
|
|
38584
38751
|
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
@@ -38611,7 +38778,7 @@ async function startServer(port, options) {
|
|
|
38611
38778
|
const host = options?.host ?? "127.0.0.1";
|
|
38612
38779
|
getDb();
|
|
38613
38780
|
const dashboardDir = resolveDashboardDir();
|
|
38614
|
-
const dashboardExists =
|
|
38781
|
+
const dashboardExists = existsSync10(dashboardDir);
|
|
38615
38782
|
if (!dashboardExists) {
|
|
38616
38783
|
console.error(`
|
|
38617
38784
|
Dashboard not found at: ${dashboardDir}`);
|
|
@@ -38620,7 +38787,7 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
38620
38787
|
console.error(` cd dashboard && bun install && bun run build
|
|
38621
38788
|
`);
|
|
38622
38789
|
}
|
|
38623
|
-
const
|
|
38790
|
+
const server = Bun.serve({
|
|
38624
38791
|
port,
|
|
38625
38792
|
hostname: host,
|
|
38626
38793
|
async fetch(req) {
|
|
@@ -38691,8 +38858,8 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
38691
38858
|
const entry = getServer(id);
|
|
38692
38859
|
if (!entry)
|
|
38693
38860
|
return json({ error: `Server '${id}' not found` }, 404, port);
|
|
38694
|
-
const
|
|
38695
|
-
return json({ ...redactServer(entry), toolCount:
|
|
38861
|
+
const tools2 = getCachedTools(id);
|
|
38862
|
+
return json({ ...redactServer(entry), toolCount: tools2.length, tools: tools2 }, 200, port);
|
|
38696
38863
|
}
|
|
38697
38864
|
if (singleMatch && method === "DELETE") {
|
|
38698
38865
|
const id = singleMatch[1];
|
|
@@ -38820,8 +38987,8 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
38820
38987
|
const entry = getServer(id);
|
|
38821
38988
|
if (!entry)
|
|
38822
38989
|
return json({ error: `Server '${id}' not found` }, 404, port);
|
|
38823
|
-
const
|
|
38824
|
-
return json(
|
|
38990
|
+
const tools2 = getCachedTools(id);
|
|
38991
|
+
return json(tools2, 200, port);
|
|
38825
38992
|
}
|
|
38826
38993
|
const serverCallMatch = path.match(/^\/api\/servers\/([^/]+)\/call$/);
|
|
38827
38994
|
if (serverCallMatch && method === "POST") {
|
|
@@ -39004,7 +39171,7 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
39004
39171
|
}
|
|
39005
39172
|
});
|
|
39006
39173
|
const shutdown = () => {
|
|
39007
|
-
|
|
39174
|
+
server.stop();
|
|
39008
39175
|
closeDb();
|
|
39009
39176
|
process.exit(0);
|
|
39010
39177
|
};
|
|
@@ -39517,18 +39684,18 @@ var build_default = Spinner;
|
|
|
39517
39684
|
|
|
39518
39685
|
// src/cli/components/ServerDetail.tsx
|
|
39519
39686
|
import { jsxDEV as jsxDEV2, Fragment } from "react/jsx-dev-runtime";
|
|
39520
|
-
function ServerDetail({ server
|
|
39521
|
-
const [
|
|
39687
|
+
function ServerDetail({ server, onSelectTool, onBack }) {
|
|
39688
|
+
const [tools2, setTools] = useState3([]);
|
|
39522
39689
|
const [loading, setLoading] = useState3(false);
|
|
39523
39690
|
const [error2, setError] = useState3(null);
|
|
39524
|
-
const cachedTools = getCachedTools(
|
|
39691
|
+
const cachedTools = getCachedTools(server.id);
|
|
39525
39692
|
const cachedKey = cachedTools.map((t) => `${t.name}|${t.description}|${JSON.stringify(t.input_schema)}`).join(";");
|
|
39526
39693
|
useEffect3(() => {
|
|
39527
39694
|
setLoading(false);
|
|
39528
39695
|
setError(null);
|
|
39529
39696
|
if (cachedTools.length > 0) {
|
|
39530
39697
|
setTools(cachedTools.map((t) => ({
|
|
39531
|
-
server_id:
|
|
39698
|
+
server_id: server.id,
|
|
39532
39699
|
name: t.name,
|
|
39533
39700
|
description: t.description,
|
|
39534
39701
|
input_schema: t.input_schema
|
|
@@ -39536,12 +39703,12 @@ function ServerDetail({ server: server2, onSelectTool, onBack }) {
|
|
|
39536
39703
|
} else {
|
|
39537
39704
|
setTools([]);
|
|
39538
39705
|
}
|
|
39539
|
-
}, [
|
|
39706
|
+
}, [server.id, cachedKey]);
|
|
39540
39707
|
const handleConnect = async () => {
|
|
39541
39708
|
setLoading(true);
|
|
39542
39709
|
setError(null);
|
|
39543
39710
|
try {
|
|
39544
|
-
const conn = await connectToServer(
|
|
39711
|
+
const conn = await connectToServer(server);
|
|
39545
39712
|
setTools(conn.tools);
|
|
39546
39713
|
} catch (err) {
|
|
39547
39714
|
setError(err.message);
|
|
@@ -39550,8 +39717,8 @@ function ServerDetail({ server: server2, onSelectTool, onBack }) {
|
|
|
39550
39717
|
}
|
|
39551
39718
|
};
|
|
39552
39719
|
const items = [
|
|
39553
|
-
...
|
|
39554
|
-
...
|
|
39720
|
+
...tools2.length === 0 && !loading ? [{ label: "Connect & fetch tools", value: "__connect" }] : [],
|
|
39721
|
+
...tools2.map((t) => ({
|
|
39555
39722
|
label: `${t.name} \u2014 ${t.description || "No description"}`,
|
|
39556
39723
|
value: t.name,
|
|
39557
39724
|
tool: t
|
|
@@ -39560,7 +39727,7 @@ function ServerDetail({ server: server2, onSelectTool, onBack }) {
|
|
|
39560
39727
|
];
|
|
39561
39728
|
const handleSelect = (item) => {
|
|
39562
39729
|
if (item.value === "__back") {
|
|
39563
|
-
disconnectServer(
|
|
39730
|
+
disconnectServer(server.id);
|
|
39564
39731
|
onBack();
|
|
39565
39732
|
} else if (item.value === "__connect") {
|
|
39566
39733
|
handleConnect();
|
|
@@ -39573,36 +39740,36 @@ function ServerDetail({ server: server2, onSelectTool, onBack }) {
|
|
|
39573
39740
|
children: [
|
|
39574
39741
|
/* @__PURE__ */ jsxDEV2(Text5, {
|
|
39575
39742
|
bold: true,
|
|
39576
|
-
children:
|
|
39743
|
+
children: server.name
|
|
39577
39744
|
}, undefined, false, undefined, this),
|
|
39578
39745
|
/* @__PURE__ */ jsxDEV2(Text5, {
|
|
39579
39746
|
dimColor: true,
|
|
39580
39747
|
children: [
|
|
39581
39748
|
"ID: ",
|
|
39582
|
-
|
|
39749
|
+
server.id
|
|
39583
39750
|
]
|
|
39584
39751
|
}, undefined, true, undefined, this),
|
|
39585
39752
|
/* @__PURE__ */ jsxDEV2(Text5, {
|
|
39586
39753
|
dimColor: true,
|
|
39587
39754
|
children: [
|
|
39588
39755
|
"Status: ",
|
|
39589
|
-
|
|
39756
|
+
server.enabled ? "enabled" : "disabled",
|
|
39590
39757
|
" | Transport: ",
|
|
39591
|
-
|
|
39758
|
+
server.transport
|
|
39592
39759
|
]
|
|
39593
39760
|
}, undefined, true, undefined, this),
|
|
39594
39761
|
/* @__PURE__ */ jsxDEV2(Text5, {
|
|
39595
39762
|
dimColor: true,
|
|
39596
39763
|
children: [
|
|
39597
39764
|
"Command: ",
|
|
39598
|
-
|
|
39765
|
+
server.command,
|
|
39599
39766
|
" ",
|
|
39600
|
-
|
|
39767
|
+
server.args.join(" ")
|
|
39601
39768
|
]
|
|
39602
39769
|
}, undefined, true, undefined, this),
|
|
39603
|
-
|
|
39770
|
+
server.description && /* @__PURE__ */ jsxDEV2(Text5, {
|
|
39604
39771
|
dimColor: true,
|
|
39605
|
-
children:
|
|
39772
|
+
children: server.description
|
|
39606
39773
|
}, undefined, false, undefined, this),
|
|
39607
39774
|
/* @__PURE__ */ jsxDEV2(Box4, {
|
|
39608
39775
|
marginTop: 1,
|
|
@@ -39624,7 +39791,7 @@ function ServerDetail({ server: server2, onSelectTool, onBack }) {
|
|
|
39624
39791
|
children: [
|
|
39625
39792
|
/* @__PURE__ */ jsxDEV2(Text5, {
|
|
39626
39793
|
bold: true,
|
|
39627
|
-
children:
|
|
39794
|
+
children: tools2.length > 0 ? `Tools (${tools2.length}):` : "Tools:"
|
|
39628
39795
|
}, undefined, false, undefined, this),
|
|
39629
39796
|
/* @__PURE__ */ jsxDEV2(SelectInput_default, {
|
|
39630
39797
|
items,
|
|
@@ -39768,8 +39935,8 @@ function SearchView({ onBack }) {
|
|
|
39768
39935
|
setInstalling(item.value);
|
|
39769
39936
|
setMessage(null);
|
|
39770
39937
|
try {
|
|
39771
|
-
const
|
|
39772
|
-
setMessage(`Installed: ${
|
|
39938
|
+
const server = await installFromRegistry(item.value);
|
|
39939
|
+
setMessage(`Installed: ${server.name} [${server.id}]`);
|
|
39773
39940
|
} catch (err) {
|
|
39774
39941
|
setMessage(`Install failed: ${err.message}`);
|
|
39775
39942
|
} finally {
|
|
@@ -39862,7 +40029,7 @@ import { useState as useState6 } from "react";
|
|
|
39862
40029
|
import { Box as Box6, Text as Text8 } from "ink";
|
|
39863
40030
|
init_config2();
|
|
39864
40031
|
import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
|
|
39865
|
-
function ToolCall({ server
|
|
40032
|
+
function ToolCall({ server, tool, onBack }) {
|
|
39866
40033
|
const [argsInput, setArgsInput] = useState6("{}");
|
|
39867
40034
|
const [calling, setCalling] = useState6(false);
|
|
39868
40035
|
const [result, setResult] = useState6(null);
|
|
@@ -39879,8 +40046,8 @@ function ToolCall({ server: server2, tool, onBack }) {
|
|
|
39879
40046
|
setError(null);
|
|
39880
40047
|
setResult(null);
|
|
39881
40048
|
try {
|
|
39882
|
-
await connectToServer(
|
|
39883
|
-
const prefixed = `${
|
|
40049
|
+
await connectToServer(server);
|
|
40050
|
+
const prefixed = `${server.id}${TOOL_PREFIX_SEPARATOR}${tool.name}`;
|
|
39884
40051
|
const res = await callTool(prefixed, args);
|
|
39885
40052
|
const text = res.content.map((c) => c.text).join(`
|
|
39886
40053
|
`);
|
|
@@ -39908,9 +40075,9 @@ function ToolCall({ server: server2, tool, onBack }) {
|
|
|
39908
40075
|
dimColor: true,
|
|
39909
40076
|
children: [
|
|
39910
40077
|
"Server: ",
|
|
39911
|
-
|
|
40078
|
+
server.name,
|
|
39912
40079
|
" [",
|
|
39913
|
-
|
|
40080
|
+
server.id,
|
|
39914
40081
|
"]"
|
|
39915
40082
|
]
|
|
39916
40083
|
}, undefined, true, undefined, this),
|
|
@@ -40023,8 +40190,8 @@ function App() {
|
|
|
40023
40190
|
}).finally(() => closeDb());
|
|
40024
40191
|
};
|
|
40025
40192
|
}, []);
|
|
40026
|
-
const handleSelectServer = (
|
|
40027
|
-
setSelectedServer(
|
|
40193
|
+
const handleSelectServer = (server) => {
|
|
40194
|
+
setSelectedServer(server);
|
|
40028
40195
|
setView("detail");
|
|
40029
40196
|
};
|
|
40030
40197
|
const handleSearch = () => {
|
|
@@ -40092,14 +40259,8 @@ function App() {
|
|
|
40092
40259
|
}
|
|
40093
40260
|
|
|
40094
40261
|
// src/cli/index.tsx
|
|
40095
|
-
var
|
|
40096
|
-
|
|
40097
|
-
const pkgPath = join12(dirname5(fileURLToPath3(import.meta.url)), "..", "..", "package.json");
|
|
40098
|
-
const pkg = JSON.parse(readFileSync6(pkgPath, "utf-8"));
|
|
40099
|
-
return pkg.version || "0.0.1";
|
|
40100
|
-
} catch {
|
|
40101
|
-
return "0.0.1";
|
|
40102
|
-
}
|
|
40262
|
+
var VERSION3 = (() => {
|
|
40263
|
+
return readPackageVersion(import.meta.url);
|
|
40103
40264
|
})();
|
|
40104
40265
|
var MACHINE_PLATFORMS = ["linux", "darwin", "unknown"];
|
|
40105
40266
|
var MACHINE_ARCHES = ["arm64", "x64", "unknown"];
|
|
@@ -40203,7 +40364,7 @@ function renderFleetInstall(reports) {
|
|
|
40203
40364
|
}
|
|
40204
40365
|
}
|
|
40205
40366
|
var program2 = new Command;
|
|
40206
|
-
program2.name("mcps").description("Meta-MCP registry & CLI \u2014 discover, manage, and proxy MCP servers").version(
|
|
40367
|
+
program2.name("mcps").description("Meta-MCP registry & CLI \u2014 discover, manage, and proxy MCP servers").version(VERSION3).enablePositionalOptions();
|
|
40207
40368
|
program2.command("list").description("List registered MCP servers").option("--json", "Output as JSON").option("--verbose", "Show detailed info including health, command, and transport").action((opts) => {
|
|
40208
40369
|
const servers = listServers();
|
|
40209
40370
|
if (opts.json) {
|
|
@@ -40295,9 +40456,9 @@ program2.command("add").passThroughOptions().argument("[command]", "Command to r
|
|
|
40295
40456
|
try {
|
|
40296
40457
|
if (opts.fromRegistry) {
|
|
40297
40458
|
console.log(chalk2.dim(`Installing "${opts.fromRegistry}" from registry...`));
|
|
40298
|
-
const
|
|
40299
|
-
console.log(chalk2.green(`Added server: ${
|
|
40300
|
-
console.log(chalk2.dim(` ${
|
|
40459
|
+
const server2 = await installFromRegistry(opts.fromRegistry);
|
|
40460
|
+
console.log(chalk2.green(`Added server: ${server2.name} [${server2.id}]`));
|
|
40461
|
+
console.log(chalk2.dim(` ${server2.command} ${server2.args.join(" ")}`));
|
|
40301
40462
|
closeDb();
|
|
40302
40463
|
return;
|
|
40303
40464
|
}
|
|
@@ -40346,7 +40507,7 @@ Server to add:`));
|
|
|
40346
40507
|
closeDb();
|
|
40347
40508
|
return;
|
|
40348
40509
|
}
|
|
40349
|
-
const
|
|
40510
|
+
const server2 = addServer({
|
|
40350
40511
|
command: wizardCommand,
|
|
40351
40512
|
args: wizardArgs,
|
|
40352
40513
|
name: wizardName || undefined,
|
|
@@ -40354,7 +40515,7 @@ Server to add:`));
|
|
|
40354
40515
|
transport,
|
|
40355
40516
|
env
|
|
40356
40517
|
});
|
|
40357
|
-
console.log(chalk2.green(`Added: ${
|
|
40518
|
+
console.log(chalk2.green(`Added: ${server2.name} [${server2.id}]`));
|
|
40358
40519
|
closeDb();
|
|
40359
40520
|
return;
|
|
40360
40521
|
}
|
|
@@ -40382,7 +40543,7 @@ Server to add:`));
|
|
|
40382
40543
|
envMap[key] = rest.join("=");
|
|
40383
40544
|
}
|
|
40384
40545
|
}
|
|
40385
|
-
const
|
|
40546
|
+
const server = addServer({
|
|
40386
40547
|
name: opts.name,
|
|
40387
40548
|
description: opts.description,
|
|
40388
40549
|
command,
|
|
@@ -40391,8 +40552,8 @@ Server to add:`));
|
|
|
40391
40552
|
url: opts.url,
|
|
40392
40553
|
env: envMap
|
|
40393
40554
|
});
|
|
40394
|
-
console.log(chalk2.green(`Added server: ${
|
|
40395
|
-
console.log(chalk2.dim(` ${
|
|
40555
|
+
console.log(chalk2.green(`Added server: ${server.name} [${server.id}]`));
|
|
40556
|
+
console.log(chalk2.dim(` ${server.command} ${server.args.join(" ")}`));
|
|
40396
40557
|
} catch (err) {
|
|
40397
40558
|
if (err.message?.includes("UNIQUE constraint")) {
|
|
40398
40559
|
console.error(chalk2.red("A server with that ID already exists."));
|
|
@@ -40405,8 +40566,8 @@ Server to add:`));
|
|
|
40405
40566
|
closeDb();
|
|
40406
40567
|
});
|
|
40407
40568
|
program2.command("update-server").argument("<id>", "Server ID to update").description("Update fields of a registered server").option("--name <name>", "New display name").option("--description <desc>", "New description").option("--command <cmd>", "New command").option("--args <args...>", "New args list").option("--transport <type>", "New transport type").option("--url <url>", "New URL").action((id, opts) => {
|
|
40408
|
-
const
|
|
40409
|
-
if (!
|
|
40569
|
+
const server = getServer(id);
|
|
40570
|
+
if (!server) {
|
|
40410
40571
|
console.error(chalk2.red(`Server "${id}" not found.`));
|
|
40411
40572
|
closeDb();
|
|
40412
40573
|
process.exit(1);
|
|
@@ -40441,53 +40602,53 @@ program2.command("clone").argument("<id>", "Server ID to clone").argument("<new-
|
|
|
40441
40602
|
closeDb();
|
|
40442
40603
|
});
|
|
40443
40604
|
program2.command("remove").argument("<id>", "Server ID to remove").description("Remove a registered server").action((id) => {
|
|
40444
|
-
const
|
|
40445
|
-
if (!
|
|
40605
|
+
const server = getServer(id);
|
|
40606
|
+
if (!server) {
|
|
40446
40607
|
console.error(chalk2.red(`Server "${id}" not found.`));
|
|
40447
40608
|
closeDb();
|
|
40448
40609
|
process.exit(1);
|
|
40449
40610
|
}
|
|
40450
40611
|
removeServer(id);
|
|
40451
|
-
console.log(chalk2.green(`Removed server: ${
|
|
40612
|
+
console.log(chalk2.green(`Removed server: ${server.name} [${id}]`));
|
|
40452
40613
|
closeDb();
|
|
40453
40614
|
});
|
|
40454
40615
|
program2.command("enable").argument("<id>", "Server ID to enable").description("Enable a server").action((id) => {
|
|
40455
|
-
const
|
|
40456
|
-
if (!
|
|
40616
|
+
const server = getServer(id);
|
|
40617
|
+
if (!server) {
|
|
40457
40618
|
console.error(chalk2.red(`Server "${id}" not found.`));
|
|
40458
40619
|
closeDb();
|
|
40459
40620
|
process.exit(1);
|
|
40460
40621
|
}
|
|
40461
40622
|
enableServer(id);
|
|
40462
|
-
console.log(chalk2.green(`Enabled server: ${
|
|
40623
|
+
console.log(chalk2.green(`Enabled server: ${server.name}`));
|
|
40463
40624
|
closeDb();
|
|
40464
40625
|
});
|
|
40465
40626
|
program2.command("disable").argument("<id>", "Server ID to disable").description("Disable a server").action((id) => {
|
|
40466
|
-
const
|
|
40467
|
-
if (!
|
|
40627
|
+
const server = getServer(id);
|
|
40628
|
+
if (!server) {
|
|
40468
40629
|
console.error(chalk2.red(`Server "${id}" not found.`));
|
|
40469
40630
|
closeDb();
|
|
40470
40631
|
process.exit(1);
|
|
40471
40632
|
}
|
|
40472
40633
|
disableServer(id);
|
|
40473
|
-
console.log(chalk2.yellow(`Disabled server: ${
|
|
40634
|
+
console.log(chalk2.yellow(`Disabled server: ${server.name}`));
|
|
40474
40635
|
closeDb();
|
|
40475
40636
|
});
|
|
40476
40637
|
program2.command("tools").argument("[server-id]", "Optional server ID to filter by").description("List tools (all or per server)").option("--connect", "Connect to servers to fetch live tools").action(async (serverId, opts) => {
|
|
40477
40638
|
if (opts.connect) {
|
|
40478
40639
|
console.log(chalk2.dim("Connecting to enabled servers..."));
|
|
40479
40640
|
await connectAllEnabled();
|
|
40480
|
-
const
|
|
40481
|
-
if (
|
|
40641
|
+
const tools2 = listAllTools();
|
|
40642
|
+
if (tools2.length === 0) {
|
|
40482
40643
|
console.log(chalk2.dim("No tools available."));
|
|
40483
40644
|
} else {
|
|
40484
|
-
for (const t of
|
|
40645
|
+
for (const t of tools2) {
|
|
40485
40646
|
console.log(` ${chalk2.bold(t.name)}`);
|
|
40486
40647
|
if (t.description)
|
|
40487
40648
|
console.log(` ${chalk2.dim(t.description)}`);
|
|
40488
40649
|
}
|
|
40489
40650
|
console.log(chalk2.dim(`
|
|
40490
|
-
${
|
|
40651
|
+
${tools2.length} tool(s) available.`));
|
|
40491
40652
|
}
|
|
40492
40653
|
await disconnectAll();
|
|
40493
40654
|
} else if (serverId) {
|
|
@@ -40567,26 +40728,26 @@ program2.command("call").argument("<tool>", "Tool name (server_id__tool_name)").
|
|
|
40567
40728
|
process.exit(exitCode);
|
|
40568
40729
|
});
|
|
40569
40730
|
program2.command("info").argument("<id>", "Server ID").description("Show server details & tools").action((id) => {
|
|
40570
|
-
const
|
|
40571
|
-
if (!
|
|
40731
|
+
const server = getServer(id);
|
|
40732
|
+
if (!server) {
|
|
40572
40733
|
console.error(chalk2.red(`Server "${id}" not found.`));
|
|
40573
40734
|
closeDb();
|
|
40574
40735
|
process.exit(1);
|
|
40575
40736
|
}
|
|
40576
|
-
console.log(chalk2.bold(
|
|
40577
|
-
console.log(` Status: ${
|
|
40578
|
-
console.log(` Source: ${
|
|
40579
|
-
console.log(` Transport: ${
|
|
40580
|
-
console.log(` Command: ${
|
|
40581
|
-
if (
|
|
40582
|
-
console.log(` URL: ${
|
|
40583
|
-
if (
|
|
40584
|
-
console.log(` Desc: ${
|
|
40585
|
-
if (Object.keys(
|
|
40586
|
-
console.log(` Env: ${Object.entries(
|
|
40587
|
-
}
|
|
40588
|
-
console.log(` Created: ${
|
|
40589
|
-
console.log(` Updated: ${
|
|
40737
|
+
console.log(chalk2.bold(server.name) + " " + chalk2.dim(`[${server.id}]`));
|
|
40738
|
+
console.log(` Status: ${server.enabled ? chalk2.green("enabled") : chalk2.red("disabled")}`);
|
|
40739
|
+
console.log(` Source: ${server.source}`);
|
|
40740
|
+
console.log(` Transport: ${server.transport}`);
|
|
40741
|
+
console.log(` Command: ${server.command} ${server.args.join(" ")}`);
|
|
40742
|
+
if (server.url)
|
|
40743
|
+
console.log(` URL: ${server.url}`);
|
|
40744
|
+
if (server.description)
|
|
40745
|
+
console.log(` Desc: ${server.description}`);
|
|
40746
|
+
if (Object.keys(server.env).length > 0) {
|
|
40747
|
+
console.log(` Env: ${Object.entries(server.env).map(([k, v]) => `${k}=${v}`).join(", ")}`);
|
|
40748
|
+
}
|
|
40749
|
+
console.log(` Created: ${server.created_at}`);
|
|
40750
|
+
console.log(` Updated: ${server.updated_at}`);
|
|
40590
40751
|
const cached2 = getCachedTools(id);
|
|
40591
40752
|
if (cached2.length > 0) {
|
|
40592
40753
|
console.log(chalk2.bold(`
|
|
@@ -40626,10 +40787,10 @@ program2.command("doctor").argument("[id]", "Server ID to check (omit to check a
|
|
|
40626
40787
|
return;
|
|
40627
40788
|
}
|
|
40628
40789
|
let allHealthy = true;
|
|
40629
|
-
for (const
|
|
40790
|
+
for (const server of servers) {
|
|
40630
40791
|
console.log(chalk2.bold(`
|
|
40631
|
-
${
|
|
40632
|
-
const report = await diagnoseServer(
|
|
40792
|
+
${server.name} [${server.id}]`));
|
|
40793
|
+
const report = await diagnoseServer(server);
|
|
40633
40794
|
for (const check2 of report.checks) {
|
|
40634
40795
|
const icon = check2.pass ? chalk2.green("\u2713") : chalk2.red("\u2717");
|
|
40635
40796
|
console.log(` ${icon} ${check2.name}: ${chalk2.dim(check2.message)}`);
|
|
@@ -40825,14 +40986,14 @@ Enter number to install (1-${results.length}), or 0 to cancel: `), resolve2);
|
|
|
40825
40986
|
return;
|
|
40826
40987
|
}
|
|
40827
40988
|
console.log(chalk2.dim(`Installing ${chosen.name}...`));
|
|
40828
|
-
const
|
|
40989
|
+
const server = addServer({
|
|
40829
40990
|
command: "npx",
|
|
40830
40991
|
args: ["-y", pkg],
|
|
40831
40992
|
name: chosen.name,
|
|
40832
40993
|
description: chosen.description,
|
|
40833
40994
|
transport: "stdio"
|
|
40834
40995
|
});
|
|
40835
|
-
const results2 = installToAgents(
|
|
40996
|
+
const results2 = installToAgents(server, ["claude", "codex", "gemini"]);
|
|
40836
40997
|
for (const r of results2) {
|
|
40837
40998
|
if (r.success) {
|
|
40838
40999
|
console.log(chalk2.green(` \u2713 ${r.agent}`));
|
|
@@ -40841,7 +41002,7 @@ Enter number to install (1-${results.length}), or 0 to cancel: `), resolve2);
|
|
|
40841
41002
|
}
|
|
40842
41003
|
}
|
|
40843
41004
|
console.log(chalk2.green(`
|
|
40844
|
-
Installed ${
|
|
41005
|
+
Installed ${server.name} [${server.id}]`));
|
|
40845
41006
|
}
|
|
40846
41007
|
} catch (err) {
|
|
40847
41008
|
console.error(chalk2.red(`Find failed: ${err.message}`));
|
|
@@ -40999,12 +41160,12 @@ program2.command("install").argument("[id]", "Server ID (from `mcps list`) to in
|
|
|
40999
41160
|
if (!targets.includes("gemini"))
|
|
41000
41161
|
targets.push("gemini");
|
|
41001
41162
|
}
|
|
41002
|
-
let
|
|
41163
|
+
let server;
|
|
41003
41164
|
if (opts.fromRegistry) {
|
|
41004
41165
|
console.log(chalk2.dim(`Installing "${opts.fromRegistry}" from registry...`));
|
|
41005
41166
|
try {
|
|
41006
|
-
|
|
41007
|
-
console.log(chalk2.green(`Added server: ${
|
|
41167
|
+
server = await installFromRegistry(opts.fromRegistry);
|
|
41168
|
+
console.log(chalk2.green(`Added server: ${server.name} [${server.id}]`));
|
|
41008
41169
|
} catch (err) {
|
|
41009
41170
|
console.error(chalk2.red(`Failed to install from registry: ${err.message}`));
|
|
41010
41171
|
closeDb();
|
|
@@ -41012,23 +41173,23 @@ program2.command("install").argument("[id]", "Server ID (from `mcps list`) to in
|
|
|
41012
41173
|
}
|
|
41013
41174
|
} else if (opts.npm) {
|
|
41014
41175
|
const pkg = opts.npm;
|
|
41015
|
-
|
|
41016
|
-
console.log(chalk2.green(`Added server: ${
|
|
41176
|
+
server = addServer({ command: "npx", args: ["-y", pkg], name: pkg, transport: "stdio" });
|
|
41177
|
+
console.log(chalk2.green(`Added server: ${server.name} [${server.id}]`));
|
|
41017
41178
|
} else {
|
|
41018
41179
|
if (!id) {
|
|
41019
41180
|
console.error(chalk2.red("Error: server ID is required (or use --from-registry or --npm)"));
|
|
41020
41181
|
closeDb();
|
|
41021
41182
|
process.exit(1);
|
|
41022
41183
|
}
|
|
41023
|
-
|
|
41024
|
-
if (!
|
|
41184
|
+
server = getServer(id);
|
|
41185
|
+
if (!server) {
|
|
41025
41186
|
console.error(chalk2.red(`Server "${id}" not found. Use \`mcps add\` first.`));
|
|
41026
41187
|
closeDb();
|
|
41027
41188
|
process.exit(1);
|
|
41028
41189
|
}
|
|
41029
41190
|
}
|
|
41030
|
-
console.log(chalk2.dim(`Installing "${
|
|
41031
|
-
const results = installToAgents(
|
|
41191
|
+
console.log(chalk2.dim(`Installing "${server.name}" to: ${targets.join(", ")}...`));
|
|
41192
|
+
const results = installToAgents(server, targets);
|
|
41032
41193
|
for (const r of results) {
|
|
41033
41194
|
if (r.success) {
|
|
41034
41195
|
console.log(chalk2.green(` \u2713 ${r.agent}`));
|
|
@@ -41271,13 +41432,13 @@ program2.command("import").argument("<file>", "Path to the export JSON file").de
|
|
|
41271
41432
|
});
|
|
41272
41433
|
var envCmd = program2.command("env").description("Manage server environment variables");
|
|
41273
41434
|
envCmd.command("list").argument("<id>").description("List env vars for a server").action((id) => {
|
|
41274
|
-
const
|
|
41275
|
-
if (!
|
|
41435
|
+
const server = getServer(id);
|
|
41436
|
+
if (!server) {
|
|
41276
41437
|
console.error(chalk2.red(`Server "${id}" not found.`));
|
|
41277
41438
|
closeDb();
|
|
41278
41439
|
process.exit(1);
|
|
41279
41440
|
}
|
|
41280
|
-
const entries = Object.entries(
|
|
41441
|
+
const entries = Object.entries(server.env);
|
|
41281
41442
|
if (entries.length === 0) {
|
|
41282
41443
|
console.log(chalk2.dim("No env vars set."));
|
|
41283
41444
|
closeDb();
|
|
@@ -41322,7 +41483,7 @@ program2.command("mcp").description("Start meta-MCP server (stdio)").action(asyn
|
|
|
41322
41483
|
});
|
|
41323
41484
|
program2.command("feedback <message>").description("Send feedback").option("--email <email>", "Contact email").option("--category <category>", "Category: bug, feature, general").action((message, opts) => {
|
|
41324
41485
|
const adapter = getAdapter();
|
|
41325
|
-
adapter.run("INSERT INTO feedback (message, email, category, version) VALUES (?, ?, ?, ?)", message, opts.email || null, opts.category || "general",
|
|
41486
|
+
adapter.run("INSERT INTO feedback (message, email, category, version) VALUES (?, ?, ?, ?)", message, opts.email || null, opts.category || "general", VERSION3);
|
|
41326
41487
|
console.log(chalk2.green("Feedback saved. Thank you!"));
|
|
41327
41488
|
closeDb();
|
|
41328
41489
|
});
|