ð€« Authenticated Remote MCP Server
ããŒã«ã«ð€« Authenticated Remote MCP Server ã«ã€ããŠ
Authenticated Remote MCP Server ã¯ãAzure API Management ã§ä¿è·ããã Entra ID èªèšŒä»ãã®ãªã¢ãŒããµãŒããŒã Azure ã«ãããã€ããæ¹æ³ã瀺ããµã³ãã«ã§ããã¯ã©ã€ã¢ã³ã㯠MCP ãµãŒããŒåãã®ããŒã¯ã³ãååŸãããªã³ãããŒããªããããŒïŒon-behalf-ofïŒã§ Microsoft Graph ãžã¢ã¯ã»ã¹ããŸããREADMEã§ã¯å®éšçãªå®è£ ã§ãããæ¬çªç°å¢ã§ã®å©çšã¯æ³å®ãããŠããªããšæèšãããŠããŸãã
äž»ãªæ©èœ
- 01ãªã¢ãŒããµãŒããŒã® Entra ID ã«ããä¿è·
- 02Microsoft Graph ã¢ã¯ã»ã¹çšã®ãªã³ãããŒããªããããŒ
- 03åçã¯ã©ã€ã¢ã³ãç»é²ãš PKCE ãããŒ
- 04åæãã©ãŒã ã® Cookie ããŒã¹ CSRF 察ç
- 05azd up ã«ãã Azure ãžã®ãããã€
掻çšã·ãŒã³
- 01Azure äžã§ä¿è·ããããªã¢ãŒããµãŒããŒããããã€ããåŠç¿
- 02MCP Inspector ã«ãã Entra ID ãµã€ã³ã€ã³ãããŒã®æ€èšŒ
- 03ãµã€ã³ã€ã³ãŠãŒã¶ãŒã® Microsoft Graph ãããã¡ã€ã«ååŸ
MCP 察å¿
ãã®ãµã³ãã«ã¯ãªã¢ãŒããµãŒããŒã SSE ãšã³ããã€ã³ãã§å ¬éããMCP Inspector ãªã©ã® MCP ã¯ã©ã€ã¢ã³ããæ¥ç¶ã㊠get_graph_user_details ããŒã«ãåŒã³åºããŸãã
èšå®
ããŒã«ã«ãµãŒããŒã®èšå®ã¯ã©ã®ã¯ã©ã€ã¢ã³ãã§ãå ±éã§ããã³ããŒããŠã¯ã©ã€ã¢ã³ãã® MCP èšå®ãã¡ã€ã«ã«è²Œãä»ããŠãã ããã
npx -y @modelcontextprotocol/inspectorããŒã«ã«ãµãŒããŒã«ã¯ãã·ã³äžã®å®è¡ç°å¢ïŒNode.js 18 以äžãªã©ïŒãå¿ èŠã§ããèšå®ãã¡ã€ã«ã®å Žæã¯ã¯ã©ã€ã¢ã³ãããšã«ç°ãªããŸãã
ããŒã«
ããŒã«ã«ãµãŒããŒã®ããŒã«ã¯ãã·ã³äžã§èµ·åããŠåããŠååŸã§ããŸããã¡ã³ãããŒã¯ãŸã ããŒã«äžèЧãæäŸããŠããŸããã
詳现
ð€« èªèšŒæžã¿ãªã¢ãŒã MCP ãµãŒããŒ
ãã®ãµã³ãã«ã¯ãEntra ID ã§ä¿è·ããã MCP ãµãŒããŒã Azure ã«ãããã€ããæ¹æ³ã瀺ããŠããŸãã
ãã®ãµã³ãã«ã§ã¯ãã¯ã©ã€ã¢ã³ãããŸã MCP ãµãŒããŒçš ã®ããŒã¯ã³ãååŸãããã®åŸ on-behalf-of ãã㌠ã䜿çšããŠãMicrosoft Graph ã§äœ¿çšã§ããããŒã¯ã³ãšäº€æããèªå¯ãã¿ãŒã³ãæ¡çšããŠããŸããããããããããã¹ãŠãå®å šã«ã·ãŒã¯ã¬ããã¬ã¹ãªæ¹æ³ã§è¡ããŸãã
â ïž éèŠ: å®éšçãªå®è£
éèŠ
ããã¯å®éšçãªå®è£ ã§ãããæ¬çªç°å¢ã§ã¯äœ¿çšããªãã§ãã ããã
ãã®ãµã³ãã«ã¯ãEntra ID ããããã®æšæºããã€ãã£ãã«ãµããŒãããŠããªãçŸç¶ã®ã®ã£ãããåé¿ãããOAuth 2.0 åçã¯ã©ã€ã¢ã³ãç»é²ããã³ PKCE ãããŒãã¿ãŒã³ãå®è£ ããããšã§ãEntra ID ã䜿çšããŠä¿è·ããã MCP ãµãŒããŒãæ§ç¯ããæ¹æ³ã瀺ããŠããŸããæè¡çãªå¯èœæ§ã瀺ããã®ã§ãããæè²ããã³æŠå¿µå®èšŒãç®çãšãããã®ã«ãããŸããã
æ¬çªç°å¢ã®ã·ããªãªã§ã¯ãäºåç»é²ãããã¢ããªã±ãŒã·ã§ã³ãšæšæºç㪠OAuth ãããŒã䜿çšããã確ç«ãããèªèšŒãã¿ãŒã³ã®äœ¿çšãæ€èšããŠãã ããã
äœ¿çšæè¡
- â¡ Azure Functions
- ðžïž Azure API Management
- ðª Bicep
- ð Python
- ð Azure Developer CLI
ã¡ã¢
ãã® MCP ãµãŒããŒããã¹ãããã«ã¯ãModel Context Protocol Inspector ãŸã㯠Visual Studio Code ã䜿çšã§ããŸãã
èªå¯ãããŒã®ä»çµã¿
ãã®å®è£ ã§ã¯ãPKCE (Proof Key for Code Exchange) ãåããé«åºŠãª OAuth 2.0 ãããŒã䜿çšããŠãMCP ã¯ã©ã€ã¢ã³ããå®å šã«èªèšŒããŸããå šäœåã¯æ¬¡ã®ãšããã§ãã
sequenceDiagram
participant Client as MCP Client
participant Browser as User's Browser
participant APIM as API Management
participant Entra as Entra ID
participant Function as Azure Function
participant Graph as Microsoft Graph
Note over Client,Graph: 1. Discovery & Registration
Client->>APIM: GET /.well-known/oauth-authorization-server
APIM->>Client: OAuth metadata (authorization_endpoint, token_endpoint, etc.)
Client->>APIM: POST /register (Dynamic Client Registration)
Note over APIM: Store client info in CosmosDB<br/>Generate unique client_id
APIM->>Client: Client credentials (client_id, no secret)
Note over Client,Graph: 2. Authorization with PKCE
Note over Client: Generate code_verifier & code_challenge
Client->>Browser: Open authorization URL with PKCE params
Browser->>APIM: GET /authorize?client_id=...&code_challenge=...
Note over APIM: Check for existing consent cookie<br/>ðª __Host-MCP_APPROVED_CLIENTS
alt No previous consent
APIM->>Browser: Redirect to /consent page
Note over Browser: User reviews permissions and clicks "Allow"
Browser->>APIM: POST /consent (with CSRF protection)
Note over APIM: Set consent cookie<br/>ðª __Host-MCP_APPROVED_CLIENTS<br/>ðª __Host-MCP_CONSENT_STATE
end
APIM->>Browser: Redirect to Entra ID with state correlation
Note over APIM: Set Entra state cookie<br/>ðª __Host-MCP_ENTRA_STATE<br/>(contains sessionId|entraidState|clientState)
Browser->>Entra: Authorize with Entra ID
Note over Browser: User authenticates with Entra ID
Entra->>APIM: Callback with authorization code
Note over APIM: Validate state correlation<br/>Exchange code for Entra access token<br/>Generate encrypted session token
APIM->>Browser: Redirect with MCP authorization code
Note over Client,Graph: 3. Token Exchange
Browser->>APIM: POST /token (code + code_verifier)
Note over APIM: Validate PKCE challenge<br/>Return encrypted session token
APIM->>Browser: Access token (encrypted session key)
Browser->>Client: Token for MCP communication
Note over Client,Graph: 4. Authenticated MCP Communication
Client->>APIM: GET /mcp/sse (with Bearer token)
Note over APIM: Decrypt session token<br/>Lookup cached Entra token<br/>Add to request for downstream
APIM->>Function: Forward with Entra access token
Function->>Graph: API calls using on-behalf-of flow
Graph->>Function: User data
Function->>APIM: MCP response
APIM->>Client: Authenticated MCP response
ã»ãã¥ãªãã£æ©èœãšäœ¿çšããã Cookie
ãã®å®è£ ã§ã¯ãå®å šãªãããŒã確ä¿ããããã«ããã€ãã®ã»ãã¥ãªãã£ã¡ã«ããºã ãš Cookie ã䜿çšããŠããŸãã
| Cookie | ç®ç |
|---|---|
__Host-MCP_APPROVED_CLIENTS | ç¹å®ã®ã¯ã©ã€ã¢ã³ãã«å¯ŸãããŠãŒã¶ãŒã®åæãèšæ¶ããŸã |
__Host-MCP_DENIED_CLIENTS | æåŠãããåæãèšæ¶ããåããã³ãããé²ããŸã |
__Host-MCP_CONSENT_STATE | åæãã©ãŒã ã®éä¿¡ãæ€èšŒããŸã |
__Host-MCP_ENTRA_STATE | Entra ID ã³ãŒã«ããã¯ãå ã®ãªã¯ãšã¹ãã«é¢é£ä»ããŸã |
__Host-MCP_CSRF_TOKEN | åæãã©ãŒã ã«å¯Ÿãã CSRF æ»æãé²ããŸã |
ã¡ã¢
ãã¹ãŠã® Cookie ã¯æå€§éã®ã»ãã¥ãªãã£ã®ããã«
__Host-ãã¬ãã£ãã¯ã¹ãSecureãHttpOnlyãSameSite=Lax ã䜿çšããŠããŸã (ã¯ãã¹ãµã€ããªãã€ã¬ã¯ãã« SameSite=None ã䜿çšãã__Host-MCP_ENTRA_STATEãé€ã)ã
äž»ãªã»ãã¥ãªãã£æ©èœ:
- ð PKCE (Proof Key for Code Exchange) - èªå¯ã³ãŒãã®ååãé²ããŸã
- ðª ã»ãã¥ã¢ Cookie - ãã¹ãŠã® Cookie ãæå€§éã®ã»ãã¥ãªãã£ã®ããã«
__Host-ãã¬ãã£ãã¯ã¹ã䜿çšããŸã - ð¡ïž CSRF ä¿è· - 宿°æéæ€èšŒã䌎ãäºééä¿¡ Cookie ãã¿ãŒã³
- ð ç¶æ ã®é¢é£ä»ã - è€æ°å±€ã®ç¶æ æ€èšŒã«ããã»ãã·ã§ã³åºå®æ»æãé²ããŸã
- ð æå·åãããã»ãã·ã§ã³ããŒã¯ã³ - ã»ãã·ã§ã³èå¥å㯠AES ã§æå·åãããŸã
- â° ããŒã¯ã³ãã£ãã·ã¥ - ããã©ãŒãã³ã¹ã®ããã« Entra ããŒã¯ã³ãæå·åãããã»ãã·ã§ã³ããŒã§ãã£ãã·ã¥ããŸã
ã¯ããã«
以äžã®æé ã«åŸã£ãŠéå§ããŠãã ããã
-
ãªããžããªãããŒã«ã«ã«ã¯ããŒã³ããŸã:
git clone https://github.com/localden/remote-auth-mcp-apim-py -
ã¿ãŒããã«ã§ãªããžããªã«ç§»åããŸã:
cd remote-auth-mcp-apim-py -
Azure portal ãŸãã¯ä»¥äžã® Azure CLI ã³ãã³ããå®è¡ããŠããµãã¹ã¯ãªãã·ã§ã³ã«
Microsoft.AppãªãœãŒã¹ãããã€ããŒãç»é²ãããŠããããšã確èªããŸã:az login az provider register --namespace Microsoft.App --wait -
Azure Developer CLI ã«ãã°ã€ã³ããŸã:
azd auth login -
ãããžã§ã¯ãã Azure ã«ãããã€ããŸã:
azd up
éèŠ
ãã®ãããžã§ã¯ãããããã€ãããšãAzure ã®ã³ã¹ããçºçããŸãããã¹ããå®éšã®ããã«ãããã€ããå Žåã¯ããã¹ãåŸã«äœæãããªãœãŒã¹ã°ã«ãŒããå¿ ãåé€ããŠãã ããã
ãããžã§ã¯ãã®ãããã€ãšãã¹ã
azd up ãå®è¡ãããšãinfra ãã£ã¬ã¯ããªã§å®£èšããããªãœãŒã¹ã Azure ã¢ã«ãŠã³ãã«ããããžã§ãã³ã°ãããŸããæ¢åã® Bicep ãã¡ã€ã«ã確èªããããšã§ãã©ã®ãããªã€ã³ãã©ã¹ãã©ã¯ãã£ãèªåçã«ãããã€ãããããææ¡ã§ããŸãã

