@mcpc-tech/core 0.3.37 → 0.3.39
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/index.cjs +225 -98
- package/index.mjs +225 -98
- package/package.json +1 -1
- package/plugins/skills.cjs +8 -2
- package/plugins/skills.mjs +8 -2
- package/plugins.cjs +146 -2
- package/plugins.mjs +145 -2
- package/types/plugins.d.ts +1 -0
- package/types/plugins.d.ts.map +1 -1
- package/types/src/plugins/bash.d.ts +10 -0
- package/types/src/plugins/bash.d.ts.map +1 -0
- package/types/src/plugins/skills.d.ts.map +1 -1
- package/types/src/utils/common/mcp.d.ts.map +1 -1
package/index.cjs
CHANGED
|
@@ -13969,6 +13969,147 @@ var ExperimentalServerTasks = class {
|
|
|
13969
13969
|
requestStream(request, resultSchema, options) {
|
|
13970
13970
|
return this._server.requestStream(request, resultSchema, options);
|
|
13971
13971
|
}
|
|
13972
|
+
/**
|
|
13973
|
+
* Sends a sampling request and returns an AsyncGenerator that yields response messages.
|
|
13974
|
+
* The generator is guaranteed to end with either a 'result' or 'error' message.
|
|
13975
|
+
*
|
|
13976
|
+
* For task-augmented requests, yields 'taskCreated' and 'taskStatus' messages
|
|
13977
|
+
* before the final result.
|
|
13978
|
+
*
|
|
13979
|
+
* @example
|
|
13980
|
+
* ```typescript
|
|
13981
|
+
* const stream = server.experimental.tasks.createMessageStream({
|
|
13982
|
+
* messages: [{ role: 'user', content: { type: 'text', text: 'Hello' } }],
|
|
13983
|
+
* maxTokens: 100
|
|
13984
|
+
* }, {
|
|
13985
|
+
* onprogress: (progress) => {
|
|
13986
|
+
* // Handle streaming tokens via progress notifications
|
|
13987
|
+
* console.log('Progress:', progress.message);
|
|
13988
|
+
* }
|
|
13989
|
+
* });
|
|
13990
|
+
*
|
|
13991
|
+
* for await (const message of stream) {
|
|
13992
|
+
* switch (message.type) {
|
|
13993
|
+
* case 'taskCreated':
|
|
13994
|
+
* console.log('Task created:', message.task.taskId);
|
|
13995
|
+
* break;
|
|
13996
|
+
* case 'taskStatus':
|
|
13997
|
+
* console.log('Task status:', message.task.status);
|
|
13998
|
+
* break;
|
|
13999
|
+
* case 'result':
|
|
14000
|
+
* console.log('Final result:', message.result);
|
|
14001
|
+
* break;
|
|
14002
|
+
* case 'error':
|
|
14003
|
+
* console.error('Error:', message.error);
|
|
14004
|
+
* break;
|
|
14005
|
+
* }
|
|
14006
|
+
* }
|
|
14007
|
+
* ```
|
|
14008
|
+
*
|
|
14009
|
+
* @param params - The sampling request parameters
|
|
14010
|
+
* @param options - Optional request options (timeout, signal, task creation params, onprogress, etc.)
|
|
14011
|
+
* @returns AsyncGenerator that yields ResponseMessage objects
|
|
14012
|
+
*
|
|
14013
|
+
* @experimental
|
|
14014
|
+
*/
|
|
14015
|
+
createMessageStream(params, options) {
|
|
14016
|
+
const clientCapabilities = this._server.getClientCapabilities();
|
|
14017
|
+
if ((params.tools || params.toolChoice) && !clientCapabilities?.sampling?.tools) {
|
|
14018
|
+
throw new Error("Client does not support sampling tools capability.");
|
|
14019
|
+
}
|
|
14020
|
+
if (params.messages.length > 0) {
|
|
14021
|
+
const lastMessage = params.messages[params.messages.length - 1];
|
|
14022
|
+
const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [lastMessage.content];
|
|
14023
|
+
const hasToolResults = lastContent.some((c) => c.type === "tool_result");
|
|
14024
|
+
const previousMessage = params.messages.length > 1 ? params.messages[params.messages.length - 2] : void 0;
|
|
14025
|
+
const previousContent = previousMessage ? Array.isArray(previousMessage.content) ? previousMessage.content : [previousMessage.content] : [];
|
|
14026
|
+
const hasPreviousToolUse = previousContent.some((c) => c.type === "tool_use");
|
|
14027
|
+
if (hasToolResults) {
|
|
14028
|
+
if (lastContent.some((c) => c.type !== "tool_result")) {
|
|
14029
|
+
throw new Error("The last message must contain only tool_result content if any is present");
|
|
14030
|
+
}
|
|
14031
|
+
if (!hasPreviousToolUse) {
|
|
14032
|
+
throw new Error("tool_result blocks are not matching any tool_use from the previous message");
|
|
14033
|
+
}
|
|
14034
|
+
}
|
|
14035
|
+
if (hasPreviousToolUse) {
|
|
14036
|
+
const toolUseIds = new Set(previousContent.filter((c) => c.type === "tool_use").map((c) => c.id));
|
|
14037
|
+
const toolResultIds = new Set(lastContent.filter((c) => c.type === "tool_result").map((c) => c.toolUseId));
|
|
14038
|
+
if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id) => toolResultIds.has(id))) {
|
|
14039
|
+
throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match");
|
|
14040
|
+
}
|
|
14041
|
+
}
|
|
14042
|
+
}
|
|
14043
|
+
return this.requestStream({
|
|
14044
|
+
method: "sampling/createMessage",
|
|
14045
|
+
params
|
|
14046
|
+
}, CreateMessageResultSchema, options);
|
|
14047
|
+
}
|
|
14048
|
+
/**
|
|
14049
|
+
* Sends an elicitation request and returns an AsyncGenerator that yields response messages.
|
|
14050
|
+
* The generator is guaranteed to end with either a 'result' or 'error' message.
|
|
14051
|
+
*
|
|
14052
|
+
* For task-augmented requests (especially URL-based elicitation), yields 'taskCreated'
|
|
14053
|
+
* and 'taskStatus' messages before the final result.
|
|
14054
|
+
*
|
|
14055
|
+
* @example
|
|
14056
|
+
* ```typescript
|
|
14057
|
+
* const stream = server.experimental.tasks.elicitInputStream({
|
|
14058
|
+
* mode: 'url',
|
|
14059
|
+
* message: 'Please authenticate',
|
|
14060
|
+
* elicitationId: 'auth-123',
|
|
14061
|
+
* url: 'https://example.com/auth'
|
|
14062
|
+
* }, {
|
|
14063
|
+
* task: { ttl: 300000 } // Task-augmented for long-running auth flow
|
|
14064
|
+
* });
|
|
14065
|
+
*
|
|
14066
|
+
* for await (const message of stream) {
|
|
14067
|
+
* switch (message.type) {
|
|
14068
|
+
* case 'taskCreated':
|
|
14069
|
+
* console.log('Task created:', message.task.taskId);
|
|
14070
|
+
* break;
|
|
14071
|
+
* case 'taskStatus':
|
|
14072
|
+
* console.log('Task status:', message.task.status);
|
|
14073
|
+
* break;
|
|
14074
|
+
* case 'result':
|
|
14075
|
+
* console.log('User action:', message.result.action);
|
|
14076
|
+
* break;
|
|
14077
|
+
* case 'error':
|
|
14078
|
+
* console.error('Error:', message.error);
|
|
14079
|
+
* break;
|
|
14080
|
+
* }
|
|
14081
|
+
* }
|
|
14082
|
+
* ```
|
|
14083
|
+
*
|
|
14084
|
+
* @param params - The elicitation request parameters
|
|
14085
|
+
* @param options - Optional request options (timeout, signal, task creation params, etc.)
|
|
14086
|
+
* @returns AsyncGenerator that yields ResponseMessage objects
|
|
14087
|
+
*
|
|
14088
|
+
* @experimental
|
|
14089
|
+
*/
|
|
14090
|
+
elicitInputStream(params, options) {
|
|
14091
|
+
const clientCapabilities = this._server.getClientCapabilities();
|
|
14092
|
+
const mode = params.mode ?? "form";
|
|
14093
|
+
switch (mode) {
|
|
14094
|
+
case "url": {
|
|
14095
|
+
if (!clientCapabilities?.elicitation?.url) {
|
|
14096
|
+
throw new Error("Client does not support url elicitation.");
|
|
14097
|
+
}
|
|
14098
|
+
break;
|
|
14099
|
+
}
|
|
14100
|
+
case "form": {
|
|
14101
|
+
if (!clientCapabilities?.elicitation?.form) {
|
|
14102
|
+
throw new Error("Client does not support form elicitation.");
|
|
14103
|
+
}
|
|
14104
|
+
break;
|
|
14105
|
+
}
|
|
14106
|
+
}
|
|
14107
|
+
const normalizedParams = mode === "form" && params.mode === void 0 ? { ...params, mode: "form" } : params;
|
|
14108
|
+
return this.requestStream({
|
|
14109
|
+
method: "elicitation/create",
|
|
14110
|
+
params: normalizedParams
|
|
14111
|
+
}, ElicitResultSchema, options);
|
|
14112
|
+
}
|
|
13972
14113
|
/**
|
|
13973
14114
|
* Gets the current status of a task.
|
|
13974
14115
|
*
|
|
@@ -16224,22 +16365,45 @@ async function auth(provider, options) {
|
|
|
16224
16365
|
}
|
|
16225
16366
|
}
|
|
16226
16367
|
async function authInternal(provider, { serverUrl, authorizationCode, scope, resourceMetadataUrl, fetchFn }) {
|
|
16368
|
+
const cachedState = await provider.discoveryState?.();
|
|
16227
16369
|
let resourceMetadata;
|
|
16228
16370
|
let authorizationServerUrl;
|
|
16229
|
-
|
|
16230
|
-
|
|
16231
|
-
|
|
16232
|
-
|
|
16371
|
+
let metadata;
|
|
16372
|
+
let effectiveResourceMetadataUrl = resourceMetadataUrl;
|
|
16373
|
+
if (!effectiveResourceMetadataUrl && cachedState?.resourceMetadataUrl) {
|
|
16374
|
+
effectiveResourceMetadataUrl = new URL(cachedState.resourceMetadataUrl);
|
|
16375
|
+
}
|
|
16376
|
+
if (cachedState?.authorizationServerUrl) {
|
|
16377
|
+
authorizationServerUrl = cachedState.authorizationServerUrl;
|
|
16378
|
+
resourceMetadata = cachedState.resourceMetadata;
|
|
16379
|
+
metadata = cachedState.authorizationServerMetadata ?? await discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn });
|
|
16380
|
+
if (!resourceMetadata) {
|
|
16381
|
+
try {
|
|
16382
|
+
resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl: effectiveResourceMetadataUrl }, fetchFn);
|
|
16383
|
+
} catch {
|
|
16384
|
+
}
|
|
16233
16385
|
}
|
|
16234
|
-
|
|
16235
|
-
|
|
16236
|
-
|
|
16237
|
-
|
|
16386
|
+
if (metadata !== cachedState.authorizationServerMetadata || resourceMetadata !== cachedState.resourceMetadata) {
|
|
16387
|
+
await provider.saveDiscoveryState?.({
|
|
16388
|
+
authorizationServerUrl: String(authorizationServerUrl),
|
|
16389
|
+
resourceMetadataUrl: effectiveResourceMetadataUrl?.toString(),
|
|
16390
|
+
resourceMetadata,
|
|
16391
|
+
authorizationServerMetadata: metadata
|
|
16392
|
+
});
|
|
16393
|
+
}
|
|
16394
|
+
} else {
|
|
16395
|
+
const serverInfo = await discoverOAuthServerInfo(serverUrl, { resourceMetadataUrl: effectiveResourceMetadataUrl, fetchFn });
|
|
16396
|
+
authorizationServerUrl = serverInfo.authorizationServerUrl;
|
|
16397
|
+
metadata = serverInfo.authorizationServerMetadata;
|
|
16398
|
+
resourceMetadata = serverInfo.resourceMetadata;
|
|
16399
|
+
await provider.saveDiscoveryState?.({
|
|
16400
|
+
authorizationServerUrl: String(authorizationServerUrl),
|
|
16401
|
+
resourceMetadataUrl: effectiveResourceMetadataUrl?.toString(),
|
|
16402
|
+
resourceMetadata,
|
|
16403
|
+
authorizationServerMetadata: metadata
|
|
16404
|
+
});
|
|
16238
16405
|
}
|
|
16239
16406
|
const resource = await selectResourceURL(serverUrl, provider, resourceMetadata);
|
|
16240
|
-
const metadata = await discoverAuthorizationServerMetadata(authorizationServerUrl, {
|
|
16241
|
-
fetchFn
|
|
16242
|
-
});
|
|
16243
16407
|
let clientInformation = await Promise.resolve(provider.clientInformation());
|
|
16244
16408
|
if (!clientInformation) {
|
|
16245
16409
|
if (authorizationCode !== void 0) {
|
|
@@ -16494,6 +16658,26 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl, { fet
|
|
|
16494
16658
|
}
|
|
16495
16659
|
return void 0;
|
|
16496
16660
|
}
|
|
16661
|
+
async function discoverOAuthServerInfo(serverUrl, opts) {
|
|
16662
|
+
let resourceMetadata;
|
|
16663
|
+
let authorizationServerUrl;
|
|
16664
|
+
try {
|
|
16665
|
+
resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl: opts?.resourceMetadataUrl }, opts?.fetchFn);
|
|
16666
|
+
if (resourceMetadata.authorization_servers && resourceMetadata.authorization_servers.length > 0) {
|
|
16667
|
+
authorizationServerUrl = resourceMetadata.authorization_servers[0];
|
|
16668
|
+
}
|
|
16669
|
+
} catch {
|
|
16670
|
+
}
|
|
16671
|
+
if (!authorizationServerUrl) {
|
|
16672
|
+
authorizationServerUrl = String(new URL("/", serverUrl));
|
|
16673
|
+
}
|
|
16674
|
+
const authorizationServerMetadata = await discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn: opts?.fetchFn });
|
|
16675
|
+
return {
|
|
16676
|
+
authorizationServerUrl,
|
|
16677
|
+
authorizationServerMetadata,
|
|
16678
|
+
resourceMetadata
|
|
16679
|
+
};
|
|
16680
|
+
}
|
|
16497
16681
|
async function startAuthorization(authorizationServerUrl, { metadata, clientInformation, redirectUrl, scope, state, resource }) {
|
|
16498
16682
|
let authorizationUrl;
|
|
16499
16683
|
if (metadata) {
|
|
@@ -17391,18 +17575,6 @@ var cleanToolSchema = (schema) => {
|
|
|
17391
17575
|
var import_node_process3 = require("node:process");
|
|
17392
17576
|
var import_node_process4 = __toESM(require("node:process"), 1);
|
|
17393
17577
|
var import_node_crypto = require("node:crypto");
|
|
17394
|
-
var mcpClientPool = /* @__PURE__ */ new Map();
|
|
17395
|
-
var mcpClientConnecting = /* @__PURE__ */ new Map();
|
|
17396
|
-
var shortHash = (s) => (0, import_node_crypto.createHash)("sha256").update(s).digest("hex").slice(0, 8);
|
|
17397
|
-
function defSignature(def) {
|
|
17398
|
-
const defCopy = {
|
|
17399
|
-
...def
|
|
17400
|
-
};
|
|
17401
|
-
if (defCopy.transportType === "memory" || defCopy.transport) {
|
|
17402
|
-
return `memory:${Date.now()}:${Math.random()}`;
|
|
17403
|
-
}
|
|
17404
|
-
return JSON.stringify(defCopy);
|
|
17405
|
-
}
|
|
17406
17578
|
function createTransport(def) {
|
|
17407
17579
|
const defAny = def;
|
|
17408
17580
|
const explicitType = defAny.transportType || defAny.type;
|
|
@@ -17450,90 +17622,43 @@ function createTransport(def) {
|
|
|
17450
17622
|
}
|
|
17451
17623
|
throw new Error(`Unsupported transport configuration: ${JSON.stringify(def)}`);
|
|
17452
17624
|
}
|
|
17453
|
-
|
|
17454
|
-
const
|
|
17455
|
-
|
|
17456
|
-
|
|
17457
|
-
|
|
17458
|
-
|
|
17459
|
-
const existingConnecting = mcpClientConnecting.get(defKey);
|
|
17460
|
-
if (existingConnecting) {
|
|
17461
|
-
const client = await existingConnecting;
|
|
17462
|
-
const entry = mcpClientPool.get(defKey);
|
|
17463
|
-
if (entry) entry.refCount += 1;
|
|
17464
|
-
return client;
|
|
17465
|
-
}
|
|
17466
|
-
const transport = createTransport(def);
|
|
17467
|
-
const connecting = (async () => {
|
|
17468
|
-
const client = new Client({
|
|
17469
|
-
name: `mcp_${shortHash(defSignature(def))}`,
|
|
17470
|
-
version: "1.0.0"
|
|
17471
|
-
});
|
|
17472
|
-
await client.connect(transport, {
|
|
17473
|
-
timeout: 6e4 * 10
|
|
17474
|
-
});
|
|
17475
|
-
return client;
|
|
17476
|
-
})();
|
|
17477
|
-
mcpClientConnecting.set(defKey, connecting);
|
|
17478
|
-
try {
|
|
17479
|
-
const client = await connecting;
|
|
17480
|
-
mcpClientPool.set(defKey, {
|
|
17481
|
-
client,
|
|
17482
|
-
refCount: 1
|
|
17483
|
-
});
|
|
17484
|
-
return client;
|
|
17485
|
-
} finally {
|
|
17486
|
-
mcpClientConnecting.delete(defKey);
|
|
17625
|
+
function defSignature(def) {
|
|
17626
|
+
const defCopy = {
|
|
17627
|
+
...def
|
|
17628
|
+
};
|
|
17629
|
+
if (defCopy.transportType === "memory" || defCopy.transport) {
|
|
17630
|
+
return `memory:${Date.now()}:${Math.random()}`;
|
|
17487
17631
|
}
|
|
17632
|
+
return JSON.stringify(defCopy);
|
|
17488
17633
|
}
|
|
17489
|
-
|
|
17490
|
-
|
|
17491
|
-
|
|
17492
|
-
|
|
17493
|
-
|
|
17494
|
-
|
|
17495
|
-
|
|
17496
|
-
|
|
17497
|
-
|
|
17498
|
-
|
|
17499
|
-
|
|
17500
|
-
}
|
|
17634
|
+
var shortHash = (s) => (0, import_node_crypto.createHash)("sha256").update(s).digest("hex").slice(0, 8);
|
|
17635
|
+
async function createMcpClient(def) {
|
|
17636
|
+
const transport = createTransport(def);
|
|
17637
|
+
const client = new Client({
|
|
17638
|
+
name: `mcp_${shortHash(defSignature(def))}`,
|
|
17639
|
+
version: "1.0.0"
|
|
17640
|
+
});
|
|
17641
|
+
await client.connect(transport, {
|
|
17642
|
+
timeout: 6e4 * 10
|
|
17643
|
+
});
|
|
17644
|
+
return client;
|
|
17501
17645
|
}
|
|
17502
|
-
var cleanupAllPooledClients = async () => {
|
|
17503
|
-
const entries = Array.from(mcpClientPool.entries());
|
|
17504
|
-
mcpClientPool.clear();
|
|
17505
|
-
await Promise.all(entries.map(async ([, { client }]) => {
|
|
17506
|
-
try {
|
|
17507
|
-
await client.close();
|
|
17508
|
-
} catch (err) {
|
|
17509
|
-
console.error("Error closing MCP client:", err);
|
|
17510
|
-
}
|
|
17511
|
-
}));
|
|
17512
|
-
};
|
|
17513
|
-
import_node_process4.default.once?.("exit", () => {
|
|
17514
|
-
cleanupAllPooledClients();
|
|
17515
|
-
});
|
|
17516
|
-
import_node_process4.default.once?.("SIGINT", () => {
|
|
17517
|
-
cleanupAllPooledClients().finally(() => import_node_process4.default.exit(0));
|
|
17518
|
-
});
|
|
17519
17646
|
async function composeMcpDepTools(mcpConfig, filterIn) {
|
|
17520
17647
|
const allTools = {};
|
|
17521
17648
|
const allClients = {};
|
|
17522
|
-
const
|
|
17649
|
+
const clientsToClose = [];
|
|
17523
17650
|
for (const [name, definition] of Object.entries(mcpConfig.mcpServers)) {
|
|
17524
17651
|
const def = definition;
|
|
17525
17652
|
if (def.disabled) continue;
|
|
17526
|
-
const defKey = shortHash(defSignature(def));
|
|
17527
|
-
const serverId = name;
|
|
17528
17653
|
try {
|
|
17529
|
-
const client = await
|
|
17530
|
-
|
|
17531
|
-
allClients[
|
|
17654
|
+
const client = await createMcpClient(def);
|
|
17655
|
+
clientsToClose.push(client);
|
|
17656
|
+
allClients[name] = client;
|
|
17532
17657
|
const { tools } = await client.listTools();
|
|
17533
17658
|
tools.forEach((tool2) => {
|
|
17534
17659
|
const toolNameWithScope = `${name}.${tool2.name}`;
|
|
17535
17660
|
const internalToolName = tool2.name;
|
|
17536
|
-
const rawToolId = `${
|
|
17661
|
+
const rawToolId = `${name}_${internalToolName}`;
|
|
17537
17662
|
const toolId = sanitizePropertyKey(rawToolId);
|
|
17538
17663
|
if (filterIn && !filterIn({
|
|
17539
17664
|
action: internalToolName,
|
|
@@ -17545,7 +17670,7 @@ async function composeMcpDepTools(mcpConfig, filterIn) {
|
|
|
17545
17670
|
})) {
|
|
17546
17671
|
return;
|
|
17547
17672
|
}
|
|
17548
|
-
const execute = (args) => allClients[
|
|
17673
|
+
const execute = (args) => allClients[name].callTool({
|
|
17549
17674
|
name: internalToolName,
|
|
17550
17675
|
arguments: args
|
|
17551
17676
|
}, void 0, {
|
|
@@ -17562,10 +17687,12 @@ async function composeMcpDepTools(mcpConfig, filterIn) {
|
|
|
17562
17687
|
}
|
|
17563
17688
|
}
|
|
17564
17689
|
const cleanupClients = async () => {
|
|
17565
|
-
await Promise.all(
|
|
17566
|
-
|
|
17567
|
-
|
|
17568
|
-
|
|
17690
|
+
await Promise.all(clientsToClose.map((client) => {
|
|
17691
|
+
try {
|
|
17692
|
+
return client.close();
|
|
17693
|
+
} catch {
|
|
17694
|
+
}
|
|
17695
|
+
}));
|
|
17569
17696
|
};
|
|
17570
17697
|
return {
|
|
17571
17698
|
tools: allTools,
|
package/index.mjs
CHANGED
|
@@ -13957,6 +13957,147 @@ var ExperimentalServerTasks = class {
|
|
|
13957
13957
|
requestStream(request, resultSchema, options) {
|
|
13958
13958
|
return this._server.requestStream(request, resultSchema, options);
|
|
13959
13959
|
}
|
|
13960
|
+
/**
|
|
13961
|
+
* Sends a sampling request and returns an AsyncGenerator that yields response messages.
|
|
13962
|
+
* The generator is guaranteed to end with either a 'result' or 'error' message.
|
|
13963
|
+
*
|
|
13964
|
+
* For task-augmented requests, yields 'taskCreated' and 'taskStatus' messages
|
|
13965
|
+
* before the final result.
|
|
13966
|
+
*
|
|
13967
|
+
* @example
|
|
13968
|
+
* ```typescript
|
|
13969
|
+
* const stream = server.experimental.tasks.createMessageStream({
|
|
13970
|
+
* messages: [{ role: 'user', content: { type: 'text', text: 'Hello' } }],
|
|
13971
|
+
* maxTokens: 100
|
|
13972
|
+
* }, {
|
|
13973
|
+
* onprogress: (progress) => {
|
|
13974
|
+
* // Handle streaming tokens via progress notifications
|
|
13975
|
+
* console.log('Progress:', progress.message);
|
|
13976
|
+
* }
|
|
13977
|
+
* });
|
|
13978
|
+
*
|
|
13979
|
+
* for await (const message of stream) {
|
|
13980
|
+
* switch (message.type) {
|
|
13981
|
+
* case 'taskCreated':
|
|
13982
|
+
* console.log('Task created:', message.task.taskId);
|
|
13983
|
+
* break;
|
|
13984
|
+
* case 'taskStatus':
|
|
13985
|
+
* console.log('Task status:', message.task.status);
|
|
13986
|
+
* break;
|
|
13987
|
+
* case 'result':
|
|
13988
|
+
* console.log('Final result:', message.result);
|
|
13989
|
+
* break;
|
|
13990
|
+
* case 'error':
|
|
13991
|
+
* console.error('Error:', message.error);
|
|
13992
|
+
* break;
|
|
13993
|
+
* }
|
|
13994
|
+
* }
|
|
13995
|
+
* ```
|
|
13996
|
+
*
|
|
13997
|
+
* @param params - The sampling request parameters
|
|
13998
|
+
* @param options - Optional request options (timeout, signal, task creation params, onprogress, etc.)
|
|
13999
|
+
* @returns AsyncGenerator that yields ResponseMessage objects
|
|
14000
|
+
*
|
|
14001
|
+
* @experimental
|
|
14002
|
+
*/
|
|
14003
|
+
createMessageStream(params, options) {
|
|
14004
|
+
const clientCapabilities = this._server.getClientCapabilities();
|
|
14005
|
+
if ((params.tools || params.toolChoice) && !clientCapabilities?.sampling?.tools) {
|
|
14006
|
+
throw new Error("Client does not support sampling tools capability.");
|
|
14007
|
+
}
|
|
14008
|
+
if (params.messages.length > 0) {
|
|
14009
|
+
const lastMessage = params.messages[params.messages.length - 1];
|
|
14010
|
+
const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [lastMessage.content];
|
|
14011
|
+
const hasToolResults = lastContent.some((c) => c.type === "tool_result");
|
|
14012
|
+
const previousMessage = params.messages.length > 1 ? params.messages[params.messages.length - 2] : void 0;
|
|
14013
|
+
const previousContent = previousMessage ? Array.isArray(previousMessage.content) ? previousMessage.content : [previousMessage.content] : [];
|
|
14014
|
+
const hasPreviousToolUse = previousContent.some((c) => c.type === "tool_use");
|
|
14015
|
+
if (hasToolResults) {
|
|
14016
|
+
if (lastContent.some((c) => c.type !== "tool_result")) {
|
|
14017
|
+
throw new Error("The last message must contain only tool_result content if any is present");
|
|
14018
|
+
}
|
|
14019
|
+
if (!hasPreviousToolUse) {
|
|
14020
|
+
throw new Error("tool_result blocks are not matching any tool_use from the previous message");
|
|
14021
|
+
}
|
|
14022
|
+
}
|
|
14023
|
+
if (hasPreviousToolUse) {
|
|
14024
|
+
const toolUseIds = new Set(previousContent.filter((c) => c.type === "tool_use").map((c) => c.id));
|
|
14025
|
+
const toolResultIds = new Set(lastContent.filter((c) => c.type === "tool_result").map((c) => c.toolUseId));
|
|
14026
|
+
if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id) => toolResultIds.has(id))) {
|
|
14027
|
+
throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match");
|
|
14028
|
+
}
|
|
14029
|
+
}
|
|
14030
|
+
}
|
|
14031
|
+
return this.requestStream({
|
|
14032
|
+
method: "sampling/createMessage",
|
|
14033
|
+
params
|
|
14034
|
+
}, CreateMessageResultSchema, options);
|
|
14035
|
+
}
|
|
14036
|
+
/**
|
|
14037
|
+
* Sends an elicitation request and returns an AsyncGenerator that yields response messages.
|
|
14038
|
+
* The generator is guaranteed to end with either a 'result' or 'error' message.
|
|
14039
|
+
*
|
|
14040
|
+
* For task-augmented requests (especially URL-based elicitation), yields 'taskCreated'
|
|
14041
|
+
* and 'taskStatus' messages before the final result.
|
|
14042
|
+
*
|
|
14043
|
+
* @example
|
|
14044
|
+
* ```typescript
|
|
14045
|
+
* const stream = server.experimental.tasks.elicitInputStream({
|
|
14046
|
+
* mode: 'url',
|
|
14047
|
+
* message: 'Please authenticate',
|
|
14048
|
+
* elicitationId: 'auth-123',
|
|
14049
|
+
* url: 'https://example.com/auth'
|
|
14050
|
+
* }, {
|
|
14051
|
+
* task: { ttl: 300000 } // Task-augmented for long-running auth flow
|
|
14052
|
+
* });
|
|
14053
|
+
*
|
|
14054
|
+
* for await (const message of stream) {
|
|
14055
|
+
* switch (message.type) {
|
|
14056
|
+
* case 'taskCreated':
|
|
14057
|
+
* console.log('Task created:', message.task.taskId);
|
|
14058
|
+
* break;
|
|
14059
|
+
* case 'taskStatus':
|
|
14060
|
+
* console.log('Task status:', message.task.status);
|
|
14061
|
+
* break;
|
|
14062
|
+
* case 'result':
|
|
14063
|
+
* console.log('User action:', message.result.action);
|
|
14064
|
+
* break;
|
|
14065
|
+
* case 'error':
|
|
14066
|
+
* console.error('Error:', message.error);
|
|
14067
|
+
* break;
|
|
14068
|
+
* }
|
|
14069
|
+
* }
|
|
14070
|
+
* ```
|
|
14071
|
+
*
|
|
14072
|
+
* @param params - The elicitation request parameters
|
|
14073
|
+
* @param options - Optional request options (timeout, signal, task creation params, etc.)
|
|
14074
|
+
* @returns AsyncGenerator that yields ResponseMessage objects
|
|
14075
|
+
*
|
|
14076
|
+
* @experimental
|
|
14077
|
+
*/
|
|
14078
|
+
elicitInputStream(params, options) {
|
|
14079
|
+
const clientCapabilities = this._server.getClientCapabilities();
|
|
14080
|
+
const mode = params.mode ?? "form";
|
|
14081
|
+
switch (mode) {
|
|
14082
|
+
case "url": {
|
|
14083
|
+
if (!clientCapabilities?.elicitation?.url) {
|
|
14084
|
+
throw new Error("Client does not support url elicitation.");
|
|
14085
|
+
}
|
|
14086
|
+
break;
|
|
14087
|
+
}
|
|
14088
|
+
case "form": {
|
|
14089
|
+
if (!clientCapabilities?.elicitation?.form) {
|
|
14090
|
+
throw new Error("Client does not support form elicitation.");
|
|
14091
|
+
}
|
|
14092
|
+
break;
|
|
14093
|
+
}
|
|
14094
|
+
}
|
|
14095
|
+
const normalizedParams = mode === "form" && params.mode === void 0 ? { ...params, mode: "form" } : params;
|
|
14096
|
+
return this.requestStream({
|
|
14097
|
+
method: "elicitation/create",
|
|
14098
|
+
params: normalizedParams
|
|
14099
|
+
}, ElicitResultSchema, options);
|
|
14100
|
+
}
|
|
13960
14101
|
/**
|
|
13961
14102
|
* Gets the current status of a task.
|
|
13962
14103
|
*
|
|
@@ -16212,22 +16353,45 @@ async function auth(provider, options) {
|
|
|
16212
16353
|
}
|
|
16213
16354
|
}
|
|
16214
16355
|
async function authInternal(provider, { serverUrl, authorizationCode, scope, resourceMetadataUrl, fetchFn }) {
|
|
16356
|
+
const cachedState = await provider.discoveryState?.();
|
|
16215
16357
|
let resourceMetadata;
|
|
16216
16358
|
let authorizationServerUrl;
|
|
16217
|
-
|
|
16218
|
-
|
|
16219
|
-
|
|
16220
|
-
|
|
16359
|
+
let metadata;
|
|
16360
|
+
let effectiveResourceMetadataUrl = resourceMetadataUrl;
|
|
16361
|
+
if (!effectiveResourceMetadataUrl && cachedState?.resourceMetadataUrl) {
|
|
16362
|
+
effectiveResourceMetadataUrl = new URL(cachedState.resourceMetadataUrl);
|
|
16363
|
+
}
|
|
16364
|
+
if (cachedState?.authorizationServerUrl) {
|
|
16365
|
+
authorizationServerUrl = cachedState.authorizationServerUrl;
|
|
16366
|
+
resourceMetadata = cachedState.resourceMetadata;
|
|
16367
|
+
metadata = cachedState.authorizationServerMetadata ?? await discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn });
|
|
16368
|
+
if (!resourceMetadata) {
|
|
16369
|
+
try {
|
|
16370
|
+
resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl: effectiveResourceMetadataUrl }, fetchFn);
|
|
16371
|
+
} catch {
|
|
16372
|
+
}
|
|
16221
16373
|
}
|
|
16222
|
-
|
|
16223
|
-
|
|
16224
|
-
|
|
16225
|
-
|
|
16374
|
+
if (metadata !== cachedState.authorizationServerMetadata || resourceMetadata !== cachedState.resourceMetadata) {
|
|
16375
|
+
await provider.saveDiscoveryState?.({
|
|
16376
|
+
authorizationServerUrl: String(authorizationServerUrl),
|
|
16377
|
+
resourceMetadataUrl: effectiveResourceMetadataUrl?.toString(),
|
|
16378
|
+
resourceMetadata,
|
|
16379
|
+
authorizationServerMetadata: metadata
|
|
16380
|
+
});
|
|
16381
|
+
}
|
|
16382
|
+
} else {
|
|
16383
|
+
const serverInfo = await discoverOAuthServerInfo(serverUrl, { resourceMetadataUrl: effectiveResourceMetadataUrl, fetchFn });
|
|
16384
|
+
authorizationServerUrl = serverInfo.authorizationServerUrl;
|
|
16385
|
+
metadata = serverInfo.authorizationServerMetadata;
|
|
16386
|
+
resourceMetadata = serverInfo.resourceMetadata;
|
|
16387
|
+
await provider.saveDiscoveryState?.({
|
|
16388
|
+
authorizationServerUrl: String(authorizationServerUrl),
|
|
16389
|
+
resourceMetadataUrl: effectiveResourceMetadataUrl?.toString(),
|
|
16390
|
+
resourceMetadata,
|
|
16391
|
+
authorizationServerMetadata: metadata
|
|
16392
|
+
});
|
|
16226
16393
|
}
|
|
16227
16394
|
const resource = await selectResourceURL(serverUrl, provider, resourceMetadata);
|
|
16228
|
-
const metadata = await discoverAuthorizationServerMetadata(authorizationServerUrl, {
|
|
16229
|
-
fetchFn
|
|
16230
|
-
});
|
|
16231
16395
|
let clientInformation = await Promise.resolve(provider.clientInformation());
|
|
16232
16396
|
if (!clientInformation) {
|
|
16233
16397
|
if (authorizationCode !== void 0) {
|
|
@@ -16482,6 +16646,26 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl, { fet
|
|
|
16482
16646
|
}
|
|
16483
16647
|
return void 0;
|
|
16484
16648
|
}
|
|
16649
|
+
async function discoverOAuthServerInfo(serverUrl, opts) {
|
|
16650
|
+
let resourceMetadata;
|
|
16651
|
+
let authorizationServerUrl;
|
|
16652
|
+
try {
|
|
16653
|
+
resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl: opts?.resourceMetadataUrl }, opts?.fetchFn);
|
|
16654
|
+
if (resourceMetadata.authorization_servers && resourceMetadata.authorization_servers.length > 0) {
|
|
16655
|
+
authorizationServerUrl = resourceMetadata.authorization_servers[0];
|
|
16656
|
+
}
|
|
16657
|
+
} catch {
|
|
16658
|
+
}
|
|
16659
|
+
if (!authorizationServerUrl) {
|
|
16660
|
+
authorizationServerUrl = String(new URL("/", serverUrl));
|
|
16661
|
+
}
|
|
16662
|
+
const authorizationServerMetadata = await discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn: opts?.fetchFn });
|
|
16663
|
+
return {
|
|
16664
|
+
authorizationServerUrl,
|
|
16665
|
+
authorizationServerMetadata,
|
|
16666
|
+
resourceMetadata
|
|
16667
|
+
};
|
|
16668
|
+
}
|
|
16485
16669
|
async function startAuthorization(authorizationServerUrl, { metadata, clientInformation, redirectUrl, scope, state, resource }) {
|
|
16486
16670
|
let authorizationUrl;
|
|
16487
16671
|
if (metadata) {
|
|
@@ -17379,18 +17563,6 @@ var cleanToolSchema = (schema) => {
|
|
|
17379
17563
|
import { cwd } from "node:process";
|
|
17380
17564
|
import process5 from "node:process";
|
|
17381
17565
|
import { createHash } from "node:crypto";
|
|
17382
|
-
var mcpClientPool = /* @__PURE__ */ new Map();
|
|
17383
|
-
var mcpClientConnecting = /* @__PURE__ */ new Map();
|
|
17384
|
-
var shortHash = (s) => createHash("sha256").update(s).digest("hex").slice(0, 8);
|
|
17385
|
-
function defSignature(def) {
|
|
17386
|
-
const defCopy = {
|
|
17387
|
-
...def
|
|
17388
|
-
};
|
|
17389
|
-
if (defCopy.transportType === "memory" || defCopy.transport) {
|
|
17390
|
-
return `memory:${Date.now()}:${Math.random()}`;
|
|
17391
|
-
}
|
|
17392
|
-
return JSON.stringify(defCopy);
|
|
17393
|
-
}
|
|
17394
17566
|
function createTransport(def) {
|
|
17395
17567
|
const defAny = def;
|
|
17396
17568
|
const explicitType = defAny.transportType || defAny.type;
|
|
@@ -17438,90 +17610,43 @@ function createTransport(def) {
|
|
|
17438
17610
|
}
|
|
17439
17611
|
throw new Error(`Unsupported transport configuration: ${JSON.stringify(def)}`);
|
|
17440
17612
|
}
|
|
17441
|
-
|
|
17442
|
-
const
|
|
17443
|
-
|
|
17444
|
-
|
|
17445
|
-
|
|
17446
|
-
|
|
17447
|
-
const existingConnecting = mcpClientConnecting.get(defKey);
|
|
17448
|
-
if (existingConnecting) {
|
|
17449
|
-
const client = await existingConnecting;
|
|
17450
|
-
const entry = mcpClientPool.get(defKey);
|
|
17451
|
-
if (entry) entry.refCount += 1;
|
|
17452
|
-
return client;
|
|
17453
|
-
}
|
|
17454
|
-
const transport = createTransport(def);
|
|
17455
|
-
const connecting = (async () => {
|
|
17456
|
-
const client = new Client({
|
|
17457
|
-
name: `mcp_${shortHash(defSignature(def))}`,
|
|
17458
|
-
version: "1.0.0"
|
|
17459
|
-
});
|
|
17460
|
-
await client.connect(transport, {
|
|
17461
|
-
timeout: 6e4 * 10
|
|
17462
|
-
});
|
|
17463
|
-
return client;
|
|
17464
|
-
})();
|
|
17465
|
-
mcpClientConnecting.set(defKey, connecting);
|
|
17466
|
-
try {
|
|
17467
|
-
const client = await connecting;
|
|
17468
|
-
mcpClientPool.set(defKey, {
|
|
17469
|
-
client,
|
|
17470
|
-
refCount: 1
|
|
17471
|
-
});
|
|
17472
|
-
return client;
|
|
17473
|
-
} finally {
|
|
17474
|
-
mcpClientConnecting.delete(defKey);
|
|
17613
|
+
function defSignature(def) {
|
|
17614
|
+
const defCopy = {
|
|
17615
|
+
...def
|
|
17616
|
+
};
|
|
17617
|
+
if (defCopy.transportType === "memory" || defCopy.transport) {
|
|
17618
|
+
return `memory:${Date.now()}:${Math.random()}`;
|
|
17475
17619
|
}
|
|
17620
|
+
return JSON.stringify(defCopy);
|
|
17476
17621
|
}
|
|
17477
|
-
|
|
17478
|
-
|
|
17479
|
-
|
|
17480
|
-
|
|
17481
|
-
|
|
17482
|
-
|
|
17483
|
-
|
|
17484
|
-
|
|
17485
|
-
|
|
17486
|
-
|
|
17487
|
-
|
|
17488
|
-
}
|
|
17622
|
+
var shortHash = (s) => createHash("sha256").update(s).digest("hex").slice(0, 8);
|
|
17623
|
+
async function createMcpClient(def) {
|
|
17624
|
+
const transport = createTransport(def);
|
|
17625
|
+
const client = new Client({
|
|
17626
|
+
name: `mcp_${shortHash(defSignature(def))}`,
|
|
17627
|
+
version: "1.0.0"
|
|
17628
|
+
});
|
|
17629
|
+
await client.connect(transport, {
|
|
17630
|
+
timeout: 6e4 * 10
|
|
17631
|
+
});
|
|
17632
|
+
return client;
|
|
17489
17633
|
}
|
|
17490
|
-
var cleanupAllPooledClients = async () => {
|
|
17491
|
-
const entries = Array.from(mcpClientPool.entries());
|
|
17492
|
-
mcpClientPool.clear();
|
|
17493
|
-
await Promise.all(entries.map(async ([, { client }]) => {
|
|
17494
|
-
try {
|
|
17495
|
-
await client.close();
|
|
17496
|
-
} catch (err) {
|
|
17497
|
-
console.error("Error closing MCP client:", err);
|
|
17498
|
-
}
|
|
17499
|
-
}));
|
|
17500
|
-
};
|
|
17501
|
-
process5.once?.("exit", () => {
|
|
17502
|
-
cleanupAllPooledClients();
|
|
17503
|
-
});
|
|
17504
|
-
process5.once?.("SIGINT", () => {
|
|
17505
|
-
cleanupAllPooledClients().finally(() => process5.exit(0));
|
|
17506
|
-
});
|
|
17507
17634
|
async function composeMcpDepTools(mcpConfig, filterIn) {
|
|
17508
17635
|
const allTools = {};
|
|
17509
17636
|
const allClients = {};
|
|
17510
|
-
const
|
|
17637
|
+
const clientsToClose = [];
|
|
17511
17638
|
for (const [name, definition] of Object.entries(mcpConfig.mcpServers)) {
|
|
17512
17639
|
const def = definition;
|
|
17513
17640
|
if (def.disabled) continue;
|
|
17514
|
-
const defKey = shortHash(defSignature(def));
|
|
17515
|
-
const serverId = name;
|
|
17516
17641
|
try {
|
|
17517
|
-
const client = await
|
|
17518
|
-
|
|
17519
|
-
allClients[
|
|
17642
|
+
const client = await createMcpClient(def);
|
|
17643
|
+
clientsToClose.push(client);
|
|
17644
|
+
allClients[name] = client;
|
|
17520
17645
|
const { tools } = await client.listTools();
|
|
17521
17646
|
tools.forEach((tool2) => {
|
|
17522
17647
|
const toolNameWithScope = `${name}.${tool2.name}`;
|
|
17523
17648
|
const internalToolName = tool2.name;
|
|
17524
|
-
const rawToolId = `${
|
|
17649
|
+
const rawToolId = `${name}_${internalToolName}`;
|
|
17525
17650
|
const toolId = sanitizePropertyKey(rawToolId);
|
|
17526
17651
|
if (filterIn && !filterIn({
|
|
17527
17652
|
action: internalToolName,
|
|
@@ -17533,7 +17658,7 @@ async function composeMcpDepTools(mcpConfig, filterIn) {
|
|
|
17533
17658
|
})) {
|
|
17534
17659
|
return;
|
|
17535
17660
|
}
|
|
17536
|
-
const execute = (args) => allClients[
|
|
17661
|
+
const execute = (args) => allClients[name].callTool({
|
|
17537
17662
|
name: internalToolName,
|
|
17538
17663
|
arguments: args
|
|
17539
17664
|
}, void 0, {
|
|
@@ -17550,10 +17675,12 @@ async function composeMcpDepTools(mcpConfig, filterIn) {
|
|
|
17550
17675
|
}
|
|
17551
17676
|
}
|
|
17552
17677
|
const cleanupClients = async () => {
|
|
17553
|
-
await Promise.all(
|
|
17554
|
-
|
|
17555
|
-
|
|
17556
|
-
|
|
17678
|
+
await Promise.all(clientsToClose.map((client) => {
|
|
17679
|
+
try {
|
|
17680
|
+
return client.close();
|
|
17681
|
+
} catch {
|
|
17682
|
+
}
|
|
17683
|
+
}));
|
|
17557
17684
|
};
|
|
17558
17685
|
return {
|
|
17559
17686
|
tools: allTools,
|
package/package.json
CHANGED
package/plugins/skills.cjs
CHANGED
|
@@ -105,7 +105,7 @@ Usage:
|
|
|
105
105
|
- ${toolName}({ skill: "skill-name" }) - Load main SKILL.md content
|
|
106
106
|
- ${toolName}({ skill: "skill-name", ref: "path/to/file" }) - Load reference file
|
|
107
107
|
|
|
108
|
-
Note: For scripts
|
|
108
|
+
Note: For scripts/, use the bash tool with the script path to execute.`;
|
|
109
109
|
}
|
|
110
110
|
function createSkillsPlugin(options) {
|
|
111
111
|
const { paths } = options;
|
|
@@ -205,7 +205,13 @@ Available skills: ${available.join(", ")}` : "\n\nNo skills available.";
|
|
|
205
205
|
"utf-8"
|
|
206
206
|
);
|
|
207
207
|
const body = extractBody(content);
|
|
208
|
-
|
|
208
|
+
const skillPathInfo = `
|
|
209
|
+
---
|
|
210
|
+
Skill path: ${meta.basePath}
|
|
211
|
+
`;
|
|
212
|
+
return {
|
|
213
|
+
content: [{ type: "text", text: body + skillPathInfo }]
|
|
214
|
+
};
|
|
209
215
|
} catch {
|
|
210
216
|
return {
|
|
211
217
|
content: [
|
package/plugins/skills.mjs
CHANGED
|
@@ -83,7 +83,7 @@ Usage:
|
|
|
83
83
|
- ${toolName}({ skill: "skill-name" }) - Load main SKILL.md content
|
|
84
84
|
- ${toolName}({ skill: "skill-name", ref: "path/to/file" }) - Load reference file
|
|
85
85
|
|
|
86
|
-
Note: For scripts
|
|
86
|
+
Note: For scripts/, use the bash tool with the script path to execute.`;
|
|
87
87
|
}
|
|
88
88
|
function createSkillsPlugin(options) {
|
|
89
89
|
const { paths } = options;
|
|
@@ -183,7 +183,13 @@ Available skills: ${available.join(", ")}` : "\n\nNo skills available.";
|
|
|
183
183
|
"utf-8"
|
|
184
184
|
);
|
|
185
185
|
const body = extractBody(content);
|
|
186
|
-
|
|
186
|
+
const skillPathInfo = `
|
|
187
|
+
---
|
|
188
|
+
Skill path: ${meta.basePath}
|
|
189
|
+
`;
|
|
190
|
+
return {
|
|
191
|
+
content: [{ type: "text", text: body + skillPathInfo }]
|
|
192
|
+
};
|
|
187
193
|
} catch {
|
|
188
194
|
return {
|
|
189
195
|
content: [
|
package/plugins.cjs
CHANGED
|
@@ -29,6 +29,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
29
29
|
// __mcpc__core_latest/node_modules/@mcpc/core/plugins.ts
|
|
30
30
|
var plugins_exports = {};
|
|
31
31
|
__export(plugins_exports, {
|
|
32
|
+
createBashPlugin: () => createBashPlugin,
|
|
32
33
|
createLargeResultPlugin: () => createLargeResultPlugin,
|
|
33
34
|
createSearchPlugin: () => createSearchPlugin,
|
|
34
35
|
createSkillsPlugin: () => createSkillsPlugin,
|
|
@@ -447,7 +448,7 @@ Usage:
|
|
|
447
448
|
- ${toolName}({ skill: "skill-name" }) - Load main SKILL.md content
|
|
448
449
|
- ${toolName}({ skill: "skill-name", ref: "path/to/file" }) - Load reference file
|
|
449
450
|
|
|
450
|
-
Note: For scripts
|
|
451
|
+
Note: For scripts/, use the bash tool with the script path to execute.`;
|
|
451
452
|
}
|
|
452
453
|
function createSkillsPlugin(options) {
|
|
453
454
|
const { paths } = options;
|
|
@@ -555,11 +556,15 @@ Available skills: ${available.join(", ")}` : "\n\nNo skills available.";
|
|
|
555
556
|
try {
|
|
556
557
|
const content = await (0, import_promises2.readFile)((0, import_node_path4.join)(meta.basePath, "SKILL.md"), "utf-8");
|
|
557
558
|
const body = extractBody(content);
|
|
559
|
+
const skillPathInfo = `
|
|
560
|
+
---
|
|
561
|
+
Skill path: ${meta.basePath}
|
|
562
|
+
`;
|
|
558
563
|
return {
|
|
559
564
|
content: [
|
|
560
565
|
{
|
|
561
566
|
type: "text",
|
|
562
|
-
text: body
|
|
567
|
+
text: body + skillPathInfo
|
|
563
568
|
}
|
|
564
569
|
]
|
|
565
570
|
};
|
|
@@ -585,8 +590,147 @@ Available skills: ${available.join(", ")}` : "\n\nNo skills available.";
|
|
|
585
590
|
}
|
|
586
591
|
};
|
|
587
592
|
}
|
|
593
|
+
|
|
594
|
+
// __mcpc__core_latest/node_modules/@mcpc/core/src/plugins/bash.js
|
|
595
|
+
var import_node_child_process = require("node:child_process");
|
|
596
|
+
var import_node_process = __toESM(require("node:process"), 1);
|
|
597
|
+
var DEFAULT_MAX_BYTES = 1e5;
|
|
598
|
+
var DEFAULT_MAX_LINES = 2e3;
|
|
599
|
+
var DEFAULT_TIMEOUT_MS = 6e4;
|
|
600
|
+
function truncateOutput(stdout, stderr, maxBytes = DEFAULT_MAX_BYTES, maxLines = DEFAULT_MAX_LINES) {
|
|
601
|
+
const fullOutput = (stderr ? `STDERR:
|
|
602
|
+
${stderr}
|
|
603
|
+
|
|
604
|
+
STDOUT:
|
|
605
|
+
` : "") + stdout;
|
|
606
|
+
const lines = fullOutput.split("\n");
|
|
607
|
+
if (lines.length > maxLines) {
|
|
608
|
+
const truncatedLines = lines.slice(-maxLines);
|
|
609
|
+
return {
|
|
610
|
+
output: `[OUTPUT TRUNCATED] Showing last ${maxLines} lines of ${lines.length} total
|
|
611
|
+
|
|
612
|
+
` + truncatedLines.join("\n"),
|
|
613
|
+
truncated: true
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
if (fullOutput.length > maxBytes) {
|
|
617
|
+
const truncatedBytes = fullOutput.slice(-maxBytes);
|
|
618
|
+
return {
|
|
619
|
+
output: `[OUTPUT TRUNCATED] Showing last ${maxBytes} bytes of ${fullOutput.length} total
|
|
620
|
+
|
|
621
|
+
` + truncatedBytes,
|
|
622
|
+
truncated: true
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
return {
|
|
626
|
+
output: fullOutput,
|
|
627
|
+
truncated: false
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
function executeBash(command, cwd, timeoutMs) {
|
|
631
|
+
return new Promise((resolve3) => {
|
|
632
|
+
const stdout = [];
|
|
633
|
+
const stderr = [];
|
|
634
|
+
const proc = (0, import_node_child_process.spawn)("bash", [
|
|
635
|
+
"-c",
|
|
636
|
+
command
|
|
637
|
+
], {
|
|
638
|
+
cwd,
|
|
639
|
+
stdio: [
|
|
640
|
+
"ignore",
|
|
641
|
+
"pipe",
|
|
642
|
+
"pipe"
|
|
643
|
+
]
|
|
644
|
+
});
|
|
645
|
+
proc.stdout?.on("data", (data) => {
|
|
646
|
+
stdout.push(data.toString());
|
|
647
|
+
});
|
|
648
|
+
proc.stderr?.on("data", (data) => {
|
|
649
|
+
stderr.push(data.toString());
|
|
650
|
+
});
|
|
651
|
+
proc.on("close", (code) => {
|
|
652
|
+
resolve3({
|
|
653
|
+
stdout: stdout.join(""),
|
|
654
|
+
stderr: stderr.join(""),
|
|
655
|
+
exitCode: code
|
|
656
|
+
});
|
|
657
|
+
});
|
|
658
|
+
proc.on("error", (err) => {
|
|
659
|
+
resolve3({
|
|
660
|
+
stdout: "",
|
|
661
|
+
stderr: err.message,
|
|
662
|
+
exitCode: null
|
|
663
|
+
});
|
|
664
|
+
});
|
|
665
|
+
setTimeout(() => {
|
|
666
|
+
proc.kill("SIGTERM");
|
|
667
|
+
resolve3({
|
|
668
|
+
stdout: stdout.join(""),
|
|
669
|
+
stderr: stderr.join("") + "\n\n[TIMEOUT] Command execution timed out",
|
|
670
|
+
exitCode: null
|
|
671
|
+
});
|
|
672
|
+
}, timeoutMs);
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
function createBashPlugin(options = {}) {
|
|
676
|
+
const { maxBytes, maxLines, timeoutMs } = {
|
|
677
|
+
maxBytes: DEFAULT_MAX_BYTES,
|
|
678
|
+
maxLines: DEFAULT_MAX_LINES,
|
|
679
|
+
timeoutMs: DEFAULT_TIMEOUT_MS,
|
|
680
|
+
...options
|
|
681
|
+
};
|
|
682
|
+
return {
|
|
683
|
+
name: "plugin-bash",
|
|
684
|
+
version: "1.0.0",
|
|
685
|
+
// Store server reference for tool registration
|
|
686
|
+
configureServer: (server) => {
|
|
687
|
+
server.tool("bash", "Execute a bash command and return its output.\n\nUse this for:\n- Running shell commands\n- Executing scripts\n- System operations\n\nNote: Output is truncated if too large.", {
|
|
688
|
+
type: "object",
|
|
689
|
+
properties: {
|
|
690
|
+
command: {
|
|
691
|
+
type: "string",
|
|
692
|
+
description: "The bash command to execute"
|
|
693
|
+
},
|
|
694
|
+
cwd: {
|
|
695
|
+
type: "string",
|
|
696
|
+
description: "Optional: Working directory for the command (defaults to current directory)"
|
|
697
|
+
}
|
|
698
|
+
},
|
|
699
|
+
required: [
|
|
700
|
+
"command"
|
|
701
|
+
]
|
|
702
|
+
}, async (args) => {
|
|
703
|
+
const cwd = args.cwd || import_node_process.default.cwd();
|
|
704
|
+
const result = await executeBash(args.command, cwd, timeoutMs);
|
|
705
|
+
const { output, truncated } = truncateOutput(result.stdout, result.stderr, maxBytes, maxLines);
|
|
706
|
+
let finalOutput = output;
|
|
707
|
+
if (result.exitCode !== null && result.exitCode !== 0) {
|
|
708
|
+
finalOutput = `[EXIT CODE: ${result.exitCode}]
|
|
709
|
+
` + finalOutput;
|
|
710
|
+
}
|
|
711
|
+
if (truncated) {
|
|
712
|
+
finalOutput += `
|
|
713
|
+
|
|
714
|
+
[Note: Output was truncated]`;
|
|
715
|
+
}
|
|
716
|
+
return {
|
|
717
|
+
content: [
|
|
718
|
+
{
|
|
719
|
+
type: "text",
|
|
720
|
+
text: finalOutput
|
|
721
|
+
}
|
|
722
|
+
],
|
|
723
|
+
isError: result.exitCode !== null && result.exitCode !== 0
|
|
724
|
+
};
|
|
725
|
+
}, {
|
|
726
|
+
internal: true
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
}
|
|
588
731
|
// Annotate the CommonJS export names for ESM import in node:
|
|
589
732
|
0 && (module.exports = {
|
|
733
|
+
createBashPlugin,
|
|
590
734
|
createLargeResultPlugin,
|
|
591
735
|
createSearchPlugin,
|
|
592
736
|
createSkillsPlugin,
|
package/plugins.mjs
CHANGED
|
@@ -411,7 +411,7 @@ Usage:
|
|
|
411
411
|
- ${toolName}({ skill: "skill-name" }) - Load main SKILL.md content
|
|
412
412
|
- ${toolName}({ skill: "skill-name", ref: "path/to/file" }) - Load reference file
|
|
413
413
|
|
|
414
|
-
Note: For scripts
|
|
414
|
+
Note: For scripts/, use the bash tool with the script path to execute.`;
|
|
415
415
|
}
|
|
416
416
|
function createSkillsPlugin(options) {
|
|
417
417
|
const { paths } = options;
|
|
@@ -519,11 +519,15 @@ Available skills: ${available.join(", ")}` : "\n\nNo skills available.";
|
|
|
519
519
|
try {
|
|
520
520
|
const content = await readFile(join2(meta.basePath, "SKILL.md"), "utf-8");
|
|
521
521
|
const body = extractBody(content);
|
|
522
|
+
const skillPathInfo = `
|
|
523
|
+
---
|
|
524
|
+
Skill path: ${meta.basePath}
|
|
525
|
+
`;
|
|
522
526
|
return {
|
|
523
527
|
content: [
|
|
524
528
|
{
|
|
525
529
|
type: "text",
|
|
526
|
-
text: body
|
|
530
|
+
text: body + skillPathInfo
|
|
527
531
|
}
|
|
528
532
|
]
|
|
529
533
|
};
|
|
@@ -549,7 +553,146 @@ Available skills: ${available.join(", ")}` : "\n\nNo skills available.";
|
|
|
549
553
|
}
|
|
550
554
|
};
|
|
551
555
|
}
|
|
556
|
+
|
|
557
|
+
// __mcpc__core_latest/node_modules/@mcpc/core/src/plugins/bash.js
|
|
558
|
+
import { spawn } from "node:child_process";
|
|
559
|
+
import process from "node:process";
|
|
560
|
+
var DEFAULT_MAX_BYTES = 1e5;
|
|
561
|
+
var DEFAULT_MAX_LINES = 2e3;
|
|
562
|
+
var DEFAULT_TIMEOUT_MS = 6e4;
|
|
563
|
+
function truncateOutput(stdout, stderr, maxBytes = DEFAULT_MAX_BYTES, maxLines = DEFAULT_MAX_LINES) {
|
|
564
|
+
const fullOutput = (stderr ? `STDERR:
|
|
565
|
+
${stderr}
|
|
566
|
+
|
|
567
|
+
STDOUT:
|
|
568
|
+
` : "") + stdout;
|
|
569
|
+
const lines = fullOutput.split("\n");
|
|
570
|
+
if (lines.length > maxLines) {
|
|
571
|
+
const truncatedLines = lines.slice(-maxLines);
|
|
572
|
+
return {
|
|
573
|
+
output: `[OUTPUT TRUNCATED] Showing last ${maxLines} lines of ${lines.length} total
|
|
574
|
+
|
|
575
|
+
` + truncatedLines.join("\n"),
|
|
576
|
+
truncated: true
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
if (fullOutput.length > maxBytes) {
|
|
580
|
+
const truncatedBytes = fullOutput.slice(-maxBytes);
|
|
581
|
+
return {
|
|
582
|
+
output: `[OUTPUT TRUNCATED] Showing last ${maxBytes} bytes of ${fullOutput.length} total
|
|
583
|
+
|
|
584
|
+
` + truncatedBytes,
|
|
585
|
+
truncated: true
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
return {
|
|
589
|
+
output: fullOutput,
|
|
590
|
+
truncated: false
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
function executeBash(command, cwd, timeoutMs) {
|
|
594
|
+
return new Promise((resolve3) => {
|
|
595
|
+
const stdout = [];
|
|
596
|
+
const stderr = [];
|
|
597
|
+
const proc = spawn("bash", [
|
|
598
|
+
"-c",
|
|
599
|
+
command
|
|
600
|
+
], {
|
|
601
|
+
cwd,
|
|
602
|
+
stdio: [
|
|
603
|
+
"ignore",
|
|
604
|
+
"pipe",
|
|
605
|
+
"pipe"
|
|
606
|
+
]
|
|
607
|
+
});
|
|
608
|
+
proc.stdout?.on("data", (data) => {
|
|
609
|
+
stdout.push(data.toString());
|
|
610
|
+
});
|
|
611
|
+
proc.stderr?.on("data", (data) => {
|
|
612
|
+
stderr.push(data.toString());
|
|
613
|
+
});
|
|
614
|
+
proc.on("close", (code) => {
|
|
615
|
+
resolve3({
|
|
616
|
+
stdout: stdout.join(""),
|
|
617
|
+
stderr: stderr.join(""),
|
|
618
|
+
exitCode: code
|
|
619
|
+
});
|
|
620
|
+
});
|
|
621
|
+
proc.on("error", (err) => {
|
|
622
|
+
resolve3({
|
|
623
|
+
stdout: "",
|
|
624
|
+
stderr: err.message,
|
|
625
|
+
exitCode: null
|
|
626
|
+
});
|
|
627
|
+
});
|
|
628
|
+
setTimeout(() => {
|
|
629
|
+
proc.kill("SIGTERM");
|
|
630
|
+
resolve3({
|
|
631
|
+
stdout: stdout.join(""),
|
|
632
|
+
stderr: stderr.join("") + "\n\n[TIMEOUT] Command execution timed out",
|
|
633
|
+
exitCode: null
|
|
634
|
+
});
|
|
635
|
+
}, timeoutMs);
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
function createBashPlugin(options = {}) {
|
|
639
|
+
const { maxBytes, maxLines, timeoutMs } = {
|
|
640
|
+
maxBytes: DEFAULT_MAX_BYTES,
|
|
641
|
+
maxLines: DEFAULT_MAX_LINES,
|
|
642
|
+
timeoutMs: DEFAULT_TIMEOUT_MS,
|
|
643
|
+
...options
|
|
644
|
+
};
|
|
645
|
+
return {
|
|
646
|
+
name: "plugin-bash",
|
|
647
|
+
version: "1.0.0",
|
|
648
|
+
// Store server reference for tool registration
|
|
649
|
+
configureServer: (server) => {
|
|
650
|
+
server.tool("bash", "Execute a bash command and return its output.\n\nUse this for:\n- Running shell commands\n- Executing scripts\n- System operations\n\nNote: Output is truncated if too large.", {
|
|
651
|
+
type: "object",
|
|
652
|
+
properties: {
|
|
653
|
+
command: {
|
|
654
|
+
type: "string",
|
|
655
|
+
description: "The bash command to execute"
|
|
656
|
+
},
|
|
657
|
+
cwd: {
|
|
658
|
+
type: "string",
|
|
659
|
+
description: "Optional: Working directory for the command (defaults to current directory)"
|
|
660
|
+
}
|
|
661
|
+
},
|
|
662
|
+
required: [
|
|
663
|
+
"command"
|
|
664
|
+
]
|
|
665
|
+
}, async (args) => {
|
|
666
|
+
const cwd = args.cwd || process.cwd();
|
|
667
|
+
const result = await executeBash(args.command, cwd, timeoutMs);
|
|
668
|
+
const { output, truncated } = truncateOutput(result.stdout, result.stderr, maxBytes, maxLines);
|
|
669
|
+
let finalOutput = output;
|
|
670
|
+
if (result.exitCode !== null && result.exitCode !== 0) {
|
|
671
|
+
finalOutput = `[EXIT CODE: ${result.exitCode}]
|
|
672
|
+
` + finalOutput;
|
|
673
|
+
}
|
|
674
|
+
if (truncated) {
|
|
675
|
+
finalOutput += `
|
|
676
|
+
|
|
677
|
+
[Note: Output was truncated]`;
|
|
678
|
+
}
|
|
679
|
+
return {
|
|
680
|
+
content: [
|
|
681
|
+
{
|
|
682
|
+
type: "text",
|
|
683
|
+
text: finalOutput
|
|
684
|
+
}
|
|
685
|
+
],
|
|
686
|
+
isError: result.exitCode !== null && result.exitCode !== 0
|
|
687
|
+
};
|
|
688
|
+
}, {
|
|
689
|
+
internal: true
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
}
|
|
552
694
|
export {
|
|
695
|
+
createBashPlugin,
|
|
553
696
|
createLargeResultPlugin,
|
|
554
697
|
createSearchPlugin,
|
|
555
698
|
createSkillsPlugin,
|
package/types/plugins.d.ts
CHANGED
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
*/ export { createSearchPlugin } from "./src/plugins/search-tool.js";
|
|
39
39
|
export { createLargeResultPlugin } from "./src/plugins/large-result.js";
|
|
40
40
|
export { createSkillsPlugin } from "./src/plugins/skills.js";
|
|
41
|
+
export { createBashPlugin } from "./src/plugins/bash.js";
|
|
41
42
|
export { default as defaultSearchPlugin } from "./src/plugins/search-tool.js";
|
|
42
43
|
export { default as defaultLargeResultPlugin } from "./src/plugins/large-result.js";
|
|
43
44
|
export type { SearchOptions } from "./src/plugins/search-tool.js";
|
package/types/plugins.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugins.d.ts","sources":["../plugins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCC,GAGD,SAAS,kBAAkB,uCAAuC;AAClE,SAAS,uBAAuB,wCAAwC;AACxE,SAAS,kBAAkB,kCAAkC;
|
|
1
|
+
{"version":3,"file":"plugins.d.ts","sources":["../plugins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCC,GAGD,SAAS,kBAAkB,uCAAuC;AAClE,SAAS,uBAAuB,wCAAwC;AACxE,SAAS,kBAAkB,kCAAkC;AAC7D,SAAS,gBAAgB,gCAAgC;AAGzD,SAAS,WAAW,mBAAmB,uCAAuC;AAC9E,SAAS,WAAW,wBAAwB,wCAAwC;AAGpF,cAAc,aAAa,uCAAuC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ToolPlugin } from "../plugin-types.js";
|
|
2
|
+
export interface BashPluginOptions {
|
|
3
|
+
/** Maximum output bytes to return */ maxBytes?: number;
|
|
4
|
+
/** Maximum output lines to return */ maxLines?: number;
|
|
5
|
+
/** Command execution timeout in ms */ timeoutMs?: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Create a bash plugin that provides command execution capability
|
|
9
|
+
*/ export declare function createBashPlugin(options?: BashPluginOptions): ToolPlugin;
|
|
10
|
+
//# sourceMappingURL=bash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash.d.ts","sources":["../../../src/plugins/bash.ts"],"names":[],"mappings":"AAWA,cAAc,UAAU,6BAA6B;AASrD,iBAAiB;EACf,mCAAmC,GACnC,WAAW,MAAM;EACjB,mCAAmC,GACnC,WAAW,MAAM;EACjB,oCAAoC,GACpC,YAAY,MAAM;;AA8FpB;;CAEC,GACD,OAAO,iBAAS,iBAAiB,UAAS,iBAAsB,GAAG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.d.ts","sources":["../../../src/plugins/skills.ts"],"names":[],"mappings":"AAOA,cAAmC,UAAU,6BAA6B;UAWhE;EACR,mCAAmC,GACnC,OAAO,MAAM;;AAoGf;;CAEC,GACD,OAAO,iBAAS,mBAAmB,SAAS,mBAAmB,GAAG;
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sources":["../../../src/plugins/skills.ts"],"names":[],"mappings":"AAOA,cAAmC,UAAU,6BAA6B;UAWhE;EACR,mCAAmC,GACnC,OAAO,MAAM;;AAoGf;;CAEC,GACD,OAAO,iBAAS,mBAAmB,SAAS,mBAAmB,GAAG;AAkJlE;;;;;;;;;;;;;CAaC,GACD,OAAO,iBAAS,aAAa,QAAQ,OAAO,MAAM,EAAE,MAAM,CAAC,GAAG;AAM9D,eAAe,mBAAmB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.d.ts","sources":["../../../../src/utils/common/mcp.ts"],"names":[],"mappings":"AAKA,cAA+B,UAAU,iCAAiC;
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sources":["../../../../src/utils/common/mcp.ts"],"names":[],"mappings":"AAKA,cAA+B,UAAU,iCAAiC;AAiG1E,OAAO,iBAAe,mBACpB,WAAW,UAAU,EACrB,YAAY;EACV,QAAQ,MAAM;EACd,MAAM,GAAG;EACT,SAAS,MAAM;EACf,mBAAmB,MAAM;EACzB,kBAAkB,MAAM;EACxB,QAAQ,MAAM;MACV,OAAO,GACZ,QAAQ,OAAO,MAAM,EAAE,GAAG"}
|