@unfragile/mcp-server 0.3.2 → 0.4.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 +12 -0
- package/dist/index.js +121 -11
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -59,6 +59,8 @@ Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
|
59
59
|
|
|
60
60
|
## Tools
|
|
61
61
|
|
|
62
|
+
### Discovery and trust (human-readable)
|
|
63
|
+
|
|
62
64
|
| Tool | Description |
|
|
63
65
|
|------|-------------|
|
|
64
66
|
| `search` | Find AI tools by intent. "best framework for building AI agents" |
|
|
@@ -72,6 +74,16 @@ Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
|
72
74
|
| `subscribe` | Watch for new artifacts matching a capability need |
|
|
73
75
|
| `unsubscribe` | Cancel a monitor |
|
|
74
76
|
|
|
77
|
+
### Capability Protocol v1 (raw JSON, machine-readable)
|
|
78
|
+
|
|
79
|
+
| Tool | Description |
|
|
80
|
+
|------|-------------|
|
|
81
|
+
| `unfragile_validate` | Validate an `unfragile.yml` manifest against the Capability Protocol v1 schema. Returns errors, warnings, and the parsed manifest. |
|
|
82
|
+
| `unfragile_passport` | Fetch the raw `trust_passport_v1` JSON for an artifact by slug. Suitable for programmatic policy checks. |
|
|
83
|
+
| `unfragile_resolve_capability` | Resolve a `capability://` URI or natural-language intent into ranked artifacts as raw JSON. Optional inline passports for one-call decisioning. |
|
|
84
|
+
|
|
85
|
+
Learn more about the protocol: <https://unfragile.ai/protocol>.
|
|
86
|
+
|
|
75
87
|
## Examples
|
|
76
88
|
|
|
77
89
|
Once installed, ask your agent:
|
package/dist/index.js
CHANGED
|
@@ -7,16 +7,21 @@
|
|
|
7
7
|
// the graph learns from every interaction.
|
|
8
8
|
//
|
|
9
9
|
// Tools:
|
|
10
|
-
// search
|
|
11
|
-
// find_mcps
|
|
12
|
-
// get_artifact
|
|
13
|
-
// resolve_capability
|
|
14
|
-
// trust_passport
|
|
15
|
-
// compare
|
|
16
|
-
// find_stack
|
|
17
|
-
// feedback
|
|
18
|
-
// subscribe
|
|
19
|
-
// unsubscribe
|
|
10
|
+
// search — Find AI tools by intent/query (with Match Proof)
|
|
11
|
+
// find_mcps — Discover MCP servers by capability need
|
|
12
|
+
// get_artifact — Get full details + capabilities for an artifact
|
|
13
|
+
// resolve_capability — Resolve capability:// URIs to trusted artifacts (formatted)
|
|
14
|
+
// trust_passport — Get machine-readable trust passport for an artifact (formatted)
|
|
15
|
+
// compare — Compare two artifacts side-by-side
|
|
16
|
+
// find_stack — Assemble a complete harness stack for a use case
|
|
17
|
+
// feedback — Report success/failure to close the learning loop
|
|
18
|
+
// subscribe — Set up persistent watch for new tools
|
|
19
|
+
// unsubscribe — Cancel a persistent watch
|
|
20
|
+
//
|
|
21
|
+
// Protocol-native (raw JSON, Unfragile Capability Protocol v1):
|
|
22
|
+
// unfragile_validate — Validate an unfragile.yml manifest
|
|
23
|
+
// unfragile_passport — Raw trust passport JSON for an artifact
|
|
24
|
+
// unfragile_resolve_capability — Raw resolver JSON for a capability:// URI / intent
|
|
20
25
|
// ─────────────────────────────────────────────────────────────
|
|
21
26
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
22
27
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -257,7 +262,7 @@ function formatResolve(data) {
|
|
|
257
262
|
// ─── MCP Server ──────────────────────────────────────────────
|
|
258
263
|
const server = new McpServer({
|
|
259
264
|
name: "unfragile",
|
|
260
|
-
version: "0.
|
|
265
|
+
version: "0.4.0",
|
|
261
266
|
});
|
|
262
267
|
// Tool 1: General search
|
|
263
268
|
server.tool("search", "Search the Unfragile match graph for AI tools, frameworks, APIs, MCP servers, agents, and more. Returns ranked results with capability matches and graph signals. Every query feeds the graph.", {
|
|
@@ -598,6 +603,111 @@ server.tool("subscribe", "Set up a persistent watch for new AI tools matching a
|
|
|
598
603
|
};
|
|
599
604
|
}
|
|
600
605
|
});
|
|
606
|
+
// ─── Protocol-native tools ──────────────────────────────────
|
|
607
|
+
//
|
|
608
|
+
// These three tools mirror the Unfragile Capability Protocol
|
|
609
|
+
// endpoints 1:1 and return raw JSON. Use them when you want
|
|
610
|
+
// machine-readable output rather than the formatted markdown
|
|
611
|
+
// returned by `trust_passport` / `resolve_capability`.
|
|
612
|
+
async function validateManifestAPI(body) {
|
|
613
|
+
const headers = {
|
|
614
|
+
"Content-Type": "application/json",
|
|
615
|
+
Accept: "application/json",
|
|
616
|
+
};
|
|
617
|
+
if (API_KEY)
|
|
618
|
+
headers["X-API-Key"] = API_KEY;
|
|
619
|
+
const controller = new AbortController();
|
|
620
|
+
const timeout = setTimeout(() => controller.abort(), 15_000);
|
|
621
|
+
try {
|
|
622
|
+
const res = await fetch(`${API_BASE}/api/v1/validate`, {
|
|
623
|
+
method: "POST",
|
|
624
|
+
headers,
|
|
625
|
+
body: JSON.stringify(body),
|
|
626
|
+
signal: controller.signal,
|
|
627
|
+
});
|
|
628
|
+
const text = await res.text();
|
|
629
|
+
try {
|
|
630
|
+
return JSON.parse(text);
|
|
631
|
+
}
|
|
632
|
+
catch {
|
|
633
|
+
throw new Error(`Validator returned non-JSON (${res.status}): ${text.slice(0, 300)}`);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
finally {
|
|
637
|
+
clearTimeout(timeout);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
// Tool: unfragile_validate
|
|
641
|
+
server.tool("unfragile_validate", "Validate an unfragile.yml manifest against the Unfragile Capability Protocol v1. Returns the structured validation result with errors, warnings, and the parsed manifest. Use this before submitting an artifact or in CI pipelines. Accepts raw YAML text via `yaml_content`.", {
|
|
642
|
+
yaml_content: z
|
|
643
|
+
.string()
|
|
644
|
+
.min(10)
|
|
645
|
+
.max(200_000)
|
|
646
|
+
.describe("Raw contents of the unfragile.yml file"),
|
|
647
|
+
}, async ({ yaml_content }) => {
|
|
648
|
+
log("unfragile_validate", `${yaml_content.length} bytes`);
|
|
649
|
+
try {
|
|
650
|
+
const data = await validateManifestAPI({ yaml: yaml_content });
|
|
651
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
652
|
+
}
|
|
653
|
+
catch (err) {
|
|
654
|
+
return {
|
|
655
|
+
content: [
|
|
656
|
+
{ type: "text", text: `Error validating manifest: ${err instanceof Error ? err.message : String(err)}` },
|
|
657
|
+
],
|
|
658
|
+
isError: true,
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
});
|
|
662
|
+
// Tool: unfragile_passport — raw JSON trust passport
|
|
663
|
+
server.tool("unfragile_passport", "Fetch the raw machine-readable trust passport for an artifact by slug (trust_passport_v1 schema). Returns JSON suitable for programmatic policy checks. Pair with `trust_passport` when you want a human-readable summary.", {
|
|
664
|
+
slug: z.string().min(1).max(200).describe("Artifact slug (e.g., 'cursor', 'langchain', 'postgres-mcp-server')"),
|
|
665
|
+
}, async ({ slug }) => {
|
|
666
|
+
log("unfragile_passport", slug);
|
|
667
|
+
try {
|
|
668
|
+
const data = await passportAPI(slug);
|
|
669
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
670
|
+
}
|
|
671
|
+
catch (err) {
|
|
672
|
+
return {
|
|
673
|
+
content: [
|
|
674
|
+
{ type: "text", text: `Error fetching passport: ${err instanceof Error ? err.message : String(err)}` },
|
|
675
|
+
],
|
|
676
|
+
isError: true,
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
// Tool: unfragile_resolve_capability — raw JSON resolver
|
|
681
|
+
server.tool("unfragile_resolve_capability", "Resolve a `capability://` URI or a natural-language capability into ranked artifacts, with trust signals and passport URLs. Returns raw JSON so an agent can make a programmatic selection. Pair with `resolve_capability` when you want a human-readable summary.", {
|
|
682
|
+
uri_or_intent: z
|
|
683
|
+
.string()
|
|
684
|
+
.min(2)
|
|
685
|
+
.max(500)
|
|
686
|
+
.describe("Capability URI like `capability://database.postgres.query.readonly`, or a natural-language capability description"),
|
|
687
|
+
limit: z.number().min(1).max(20).default(5).describe("Max resolutions"),
|
|
688
|
+
risk: z
|
|
689
|
+
.enum(["default", "production", "enterprise", "strict"])
|
|
690
|
+
.default("default")
|
|
691
|
+
.describe("Risk posture — stricter modes require stronger quality/status gates"),
|
|
692
|
+
passport: z
|
|
693
|
+
.boolean()
|
|
694
|
+
.default(false)
|
|
695
|
+
.describe("Inline the full trust passport for each resolution (larger response)"),
|
|
696
|
+
}, async ({ uri_or_intent, limit, risk, passport }) => {
|
|
697
|
+
log("unfragile_resolve_capability", uri_or_intent);
|
|
698
|
+
try {
|
|
699
|
+
const data = await resolveAPI(uri_or_intent, { limit, risk, passport });
|
|
700
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
701
|
+
}
|
|
702
|
+
catch (err) {
|
|
703
|
+
return {
|
|
704
|
+
content: [
|
|
705
|
+
{ type: "text", text: `Error resolving capability: ${err instanceof Error ? err.message : String(err)}` },
|
|
706
|
+
],
|
|
707
|
+
isError: true,
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
});
|
|
601
711
|
// Tool 10: Unsubscribe — delete a monitor
|
|
602
712
|
server.tool("unsubscribe", "Cancel a persistent watch (monitor). Use the monitor ID returned from subscribe.", {
|
|
603
713
|
monitorId: z.string().min(1).describe("Monitor ID from subscribe (e.g., 'mon_...')"),
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unfragile/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"mcpName": "io.github.Savirinc/unfragile",
|
|
5
|
-
"description": "Unfragile MCP Server — agent-native discovery, trust, and routing for AI artifacts.",
|
|
5
|
+
"description": "Unfragile MCP Server — agent-native discovery, trust, and routing for AI artifacts. Implements the Unfragile Capability Protocol v1.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mcp",
|
|
8
8
|
"ai",
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
"routing",
|
|
13
13
|
"capabilities",
|
|
14
14
|
"unfragile",
|
|
15
|
-
"harness-engineering"
|
|
15
|
+
"harness-engineering",
|
|
16
|
+
"capability-protocol",
|
|
17
|
+
"unfragile.yml"
|
|
16
18
|
],
|
|
17
19
|
"license": "MIT",
|
|
18
20
|
"author": "Unfragile <hello@unfragile.ai>",
|