@ductape/mcp 0.1.2 → 0.1.4
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/dist/index.js +134 -19
- package/package.json +1 -1
- package/src/index.ts +146 -20
package/dist/index.js
CHANGED
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* publishable_key on every tool call. Per-call publishable_key still overrides
|
|
10
10
|
* the env var when provided.
|
|
11
11
|
*/
|
|
12
|
+
import { createRequire } from 'module';
|
|
13
|
+
import { execSync } from 'child_process';
|
|
12
14
|
import { z } from 'zod';
|
|
13
15
|
import { executeViaProxy, generateExecutablePayload, getAssetSchemas, } from './proxy-client.js';
|
|
14
16
|
const MODULES = [
|
|
@@ -23,18 +25,26 @@ const MODULES = [
|
|
|
23
25
|
const METHOD_DOCS = `
|
|
24
26
|
━━━ TOOL SELECTION GUIDE ━━━
|
|
25
27
|
|
|
26
|
-
There are
|
|
28
|
+
There are THREE categories of operations. Use the right tool for each:
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
→
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
0. ADMINISTRATIVE OPERATIONS (create/update products, apps, environments, cloud connections…)
|
|
31
|
+
These require an access key and CANNOT be done via ductape_execute (publishable key only).
|
|
32
|
+
→ Use ductape_cli instead. Examples:
|
|
33
|
+
ductape_cli("products list")
|
|
34
|
+
ductape_cli("product create --name \\"My Product\\" --tag my-product")
|
|
35
|
+
ductape_cli("environments list my-product")
|
|
36
|
+
ductape_cli("cloud connections list")
|
|
37
|
+
If the CLI is not installed, ductape_cli will return install instructions automatically.
|
|
38
|
+
|
|
39
|
+
1. ASSET CREATION / UPDATE (create, update, add, register… for ANY asset type)
|
|
40
|
+
ALL creation and update operations require an access key and CANNOT go through ductape_execute.
|
|
41
|
+
→ Use ductape_cli for every create/update operation. Examples:
|
|
42
|
+
ductape_cli("app create --name \\"Email Service\\" --description \\"Transactional email\\"")
|
|
43
|
+
ductape_cli("apps list")
|
|
44
|
+
ductape_cli("actions list my-app-tag")
|
|
45
|
+
This applies to: products, apps, actions, auths, environments, databases, storage,
|
|
46
|
+
graphs, vectors, brokers, sessions, notifications, jobs, features, quotas, fallbacks,
|
|
47
|
+
healthchecks, caches, secrets, and webhooks.
|
|
38
48
|
|
|
39
49
|
2. RUNTIME OPERATIONS (run, dispatch, execute, start, send, produce, query, insert, update, delete…)
|
|
40
50
|
The "input" field shape is product- and operation-specific — it is NOT derivable from Joi validators.
|
|
@@ -776,6 +786,68 @@ function buildSnippet(language, payload, operationFamily, method) {
|
|
|
776
786
|
? buildPythonSnippet(payload, operationFamily, method)
|
|
777
787
|
: buildTypeScriptSnippet(payload, operationFamily, method);
|
|
778
788
|
}
|
|
789
|
+
// ─── CLI helpers ─────────────────────────────────────────────────────────────
|
|
790
|
+
const ADMIN_SUBCOMMANDS = [
|
|
791
|
+
'products', 'product',
|
|
792
|
+
'apps', 'app',
|
|
793
|
+
'workspaces', 'workspace',
|
|
794
|
+
'environments', 'environment',
|
|
795
|
+
'cloud',
|
|
796
|
+
'secrets',
|
|
797
|
+
'databases',
|
|
798
|
+
'storage',
|
|
799
|
+
'graphs',
|
|
800
|
+
'vectors',
|
|
801
|
+
'brokers',
|
|
802
|
+
'notifications',
|
|
803
|
+
'sessions',
|
|
804
|
+
'caches',
|
|
805
|
+
'jobs',
|
|
806
|
+
'generate',
|
|
807
|
+
'resources',
|
|
808
|
+
'init',
|
|
809
|
+
'login',
|
|
810
|
+
'logout',
|
|
811
|
+
'whoami',
|
|
812
|
+
];
|
|
813
|
+
function checkCli() {
|
|
814
|
+
try {
|
|
815
|
+
const out = execSync('ductape --version', { encoding: 'utf8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
816
|
+
return { available: true, version: out || 'unknown' };
|
|
817
|
+
}
|
|
818
|
+
catch {
|
|
819
|
+
return { available: false };
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
function runCli(command) {
|
|
823
|
+
const first = command.trim().split(/\s+/)[0];
|
|
824
|
+
if (!ADMIN_SUBCOMMANDS.includes(first)) {
|
|
825
|
+
return {
|
|
826
|
+
success: false,
|
|
827
|
+
output: `Subcommand "${first}" is not in the allowed admin subcommand list. Allowed: ${ADMIN_SUBCOMMANDS.join(', ')}.`,
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
try {
|
|
831
|
+
const output = execSync(`ductape ${command}`, {
|
|
832
|
+
encoding: 'utf8',
|
|
833
|
+
timeout: 30000,
|
|
834
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
835
|
+
});
|
|
836
|
+
return { success: true, output: output.trim() };
|
|
837
|
+
}
|
|
838
|
+
catch (err) {
|
|
839
|
+
const msg = (err.stderr || err.stdout || err.message || String(err)).trim();
|
|
840
|
+
return { success: false, output: msg };
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
const cliInputSchema = z.object({
|
|
844
|
+
command: z.string().describe('The ductape CLI command to run, without the leading "ductape" word. ' +
|
|
845
|
+
'Examples: "products list", "product create --name \\"My Product\\" --tag my-product", ' +
|
|
846
|
+
'"environments list my-product", "cloud connections list".\n\n' +
|
|
847
|
+
'Use this tool for ALL administrative operations: creating or updating products, apps, ' +
|
|
848
|
+
'environments, resources, cloud connections, and workspace configuration.\n\n' +
|
|
849
|
+
'The CLI uses the user\'s local logged-in session (ductape login) — no key is required.'),
|
|
850
|
+
});
|
|
779
851
|
async function loadMcpSdk() {
|
|
780
852
|
try {
|
|
781
853
|
const [{ McpServer }, { StdioServerTransport }] = await Promise.all([
|
|
@@ -805,8 +877,7 @@ async function loadMcpSdk() {
|
|
|
805
877
|
function handleCliFlags() {
|
|
806
878
|
const arg = process.argv[2];
|
|
807
879
|
if (arg === '--version' || arg === '-v') {
|
|
808
|
-
|
|
809
|
-
const { version } = require('../package.json');
|
|
880
|
+
const { version } = createRequire(import.meta.url)('../package.json');
|
|
810
881
|
process.stdout.write(version + '\n');
|
|
811
882
|
return true;
|
|
812
883
|
}
|
|
@@ -831,6 +902,33 @@ async function main() {
|
|
|
831
902
|
const { McpServer, StdioServerTransport } = await loadMcpSdk();
|
|
832
903
|
const server = new McpServer({ name: 'ductape-mcp', version: '0.1.0' });
|
|
833
904
|
const transport = new StdioServerTransport();
|
|
905
|
+
const cliHandler = async (args) => {
|
|
906
|
+
const cli = checkCli();
|
|
907
|
+
if (!cli.available) {
|
|
908
|
+
return {
|
|
909
|
+
content: [{
|
|
910
|
+
type: 'text',
|
|
911
|
+
text: [
|
|
912
|
+
'The Ductape CLI is not installed or not in PATH.',
|
|
913
|
+
'',
|
|
914
|
+
'Install it with:',
|
|
915
|
+
' npm install --global @ductape/cli',
|
|
916
|
+
'',
|
|
917
|
+
'Then log in:',
|
|
918
|
+
' ductape login',
|
|
919
|
+
'',
|
|
920
|
+
'After logging in, retry this operation.',
|
|
921
|
+
].join('\n'),
|
|
922
|
+
}],
|
|
923
|
+
isError: true,
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
const result = runCli(args.command);
|
|
927
|
+
return {
|
|
928
|
+
content: [{ type: 'text', text: result.output || '(no output)' }],
|
|
929
|
+
...(result.success ? {} : { isError: true }),
|
|
930
|
+
};
|
|
931
|
+
};
|
|
834
932
|
const executeHandler = async (args) => {
|
|
835
933
|
try {
|
|
836
934
|
const key = args.publishable_key || process.env.DUCTAPE_PUBLISHABLE_KEY;
|
|
@@ -899,12 +997,14 @@ async function main() {
|
|
|
899
997
|
if (typeof server.registerTool === 'function') {
|
|
900
998
|
server.registerTool('ductape_execute', {
|
|
901
999
|
title: 'Ductape SDK Execute',
|
|
902
|
-
description: 'Execute a Ductape SDK operation via the backend proxy.\n\n' +
|
|
903
|
-
'
|
|
904
|
-
'
|
|
905
|
-
'
|
|
906
|
-
'
|
|
907
|
-
'
|
|
1000
|
+
description: 'Execute a Ductape SDK RUNTIME operation via the backend proxy (publishable key).\n\n' +
|
|
1001
|
+
'ONLY use this tool for runtime operations: run, dispatch, execute, start, send, produce, query, insert, update, delete.\n' +
|
|
1002
|
+
'Do NOT use this for creating or updating any asset (product, app, action, environment, database, storage, etc.) — ' +
|
|
1003
|
+
'those require an access key. Use ductape_cli for all creation and update operations.\n\n' +
|
|
1004
|
+
'Two-step rule for runtime operations:\n' +
|
|
1005
|
+
' 1. Call ductape_generate_payload first to get the canonical payload template.\n' +
|
|
1006
|
+
' This reveals the exact "input" field keys — they are product/env/operation-specific.\n' +
|
|
1007
|
+
' 2. Fill in the values from the template, then call ductape_execute.',
|
|
908
1008
|
inputSchema: executeInputSchema,
|
|
909
1009
|
}, executeHandler);
|
|
910
1010
|
server.registerTool('ductape_generate_payload', {
|
|
@@ -931,12 +1031,27 @@ async function main() {
|
|
|
931
1031
|
'Pass module="app" or module="product" to scope the result.',
|
|
932
1032
|
inputSchema: schemaInputSchema,
|
|
933
1033
|
}, schemaHandler);
|
|
1034
|
+
server.registerTool('ductape_cli', {
|
|
1035
|
+
title: 'Ductape CLI',
|
|
1036
|
+
description: 'Run a Ductape CLI command for administrative operations.\n\n' +
|
|
1037
|
+
'USE THIS TOOL for any operation that creates or modifies platform configuration:\n' +
|
|
1038
|
+
' - Creating or updating products, apps, environments\n' +
|
|
1039
|
+
' - Managing cloud connections and resources\n' +
|
|
1040
|
+
' - Listing workspaces, products, secrets\n' +
|
|
1041
|
+
' - Any operation that would require an access key via the SDK\n\n' +
|
|
1042
|
+
'DO NOT use ductape_execute for these — it uses a publishable key which only ' +
|
|
1043
|
+
'covers runtime operations. Administrative operations will fail with "Authentication failed".\n\n' +
|
|
1044
|
+
'The CLI uses the user\'s local logged-in session (ductape login). ' +
|
|
1045
|
+
'If the CLI is not installed, this tool will return install instructions automatically.',
|
|
1046
|
+
inputSchema: cliInputSchema,
|
|
1047
|
+
}, cliHandler);
|
|
934
1048
|
}
|
|
935
1049
|
else if (typeof server.tool === 'function') {
|
|
936
1050
|
server.tool('ductape_execute', executeInputSchema.shape, executeHandler);
|
|
937
1051
|
server.tool('ductape_generate_payload', payloadGenerateInputSchema.shape, payloadGenerateHandler);
|
|
938
1052
|
server.tool('ductape_generate_snippet', snippetGenerateInputSchema.shape, snippetGenerateHandler);
|
|
939
1053
|
server.tool('ductape_schema', schemaInputSchema.shape, schemaHandler);
|
|
1054
|
+
server.tool('ductape_cli', cliInputSchema.shape, cliHandler);
|
|
940
1055
|
}
|
|
941
1056
|
else {
|
|
942
1057
|
console.error('MCP server does not expose .registerTool() or .tool()');
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* the env var when provided.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import { createRequire } from 'module';
|
|
14
|
+
import { execSync } from 'child_process';
|
|
13
15
|
import { z } from 'zod';
|
|
14
16
|
import {
|
|
15
17
|
executeViaProxy,
|
|
@@ -34,18 +36,26 @@ const MODULES: SDKModule[] = [
|
|
|
34
36
|
const METHOD_DOCS = `
|
|
35
37
|
━━━ TOOL SELECTION GUIDE ━━━
|
|
36
38
|
|
|
37
|
-
There are
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
→
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
There are THREE categories of operations. Use the right tool for each:
|
|
40
|
+
|
|
41
|
+
0. ADMINISTRATIVE OPERATIONS (create/update products, apps, environments, cloud connections…)
|
|
42
|
+
These require an access key and CANNOT be done via ductape_execute (publishable key only).
|
|
43
|
+
→ Use ductape_cli instead. Examples:
|
|
44
|
+
ductape_cli("products list")
|
|
45
|
+
ductape_cli("product create --name \\"My Product\\" --tag my-product")
|
|
46
|
+
ductape_cli("environments list my-product")
|
|
47
|
+
ductape_cli("cloud connections list")
|
|
48
|
+
If the CLI is not installed, ductape_cli will return install instructions automatically.
|
|
49
|
+
|
|
50
|
+
1. ASSET CREATION / UPDATE (create, update, add, register… for ANY asset type)
|
|
51
|
+
ALL creation and update operations require an access key and CANNOT go through ductape_execute.
|
|
52
|
+
→ Use ductape_cli for every create/update operation. Examples:
|
|
53
|
+
ductape_cli("app create --name \\"Email Service\\" --description \\"Transactional email\\"")
|
|
54
|
+
ductape_cli("apps list")
|
|
55
|
+
ductape_cli("actions list my-app-tag")
|
|
56
|
+
This applies to: products, apps, actions, auths, environments, databases, storage,
|
|
57
|
+
graphs, vectors, brokers, sessions, notifications, jobs, features, quotas, fallbacks,
|
|
58
|
+
healthchecks, caches, secrets, and webhooks.
|
|
49
59
|
|
|
50
60
|
2. RUNTIME OPERATIONS (run, dispatch, execute, start, send, produce, query, insert, update, delete…)
|
|
51
61
|
The "input" field shape is product- and operation-specific — it is NOT derivable from Joi validators.
|
|
@@ -819,6 +829,73 @@ function buildSnippet(
|
|
|
819
829
|
}
|
|
820
830
|
|
|
821
831
|
|
|
832
|
+
// ─── CLI helpers ─────────────────────────────────────────────────────────────
|
|
833
|
+
|
|
834
|
+
const ADMIN_SUBCOMMANDS = [
|
|
835
|
+
'products', 'product',
|
|
836
|
+
'apps', 'app',
|
|
837
|
+
'workspaces', 'workspace',
|
|
838
|
+
'environments', 'environment',
|
|
839
|
+
'cloud',
|
|
840
|
+
'secrets',
|
|
841
|
+
'databases',
|
|
842
|
+
'storage',
|
|
843
|
+
'graphs',
|
|
844
|
+
'vectors',
|
|
845
|
+
'brokers',
|
|
846
|
+
'notifications',
|
|
847
|
+
'sessions',
|
|
848
|
+
'caches',
|
|
849
|
+
'jobs',
|
|
850
|
+
'generate',
|
|
851
|
+
'resources',
|
|
852
|
+
'init',
|
|
853
|
+
'login',
|
|
854
|
+
'logout',
|
|
855
|
+
'whoami',
|
|
856
|
+
];
|
|
857
|
+
|
|
858
|
+
function checkCli(): { available: boolean; version?: string } {
|
|
859
|
+
try {
|
|
860
|
+
const out = execSync('ductape --version', { encoding: 'utf8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
861
|
+
return { available: true, version: out || 'unknown' };
|
|
862
|
+
} catch {
|
|
863
|
+
return { available: false };
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
function runCli(command: string): { success: boolean; output: string } {
|
|
868
|
+
const first = command.trim().split(/\s+/)[0];
|
|
869
|
+
if (!ADMIN_SUBCOMMANDS.includes(first)) {
|
|
870
|
+
return {
|
|
871
|
+
success: false,
|
|
872
|
+
output: `Subcommand "${first}" is not in the allowed admin subcommand list. Allowed: ${ADMIN_SUBCOMMANDS.join(', ')}.`,
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
try {
|
|
876
|
+
const output = execSync(`ductape ${command}`, {
|
|
877
|
+
encoding: 'utf8',
|
|
878
|
+
timeout: 30000,
|
|
879
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
880
|
+
});
|
|
881
|
+
return { success: true, output: output.trim() };
|
|
882
|
+
} catch (err: any) {
|
|
883
|
+
const msg = (err.stderr || err.stdout || err.message || String(err)).trim();
|
|
884
|
+
return { success: false, output: msg };
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
const cliInputSchema = z.object({
|
|
889
|
+
command: z.string().describe(
|
|
890
|
+
'The ductape CLI command to run, without the leading "ductape" word. ' +
|
|
891
|
+
'Examples: "products list", "product create --name \\"My Product\\" --tag my-product", ' +
|
|
892
|
+
'"environments list my-product", "cloud connections list".\n\n' +
|
|
893
|
+
'Use this tool for ALL administrative operations: creating or updating products, apps, ' +
|
|
894
|
+
'environments, resources, cloud connections, and workspace configuration.\n\n' +
|
|
895
|
+
'The CLI uses the user\'s local logged-in session (ductape login) — no key is required.',
|
|
896
|
+
),
|
|
897
|
+
});
|
|
898
|
+
|
|
822
899
|
async function loadMcpSdk(): Promise<{
|
|
823
900
|
McpServer: new (info: { name: string; version: string }) => any;
|
|
824
901
|
StdioServerTransport: new () => any;
|
|
@@ -854,8 +931,7 @@ async function loadMcpSdk(): Promise<{
|
|
|
854
931
|
function handleCliFlags(): boolean {
|
|
855
932
|
const arg = process.argv[2];
|
|
856
933
|
if (arg === '--version' || arg === '-v') {
|
|
857
|
-
|
|
858
|
-
const { version } = require('../package.json') as { version: string };
|
|
934
|
+
const { version } = createRequire(import.meta.url)('../package.json') as { version: string };
|
|
859
935
|
process.stdout.write(version + '\n');
|
|
860
936
|
return true;
|
|
861
937
|
}
|
|
@@ -884,6 +960,34 @@ async function main() {
|
|
|
884
960
|
const server = new McpServer({ name: 'ductape-mcp', version: '0.1.0' });
|
|
885
961
|
const transport = new StdioServerTransport();
|
|
886
962
|
|
|
963
|
+
const cliHandler = async (args: { command: string }) => {
|
|
964
|
+
const cli = checkCli();
|
|
965
|
+
if (!cli.available) {
|
|
966
|
+
return {
|
|
967
|
+
content: [{
|
|
968
|
+
type: 'text',
|
|
969
|
+
text: [
|
|
970
|
+
'The Ductape CLI is not installed or not in PATH.',
|
|
971
|
+
'',
|
|
972
|
+
'Install it with:',
|
|
973
|
+
' npm install --global @ductape/cli',
|
|
974
|
+
'',
|
|
975
|
+
'Then log in:',
|
|
976
|
+
' ductape login',
|
|
977
|
+
'',
|
|
978
|
+
'After logging in, retry this operation.',
|
|
979
|
+
].join('\n'),
|
|
980
|
+
}],
|
|
981
|
+
isError: true,
|
|
982
|
+
};
|
|
983
|
+
}
|
|
984
|
+
const result = runCli(args.command);
|
|
985
|
+
return {
|
|
986
|
+
content: [{ type: 'text', text: result.output || '(no output)' }],
|
|
987
|
+
...(result.success ? {} : { isError: true }),
|
|
988
|
+
};
|
|
989
|
+
};
|
|
990
|
+
|
|
887
991
|
const executeHandler = async (args: { publishable_key?: string; module: SDKModule; method: string; params: unknown[] }) => {
|
|
888
992
|
try {
|
|
889
993
|
const key = args.publishable_key || process.env.DUCTAPE_PUBLISHABLE_KEY;
|
|
@@ -963,12 +1067,14 @@ async function main() {
|
|
|
963
1067
|
{
|
|
964
1068
|
title: 'Ductape SDK Execute',
|
|
965
1069
|
description:
|
|
966
|
-
'Execute a Ductape SDK operation via the backend proxy.\n\n' +
|
|
967
|
-
'
|
|
968
|
-
'
|
|
969
|
-
'
|
|
970
|
-
'
|
|
971
|
-
'
|
|
1070
|
+
'Execute a Ductape SDK RUNTIME operation via the backend proxy (publishable key).\n\n' +
|
|
1071
|
+
'ONLY use this tool for runtime operations: run, dispatch, execute, start, send, produce, query, insert, update, delete.\n' +
|
|
1072
|
+
'Do NOT use this for creating or updating any asset (product, app, action, environment, database, storage, etc.) — ' +
|
|
1073
|
+
'those require an access key. Use ductape_cli for all creation and update operations.\n\n' +
|
|
1074
|
+
'Two-step rule for runtime operations:\n' +
|
|
1075
|
+
' 1. Call ductape_generate_payload first to get the canonical payload template.\n' +
|
|
1076
|
+
' This reveals the exact "input" field keys — they are product/env/operation-specific.\n' +
|
|
1077
|
+
' 2. Fill in the values from the template, then call ductape_execute.',
|
|
972
1078
|
inputSchema: executeInputSchema,
|
|
973
1079
|
},
|
|
974
1080
|
executeHandler,
|
|
@@ -1011,11 +1117,31 @@ async function main() {
|
|
|
1011
1117
|
},
|
|
1012
1118
|
schemaHandler,
|
|
1013
1119
|
);
|
|
1120
|
+
server.registerTool(
|
|
1121
|
+
'ductape_cli',
|
|
1122
|
+
{
|
|
1123
|
+
title: 'Ductape CLI',
|
|
1124
|
+
description:
|
|
1125
|
+
'Run a Ductape CLI command for administrative operations.\n\n' +
|
|
1126
|
+
'USE THIS TOOL for any operation that creates or modifies platform configuration:\n' +
|
|
1127
|
+
' - Creating or updating products, apps, environments\n' +
|
|
1128
|
+
' - Managing cloud connections and resources\n' +
|
|
1129
|
+
' - Listing workspaces, products, secrets\n' +
|
|
1130
|
+
' - Any operation that would require an access key via the SDK\n\n' +
|
|
1131
|
+
'DO NOT use ductape_execute for these — it uses a publishable key which only ' +
|
|
1132
|
+
'covers runtime operations. Administrative operations will fail with "Authentication failed".\n\n' +
|
|
1133
|
+
'The CLI uses the user\'s local logged-in session (ductape login). ' +
|
|
1134
|
+
'If the CLI is not installed, this tool will return install instructions automatically.',
|
|
1135
|
+
inputSchema: cliInputSchema,
|
|
1136
|
+
},
|
|
1137
|
+
cliHandler,
|
|
1138
|
+
);
|
|
1014
1139
|
} else if (typeof server.tool === 'function') {
|
|
1015
1140
|
server.tool('ductape_execute', executeInputSchema.shape, executeHandler);
|
|
1016
1141
|
server.tool('ductape_generate_payload', payloadGenerateInputSchema.shape, payloadGenerateHandler);
|
|
1017
1142
|
server.tool('ductape_generate_snippet', snippetGenerateInputSchema.shape, snippetGenerateHandler);
|
|
1018
1143
|
server.tool('ductape_schema', schemaInputSchema.shape, schemaHandler);
|
|
1144
|
+
server.tool('ductape_cli', cliInputSchema.shape, cliHandler);
|
|
1019
1145
|
} else {
|
|
1020
1146
|
console.error('MCP server does not expose .registerTool() or .tool()');
|
|
1021
1147
|
process.exit(1);
|