@@ -2,81 +2,85 @@ import type { APIRoute } from "astro";
22
33export const prerender = false ;
44
5+ /**
6+ * Implements RFC 9727 (API Catalog) returning application/linkset+json
7+ * conforming to RFC 9264 Linkset specification.
8+ */
59export const GET : APIRoute = async ( { locals } ) => {
610 const origin = locals . siteUrl . origin ;
711
812 const catalog = {
9- "api-catalog-version" : "1.0" ,
10- title : "CodingCat.dev Public API Catalog" ,
11- description :
12- "Machine-readable directory of public APIs, search services, and AI agent endpoints hosted on CodingCat.dev conforming to RFC 9727." ,
13- documentation : `${ origin } /llms.txt` ,
14- apis : [
13+ linkset : [
1514 {
16- name : "Content Search API" ,
17- description :
18- "Fast keyword and semantic search across technical blog posts, tutorials, and podcast episodes." ,
19- endpoints : [
15+ anchor : `${ origin } /api/search` ,
16+ "service-desc" : [
2017 {
21- url : `${ origin } /api/search` ,
22- method : "GET" ,
23- parameters : [
24- {
25- name : "q" ,
26- in : "query" ,
27- required : true ,
28- description : "Search keyword or natural language query" ,
29- schema : { type : "string" } ,
30- } ,
31- ] ,
18+ href : `${ origin } /.well-known/openapi.json` ,
19+ type : "application/vnd.oai.openapi+json" ,
20+ } ,
21+ ] ,
22+ "service-doc" : [
23+ {
24+ href : `${ origin } /llms.txt` ,
25+ type : "text/markdown" ,
26+ } ,
27+ ] ,
28+ status : [
29+ {
30+ href : `${ origin } /api/search?q=test` ,
31+ type : "application/json" ,
3232 } ,
3333 ] ,
3434 } ,
3535 {
36- name : "Model Context Protocol (MCP) Server" ,
37- description :
38- "Streamable HTTP MCP server implementing tools and resources for AI coding assistants and autonomous agents." ,
39- endpoints : [
36+ anchor : `${ origin } /api/mcp` ,
37+ "service-desc" : [
38+ {
39+ href : `${ origin } /.well-known/mcp/server-card.json` ,
40+ type : "application/mcp-server-card+json" ,
41+ } ,
42+ {
43+ href : `${ origin } /.well-known/openapi.json` ,
44+ type : "application/vnd.oai.openapi+json" ,
45+ } ,
46+ ] ,
47+ "service-doc" : [
4048 {
41- url : `${ origin } /api/mcp` ,
42- method : "POST" ,
43- description : "JSON-RPC 2.0 / Streamable HTTP MCP endpoint" ,
49+ href : `${ origin } /llms.txt` ,
50+ type : "text/markdown" ,
4451 } ,
4552 ] ,
46- metadata : {
47- serverCard : `${ origin } /.well-known/mcp/server-card.json` ,
48- mcpJson : `${ origin } /.well-known/mcp.json` ,
49- } ,
5053 } ,
5154 {
52- name : "Sponsorship Inquiry API" ,
53- description :
54- "Submit partnership and sponsorship inquiries for CodingCat.dev media channels." ,
55- endpoints : [
55+ anchor : `${ origin } /api/sponsorship` ,
56+ "service-desc" : [
57+ {
58+ href : `${ origin } /.well-known/openapi.json` ,
59+ type : "application/vnd.oai.openapi+json" ,
60+ } ,
61+ ] ,
62+ "service-doc" : [
5663 {
57- url : `${ origin } /api/sponsorship ` ,
58- method : "POST " ,
64+ href : `${ origin } /sponsorships ` ,
65+ type : "text/html " ,
5966 } ,
6067 ] ,
6168 } ,
6269 {
63- name : "Blog Content Syndication Feed" ,
64- description : "RSS 2.0 feed containing full articles and metadata." ,
65- endpoints : [
70+ anchor : `${ origin } /blog/rss.xml` ,
71+ "service-doc" : [
6672 {
67- url : `${ origin } /blog/rss.xml ` ,
68- method : "GET " ,
73+ href : `${ origin } /blog` ,
74+ type : "text/html " ,
6975 } ,
7076 ] ,
7177 } ,
7278 {
73- name : "Podcast Media Feed" ,
74- description :
75- "RSS feed with podcast audio enclosures, chapters, and show notes." ,
76- endpoints : [
79+ anchor : `${ origin } /podcasts/rss.xml` ,
80+ "service-doc" : [
7781 {
78- url : `${ origin } /podcasts/rss.xml ` ,
79- method : "GET " ,
82+ href : `${ origin } /podcasts` ,
83+ type : "text/html " ,
8084 } ,
8185 ] ,
8286 } ,
@@ -85,10 +89,11 @@ export const GET: APIRoute = async ({ locals }) => {
8589
8690 return new Response ( JSON . stringify ( catalog , null , 2 ) , {
8791 headers : {
88- "content-type" : "application/json; charset=utf-8" ,
92+ "content-type" : "application/linkset+json; charset=utf-8" ,
93+ "access-control-allow-origin" : "*" ,
8994 "cache-control" : "public, max-age=3600, s-maxage=86400" ,
9095 Vary : "Accept" ,
91- Link : `<${ origin } /.well-known/mcp/server-card.json>; rel="mcp-server-card", <${ origin } /llms.txt>; rel="llms-txt"` ,
96+ Link : `<${ origin } /.well-known/mcp/server-card.json>; rel="mcp-server-card", <${ origin } /llms.txt>; rel="llms-txt", < ${ origin } /.well-known/ai-catalog.json>; rel="ai-catalog" ` ,
9297 } ,
9398 } ) ;
9499} ;
0 commit comments