resolve_capability
Resolve a capability URI or natural-language phrase into ranked AI artifacts. This enables runtime selection of the current artifact for a capability.
Instructions
Resolve a capability:// URI or natural-language capability into ranked AI artifacts. This is Unfragile's capability DNS primitive. Use when an agent knows what capability it needs and must choose the safest current artifact at runtime.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| capability | Yes | Capability URI or phrase, e.g. 'capability://database.postgres.query.readonly' or 'read-only Postgres database access' | |
| limit | No | Max resolutions | |
| type | No | Filter by artifact type | |
| risk | No | Risk posture. production/enterprise/strict require stronger quality/status gates. | default |
Implementation Reference
- src/index.ts:527-545 (registration)Registration of the resolve_capability tool on the MCP server with Zod schema for parameters (capability, limit, type, risk).
server.tool( "resolve_capability", "Resolve a capability:// URI or natural-language capability into ranked AI artifacts. This is Unfragile's capability DNS primitive. Use when an agent knows what capability it needs and must choose the safest current artifact at runtime.", { capability: z.string().min(2).max(500).describe("Capability URI or phrase, e.g. 'capability://database.postgres.query.readonly' or 'read-only Postgres database access'"), limit: z.number().min(1).max(20).default(5).describe("Max resolutions"), type: z.enum(["agent", "api", "app", "benchmark", "cli", "dataset", "extension", "finetune", "framework", "mcp", "model", "platform", "product", "prompt", "repo", "skill", "template", "webapp", "workflow"]).optional().describe("Filter by artifact type"), risk: z.enum(["default", "production", "enterprise", "strict"]).default("default").describe("Risk posture. production/enterprise/strict require stronger quality/status gates."), }, async ({ capability, limit, type, risk }) => { log("resolve_capability", capability); try { const data = await resolveAPI(capability, { limit, type, risk }); return { content: [{ type: "text" as const, text: formatResolve(data) }] }; } catch (err) { return { content: [{ type: "text" as const, text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true }; } } ); - src/index.ts:536-544 (handler)Handler function that logs, calls resolveAPI, and formats the response using formatResolve.
async ({ capability, limit, type, risk }) => { log("resolve_capability", capability); try { const data = await resolveAPI(capability, { limit, type, risk }); return { content: [{ type: "text" as const, text: formatResolve(data) }] }; } catch (err) { return { content: [{ type: "text" as const, text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true }; } } - src/index.ts:229-260 (helper)resolveAPI helper: calls the Unfragile /api/v1/resolve endpoint with capability, limit, type, and risk parameters.
async function resolveAPI( capability: string, options: { limit?: number; type?: string; risk?: string; passport?: boolean } = {} ): Promise<ResolveResponse> { const params = new URLSearchParams({ capability, source: SOURCE }); if (options.limit) params.set("limit", String(options.limit)); if (options.type) params.set("type", options.type); if (options.risk) params.set("risk", options.risk); if (options.passport) params.set("passport", "true"); const headers: Record<string, string> = { Accept: "application/json" }; if (API_KEY) headers["X-API-Key"] = API_KEY; const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 15_000); try { const res = await fetch(`${API_BASE}/api/v1/resolve?${params}`, { headers, signal: controller.signal, }); if (!res.ok) { const text = await res.text(); throw new Error(`Unfragile resolver API error ${res.status}: ${text}`); } return res.json() as Promise<ResolveResponse>; } finally { clearTimeout(timeout); } } - src/index.ts:386-418 (helper)formatResolve helper: formats the ResolveResponse into a human-readable string for the tool output.
function formatResolve(data: ResolveResponse): string { const lines: string[] = []; lines.push(`# Resolve: ${data.capability}`); lines.push(`Normalized query: ${data.normalizedQuery}`); lines.push(`Mode: ${data.resolver.mode} | Risk mode: ${data.resolver.riskMode}`); if (data.resolutions.length === 0) { lines.push("\nNo trusted artifacts resolved for this capability. This is a demand gap."); return lines.join("\n"); } for (let i = 0; i < data.resolutions.length; i++) { const r = data.resolutions[i]; const verified = r.artifact.verified ? " ✓" : ""; lines.push(`\n## ${i + 1}. ${r.artifact.name}${verified}`); lines.push(`**Type:** ${r.artifact.type} | **Resolver score:** ${r.resolverScore}/100 | **Trust:** ${r.trust.score}/100 | **Risk:** ${r.dataAccessRisk}`); lines.push(`**URL:** ${r.artifact.url}`); if (r.capabilities.length > 0) { lines.push("**Matched capabilities:**"); for (const cap of r.capabilities.slice(0, 4)) { lines.push(`- ${cap.name} (${Math.round(cap.matchScore * 100)}% match)`); if (cap.requires.length > 0) lines.push(` Requires: ${cap.requires.join(", ")}`); if (cap.limitations.length > 0) lines.push(` Limitations: ${cap.limitations.join(", ")}`); } } if (r.trust.observedMatches > 0) { lines.push(`Observed outcomes: ${r.trust.observedMatches} matches, ${Math.round(r.trust.successRate * 100)}% success`); } lines.push(`Passport: ${r.artifact.passportUrl}`); } return lines.join("\n"); } - src/index.ts:127-165 (schema)TypeScript interface ResolveResponse defining the structure returned by the resolve API (capability, resolver, resolutions with artifact, trust, capabilities).
interface ResolveResponse { capability: string; normalizedQuery: string; resolver: { id: string; mode: string; riskMode: string; gapDetected: boolean; }; resolutions: Array<{ artifact: { slug: string; name: string; type: string; url: string; pageUrl: string; passportUrl: string; verified: boolean; status: string; unfragileRank: number; }; resolverScore: number; dataAccessRisk: "low" | "moderate" | "high"; capabilities: Array<{ name: string; matchScore: number; limitations: string[]; requires: string[]; }>; trust: { score: number; verified: boolean; observedMatches: number; successRate: number; topIntents: string[]; }; }>; _links: Record<string, string>; }