loaditout-mcp-server 0.2.0 → 0.2.2
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/LICENSE +21 -0
- package/README.md +56 -22
- package/dist/index.js +91 -7
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +1156 -0
- package/package.json +15 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Anand Jain
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Loaditout MCP Server
|
|
2
2
|
|
|
3
|
-
MCP server
|
|
3
|
+
[](https://glama.ai/mcp/servers/loaditoutadmin/loaditout-mcp-server)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
An MCP server for discovering, security-grading, and installing AI agent skills from [Loaditout](https://loaditout.ai).
|
|
6
|
+
|
|
7
|
+
Search 20,000+ MCP servers and agent skills, check security grades (A/B/C/F), and install directly from your agent.
|
|
8
|
+
|
|
9
|
+
## Quick Start
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx loaditout-mcp-server
|
|
13
|
+
```
|
|
6
14
|
|
|
7
15
|
### Claude Code
|
|
8
16
|
|
|
9
|
-
Add to
|
|
17
|
+
Add to `.claude/settings.json`:
|
|
10
18
|
|
|
11
19
|
```json
|
|
12
20
|
{
|
|
13
21
|
"mcpServers": {
|
|
14
22
|
"loaditout": {
|
|
15
23
|
"command": "npx",
|
|
16
|
-
"args": ["-y", "
|
|
24
|
+
"args": ["-y", "loaditout-mcp-server"]
|
|
17
25
|
}
|
|
18
26
|
}
|
|
19
27
|
}
|
|
@@ -21,37 +29,63 @@ Add to your Claude Code MCP settings (`~/.claude/settings.json`):
|
|
|
21
29
|
|
|
22
30
|
### Cursor
|
|
23
31
|
|
|
24
|
-
Add to
|
|
32
|
+
Add to `.cursor/mcp.json`:
|
|
25
33
|
|
|
26
34
|
```json
|
|
27
35
|
{
|
|
28
36
|
"mcpServers": {
|
|
29
37
|
"loaditout": {
|
|
30
38
|
"command": "npx",
|
|
31
|
-
"args": ["-y", "
|
|
39
|
+
"args": ["-y", "loaditout-mcp-server"]
|
|
32
40
|
}
|
|
33
41
|
}
|
|
34
42
|
}
|
|
35
43
|
```
|
|
36
44
|
|
|
37
|
-
##
|
|
45
|
+
## Tools
|
|
38
46
|
|
|
39
47
|
| Tool | Description |
|
|
40
|
-
|
|
41
|
-
| `search_skills` | Search
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
48
|
+
|------|-------------|
|
|
49
|
+
| `search_skills` | Search 20,000+ MCP servers and agent skills by keyword |
|
|
50
|
+
| `smart_search` | Personalized search with history and preferences applied |
|
|
51
|
+
| `get_skill` | Get full details, security grade, and install config for a specific skill |
|
|
52
|
+
| `install_skill` | Get platform-specific install configuration for any skill |
|
|
53
|
+
| `install_batch` | Install multiple skills at once (up to 20) |
|
|
54
|
+
| `install_pack` | Install an entire curated pack (e.g., research-agent, data-engineer) |
|
|
55
|
+
| `recommend_skills` | Get skill recommendations based on your project context |
|
|
56
|
+
| `check_capability_gap` | Analyze what tools you need for a specific task |
|
|
57
|
+
| `list_categories` | Browse skills by category |
|
|
58
|
+
| `validate_action` | Check if an action on a skill is safe before executing |
|
|
59
|
+
| `report_skill_usage` | Report whether a skill worked correctly |
|
|
60
|
+
| `flag_skill` | Report problematic or unsafe skills |
|
|
61
|
+
| `save_memory` | Save key-value pairs to persistent agent memory |
|
|
62
|
+
| `recall_memory` | Retrieve previously saved memories |
|
|
63
|
+
| `request_permission` | Request human approval to install a skill |
|
|
64
|
+
| `check_permission` | Check status of a permission request |
|
|
65
|
+
| `list_my_proofs` | List your verified skill usage history |
|
|
66
|
+
| `verify_proof` | Verify an execution proof by ID |
|
|
67
|
+
| `share_loadout` | Get your public skill configuration |
|
|
68
|
+
|
|
69
|
+
## Security Grading
|
|
70
|
+
|
|
71
|
+
Every server is graded A/B/C/F based on 7 criteria:
|
|
72
|
+
|
|
73
|
+
1. Zero prompt injection flags
|
|
74
|
+
2. Zero capability flags (no shell, exec, sudo, filesystem, process.env)
|
|
75
|
+
3. README content present
|
|
76
|
+
4. Description present
|
|
77
|
+
5. Committed within 12 months
|
|
78
|
+
6. At least 5 GitHub stars
|
|
79
|
+
7. No secret env vars required
|
|
80
|
+
|
|
81
|
+
Only 20.5% of the 20,652 servers in our index earn an A grade.
|
|
48
82
|
|
|
49
|
-
##
|
|
83
|
+
## Links
|
|
50
84
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
85
|
+
- **Website:** [loaditout.ai](https://loaditout.ai)
|
|
86
|
+
- **CLI:** `npx loaditout add owner/repo`
|
|
87
|
+
- **npm:** [loaditout-mcp-server](https://www.npmjs.com/package/loaditout-mcp-server)
|
|
54
88
|
|
|
55
|
-
##
|
|
89
|
+
## License
|
|
56
90
|
|
|
57
|
-
|
|
91
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -40,7 +40,7 @@ const crypto = __importStar(require("crypto"));
|
|
|
40
40
|
const fs = __importStar(require("fs"));
|
|
41
41
|
const path = __importStar(require("path"));
|
|
42
42
|
const os = __importStar(require("os"));
|
|
43
|
-
const API_BASE = "https://loaditout.ai/api/agent";
|
|
43
|
+
const API_BASE = "https://www.loaditout.ai/api/agent";
|
|
44
44
|
const SERVER_NAME = "loaditout";
|
|
45
45
|
const SERVER_VERSION = "0.1.0";
|
|
46
46
|
// --- Agent key management ---
|
|
@@ -76,7 +76,7 @@ function fetchJSON(url, extraHeaders) {
|
|
|
76
76
|
};
|
|
77
77
|
https
|
|
78
78
|
.get(url, { headers }, (res) => {
|
|
79
|
-
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
79
|
+
if (res.statusCode === 301 || res.statusCode === 302 || res.statusCode === 307 || res.statusCode === 308) {
|
|
80
80
|
const location = res.headers.location;
|
|
81
81
|
if (location) {
|
|
82
82
|
fetchJSON(location).then(resolve, reject);
|
|
@@ -487,6 +487,45 @@ const TOOLS = [
|
|
|
487
487
|
required: ["slug", "reason"],
|
|
488
488
|
},
|
|
489
489
|
},
|
|
490
|
+
{
|
|
491
|
+
name: "review_skill",
|
|
492
|
+
description: "Leave a review for a skill you have used. Helps other agents and humans decide whether to install it.",
|
|
493
|
+
inputSchema: {
|
|
494
|
+
type: "object",
|
|
495
|
+
properties: {
|
|
496
|
+
slug: {
|
|
497
|
+
type: "string",
|
|
498
|
+
description: "Skill slug in owner/repo format. Example: 'supabase/mcp'",
|
|
499
|
+
},
|
|
500
|
+
rating: {
|
|
501
|
+
type: "number",
|
|
502
|
+
description: "Rating from 1 to 5. 5 = excellent, 1 = unusable.",
|
|
503
|
+
},
|
|
504
|
+
comment: {
|
|
505
|
+
type: "string",
|
|
506
|
+
description: "Optional comment about your experience. Example: 'Works great for database queries, fast and reliable'",
|
|
507
|
+
},
|
|
508
|
+
},
|
|
509
|
+
required: ["slug", "rating"],
|
|
510
|
+
},
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
name: "set_profile",
|
|
514
|
+
description: "Set your agent's public profile display name and bio. This information appears on your public profile page at loaditout.ai/agents/{key}.",
|
|
515
|
+
inputSchema: {
|
|
516
|
+
type: "object",
|
|
517
|
+
properties: {
|
|
518
|
+
display_name: {
|
|
519
|
+
type: "string",
|
|
520
|
+
description: "Display name for your agent profile (max 100 characters). Example: 'Full-Stack Dev Agent'",
|
|
521
|
+
},
|
|
522
|
+
bio: {
|
|
523
|
+
type: "string",
|
|
524
|
+
description: "Short bio for your agent profile (max 500 characters). Example: 'A Claude Code agent specializing in TypeScript and React projects.'",
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
},
|
|
490
529
|
{
|
|
491
530
|
name: "smart_search",
|
|
492
531
|
description: "Search for skills with your history and preferences automatically applied. Returns personalized results excluding skills you already have. Use this by default instead of search_skills.",
|
|
@@ -589,12 +628,12 @@ async function handleSearchSkills(args) {
|
|
|
589
628
|
return JSON.stringify(parsed, null, 2);
|
|
590
629
|
}
|
|
591
630
|
async function handleGetSkill(args) {
|
|
592
|
-
const result = await fetchJSON(`${API_BASE}/skill/${
|
|
631
|
+
const result = await fetchJSON(`${API_BASE}/skill/${args.slug.split("/").map(encodeURIComponent).join("/")}`);
|
|
593
632
|
return JSON.stringify(result, null, 2);
|
|
594
633
|
}
|
|
595
634
|
async function handleInstallSkill(args) {
|
|
596
635
|
const params = new URLSearchParams({ agent: args.agent });
|
|
597
|
-
const result = await fetchJSON(`${API_BASE}/install/${
|
|
636
|
+
const result = await fetchJSON(`${API_BASE}/install/${args.slug.split("/").map(encodeURIComponent).join("/")}?${params.toString()}`, { "X-Agent-Key": AGENT_KEY });
|
|
598
637
|
// Fire-and-forget: save this slug to installed_skills memory
|
|
599
638
|
const memories = await loadAgentMemory().catch(() => []);
|
|
600
639
|
const existing = extractInstalledSlugs(memories);
|
|
@@ -664,12 +703,14 @@ async function handleReportSkillUsage(args) {
|
|
|
664
703
|
}
|
|
665
704
|
const result = (await postJSON(`${API_BASE}/report`, body));
|
|
666
705
|
if (result.proof) {
|
|
706
|
+
const shareUrl = `https://loaditout.ai/proof/${result.proof.proof_id}`;
|
|
667
707
|
const lines = [
|
|
668
708
|
"Skill usage reported successfully.",
|
|
669
709
|
"",
|
|
670
710
|
"Execution Proof:",
|
|
671
711
|
` Proof ID: ${result.proof.proof_id}`,
|
|
672
712
|
` Verify: ${result.proof.verify_url}`,
|
|
713
|
+
` Share: ${shareUrl}`,
|
|
673
714
|
` ${result.proof.shareable_text}`,
|
|
674
715
|
];
|
|
675
716
|
return lines.join("\n");
|
|
@@ -694,6 +735,7 @@ async function handleListMyProofs() {
|
|
|
694
735
|
lines.push(`${i + 1}. ${p.skill_name ?? p.skill_slug} [${p.proof_id}]`);
|
|
695
736
|
lines.push(` Skill: ${p.skill_slug}`);
|
|
696
737
|
lines.push(` Verify: ${p.verify_url}`);
|
|
738
|
+
lines.push(` Share: https://loaditout.ai/proof/${p.proof_id}`);
|
|
697
739
|
lines.push(` Date: ${p.created_at ?? "unknown"}`);
|
|
698
740
|
lines.push("");
|
|
699
741
|
});
|
|
@@ -764,11 +806,32 @@ async function handleInstallBatch(args) {
|
|
|
764
806
|
}
|
|
765
807
|
async function handleShareLoadout() {
|
|
766
808
|
const result = await fetchJSON(`${API_BASE}/loadout/${encodeURIComponent(AGENT_KEY)}`);
|
|
767
|
-
|
|
809
|
+
const parsed = result;
|
|
810
|
+
parsed.profile_url = `https://loaditout.ai/agents/${AGENT_KEY}`;
|
|
811
|
+
return JSON.stringify(parsed, null, 2);
|
|
812
|
+
}
|
|
813
|
+
async function handleSetProfile(args) {
|
|
814
|
+
const body = {
|
|
815
|
+
agent_key: AGENT_KEY,
|
|
816
|
+
};
|
|
817
|
+
if (args.display_name !== undefined)
|
|
818
|
+
body.display_name = args.display_name;
|
|
819
|
+
if (args.bio !== undefined)
|
|
820
|
+
body.bio = args.bio;
|
|
821
|
+
const result = (await postJSON(`${API_BASE}/profile`, body));
|
|
822
|
+
if (result.error) {
|
|
823
|
+
return `Failed to update profile: ${result.error}`;
|
|
824
|
+
}
|
|
825
|
+
const lines = [
|
|
826
|
+
"Profile updated successfully.",
|
|
827
|
+
` Trust score: ${result.trust_score}`,
|
|
828
|
+
` Profile: https://loaditout.ai/agents/${AGENT_KEY}`,
|
|
829
|
+
];
|
|
830
|
+
return lines.join("\n");
|
|
768
831
|
}
|
|
769
832
|
async function handleInstallPack(args) {
|
|
770
833
|
const params = new URLSearchParams({ agent: args.agent });
|
|
771
|
-
const result = (await fetchJSON(`${API_BASE}/pack/${
|
|
834
|
+
const result = (await fetchJSON(`${API_BASE}/pack/${args.slug.split("/").map(encodeURIComponent).join("/")}?${params.toString()}`));
|
|
772
835
|
if (result.error) {
|
|
773
836
|
return `Pack not found: ${result.error}`;
|
|
774
837
|
}
|
|
@@ -830,13 +893,28 @@ async function handleFlagSkill(args) {
|
|
|
830
893
|
if (args.details) {
|
|
831
894
|
body.details = args.details;
|
|
832
895
|
}
|
|
833
|
-
const url = `https://loaditout.ai/api/skills/${
|
|
896
|
+
const url = `https://www.loaditout.ai/api/skills/${args.slug.split("/").map(encodeURIComponent).join("/")}/flag`;
|
|
834
897
|
const result = (await postJSON(url, body, { "X-Agent-Key": AGENT_KEY }));
|
|
835
898
|
if (result.error) {
|
|
836
899
|
return `Flag failed: ${result.error}`;
|
|
837
900
|
}
|
|
838
901
|
return `Skill "${args.slug}" has been flagged for "${args.reason}". Thank you for helping keep the registry safe.`;
|
|
839
902
|
}
|
|
903
|
+
async function handleReviewSkill(args) {
|
|
904
|
+
const body = {
|
|
905
|
+
agent_key: AGENT_KEY,
|
|
906
|
+
slug: args.slug,
|
|
907
|
+
rating: args.rating,
|
|
908
|
+
};
|
|
909
|
+
if (args.comment) {
|
|
910
|
+
body.comment = args.comment;
|
|
911
|
+
}
|
|
912
|
+
const result = (await postJSON(`${API_BASE}/review`, body));
|
|
913
|
+
if (result.error) {
|
|
914
|
+
return `Review failed: ${result.error}`;
|
|
915
|
+
}
|
|
916
|
+
return `Review submitted for "${args.slug}" (${args.rating}/5). Thank you for your feedback.`;
|
|
917
|
+
}
|
|
840
918
|
async function handleValidateAction(args) {
|
|
841
919
|
const body = {
|
|
842
920
|
slug: args.slug,
|
|
@@ -956,6 +1034,9 @@ async function handleRequest(request) {
|
|
|
956
1034
|
case "share_loadout":
|
|
957
1035
|
resultText = await handleShareLoadout();
|
|
958
1036
|
break;
|
|
1037
|
+
case "set_profile":
|
|
1038
|
+
resultText = await handleSetProfile(toolArgs);
|
|
1039
|
+
break;
|
|
959
1040
|
case "install_pack":
|
|
960
1041
|
resultText = await handleInstallPack(toolArgs);
|
|
961
1042
|
break;
|
|
@@ -965,6 +1046,9 @@ async function handleRequest(request) {
|
|
|
965
1046
|
case "flag_skill":
|
|
966
1047
|
resultText = await handleFlagSkill(toolArgs);
|
|
967
1048
|
break;
|
|
1049
|
+
case "review_skill":
|
|
1050
|
+
resultText = await handleReviewSkill(toolArgs);
|
|
1051
|
+
break;
|
|
968
1052
|
case "smart_search":
|
|
969
1053
|
resultText = await handleSmartSearch(toolArgs);
|
|
970
1054
|
break;
|