मुख्य सामग्री पर जाएं

MCP Server

B1 API /mcp पर एक MCP (Model Context Protocol) server ships करता है। कोई भी MCP-aware AI क्लाइंट -- Claude Code, Claude Desktop, OpenAI Agents SDK, Cursor, या आपका स्वयं का -- इसे connect कर सकता है और एक authenticated चर्च उपयोगकर्ता की ओर से underlying REST API को कॉल कर सकता है। यह एक thin, generic wrapper है: तीन tools हैं, और वे पूरे API surface को dynamically expose करते हैं बजाय प्रत्येक endpoint को hand-modeling के।

शुरू करने से पहले

  • एक B1 API key (cak_…) जिसके पास जो scopes क्लाइंट को होने चाहिए
  • एक पहुंच योग्य B1 API host -- hosted चर्चों के लिए https://api.churchapps.org, या आपका स्वयं का deployment
  • एक MCP क्लाइंट। end-user setup के लिए Claude और ChatGPT देखें

Endpoint

POST /mcp
Content-Type: application/json
Accept: application/json, text/event-stream
Authorization: Bearer cak_<prefix>.<secret>
AspectValue
Path/mcp (API host के relative)
MethodPOST केवल -- request/response और SSE streaming दोनों समान endpoint पर होते हैं
TransportMCP Streamable HTTP
Session modelStateless। प्रति request एक fresh MCP server instance बनाया जाता है -- कोई session id, कोई resumption नहीं
AuthBearer token. cak_… API keys और B1 JWTs दोनों काम करते हैं; resolution किसी अन्य authenticated endpoint के समान है

एक अनुरोध जिसका Authorization हेडर missing या invalid है:

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

रिटर्न करता है HTTP 401 के साथ।

Tools

तीन tools, सभी generic। मॉडल discovery के लिए list_endpoints का उपयोग करता है, एक endpoint को जानने के लिए describe_endpoint, और वास्तव में API को invoke करने के लिए api_call

list_endpoints

Registered REST routes के पूरे inventory को रिटर्न करता है, एक optional substring और/या HTTP verb द्वारा filtered। प्रत्येक entry में controller नाम और most likely जरूरी API key scopes शामिल हैं।

Input:

FieldTypeDescription
filterstring (optional)Case-insensitive substring path से match किया गया, जैसे "people"
methodenum (optional)GET / POST / PUT / DELETE / PATCH

Output: एक JSON document जिसका form है

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

Inventory API startup से एक बार बनाया जाता है live route table से -- कुछ भी जो आप curl के साथ hit कर सकते हैं यहां दिखाई देता है।

describe_endpoint

एक short summary plus, जहां उपलब्ध हो, एक hand-curated request body और response sample एक endpoint के लिए।

Input:

FieldTypeDescription
methodstringHTTP verb
pathstringFull path जैसा list_endpoints द्वारा रिटर्न किया जाता है

Output: curated endpoints के लिए, एक उदाहरण जिसमें summary, requestBody, और responseSample हो। Un-curated endpoints के लिए, एक fallback संदेश मॉडल को GET कॉल करने के लिए shape देखने को निर्देश देता है। लगभग दर्जन high-traffic routes (people, groups, donations, attendance, funds) curated हैं।

api_call

चुने हुए REST endpoint को invoke करता है, in-process, Express middleware stack के माध्यम से एक normal HTTP request के रूप में -- auth, body parsing, audit logging, और per-church scoping सभी apply होते हैं।

Input:

FieldTypeDescription
methodenumGET / POST / PUT / DELETE / PATCH
pathstringPath जिसमें कोई भी module prefix शामिल हो, जैसे /membership/people
queryobject (optional)Query-string parameters का flat object
bodyany (optional)JSON request body -- typically model objects की एक array POST के लिए

Output:

{
"status": 200,
"truncated": false,
"body": [ /* controller का JSON response */ ]
}

Tool result को isError: true के साथ marked किया जाता है किसी भी response के लिए status ≥ 400।

Auth Model

