tokrepo-mcp-server 2.1.0 → 2.2.0
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/README.md +5 -0
- package/bin/server.js +198 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,6 +40,7 @@ Once connected, your AI assistant can:
|
|
|
40
40
|
- **Get details** — full documentation, install instructions, and metadata
|
|
41
41
|
- **Plan before install** — get install plan v2 with policy decisions, rollback, and verification
|
|
42
42
|
- **Safe Codex install** — dry-run by default; risky assets must be staged or explicitly approved
|
|
43
|
+
- **Lifecycle control** — list installed assets, uninstall managed files, and roll back install sessions
|
|
43
44
|
|
|
44
45
|
## Available Tools
|
|
45
46
|
|
|
@@ -50,6 +51,9 @@ Once connected, your AI assistant can:
|
|
|
50
51
|
| `tokrepo_install_plan` | Get agent-native install plan v2 |
|
|
51
52
|
| `tokrepo_codex_install` | Dry-run, stage, or install a Codex skill safely |
|
|
52
53
|
| `tokrepo_clone_plan` | Bulk profile clone dry-run plan |
|
|
54
|
+
| `tokrepo_installed` | List TokRepo-managed Codex installs |
|
|
55
|
+
| `tokrepo_uninstall` | Dry-run or remove a managed Codex install |
|
|
56
|
+
| `tokrepo_rollback` | Dry-run or roll back a prior Codex install session |
|
|
53
57
|
| `tokrepo_install` | Get raw installable content |
|
|
54
58
|
| `tokrepo_trending` | Browse popular/latest assets |
|
|
55
59
|
|
|
@@ -65,6 +69,7 @@ AI: [calls tokrepo_trending] → Shows top assets by popularity
|
|
|
65
69
|
You: "Install that cursor rules asset"
|
|
66
70
|
AI: [calls tokrepo_install_plan] → Reviews policy and actions
|
|
67
71
|
AI: [calls tokrepo_codex_install with dry_run=false, confirm=true] → Writes only after explicit confirmation
|
|
72
|
+
AI: [calls tokrepo_rollback with dry_run=true] → Shows exactly what would be removed before rollback
|
|
68
73
|
```
|
|
69
74
|
|
|
70
75
|
## Why TokRepo?
|
package/bin/server.js
CHANGED
|
@@ -19,7 +19,7 @@ const API_BASE = process.env.TOKREPO_API || 'https://api.tokrepo.com';
|
|
|
19
19
|
const TOKREPO_URL = 'https://tokrepo.com';
|
|
20
20
|
const TOKREPO_TOKEN = process.env.TOKREPO_TOKEN || '';
|
|
21
21
|
const TOKREPO_CLI = process.env.TOKREPO_CLI || '';
|
|
22
|
-
const SERVER_VERSION = '2.
|
|
22
|
+
const SERVER_VERSION = '2.2.0';
|
|
23
23
|
|
|
24
24
|
// ─── MCP Protocol (JSON-RPC over stdio) ───
|
|
25
25
|
|
|
@@ -53,6 +53,20 @@ const TOOLS = [
|
|
|
53
53
|
description: 'Max results (default 10, max 20)',
|
|
54
54
|
default: 10,
|
|
55
55
|
},
|
|
56
|
+
target: {
|
|
57
|
+
type: 'string',
|
|
58
|
+
description: 'Optional agent target filter. Use codex for Codex-compatible assets.',
|
|
59
|
+
enum: ['codex'],
|
|
60
|
+
},
|
|
61
|
+
kind: {
|
|
62
|
+
type: 'string',
|
|
63
|
+
description: 'Optional asset kind filter, e.g. skill, prompt, knowledge, mcp_config, script',
|
|
64
|
+
},
|
|
65
|
+
policy: {
|
|
66
|
+
type: 'string',
|
|
67
|
+
description: 'Optional Codex install policy filter.',
|
|
68
|
+
enum: ['allow', 'confirm', 'stage_only', 'deny'],
|
|
69
|
+
},
|
|
56
70
|
},
|
|
57
71
|
required: ['query'],
|
|
58
72
|
},
|
|
@@ -161,6 +175,76 @@ const TOOLS = [
|
|
|
161
175
|
required: ['user'],
|
|
162
176
|
},
|
|
163
177
|
},
|
|
178
|
+
{
|
|
179
|
+
name: 'tokrepo_installed',
|
|
180
|
+
description: 'List Codex assets installed by TokRepo from the local install manifest, including file status and session ids.',
|
|
181
|
+
inputSchema: {
|
|
182
|
+
type: 'object',
|
|
183
|
+
properties: {},
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: 'tokrepo_uninstall',
|
|
188
|
+
description: 'Safely uninstall a TokRepo-managed Codex asset. Defaults to dry_run=true. To remove files, set dry_run=false and confirm=true. Local changes are blocked unless force=true.',
|
|
189
|
+
inputSchema: {
|
|
190
|
+
type: 'object',
|
|
191
|
+
properties: {
|
|
192
|
+
uuid: {
|
|
193
|
+
type: 'string',
|
|
194
|
+
description: 'Installed asset UUID, UUID prefix, or title.',
|
|
195
|
+
},
|
|
196
|
+
dry_run: {
|
|
197
|
+
type: 'boolean',
|
|
198
|
+
description: 'When true, return the removal plan without deleting files. Default true.',
|
|
199
|
+
default: true,
|
|
200
|
+
},
|
|
201
|
+
confirm: {
|
|
202
|
+
type: 'boolean',
|
|
203
|
+
description: 'Required when dry_run=false to prevent accidental deletes.',
|
|
204
|
+
default: false,
|
|
205
|
+
},
|
|
206
|
+
force: {
|
|
207
|
+
type: 'boolean',
|
|
208
|
+
description: 'Allow removal when local files changed since installation.',
|
|
209
|
+
default: false,
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
required: ['uuid'],
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
name: 'tokrepo_rollback',
|
|
217
|
+
description: 'Roll back a previous TokRepo Codex install session. Defaults to dry_run=true and last=true.',
|
|
218
|
+
inputSchema: {
|
|
219
|
+
type: 'object',
|
|
220
|
+
properties: {
|
|
221
|
+
session_id: {
|
|
222
|
+
type: 'string',
|
|
223
|
+
description: 'Session id to roll back. Omit when last=true.',
|
|
224
|
+
},
|
|
225
|
+
last: {
|
|
226
|
+
type: 'boolean',
|
|
227
|
+
description: 'Use the latest install/stage session. Default true.',
|
|
228
|
+
default: true,
|
|
229
|
+
},
|
|
230
|
+
dry_run: {
|
|
231
|
+
type: 'boolean',
|
|
232
|
+
description: 'When true, return the rollback plan without deleting files. Default true.',
|
|
233
|
+
default: true,
|
|
234
|
+
},
|
|
235
|
+
confirm: {
|
|
236
|
+
type: 'boolean',
|
|
237
|
+
description: 'Required when dry_run=false to prevent accidental deletes.',
|
|
238
|
+
default: false,
|
|
239
|
+
},
|
|
240
|
+
force: {
|
|
241
|
+
type: 'boolean',
|
|
242
|
+
description: 'Allow rollback when local files changed since installation.',
|
|
243
|
+
default: false,
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
},
|
|
164
248
|
{
|
|
165
249
|
name: 'tokrepo_trending',
|
|
166
250
|
description: 'Get trending/popular AI assets on TokRepo. Use when user asks for recommended or popular AI tools.',
|
|
@@ -435,7 +519,22 @@ function jsonText(title, data) {
|
|
|
435
519
|
// ─── Tool Handlers ───
|
|
436
520
|
|
|
437
521
|
async function handleSearch(args) {
|
|
438
|
-
const { query, tag, limit = 10 } = args;
|
|
522
|
+
const { query, tag, limit = 10, target = '', kind = '', policy = '' } = args;
|
|
523
|
+
if (target || kind || policy) {
|
|
524
|
+
const cliArgs = ['search', query, '--json', '--page-size', String(Math.min(limit, 20))];
|
|
525
|
+
if (target) cliArgs.push('--target', target);
|
|
526
|
+
if (kind) cliArgs.push('--kind', kind);
|
|
527
|
+
if (policy) cliArgs.push('--policy', policy);
|
|
528
|
+
const { stdout, stderr } = await runTokrepoCli(cliArgs);
|
|
529
|
+
let data;
|
|
530
|
+
try {
|
|
531
|
+
data = JSON.parse(stdout);
|
|
532
|
+
} catch {
|
|
533
|
+
data = { stdout, stderr };
|
|
534
|
+
}
|
|
535
|
+
return { content: [{ type: 'text', text: jsonText('Filtered TokRepo search results', data) }] };
|
|
536
|
+
}
|
|
537
|
+
|
|
439
538
|
// Normalize: hyphens/underscores/dots → spaces for better matching
|
|
440
539
|
const normalized = query.replace(/[-_.]/g, ' ').replace(/\s+/g, ' ').trim();
|
|
441
540
|
const params = new URLSearchParams({
|
|
@@ -551,20 +650,37 @@ async function handleCodexInstall(args) {
|
|
|
551
650
|
const plan = await fetchInstallPlan(uuid, 'codex');
|
|
552
651
|
const decision = planPolicyDecision(plan);
|
|
553
652
|
if (dry_run !== false) {
|
|
653
|
+
const cliArgs = ['install', plan.asset_uuid || uuid, '--target', 'codex', '--dry-run', '--json'];
|
|
654
|
+
if (stage) cliArgs.push('--stage');
|
|
655
|
+
const { stdout, stderr } = await runTokrepoCli(cliArgs);
|
|
656
|
+
let data;
|
|
657
|
+
try {
|
|
658
|
+
data = JSON.parse(stdout);
|
|
659
|
+
} catch {
|
|
660
|
+
data = { stdout, stderr };
|
|
661
|
+
}
|
|
554
662
|
return {
|
|
555
663
|
content: [{
|
|
556
664
|
type: 'text',
|
|
557
|
-
text: jsonText(`Dry run only. Policy: ${decision}. Set dry_run=false and confirm=true to write files.`,
|
|
665
|
+
text: jsonText(`Dry run only. Policy: ${decision}. Set dry_run=false and confirm=true to write files.`, data),
|
|
558
666
|
}],
|
|
559
667
|
};
|
|
560
668
|
}
|
|
561
669
|
|
|
562
670
|
if (!confirm) {
|
|
671
|
+
const cliArgs = ['install', plan.asset_uuid || uuid, '--target', 'codex', '--dry-run', '--json'];
|
|
672
|
+
const { stdout, stderr } = await runTokrepoCli(cliArgs);
|
|
673
|
+
let data;
|
|
674
|
+
try {
|
|
675
|
+
data = JSON.parse(stdout);
|
|
676
|
+
} catch {
|
|
677
|
+
data = { stdout, stderr };
|
|
678
|
+
}
|
|
563
679
|
return {
|
|
564
680
|
isError: true,
|
|
565
681
|
content: [{
|
|
566
682
|
type: 'text',
|
|
567
|
-
text: jsonText('Refused to write files because confirm=true was not provided.',
|
|
683
|
+
text: jsonText('Refused to write files because confirm=true was not provided. Dry-run plan follows.', data),
|
|
568
684
|
}],
|
|
569
685
|
};
|
|
570
686
|
}
|
|
@@ -612,6 +728,81 @@ async function handleClonePlan(args) {
|
|
|
612
728
|
return { content: [{ type: 'text', text: jsonText('Bulk Codex clone dry-run plan', data) }] };
|
|
613
729
|
}
|
|
614
730
|
|
|
731
|
+
async function handleInstalled() {
|
|
732
|
+
const { stdout, stderr } = await runTokrepoCli(['installed', '--target', 'codex', '--json']);
|
|
733
|
+
let data;
|
|
734
|
+
try {
|
|
735
|
+
data = JSON.parse(stdout);
|
|
736
|
+
} catch {
|
|
737
|
+
data = { stdout, stderr };
|
|
738
|
+
}
|
|
739
|
+
return { content: [{ type: 'text', text: jsonText('TokRepo Codex installed assets', data) }] };
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
async function handleUninstall(args) {
|
|
743
|
+
const { uuid, dry_run = true, confirm = false, force = false } = args;
|
|
744
|
+
const cliArgs = ['uninstall', uuid, '--target', 'codex', '--json'];
|
|
745
|
+
if (dry_run !== false) cliArgs.push('--dry-run');
|
|
746
|
+
if (force) cliArgs.push('--force');
|
|
747
|
+
|
|
748
|
+
if (dry_run === false && !confirm) {
|
|
749
|
+
cliArgs.push('--dry-run');
|
|
750
|
+
const { stdout, stderr } = await runTokrepoCli(cliArgs);
|
|
751
|
+
let data;
|
|
752
|
+
try {
|
|
753
|
+
data = JSON.parse(stdout);
|
|
754
|
+
} catch {
|
|
755
|
+
data = { stdout, stderr };
|
|
756
|
+
}
|
|
757
|
+
return {
|
|
758
|
+
isError: true,
|
|
759
|
+
content: [{ type: 'text', text: jsonText('Refused to uninstall because confirm=true was not provided. Dry-run plan follows.', data) }],
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
const { stdout, stderr } = await runTokrepoCli(cliArgs);
|
|
764
|
+
let data;
|
|
765
|
+
try {
|
|
766
|
+
data = JSON.parse(stdout);
|
|
767
|
+
} catch {
|
|
768
|
+
data = { stdout, stderr };
|
|
769
|
+
}
|
|
770
|
+
return { content: [{ type: 'text', text: jsonText(dry_run === false ? 'TokRepo Codex uninstall result' : 'TokRepo Codex uninstall dry-run', data) }] };
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
async function handleRollback(args) {
|
|
774
|
+
const { session_id = '', last = true, dry_run = true, confirm = false, force = false } = args;
|
|
775
|
+
const cliArgs = ['rollback', '--target', 'codex', '--json'];
|
|
776
|
+
if (session_id) cliArgs.push(session_id);
|
|
777
|
+
else if (last !== false) cliArgs.push('--last');
|
|
778
|
+
if (dry_run !== false) cliArgs.push('--dry-run');
|
|
779
|
+
if (force) cliArgs.push('--force');
|
|
780
|
+
|
|
781
|
+
if (dry_run === false && !confirm) {
|
|
782
|
+
cliArgs.push('--dry-run');
|
|
783
|
+
const { stdout, stderr } = await runTokrepoCli(cliArgs);
|
|
784
|
+
let data;
|
|
785
|
+
try {
|
|
786
|
+
data = JSON.parse(stdout);
|
|
787
|
+
} catch {
|
|
788
|
+
data = { stdout, stderr };
|
|
789
|
+
}
|
|
790
|
+
return {
|
|
791
|
+
isError: true,
|
|
792
|
+
content: [{ type: 'text', text: jsonText('Refused to roll back because confirm=true was not provided. Dry-run plan follows.', data) }],
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
const { stdout, stderr } = await runTokrepoCli(cliArgs);
|
|
797
|
+
let data;
|
|
798
|
+
try {
|
|
799
|
+
data = JSON.parse(stdout);
|
|
800
|
+
} catch {
|
|
801
|
+
data = { stdout, stderr };
|
|
802
|
+
}
|
|
803
|
+
return { content: [{ type: 'text', text: jsonText(dry_run === false ? 'TokRepo Codex rollback result' : 'TokRepo Codex rollback dry-run', data) }] };
|
|
804
|
+
}
|
|
805
|
+
|
|
615
806
|
async function handleTrending(args) {
|
|
616
807
|
const { sort = 'popular', limit = 10 } = args;
|
|
617
808
|
const params = new URLSearchParams({
|
|
@@ -763,6 +954,9 @@ async function handleRequest(msg) {
|
|
|
763
954
|
case 'tokrepo_install_plan': result = await handleInstallPlan(args || {}); break;
|
|
764
955
|
case 'tokrepo_codex_install': result = await handleCodexInstall(args || {}); break;
|
|
765
956
|
case 'tokrepo_clone_plan': result = await handleClonePlan(args || {}); break;
|
|
957
|
+
case 'tokrepo_installed': result = await handleInstalled(args || {}); break;
|
|
958
|
+
case 'tokrepo_uninstall': result = await handleUninstall(args || {}); break;
|
|
959
|
+
case 'tokrepo_rollback': result = await handleRollback(args || {}); break;
|
|
766
960
|
case 'tokrepo_trending': result = await handleTrending(args || {}); break;
|
|
767
961
|
case 'tokrepo_push': result = await handlePush(args || {}); break;
|
|
768
962
|
case 'tokrepo_status': result = await handleStatus(args || {}); break;
|
package/package.json
CHANGED