ãããã€ãå®äºãããšãã¿ãŒããã«ã« ãšã³ããã€ã³ã ãåºåãããŸã:

ããšãã°ãäžã®ã¹ã¯ãªãŒã³ã·ã§ããã§ã¯ãšã³ããã€ã³ã㯠https://apim-2lzunaz2nu642.azure-api.net/mcp/sse ã§ãããããã³ããŒããŸãã
ã¡ã¢
次ã®ã¹ãããã«é²ãåã«ãNode.js ãã€ã³ã¹ããŒã«ãããŠããããšã確èªããŠãã ãããModel Context Protocol Inspector ãå®è¡ããããã«å¿ èŠã§ãã
ã¿ãŒããã«ã§ä»¥äžãå®è¡ããŸã:
npx @modelcontextprotocol/[email protected]
ã¡ã¢
ä¿è·ããã MCP ãµãŒããŒããã¹ãããéã«æãå®å®ããããŒãžã§ã³ã§ãããããModel Context Protocol Inspector ã®
0.9.0ãªãªãŒã¹ã䜿çšããŠããŸãã
ããã«ãããModel Context Protocol Inspector ãããŒã«ã«ã§å®è¡ãããŠãããšã³ããã€ã³ãã衚瀺ãããŸãããã©ãŠã¶ãŒã§ãã® URL ãéããŸãã
Transport Type ã SSE ã«åãæ¿ããURL ããããã€ã®å®è¡ã§ååŸãããšã³ããã€ã³ãã«èšå®ããŸããConnect ãã¯ãªãã¯ããŸãã