MCP request स्वयं CustomAuthProvider.getUser() के through चलता है -- same path हर authenticated B1 endpoint उपयोग करता है। एक cak_… bearer एक Principal को resolve करता है जिसकी अनुमतियां issuing व्यक्ति की current RBAC हैं, key के granted scopes के साथ intersected। यह intersection हर request पर recomputed है, तो:

  • एक key से scope को हटाना (deleting और recreating द्वारा) अगली call पर एक्सेस को cut करता है।
  • B1Admin में underlying व्यक्ति से एक अनुमति हटाना अगली call पर एक्सेस को cut करता है, यहां तक कि यदि key अभी भी मौजूद है।

Nested api_call invocations के लिए, original Authorization हेडर synthetic request पर copied किया जाता है, तो CustomAuthProvider फिर से run होता है और scope intersection re-applied होता है प्रति call। कोई token caching नहीं है।

Path Blocklist

Routes का एक छोटा सेट api_call के through reachable नहीं है, यहां तक कि एक वैलिड key के साथ:

PatternWhy
/giving/donate/webhook/*Provider webhook endpoints raw, signature-verified bodies की अपेक्षा करते हैं Stripe/PayPal से -- general callers से नहीं
/membership/oauth/clients*OAuth client registration operator-only है
/membership/people/apiEmailsOperator jwtSecret द्वारा gated है, user permissions द्वारा नहीं
कोई भी route expecting multipart/form-dataFile uploads JSON-RPC-friendly नहीं हैं

एक blocked path एक isError: true tool result एक descriptive संदेश के साथ रिटर्न करता है; underlying route को कभी invoke नहीं किया जाता है।

Response Size Cap

प्रत्येक api_call response body captured output के 64 KB पर capped है। यदि एक query cap को exceed करता है, तो response "truncated": true carry करता है और मॉडल को narrower query parameters के साथ retry करने की अपेक्षा की जाती है। यह एक single tool response को क्लाइंट के context window से blow out होने से रोकता है।

Rate Limiting

/mcp पर कोई application-level rate limit नहीं है। Throttling production में API Gateway / Lambda concurrency को defer किया जाता है, और जो भी आपके reverse proxy self-hosted deployments में enforce करता है।

OAuth Discovery

MCP server OAuth 2.1 metadata (/.well-known/oauth-authorization-server, dynamic client registration, PKCE flow) advertise नहीं करता है। Clients जिन्हें OAuth-discovered MCP servers की आवश्यकता है -- notably Claude.ai के "Add custom connector" UI और ChatGPT के "Connectors" feature -- बिना उस surface के connect नहीं कर सकते।

Clients जो उनके config में एक static bearer token स्वीकार करते हैं -- Claude Code, Claude Desktop, OpenAI Agents SDK, Cursor, कस्टम कोड -- आज काम करते हैं। Existing OAuthController पहले से ही authorization-code + PKCE के through tokens issue करता है तीसरे पक्ष के ऐप के लिए; एक MCP-spec-compliant discovery layer इसके top पर अंतराल को close करेगा।

स्थानीय विकास

MCP endpoint सब कुछ के साथ mount करता है जब API locally चलता है:

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

Startup पर log line 📡 MCP server ready at /mcp — N routes in inventory inventory के built होने की पुष्टि करता है।

MCP Inspector के साथ probe करें:

npx @modelcontextprotocol/inspector

Inspector UI में, इसे http://localhost:8084/mcp पर point करें और Authorization हेडर को Bearer cak_<prefix>.<secret> पर set करें। पहले list_endpoints कॉल करें; आपको पूरी route list दिखनी चाहिए। फिर api_call({ method: "GET", path: "/membership/people" }) आपके local seed लोगों को रिटर्न करना चाहिए।

कोड लेआउट

MCP server Api repo में src/modules/mcp/ पर रहता है। Notable files:

FilePurpose
McpController.ts@controller("/mcp"); per request StreamableHTTPServerTransport को wire करता है
McpServer.tsएक MCP Server बनाता है, तीन tools को रजिस्टर करता है
RouteInventory.tsStartup पर routes को enumerate करने के लिए inversify-express-utils metadata को walk करता है
internalDispatch.tsSynthetic req/res जो in-process Express app में फिर से प्रवेश करता है
tools/listEndpoints.ts, describeEndpoint.ts, apiCall.ts
examples.tsHigh-traffic endpoints के लिए curated request/response samples

संबंधित