Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions eval/tasks/xquik.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
vendor: xquik
tasks:
- id: search-tweets
goal: "Search recent X posts matching a query."
expected_ops:
- method: GET
path: "/api/v1/x/tweets/search"
- id: get-user-posts
goal: "Fetch posts for an X user."
expected_ops:
- method: GET
path: "/api/v1/x/users/{id}/tweets"
- id: create-post
goal: "Create a new X post."
expected_ops:
- method: POST
path: "/api/v1/x/tweets"
- id: start-extraction
goal: "Start a bulk extraction job."
expected_ops:
- method: POST
path: "/api/v1/extractions"
- id: register-webhook
goal: "Register a webhook endpoint for activity events."
expected_ops:
- method: POST
path: "/api/v1/webhooks"
10 changes: 9 additions & 1 deletion eval/vendors.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Evaluation harness: five vendors picked for surface-mix diversity.
# Each vendor's actual .skillship/ project lives under eval/projects/<id>/.
# That directory is *not* created automatically seed it by running
# That directory is *not* created automatically - seed it by running
# `skillship init --domain <domain>` (or handcraft one for air-gapped runs).
vendors:
- id: supabase
Expand Down Expand Up @@ -77,3 +77,11 @@ vendors:
surfaces: [rest, docs, llms_txt, mcp]
ops_min: 20
baseline_path: null

- id: xquik
domain: xquik.com
github_org: Xquik-dev
expected:
surfaces: [rest, mcp]
ops_min: 90
baseline_path: null
12 changes: 10 additions & 2 deletions src/discovery/crawler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,16 @@ export function buildProbeTargets(base: URL): ProbeTarget[] {
targets.push({ surface: "rest", url });
}
}
const mcpUrl = `${base.protocol}//mcp.${base.hostname}/.well-known/oauth-protected-resource/mcp`;
targets.push({ surface: "mcp", url: mcpUrl });
const mcpProtectedResourcePath =
"/.well-known/oauth-protected-resource/mcp";
targets.push({
surface: "mcp",
url: new URL(mcpProtectedResourcePath, base).toString(),
});
targets.push({
surface: "mcp",
url: `${base.protocol}//mcp.${base.hostname}${mcpProtectedResourcePath}`,
});
}
return targets;
}
Expand Down
5 changes: 4 additions & 1 deletion tests/discovery/crawler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe("normalizeBase", () => {
});

describe("buildProbeTargets", () => {
it("emits llms.txt, sitemap, OpenAPI guesses, + mcp subdomain for real hosts", () => {
it("emits llms.txt, sitemap, OpenAPI guesses, and MCP probes for real hosts", () => {
const targets = buildProbeTargets(normalizeBase("supabase.com"));
const urls = targets.map((t) => t.url);
expect(urls).toContain("https://supabase.com/llms.txt");
Expand All @@ -37,6 +37,9 @@ describe("buildProbeTargets", () => {
expect(urls).toContain(
"https://mcp.supabase.com/.well-known/oauth-protected-resource/mcp",
);
expect(urls).toContain(
"https://supabase.com/.well-known/oauth-protected-resource/mcp",
);
});

it("includes runtime-generated OpenAPI probe paths", () => {
Expand Down