ã€ã³ãã©ã¹ãã©ã¯ãã£ããããã€ããããã³ãå ã®è³æ Œæ å ±ã§èªèšŒããããæ±ããããŸããEntra ID ã¢ããªã±ãŒã·ã§ã³ã¯ãããã€æã«åçã«ç»é²ãããŸãã1 ã€ã¯ãµãŒããŒçšã§ããã 1 ã€ã¯ Microsoft Graph ãžã®ã¢ã¯ã»ã¹ãååŸããããã® on-behalf-of ãããŒã«äœ¿çšãããŸãã
åæãããšãModel Context Protocol Inspector ã®ã©ã³ãã£ã³ã°ããŒãžã«æ»ããŸããæ¥ç¶ã確ç«ããããŸã§æ°ç§åŸ ã¡ãŸããããŒãžã«ç·è²ã® Connected ã©ãã«ã衚瀺ãããŸãã

æ¥ç¶ããããList Tools ãã¯ãªãã¯ããget_graph_user_details ãéžæããŸããããã«ãããMicrosoft Graph ããçŸåšèªèšŒãããŠãããŠãŒã¶ãŒã«é¢ããããŒã¿ãååŸã§ããŸããRun Tool ãã¯ãªãã¯ããŸãã

ãã¹ãŠãããŸãããã°ã次ã®ããã«ã¬ã¹ãã³ã¹ãããã¯ã«ãŠãŒã¶ãŒããŒã¿ã衚瀺ãããŸã:
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"businessPhones": [],
"displayName": "YOUR_NAME",
"givenName": null,
"jobTitle": null,
"mail": "YOUR_EMAIL",
"mobilePhone": null,
"officeLocation": null,
"preferredLanguage": null,
"surname": null,
"userPrincipalName": "YOUR_UPN",
"id": "c6b77314-c0ec-44b2-b0bb-2c971a753f0c",
"success": true
}
ãã£ãŒãããã¯ãšåé¡ã®å ±å
åé¡ã«çŽé¢ãããã³ã¡ã³ããããå Žåã¯ãå¿ ãã€ã·ã¥ãŒãäœæããŠãã ããã
ã³ã¡ã³ã
MCP ã¯åããŠã§ããïŒ
ãããã³ã«ã®æŠèŠããæåã®ãµãŒããŒã®å°å ¥ãŸã§ãããããçåã«ãŸãšããŠçããŸãã
AI ã¢ããªã±ãŒã·ã§ã³ãå€éšã®ããŒã«ãããŒã¿ãœãŒã¹ã«çµ±äžçãªæ¹æ³ã§æ¥ç¶ããããã®ãªãŒãã³ãªãããã³ã«ã§ããã¯ã©ã€ã¢ã³ãã¯ã¢ãã«ãšã®å¯Ÿè©±ãæ ããMCP ãµãŒããŒã¯ããŒã«ã»ãªãœãŒã¹ã»ããã³ãããã³ãã¬ãŒããæäŸããŸããæšæºã¡ãã»ãŒãžã§ããåãããããã1 ã€ã®ãµãŒããŒãè€æ°ã®ã¯ã©ã€ã¢ã³ãã§åå©çšã§ããŸãã