MedRecPro Drug Label Server
com.medrecpro由 medrecpro.com 發布官方發布者v1.0.3更新於 Oct 24, 2026
Search and export FDA drug labels by brand name, generic ingredient, or UNII code.
概覽
一個遠端 MCP 伺服器,讓助理依品牌名、通用成分或 UNII 代碼搜尋並匯出 FDA 藥品標籤。
- 可以做什麼
- 依品牌名、通用成分或 UNII 代碼搜尋 FDA 藥品標籤,並將標籤匯出為 Markdown。搜尋即將到期的藥品專利,並依藥理分類查找藥品。查看已登入使用者的個人資料與活動紀錄,包括指定日期範圍內的活動。
- 適用情境
- 適合在助理內查詢藥品標籤資訊、專利到期情況或依藥理分類檢索藥品,並以唯讀方式查看自己在 MedRecPro 的資料與活動紀錄。
- 執行需求
- 透過 Streamable HTTP 連線至 medrecpro.com 的遠端端點,無需本機安裝。需要使用 Google 或 Microsoft 帳戶進行 OAuth 登入,新使用者會自動建立。需要能存取該服務的網路。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 MedRecPro Drug Label Server,將其新增到工作區。
- 連接 所需的 憑證。它們會被私密儲存,絕不會在公開頁面上展示。
- 為需要使用其工具的對話啟用該服務。
Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。
交給代理程式安裝
把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。
閱讀 https://sourceweft.com/mcp/com.medrecpro%2Fdrug-label-server/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。其他 MCP 客戶端
把它新增到你客戶端的 mcpServers 設定中。 客戶端會在首次連接時完成 OAuth 登入。
{
"mcpServers": {
"medrecpro-drug-label": {
"type": "http",
"url": "https://www.medrecpro.com/mcp"
}
}
}README
MedRecPro MCP Server
MCP (Model Context Protocol) server for the MedRecPro application. Acts as an OAuth 2.1 gateway between MCP clients (Claude, etc.) and the MedRecPro Web API.
Version: 1.0.0 Runtime: ASP.NET Core 8.0 Production URL: https://www.medrecpro.com/mcp
Architecture
The MCP server runs as an IIS virtual application at /mcp on the same Azure App Service as the main MedRecPro UI and API. IIS handles path-based routing to three separate ASP.NET Core processes:
Endpoints
All endpoints are externally prefixed with /mcp by the IIS virtual application.
Note:
GET /mcpreturns HTTP 405 (Method Not Allowed). This is correct behavior. The MCP transport only accepts POST requests. For browser-accessible pages, use/mcp/docs(technical documentation) or/mcp/getting-started(user-facing guide).
Authentication Flow
User Resolution and Auto-Provisioning
During the OAuth callback (step 9), the MCP server must map the upstream identity provider's identifier (Google sub / Microsoft GUID) to a numeric MedRecPro database user ID. The API's getEncryptedIdFromClaim() method expects a numeric NameIdentifier claim — without this resolution, all API calls would fail with 401.
How it works:
OAuthEndpoints.csextracts email, display name, and provider from upstream IdP claimsUserResolutionServicegenerates a temporary MCP JWT and callsPOST /api/users/resolve-mcp- The API's
UsersController.ResolveMcpUser()looks up the user by email:- User exists: Returns their encrypted database user ID
- User doesn't exist: Auto-provisions a new user record (matching
AuthController.createUserForExternalLogin()defaults: EmailConfirmed=true, Timezone="UTC", Locale="en-US", no password), then returns the encrypted ID
UserResolutionServicedecrypts the encrypted ID using the sharedSecurity:DB:PKSecretviaStringCipherOAuthEndpoints.csreplaces the upstreamNameIdentifierclaim with the numeric database user IDMcpTokenService.normalizeClaimType()convertsClaimTypes.NameIdentifierto the standard JWTsubclaim during token creation, andOutboundClaimTypeMapis cleared to prevent double-mapping- The MCP JWT is issued with the numeric user ID as the
subclaim, enabling all API calls to succeed
Key architecture:
TokenForwardingHandlerforwards the MCP JWT directly to the API (not the upstream Google/Microsoft token). The API'sMcpBearerauthentication scheme validates these MCP-signed JWTs.- Both the MCP server and API share
Security:DB:PKSecretfrom Azure Key Vault forStringCipherencryption/decryption of user IDs. UserResolutionServiceuses a dedicated"MedRecProApiDirect"named HttpClient (withoutTokenForwardingHandler) to avoid circular token forwarding during resolution.- Claim normalization:
McpTokenServicenormalizes .NETClaimTypesURIs to standard JWT short names (sub,name,email,given_name,family_name) before token creation. Both JWT handlers setMapInboundClaims = falseso claims retain their short names when read back. The API'sClaimHelperresolves user IDs from bothClaimTypes.NameIdentifier(cookie auth) and"sub"(MCP JWT auth).
Compiler Directives (#if DEBUG)
Route paths use compiler directives to handle IIS virtual application path stripping. This follows the same pattern as ApiControllerBase in the MedRecPro API project.
Problem: IIS strips the /mcp prefix from requests before forwarding to the app. A request to www.medrecpro.com/mcp/oauth/authorize arrives at Kestrel as /oauth/authorize. Routes must account for this.
Files with compiler directives:
Program.cs- MCP transport, health check, docs, getting-started, image serving, PRM redirectEndpoints/OAuthEndpoints.cs- OAuth route group prefixEndpoints/OAuthMetadataEndpoints.cs- Well-known metadata paths
Config-driven (no directives needed):
- OAuth callback URLs - Built from
McpServer:ServerUrlat runtime - OAuth metadata document contents - Built from
McpServer:ServerUrlat runtime - Protected Resource Metadata - Built from
McpServer:ServerUrlat runtime
Setup Guide
Prerequisites
- .NET 8.0 SDK
- Azure subscription with:
- App Service (Windows, IIS) - shared with MedRecPro
- Key Vault (
medrecprovault) - Application Insights (optional)
- Cloudflare account with
medrecpro.comdomain - Google Cloud Console project with OAuth 2.0 credentials
- Microsoft Entra ID app registration
1. Local Development Setup
Clone and restore
Configure user secrets
Run locally
The server runs at http://localhost:5233. In DEBUG mode, endpoints include the /mcp prefix:
- Health check: http://localhost:5233/
- MCP transport: http://localhost:5233/mcp (POST only)
- Documentation: http://localhost:5233/mcp/docs
- Getting started: http://localhost:5233/mcp/getting-started
- Screenshot images: http://localhost:5233/mcp/docs/images/{filename}
- OAuth metadata: http://localhost:5233/mcp/.well-known/oauth-authorization-server
2. Azure App Service Setup
Add virtual application
In Azure Portal:
- Navigate to App Service "MedRecPro" > Configuration > Path mappings
- Click "+ Add virtual application or directory"
- Configure:
- Virtual path:
/mcp - Physical path:
site\wwwroot\mcp - Type: Check Application
- Virtual path:
- Click Save
Key Vault secrets
Ensure the following secrets exist in Azure Key Vault (medrecprovault). These are shared with the MedRecPro API since both apps use the same Key Vault:
Note: Key Vault uses
--as separator. ASP.NET Core maps these to:in configuration (e.g.,Jwt--KeybecomesJwt:Key).
Managed identity
The App Service must have a system-assigned managed identity with Get and List permissions on Key Vault secrets. Since the MCP virtual application shares the same App Service as the API, the existing managed identity should already have access.
3. OAuth Provider Configuration
Google Cloud Console
- Go to Google Cloud Console > APIs & Services > Credentials
- Edit your OAuth 2.0 Client ID
- Add authorized redirect URIs:
https://www.medrecpro.com/mcp/oauth/callback/google(production)http://localhost:5233/mcp/oauth/callback/google(development)
Microsoft Entra ID
- Go to Azure Portal > Microsoft Entra ID > App registrations
- Select your app > Authentication
- Add redirect URIs:
https://www.medrecpro.com/mcp/oauth/callback/microsoft(production)http://localhost:5233/mcp/oauth/callback/microsoft(development)
4. Cloudflare Configuration
Since the MCP server runs on the same domain (www.medrecpro.com), no DNS changes are needed. Configure the following rules:
Cache Rule — Bypass cache for /mcp
Caching > Cache Rules > Create rule
- Rule name:
Bypass cache for MCP server - When: Hostname equals
www.medrecpro.comAND URI Path starts with/mcp - Then: Cache eligibility: Bypass cache
Transform Rule — Disable response buffering for SSE
Rules > Transform Rules > Modify Response Header > Create rule
- Rule name:
Disable buffering for MCP SSE - When: Hostname equals
www.medrecpro.comAND URI Path starts with/mcp - Then: Set static header
X-Accel-Buffering=no
This prevents Cloudflare from buffering Server-Sent Events used by MCP Streamable HTTP transport.
WAF Rules (optional)
Only needed if you have existing WAF rules that might block POST requests to /mcp or /mcp/oauth/*. If your WAF has no custom rules, this step can be skipped.
5. Deployment
Publish from Visual Studio
- Right-click MedRecProMCP in Solution Explorer > Publish
- Select the "MedRecProMCP - Web Deploy" profile
- Verify settings:
- Configuration: Release
- Target Framework: net8.0
- Deployment Mode: Framework-dependent
- Click Publish
The publish profile deploys to site\wwwroot\mcp via the <DeployIisAppPath>MedRecPro/mcp</DeployIisAppPath> setting.
Publish from CLI
Then deploy via Azure CLI or zip deploy to the /mcp virtual application path.
6. Verification
After deployment, verify each endpoint:
Configuration Reference
appsettings.json (base)
Non-secret configuration shared across all environments.
appsettings.Development.json
appsettings.Production.json
Project Structure
Claude.ai Connector Integration
This section documents the process of connecting the MCP server as a custom connector in Claude.ai's Settings > Connectors. This was a multi-session effort with numerous obstacles specific to the IIS virtual application + Cloudflare + Azure architecture.
Anthropic Connectors Directory Submission
Submission materials for the Anthropic Connectors Directory:
Documentation.md— Submission document following Anthropic's template (description, features, setup, examples with screenshots)/mcp/getting-started— User-facing HTML page linked from the directory listing- Tool annotations — All 5 tools include
ReadOnly,Destructive, andOpenWorldsafety annotations - Authentication — OAuth 2.1 with PKCE, supports Dynamic Client Registration (RFC 7591). No special account required — reviewers authenticate with any Google or Microsoft account and are auto-provisioned.
Connection Status
Tool Safety Annotations
All 7 tools have MCP safety annotations declared via [McpServerTool] attribute properties (supported in ModelContextProtocol SDK v0.7.0-preview.1):
Annotation rationale:
- All tools are read-only — no data is modified by any tool
- All tools use
OpenWorld = falsebecause all data is self-contained in the MedRecPro database, populated via the console application
Issues Encountered and Fixes
The following issues were encountered in order during integration. Each had to be resolved before the next became visible.
1. PKCE Validation Failure
Symptom: OAuth token exchange failed with PKCE mismatch.
Root Cause: The PKCE verifier/challenge pair was not being correctly stored and matched across the authorization flow.
Fix: Corrected the PKCE storage and validation logic in PkceService.cs.
2. Discovery Endpoints Returning 302 Redirects
Symptom: Claude's MCP SDK received 302 redirects instead of JSON for /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server.
Root Cause: IIS path-based routing and the virtual application at /mcp caused discovery URL resolution issues. The MCP SDK expects /.well-known/* at the domain root, but the MCP server only handles requests under /mcp.
Fix: Added the well-known endpoints directly to MedRecProStatic/Program.cs (the root site), serving the OAuth metadata as static JSON responses. This avoids redirects entirely.
3. Missing [Authorize] on MCP Transport
Symptom: Claude could connect without authentication — no 401 challenge was sent.
Root Cause: The MapMcp() endpoint lacked .RequireAuthorization().
Fix: Added .RequireAuthorization() to the MapMcp("/") call in Program.cs (RELEASE configuration).
4. [AllowAnonymous] on MCP Transport
Symptom: Even with .RequireAuthorization(), the MCP transport was not triggering 401.
Root Cause: The MCP SDK's default transport middleware was internally applying [AllowAnonymous].
Fix: Used the McpAuthenticationHandler challenge scheme to ensure the WWW-Authenticate header with resource_metadata URI is returned on unauthenticated requests.
5. IIS Replacing 401 with HTML Error Pages
Symptom: Claude received HTML error pages instead of the JSON 401 response with WWW-Authenticate header.
Root Cause: IIS intercepts HTTP error responses and replaces them with its own HTML pages.
Fix: Added <httpErrors existingResponse="PassThrough" /> to web.config in both MedRecProStatic (root site) and MedRecProMCP. The root site's setting is critical because it is inherited by child virtual applications.
6. Wrong resource_metadata URL in 401 Response
Symptom: Claude could not find the Protected Resource Metadata (PRM) endpoint.
Root Cause: The resource_metadata URI in the WWW-Authenticate header was pointing to the wrong path.
Fix: Explicitly set ResourceMetadataUri in the McpAuthenticationHandler configuration to {ServerUrl}/.well-known/oauth-protected-resource.
7. PRM Endpoint 404
Symptom: The PRM endpoint returned 404 after the URL was corrected.
Root Cause: Route registration order and IIS path stripping resulted in the endpoint not being mapped.
Fix: Added explicit PRM endpoint registration in OAuthMetadataEndpoints.cs with correct routing.
8. Cloudflare "Manage AI Bots" WAF Rule Blocking Claude
Symptom: Claude's requests never reached the server (Cloudflare returned 403). Root Cause: Cloudflare's managed WAF rule "Block AI Bots" was blocking all requests from Claude-User (Anthropic's crawler user agent). The AI Crawl Control dashboard showed 149 blocked requests and 0 allowed. Fix (Cloudflare Dashboard):
- Security > Settings > Block AI Bots Scope — Changed to "Block only on hostnames with ads"
- Security > AI Crawl Control > Crawlers — Set
Claude-User(Anthropic) to Allow
9. JWT Audience Validation Failed (IDX10214)
Symptom: IDX10214: Audience validation failed. Audiences: 'https://www.medrecpro.com/mcp'. Did not match: validationParameters.ValidAudience: 'MedRecUsers'
Root Cause: McpTokenService issues tokens with audience set to ServerUrl (https://www.medrecpro.com/mcp), but the JWT Bearer handler only accepted MedRecUsers (from Jwt:Audience config).
Fix: Changed ValidAudience (single) to ValidAudiences (array) accepting both jwtSettings.Audience and mcpSettings.ServerUrl.TrimEnd('/').
10. JWT Issuer Validation Failed (IDX10205)
Symptom: IDX10205: Issuer validation failed. Issuer: 'https://www.medrecpro.com/mcp'. Did not match: validationParameters.ValidIssuer: 'MedRecPro'
Root Cause: Same dual-token issue as audience — McpTokenService uses ServerUrl as issuer, but JWT handler only accepted MedRecPro.
Fix: Changed ValidIssuer (single) to ValidIssuers (array) accepting both jwtSettings.Issuer and mcpSettings.ServerUrl.TrimEnd('/').
11. Downstream API Calls Blocked by Cloudflare Bot Fight Mode
Symptom: MCP tools executed but returned 403. The MCP server's HTTP calls to https://www.medrecpro.com/api/... were blocked.
Root Cause: The MCP server (running on Azure) makes outbound HTTP requests to the public API URL. These requests go through Cloudflare, which flagged them via Bot Fight Mode because they came from Azure IP addresses with an empty User-Agent header.
Fix (two-part):
- Code — Added
User-Agent: MedRecProMCP/1.0 (Internal-API-Client)header to both HttpClient registrations inProgram.cs - Cloudflare — Bot Fight Mode cannot be skipped via WAF custom rules, but it will not trigger if an IP Access Rule matches the request. Added IP Access Rules (action: Allow) for all 32 Azure App Service outbound IPs:
12. Azure SQL Database Cold Start Timeouts
Symptom: First tool calls after idle periods fail with Database 'MedRecProDB' is not currently available or Execution Timeout Expired (30-second command timeout).
Root Cause: Azure SQL Serverless auto-pauses after inactivity. Resuming takes 15-30+ seconds, exceeding both the HttpClient timeout (30s) and SQL command timeout (30s).
Status: Known issue. Subsequent requests succeed once the database warms up. Mitigation options include increasing the auto-pause delay, enabling EnableRetryOnFailure on UseSqlServer, or increasing the TimeoutSeconds in MedRecProApi settings.
13. JWT Claim Type Mapping Mismatch (401 on Tool Calls)
Symptom: After OAuth login succeeds and MCP JWT is generated, all tool calls that hit the API return 401. Logs show [Auth] Token validated for user: unknown and getEncryptedIdFromClaim() throws UnauthorizedAccessException: Unable to determine user ID from authentication context.
Root Cause: JwtSecurityTokenHandler.OutboundClaimTypeMap silently converts ClaimTypes.NameIdentifier to "sub" and ClaimTypes.Name to "unique_name" during JWT serialization. On the API side, getEncryptedIdFromClaim() searched for c.Type.Contains("NameIdentifier") which does not match "sub". Additionally, NameClaimType = "name" expected a "name" claim but the JWT contained "unique_name", causing Identity.Name to be null.
Fix (three-part):
- McpTokenService — Added
normalizeClaimType()to explicitly mapClaimTypes.*URIs to standard JWT short names (sub,name,email,given_name,family_name) before token creation. ClearedOutboundClaimTypeMapto prevent double-mapping. - Both JWT handlers — Added
MapInboundClaims = falseon the MCP server and APIMcpBearerhandlers so claims retain their original short names when read back intoClaimsPrincipal. - API claim readers — Created
ClaimHelper.csto resolve user IDs from bothClaimTypes.NameIdentifier(cookie auth) and"sub"(MCP JWT). Updated 9 scattered NameIdentifier lookups acrossUsersController,AiController,AuthController,LabelController,RequireActorAttributeFilter,RequireUserRoleAttributeFilter,ActivityLogActionFilter, andLogHelperto use the shared helper.
14. Missing [Authorize] on UsersController (401 on MCP Tool Calls)
Symptom: After fixing JWT claim normalization (Issue #13), MCP-side logs now show [Auth] Token validated for user: Christopher Barnes correctly, but API tool calls still return 401. ClaimHelper.GetEncryptedUserIdOrThrow throws because User.Claims is empty. IIS logs show Logon User: Anonymous. No [MCP Auth] log from the API side.
Root Cause: UsersController had no [Authorize] attribute at the class level or on individual endpoints (except resolve-mcp). Without [Authorize], ASP.NET Core's JWT bearer handler is never invoked for McpBearer tokens — the request arrives as anonymous and User.Claims is empty. Cookie auth worked without [Authorize] because Identity middleware runs globally and populates User.Claims from session cookies on every request, but JWT Bearer schemes require explicit [Authorize] to trigger validation.
Fix: Added [Authorize(Policy = "ApiAccess")] to the UsersController class. The ApiAccess policy (Program.cs) accepts both IdentityConstants.ApplicationScheme (cookies) and "McpBearer" (JWT), so this triggers the JWT handler for MCP requests while preserving existing cookie auth behavior. Added [AllowAnonymous] to signup and authenticate endpoints that must remain publicly accessible. Also fixed OnAuthenticationFailed handler that was silently suppressing SecurityTokenException log output.
15. GetMyActivity / GetMyActivityByDateRange Failing Silently
Symptom: After fixing Issue #14, GetMyProfile returns 200 successfully, but GetMyActivity and GetMyActivityByDateRange complete quickly with no second HTTP request to the activity endpoint. The MCP tools return {"error":"Could not determine user ID"} to Claude.
Root Cause (A — MCP side): UserTools.cs calls profile.TryGetProperty("encryptedId", ...) but the API serializes with Newtonsoft.Json using CamelCasePropertyNamesContractResolver — the actual JSON property name is "encryptedUserId" (camelCase, and "User" was missing from the original lookup key). The case-sensitive TryGetProperty lookup fails and the second API call is never made.
Root Cause (B — API side): UsersController.cs GetUserActivity (line 452) and GetUserActivityByDateRange (line 630) used if (!isSelf || !claimsUser.IsUserAdmin()) — OR instead of AND. This blocked non-admin users from viewing their own activity logs. Only users who were both the target AND an admin could pass the check.
Fix: Changed "encryptedId" → "encryptedUserId" in UserTools.cs (both occurrences) to match the camelCase JSON property name. Changed || → && in both authorization checks in UsersController.cs so that self-access is allowed for all users, and admin access is allowed for any user's logs.
Lessons Learned
-
IIS virtual applications strip path prefixes. A request to
/mcp/oauth/authorizearrives at Kestrel as/oauth/authorize. All route mappings must account for this in RELEASE builds. Use#if DEBUGdirectives. -
OAuth discovery must be at the domain root. The MCP SDK resolves
/.well-known/*relative to the domain, not the MCP endpoint path. Serve these endpoints from the root site (MedRecProStatic), not the MCP virtual application. -
httpErrors existingResponse="PassThrough"is critical. Without it, IIS replaces 401 responses (needed for OAuth challenge) with HTML error pages. This must be set in the root site'sweb.configbecause child virtual applications inherit the setting. -
Cloudflare has multiple independent bot-blocking systems:
- "Block AI Bots" (WAF managed rule) — Controls AI crawler access. Allow Claude-User via AI Crawl Control.
- "Bot Fight Mode" — Blocks automated traffic from hosting provider IPs. Cannot be skipped with WAF rules. The only bypass is IP Access Rules.
-
Server-to-server calls through Cloudflare require whitelisting. When your server makes HTTP calls to your own public domain, those requests go through Cloudflare and will be flagged as bot traffic. Always set a
User-Agentheader on outbound HttpClients, and whitelist your server's outbound IPs in Cloudflare IP Access Rules. -
Azure App Service cannot make localhost connections. The sandbox prevents outbound socket connections to
127.0.0.1:80. Server-to-server calls within the same App Service must go through the public hostname. -
JWT tokens from different issuers need
ValidIssuers/ValidAudiencesarrays. When the MCP server issues tokens with different issuer/audience values than the existing user auth system, the JWT Bearer handler must accept both. Use the plural array properties, not the singular ones. -
Azure SQL Serverless cold starts can cascade. A paused database takes 15-30+ seconds to resume. If the MCP HttpClient timeout (30s) expires before the database wakes, the tool call fails. Consider
EnableRetryOnFailureand generous timeouts for serverless databases. -
Cloudflare API authentication: The Global API Key uses
X-Auth-Email+X-Auth-Keyheaders, notAuthorization: Bearer. API Tokens (scoped) useAuthorization: Bearer. Using the wrong format returnsUnable to authenticate request. -
JwtSecurityTokenHandlersilently renames claim types. TheOutboundClaimTypeMapconvertsClaimTypes.NameIdentifierto"sub"andClaimTypes.Nameto"unique_name"during JWT serialization. On the inbound side,MapInboundClaims(defaulttrue) may or may not reverse this depending on the handler implementation (JsonWebTokenHandlerin .NET 8 does not). Always explicitly normalize claims to standard JWT short names before token creation, clearOutboundClaimTypeMap, and setMapInboundClaims = falseon JWT handlers to ensure claim types are predictable end-to-end. -
JWT Bearer schemes require
[Authorize]to trigger validation. Unlike cookie/Identity middleware which runs globally on every request and populatesUser.Claimsfrom session cookies, JWT Bearer handlers only validate tokens when an endpoint has[Authorize](or a policy that references the scheme). Without it, the Bearer token in theAuthorizationheader is ignored, the request arrives as anonymous, andUser.Claimsis empty. If a controller mixes public and protected endpoints, use class-level[Authorize(Policy = "...")]with[AllowAnonymous]on public endpoints. -
JSON property names must match the API's serialization casing. The MedRecPro API uses Newtonsoft.Json with PascalCase (no camelCase conversion). When parsing API responses with
System.Text.Jsonin the MCP project,TryGetProperty()is case-sensitive —"encryptedId"will not match"EncryptedUserId". Always verify the exact property names returned by the API. -
De Morgan's law in authorization logic.
if (!isSelf || !isAdmin)is equivalent toif (!(isSelf && isAdmin))— this requires BOTH conditions to be true, not either. For "allow if self OR admin", useif (!isSelf && !isAdmin).
Troubleshooting
502 Bad Gateway
The MCP app is crashing on startup. Check:
- Kudu console — Browse to
https://<app>.scm.azurewebsites.net, navigate toLogFiles/and look forstdout-mcp*log files - Enable stdout logging — In
site\wwwroot\mcp\web.config, setstdoutLogEnabled="true", hit the URL again, check the log - Common cause: Key Vault not accessible. Verify
KeyVaultUrlis set inappsettings.Production.jsonand managed identity has access
IDX10703: key length is zero
The JWT signing key is empty. This means Key Vault secrets aren't loading:
- Verify
KeyVaultUrlis set tohttps://medrecprovault.vault.azure.net/inappsettings.Production.json - Verify the App Service managed identity has
GetandListpermissions on Key Vault secrets - Verify
ASPNETCORE_ENVIRONMENTis set toProductionin App Service environment variables
IDX10214 / IDX10205: Audience or Issuer validation failed
JWT tokens issued by McpTokenService use ServerUrl as both issuer and audience. The JWT Bearer handler must accept both the MCP values and the existing user auth values:
405 Method Not Allowed on /mcp
This is expected behavior. The MCP Streamable HTTP transport at /mcp only accepts POST requests. Browsers send GET, which returns 405.
403 Forbidden on downstream API calls
The MCP server's outbound HTTP calls to https://www.medrecpro.com/api/... are being blocked by Cloudflare:
- Check Cloudflare Firewall Events — Look for blocks with source
botFightormanagedChallenge - Verify IP Access Rules — All Azure App Service outbound IPs must be whitelisted in Cloudflare (Security > WAF > Tools > IP Access Rules, action: Allow)
- Verify User-Agent header — The HttpClient must send a non-empty User-Agent. Check
Program.csforclient.DefaultRequestHeaders.Add("User-Agent", ...) - Get outbound IPs:
az webapp show --resource-group <rg> --name <app> --query possibleOutboundIpAddresses --output tsv
OAuth callback errors
- Verify redirect URIs are registered in Google Cloud Console and Microsoft Entra ID
- Check that
McpServer:ServerUrlincludes/mcp(e.g.,https://www.medrecpro.com/mcp) - Callback URLs are built as
{ServerUrl}/oauth/callback/{provider}
SSE connection drops
- Verify Cloudflare transform rule sets
X-Accel-Buffering: nofor/mcppaths - Verify Cloudflare cache rule bypasses cache for
/mcppaths - Check Azure App Service always-on is enabled
Database timeout on first tool call
Azure SQL Serverless may be paused. The first request triggers a resume that takes 15-30+ seconds:
- Retry — The second attempt usually succeeds after the database warms up
- Increase auto-pause delay — In Azure Portal, set the serverless auto-pause delay to 10-15 minutes during testing
- Add retry logic — Consider
EnableRetryOnFailure()inUseSqlServer()configuration
MCP Registry Publishing
The server is registered on the official MCP Registry for discoverability by MCP clients.
Registry Entry: com.medrecpro/drug-label-server
Registry Search: https://registry.modelcontextprotocol.io/v0.1/servers?search=medrecpro
Prerequisites
-
mcp-publisher CLI — Install from GitHub releases:
-
Ed25519 keypair — Used for DNS domain verification (stored locally, NOT in repo)
-
DNS TXT record — Already configured in Cloudflare:
server.json
The registry metadata file is at MedRecProMCP/server.json:
Key points:
nameuses thecom.medrecpro/namespace (verified via DNS)iconsprovides an SVG (scalable) and 96x96 PNG for client displayremotesdeclares this as a hosted server (not an npm/PyPI package)packagesis omitted since the server isn't distributed as a package
Publishing Process
-
Authenticate with DNS verification:
⚠️ The private key is stored in a local script outside the repo. See
C:\Users\{user}\{folder}\{publisher-script}.ps1 -
Publish to the registry:
-
Verify the listing:
When to Publish Updates
Bump the version in server.json and re-publish when:
- Adding, removing, or renaming tools
- Changing the server URL
- Updating the description or metadata
The registry stores each version separately. Publishing does not deploy code — it only updates the catalog entry.
Maintaining Backward Compatibility
Since the deployed server is a single instance (not versioned packages), avoid breaking changes:
DNS Verification Reference
If you need to re-generate the keypair or set up on a new machine:
DNS TXT record format (in Cloudflare):
- Type: TXT
- Name:
@(root domain) - Content:
v=MCPv1; k=ed25519; p=<base64-public-key>
來源:MedRecProMCP/README.md,提交 ab920e6
工具
0版本歷史
1- v1.0.3最新Sep 16, 2026
評分
已滿足適用檢查項的 85%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通必需25 分
- 已宣告認證方式必需10 分
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分