Hopp til hovedinnhold

MCP-server

B1-API-et leverer en MCP (Model Context Protocol)-server på /mcp. Enhver MCP-kompatibel AI-klient — Claude Code, Claude Desktop, OpenAI Agents SDK, Cursor eller din egen — kan koble til den og kalle det underliggende REST-API-et på vegne av en autentisert kirkebruker. Det er en tynn, generisk innpakning: tre generiske verktøy eksponerer hele API-overflaten dynamisk i stedet for å håndmodellere hvert endepunkt, pluss ett domeneveiledningsverktøy for nettstedsbyggeren.

Før du begynner

  • En B1 API-nøkkel (cak_…) med de omfangene klienten skal ha
  • En tilgjengelig B1-API-vert — https://api.churchapps.org for verts-baserte kirker, eller din egen distribusjon
  • En MCP-klient. Se Claude og ChatGPT for sluttbrukeroppsett

Endepunkt

POST /mcp
Content-Type: application/json
Accept: application/json, text/event-stream
Authorization: Bearer cak_<prefix>.<secret>
AspektVerdi
Sti/mcp (relativ til API-verten)
MetodeBare POST — både request/response og SSE-strømming skjer på samme endepunkt
TransportMCP Streamable HTTP
ØktmodellTilstandsløs. En ny MCP-serverinstans bygges per forespørsel — ingen økt-ID, ingen gjenopptakelse
AutentiseringBærertoken. Både cak_…-API-nøkler og B1-JWT-er fungerer; oppløsningen er den samme som for ethvert annet autentisert endepunkt

En forespørsel der Authorization-headeren mangler eller er ugyldig, returnerer:

{ "error": "Unauthorized — MCP requires a valid bearer token (cak_* API key or JWT)." }

med HTTP 401.

Verktøy

Tre generiske verktøy pluss én veiledning. Modellen bruker list_endpoints for oppdagelse, describe_endpoint for å lære en nyttelastform, api_call for faktisk å kalle API-et, og describe_page_builder når oppgaven involverer nettstedsinnhold.

list_endpoints

Returnerer den fullstendige oversikten over registrerte REST-ruter, filtrert etter en valgfri delstreng og/eller HTTP-verb. Hvert element inkluderer kontrollernavnet og de API-nøkkelomfangene som mest sannsynlig er nødvendige.

Inndata:

FeltTypeBeskrivelse
filterstreng (valgfritt)Delstreng, ikke skiller mellom store/små bokstaver, matchet mot stien, f.eks. "people"
methodenum (valgfritt)GET / POST / PUT / DELETE / PATCH

Utdata: et JSON-dokument av formen

{
"total": 24,
"endpoints": [
{
"method": "GET",
"path": "/membership/people",
"controller": "PersonController.getAll",
"likelyScopes": ["people:read", "people:write"]
}
]
}

Oversikten bygges én gang ved API-oppstart fra den aktive rutetabellen — alt du kan treffe med curl vises her.

describe_endpoint

Returnerer et kort sammendrag pluss, der det er tilgjengelig, en håndkuratert eksempel-forespørselskropp og responseksempel for ett endepunkt.

Inndata:

FeltTypeBeskrivelse
methodstrengHTTP-verb
pathstrengFull sti slik den returneres av list_endpoints

Utdata: for kuraterte endepunkter, et eksempel med summary, requestBody og responseSample. For ikke-kuraterte endepunkter, en fallback-melding som instruerer modellen til å kalle GET først for å se formen. Omtrent et dusin endepunkter med høy trafikk (personer, grupper, donasjoner, oppmøte, fond) er kuratert.

api_call

Kaller det valgte REST-endepunktet, in-process, gjennom den samme Express-mellomvarestabelen som en vanlig HTTP-forespørsel — autentisering, kroppsparsing, revisjonslogging og per-kirke-omfang gjelder alle.

Inndata:

FeltTypeBeskrivelse
methodenumGET / POST / PUT / DELETE / PATCH
pathstrengSti inkludert eventuelt modulprefiks, f.eks. /membership/people
queryobjekt (valgfritt)Flatt objekt med spørrestreng-parametere
bodyvalgfri (any)JSON-forespørselskropp — vanligvis et array av modellobjekter for POST

Utdata:

{
"status": 200,
"truncated": false,
"body": [ /* the controller's JSON response */ ]
}

Verktøyresultatet merkes isError: true for enhver respons med status ≥ 400.

describe_page_builder

Det eneste ikke-generiske verktøyet: en statisk, selvstendig veiledning til å bygge nettsteder gjennom /content/*-endepunktene — datamodellen side → seksjon → element, opprettelsesarbeidsflyten, hver elementType med sin answersJSON-form, innstillinger på seksjonsnivå som formdelerne dividerTop/dividerBottom, og et gjennomarbeidet ende-til-ende-eksempel. Det tar ingen inndata og speiler elementkatalogen som vedlikeholdes i B1Admin-redigeringsprogrammet (se Nettstedsbyggerarkitektur). Agenter forventes å kalle det én gang før de oppretter eller redigerer sideinnhold, og deretter handle via api_call.

Autentiseringsmodell

MCP-forespørselen selv kjøres gjennom CustomAuthProvider.getUser() — den samme stien som ethvert autentisert B1-endepunkt bruker. En cak_…-bærer løses til en Principal hvis tillatelser er den utstedende personens gjeldende RBAC, kryssgruppet med nøkkelens tildelte omfang. Dette krysset beregnes på nytt ved hver forespørsel, så:

  • Å fjerne et omfang fra en nøkkel (ved å slette og gjenskape den) kutter tilgangen ved neste kall.
  • Å fjerne en tillatelse fra den underliggende personen i B1Admin kutter tilgangen ved neste kall, selv om nøkkelen fortsatt finnes.

For nøstede api_call-kall kopieres den opprinnelige Authorization-headeren over til den syntetiske forespørselen, slik at CustomAuthProvider kjøres på nytt og omfangskrysset gjenanvendes for hvert kall. Det finnes ingen token-caching.

Stiblokkeringsliste

Et lite sett med ruter er ikke tilgjengelige via api_call, selv med en gyldig nøkkel:

MønsterHvorfor
/giving/donate/webhook/*Leverandørens webhook-endepunkter forventer rå, signaturverifiserte kropper fra Stripe/PayPal — ikke generelle kallere
/membership/oauth/clients*OAuth-klientregistrering er kun for operatør
/membership/people/apiEmailsBeskyttet av operatørens jwtSecret, ikke brukertillatelser
Enhver rute som forventer multipart/form-dataFilopplastinger er ikke JSON-RPC-vennlige

En blokkert sti returnerer et verktøyresultat med isError: true og en beskrivende melding; den underliggende ruten kalles aldri.

Grense for responsstørrelse

Hver api_call-responskropp er begrenset til 64 KB med fanget utdata. Hvis en spørring overskrider grensen, bærer responsen "truncated": true, og modellen forventes å prøve på nytt med snevrere spørreparametere. Dette hindrer at en enkelt verktøyrespons sprenger klientens kontekstvindu.

Hastighetsbegrensning

Det finnes ingen hastighetsbegrensning på applikasjonsnivå for /mcp. Strupingen overlates til API Gateway/Lambda-samtidighet i produksjon, og til det som reverse-proxyen din håndhever i selvhostede distribusjoner.

OAuth-oppdagelse

MCP-serveren annonserer ikke OAuth 2.1-metadata (/.well-known/oauth-authorization-server, dynamisk klientregistrering, PKCE-flyt). Klienter som krever OAuth-oppdagbare MCP-servere — særlig Claude.ai sitt «Legg til egendefinert kobling»-grensesnitt og ChatGPTs «Connectors»-funksjon — kan ikke koble til uten den overflaten.

Klienter som godtar et statisk bærertoken i konfigurasjonen sin — Claude Code, Claude Desktop, OpenAI Agents SDK, Cursor, egendefinert kode — fungerer i dag. Den eksisterende OAuthController utsteder allerede tokener via autorisasjonskode + PKCE for tredjepartsapper; et MCP-spesifikasjonskompatibelt oppdagelseslag oppå den ville tette gapet.

Lokal utvikling

MCP-endepunktet monteres sammen med alt annet når API-et kjøres lokalt:

cd Api
npm run dev
# Server listening on http://localhost:8084

Ved oppstart bekrefter loggraden 📡 MCP server ready at /mcp — N routes in inventory at oversikten ble bygget.

Test det med MCP Inspector:

npx @modelcontextprotocol/inspector

I Inspector-grensesnittet, pek det mot http://localhost:8084/mcp og sett Authorization-headeren til Bearer cak_<prefix>.<secret>. Kall list_endpoints først; du bør se hele rutelisten. Deretter bør api_call({ method: "GET", path: "/membership/people" }) returnere dine lokale seed-personer.

Kodeoppsett

MCP-serveren ligger i src/modules/mcp/ i Api-repositoriet. Bemerkelsesverdige filer:

FilFormål
McpController.ts@controller("/mcp"); kobler StreamableHTTPServerTransport per forespørsel
McpServer.tsBygger en MCP Server, registrerer de fire verktøyene
RouteInventory.tsGår gjennom inversify-express-utils-metadata ved oppstart for å liste opp ruter
internalDispatch.tsSyntetisk req/res som går inn i Express-appen igjen in-process
tools/listEndpoints.ts, describeEndpoint.ts, apiCall.ts, describePageBuilder.ts
examples.tsKuraterte forespørsel-/respons-eksempler for endepunkter med høy trafikk

Relatert