ð HTTP + SSE MCP Server w/ OAuth
ããŒã«ã«ð HTTP + SSE MCP Server w/ OAuth ã«ã€ããŠ
ããã¯ãMCP 仿§ã®èªå¯æ¡åŒµã«åºã¥ããStreamable HTTP ãš SSE ãã©ã³ã¹ããŒãããã³ OAuth èªå¯ã«å¯Ÿå¿ãããªã¢ãŒã MCP ãµãŒããŒã®åç §å®è£ ã§ããç¬èªã®ãªã¢ãŒããµãŒããŒãæ§ç¯ããã TypeScript éçºè åãã§ãMCP ã®ããžãã¯ã OAuth èªèšŒæ å ±ãå·®ãæ¿ããŠå©çšã§ããŸãã
äž»ãªæ©èœ
- 01Streamable HTTP ãš SSE ãã©ã³ã¹ããŒããžã®å¯Ÿå¿
- 02Express ããŒã¹ã® OAuth èªå¯ãããã·
- 03åçã¯ã©ã€ã¢ã³ãç»é²ïŒRFC7591ïŒãžã®å¯Ÿå¿
- 04ã¹ããŒãã¬ã¹ãšã¹ããŒããã«ã®2ã€ã®ãšã³ããªãŒãã€ã³ã
- 05mcp-remote çµç±ã§ã® Cursor ãš Claude ããã®æ¥ç¶
掻çšã·ãŒã³
- 01ç¬èªã® MCP ãµãŒããŒãžã® OAuth ä¿è·ããããªã¢ãŒãã¢ã¯ã»ã¹ã®è¿œå
- 02mcp-remote ã䜿ã£ã Cursor ã Claude Desktop ããã®ãªã¢ãŒããµãŒããŒæ¥ç¶
- 03Auth0 ã§ã®åçã¯ã©ã€ã¢ã³ãç»é²ã®èšå®
MCP 察å¿
ãã®ãããžã§ã¯ãã¯ãStreamable HTTP ãš SSE ã§ MCP ã¯ã©ã€ã¢ã³ãã«ãµãŒãã¹ãæäŸããOAuth ã§èªå¯ãè¡ããªã¢ãŒã MCP ãµãŒããŒã®åç §å®è£ ã§ãã
èšå®
ããŒã«ã«ãµãŒããŒã®èšå®ã¯ã©ã®ã¯ã©ã€ã¢ã³ãã§ãå ±éã§ããã³ããŒããŠã¯ã©ã€ã¢ã³ãã® MCP èšå®ãã¡ã€ã«ã«è²Œãä»ããŠãã ããã
ãã®ãµãŒããŒã®ããã±ãŒãžããªã¢ãŒããšã³ããã€ã³ãã¯ãŸã ååŸã§ããŠããŸããããããžã§ã¯ãã® README ã®æé ã«åŸã£ãŠãã ããã
ããŒã«
ããŒã«ã«ãµãŒããŒã®ããŒã«ã¯ãã·ã³äžã§èµ·åããŠåããŠååŸã§ããŸããã¡ã³ãããŒã¯ãŸã ããŒã«äžèЧãæäŸããŠããŸããã
詳现
ð OAuth ã䜿çšãã HTTP + SSE MCP ãµãŒããŒ
ã¯ããã«
ãã®ãªããžããªã«ã¯ãMCP 仿§ã«åºã¥ã OAuth èªèšŒã«å¯Ÿå¿ããã¹ããªãŒãã³ã°å¯èœãª HTTP ããã³ SSE ãã©ã³ã¹ããŒãããµããŒããããªã¢ãŒã MCP ãµãŒããŒã®äœæã«åããããªãã¡ã¬ã³ã¹å®è£ ãå«ãŸããŠããŸãã
ãã®ãªããžããªã® MCP ãµãŒããŒã¯ãã¬ããŒãã® SSE ããã³ HTTP ãã©ã³ã¹ããŒããåŠçããã¢ããªã±ãŒã·ã§ã³ãããã³ OAuth ãšã¯è«ççã«åé¢ãããŠããç¹ã«ã泚æãã ããã
ãã®ããããã®ãªããžããªãç°¡åã«ãã©ãŒã¯ããç¬èªã® MCP ãµãŒããŒãš OAuth èªèšŒæ å ±ãçµã¿åãããããšã§ãç¬èªã®æ©èœãåãã SSEïŒHTTP + OAuth å¯Ÿå¿ MCP ãµãŒããŒãæ§ç¯ã§ããŸãã
ããã¯ãªãã§ããïŒ
ãã質åã§ãïŒMCP 仿§ã«ã¯ã2025 幎 3 æ 25 æ¥ã« OAuth ã«åºã¥ãèªå¯ä»æ§ã远å ãããŸããã2025 幎 5 æ 1 æ¥çŸåšã®ç¶æ³ã¯æ¬¡ã®ãšããã§ãã
- TypeScript SDK ã«ã¯ãã¹ããªãŒãã³ã°å¯èœãª HTTP ã䜿çšãã OAuth èªèšŒæžã¿ MCP ãµãŒããŒã®æ§ç¯ã«å¿ èŠãªéšåã倿°å«ãŸããŠããŸããããã®ãããªãµãŒããŒã®æ§ç¯æ¹æ³ã説æããããã¥ã¡ã³ãããã¥ãŒããªã¢ã«ã¯ãããŸãã
- Python SDK ã«ã¯ãã¹ããªãŒãã³ã°å¯èœãª HTTP ãã©ã³ã¹ããŒãã®å®è£ ããTypeScript SDK ã«å«ãŸããŠãã OAuth ã®éšåã®å®è£ ããããŸãã
- Cursor ã Claude ãã¹ã¯ããããªã©ã® MCP ãã¹ãã¢ããªã±ãŒã·ã§ã³ã§ã¯ãã¹ããªãŒãã³ã°å¯èœãª HTTP ãã©ã³ã¹ããŒãã¯åºããµããŒããããŠããŸããããã ããJS/TS SDK ã®
StreamableHttpClientTransportã¯ã©ã¹ã䜿çšããŠãJavaScript ã§äœæãããšãŒãžã§ã³ãã«çŽæ¥çµã¿èŸŒãããšã¯ã§ããŸã
Naptha AI ã§ã¯ãã¹ããªãŒãã³ã°å¯èœãª HTTP ãã©ã³ã¹ããŒãã䜿çšãã OAuth èªèšŒæžã¿ MCP ãµãŒããŒããã²æ§ç¯ããããšèããŠããŸãããããªãã¡ã¬ã³ã¹å®è£ ãèŠã€ãããªãã£ããããèªåãã¡ã§äœãããšã«ããŸããïŒ
äŸåé¢ä¿
Bun ã¯ãé«éã§ãªãŒã«ã€ã³ã¯ã³ã® JavaScript ã©ã³ã¿ã€ã ã§ãããã®ãªããžããªã§ã¯ãæšå¥šãããã©ã³ã¿ã€ã ããã³ããã±ãŒãžãããŒãžã£ãŒã§ããnpm + tsc ãšã®äºææ§ãã¹ãã¯éå®çã«å®æœãããŠããŸãã
æŠèŠ
ãã®ãªããžããªã§ã¯ã次ã®ãã®ãæäŸããŸãã
- ç¬èªã®ãã®ã«ç°¡åã«çœ®ãæãããã MCP ãµãŒããŒ
- SSE ãšã¹ããªãŒãã³ã°å¯èœãª HTTP ã®äž¡æ¹ã®ãã©ã³ã¹ããŒããããã³ OAuth èªå¯ã管çãã Express.js ã¢ããªã±ãŒã·ã§ã³
ãã® Express ã¢ããªã±ãŒã·ã§ã³ã«ãèªèšŒæ å ±ãš MCP ãµãŒããŒãçµã¿èŸŒã¿ãŸãã
ãã® Express ã¢ããªã¯ã/authorize ã Authorization Server Metadata ãšã³ããã€ã³ãïŒRFC8414ïŒãªã©ãå¿
èŠãª OAuth ãšã³ããã€ã³ããå®è£
ããŠããŸãããOAuth èªå¯ãµãŒããŒã¯å®è£
ããŠããŸããïŒ
ãã®äŸã§ã¯ãåçã¯ã©ã€ã¢ã³ãç»é²ïŒRFC7591ïŒããµããŒãããäžæµã® OAuth ãµãŒããŒã« OAuth ããããã·ããŸãããã®äŸã䜿çšããã«ã¯ãèªå¯ãµãŒããŒãåèªã§çšæããå¿ èŠããããŸããAuth0 ã®äœ¿çšãããããããŸãã詳ããã¯ã以äžã®ãOAuth ã®èšå®ãã»ã¯ã·ã§ã³ãã芧ãã ããã
ãµãŒããŒã®èšå®
OAuth ãšåçã¯ã©ã€ã¢ã³ãç»é²ã«é¢ããæ³šæäºé
ãã®äŸã䜿çšããã«ã¯ãOAuth èªå¯ãµãŒããŒãå¿ èŠã§ãããèªèº«ã§å®è£ ããªãã§ãã ããïŒ ãã¢ã®äœæã«ã¯ Auth0 ã䜿çšããŸãããAuth0 ã¯åªããéžæè¢ã§ãããã»ãã«ãå€ãã®éžæè¢ããããŸãã
MCP 仿§ã§ã¯ãäžè¬çã§ã¯ãªã OAuth æ©èœãå ·äœçã«ã¯ RFC7591 ã®åçã¯ã©ã€ã¢ã³ãç»é²ãžã®å¯Ÿå¿ãå¿ é ã§ããMCP 仿§ã§ã¯ãMCP ã¯ã©ã€ã¢ã³ããšãµãŒããŒãåçã¯ã©ã€ã¢ã³ãç»é²ãããã³ã«ã«å¯Ÿå¿ããããšãæšå¥šãããŠããŸããããã«ãããMCP ã¯ã©ã€ã¢ã³ãïŒã¯ã©ã€ã¢ã³ãã®ãã©ã³ã¹ããŒããã©ãã§åäœããŠããŠãïŒã¯ããŠãŒã¶ãŒç»é²ãªãã§ã¯ã©ã€ã¢ã³ã ID ãååŸã§ããŸããæ°ããã¯ã©ã€ã¢ã³ãïŒãšãŒãžã§ã³ããã¢ããªãªã©ïŒããæ°ãããµãŒããŒã«èªåçã«ç»é²ã§ããããã«ãªããŸãã詳现ã¯MCP 仿§ã®èªå¯ã«é¢ããã»ã¯ã·ã§ã³ãã芧ãã ããããã ããæ®å¿µãªãããåçã¯ã©ã€ã¢ã³ãç»é²ã«å¯Ÿå¿ããŠããªã Google ã GitHub ã®ãããªãããã€ããŒã«ãçŽæ¥ãããã·ããããšã¯ã§ããŸããïŒãããã®ãããã€ããŒã§ã¯ãUI äžã§ã¯ã©ã€ã¢ã³ããç»é²ããå¿ èŠããããŸãïŒã
éžæè¢ã¯æ¬¡ã® 2 ã€ã§ãã
- èªèšŒã« Google ã GitHub ãªã©ã® OIDC IDP ã䜿çšã§ããåçã¯ã©ã€ã¢ã³ãç»é²ã«ã察å¿ããŠãã Auth0 ã®ãããªäžæµ OAuth ãããã€ããŒãéžã¶ã
- åçã¯ã©ã€ã¢ã³ãç»é²ãã¢ããªã±ãŒã·ã§ã³åŽã§å®è£ ããïŒã€ãŸããExpress ã¢ããªã±ãŒã·ã§ã³ãåãªã OAuth ãããã·ã§ã¯ãªããå®å šãŸãã¯éšåç㪠OAuth ãµãŒããŒã«ããïŒãCloudflare ã¯ãWorkers OAuth MCP ãµãŒããŒåãã«ããã«äŒŒããã®ãå®è£ ããŠãããåŸæ¥ãã®ãããžã§ã¯ãã«æ¡åŒµãšããŠè¿œå ããå¯èœæ§ããããŸãã詳现ã¯ãã¡ããã芧ãã ããã
ç°¡åã«ãããããä»å㯠Auth0 ã䜿çšããåè ã®æ¹æ³ãéžã³ãŸããã
ã¡ã¢
ãã®å®è£ ã§ã¯äžæµ OAuth ãµãŒããŒã«ãããã·ãããããOAuth ãµãŒããŒããã®ã¢ã¯ã»ã¹ããŒã¯ã³ãã¯ã©ã€ã¢ã³ãã«è»¢éããæšæºçãªæ¹æ³ã§ã¯ããŠãŒã¶ãŒã®äžæµã¢ã¯ã»ã¹ããŒã¯ã³ãäžæµã®ã¯ã©ã€ã¢ã³ããš MCP ãã¹ãã«å ¬éãããŠããŸããŸãããã®æ¹æ³ã¯å€ãã®ãŠãŒã¹ã±ãŒã¹ã«é©ããªãããããã®å®è£ ã§ã¯@modelcontextprotocol/typescript-sdkã®äžéšã®ã¯ã©ã¹ãåå®è£ ãããã®åé¡ã解決ããŠããŸãã
äžæµã®èªå¯ãµãŒããŒã«ã¯ãããã·ããŸããããšã³ããŠãŒã¶ãŒã®èªèšŒããŒã¯ã³ã MCP ã¯ã©ã€ã¢ã³ãïŒãã¹ãã«è¿ãããšã¯ãããŸããã代ããã«ç¬èªã®ããŒã¯ã³ãçºè¡ããã¯ã©ã€ã¢ã³ãïŒãã¹ãããã®ããŒã¯ã³ã䜿ã£ãŠãã®ãµãŒããŒã«å¯Ÿããèªå¯ãè¡ããããã«ããŸããããã«ãããæªæã®ããã¯ã©ã€ã¢ã³ãããã¹ãã«ããããŒã¯ã³ã®æªçšããããŒã¯ã³ãæŒããããå Žåã®æªçšãé²ããŸãã
Auth0 ã§ã® OAuth ã®èšå®
Auth0 ã䜿ãå§ããã«ã¯ãæ¬¡ã®æé ã«åŸããŸãã
- Auth0.com ã§ Auth0 ã¢ã«ãŠã³ããäœæããŸãã
- Google ã GitHub ãªã©ã® IDP ãžã®æ¥ç¶ã 1 ã€ä»¥äžäœæããŸããèšå®æ¹æ³ã¯ãã¡ããã芧ãã ããã
- æ¥ç¶ã_ãã¡ã€ã³ã¬ãã«ã®æ¥ç¶_ã«ææ ŒãããŸããMCP ã¯ã©ã€ã¢ã³ãããšã«æ°ãã OAuth ã¯ã©ã€ã¢ã³ããç»é²ããããããIDP æ¥ç¶ãã¢ããªã±ãŒã·ã§ã³ïŒã¯ã©ã€ã¢ã³ãããšã«èšå®ããããšã¯ã§ããŸãããã€ãŸãããã¡ã€ã³å ã®ãã¹ãŠã®ã¢ããªã§æ¥ç¶ãå©çšã§ããããã«ããå¿ èŠããããŸããèšå®æ¹æ³ã¯ãã¡ããã芧ãã ããã
- åçã¯ã©ã€ã¢ã³ãç»é²ãæå¹ã«ããŸãïŒAuth0 ã§ã¯ãåçã¢ããªã±ãŒã·ã§ã³ç»é²ããšãåŒã°ããŸãïŒãèšå®æ¹æ³ã¯ãã¡ããã芧ãã ããã
ãã¹ãŠèšå®ããããæ¬¡ã®æ å ±ãå¿ èŠã«ãªããŸãã
- Auth0 ã®ã¯ã©ã€ã¢ã³ã ID
- Auth0 ã®ã¯ã©ã€ã¢ã³ãã·ãŒã¯ã¬ãã
- Auth0 ã®ããã³ããã¡ã€ã³
ãããã®æ
å ±ã .env ã«èšå
¥ããŠãã ããã.env.template ãã³ããŒããå€ãèšå®ãšã·ãŒã¯ã¬ããã«åãããŠæŽæ°ããŸãã
ãµãŒããŒã®å®è¡
ãã®ãªããžããªã«ã¯ãç¬ç«ãããµãŒããŒã 2 çš®é¡å«ãŸããŠããŸãã
src/app.stateless.tsã«ãããã¹ããªãŒãã³ã°å¯èœãª HTTP ãµãŒããŒã®ã¹ããŒãã¬ã¹ãªå®è£ ã§ããã¹ããªãŒãã³ã°å¯èœãª HTTP ãã©ã³ã¹ããŒãã®ã¿ããµããŒãããçè«äžã¯ãµãŒããŒã¬ã¹ç°å¢ãžã®ãããã€ã«é©ããŠããŸããsrc/app.stateful.tsã«ãããSSE ãšã¹ããªãŒãã³ã°å¯èœãª HTTP ã®äž¡æ¹ã«å¯Ÿå¿ããã¹ããŒããã«ãªå®è£ ã§ãããã®ã¢ããªã¯äž¡æ¹ã®ãã©ã³ã¹ããŒããæäŸããŸãããredisã¹ãã¬ãŒãžæŠç¥ã䜿çšããå Žåãã€ã³ã¡ã¢ãªç¶æ ãç¶æããŸãïŒæ¥ç¶ãã€ã³ã¡ã¢ãªã«ä¿æããå¿ èŠããããŸãïŒããã®ããããµãŒããŒã¬ã¹ç°å¢ãžã®ãããã€ããåçŽãªæ°Žå¹³ã¹ã±ãŒãªã³ã°ã«ã¯é©ããŠããŸããã
ã©ã¡ãã bun ã§å®è¡ã§ããŸãã
bun run src/app.stateless.ts
# or,
bun run src/app.stateful.ts
ãã¹ãŠããŸãšãã
ã¹ããªãŒãã³ã°å¯èœãª HTTP ãš OAuth ã«å¯Ÿå¿ãã MCP ãµãŒããŒããã¹ãããã«ã¯ãããã€ãã®æ¹æ³ããããŸãã
åè¿°ã®ãšãããPython MCP SDK ã¯ãããã®æ©èœããµããŒãããŠããŸããããã®ããçŸæç¹ã§ã¯ããªã¢ãŒããµãŒããŒã Cursor ã Claude Desktop ãªã©ã® MCP ãã¹ãã«æ¥ç¶ããããTypeScriptïŒJavaScript ã¢ããªã±ãŒã·ã§ã³ã«çŽæ¥æ¥ç¶ã§ããŸãããPython ã¢ããªã±ãŒã·ã§ã³ã«ã¯æ¥ç¶ã§ããŸããã
ãµãŒããŒã MCP ãã¹ãïŒCursorïŒClaudeïŒã«æ¥ç¶ãã
ã»ãšãã©ã® MCP ãã¹ãã¯ãã¹ããªãŒãã³ã°å¯èœãª HTTPïŒããŸããŸãªç¹ã§ SSE ããåªããŠããŸãïŒã OAuth ããµããŒãããŠããªããããOAuth èªèšŒãåŠçãããªã¢ãŒããã©ã³ã¹ããŒãããã¹ãåãã® STDIO ãã©ã³ã¹ããŒãã«ããªããžãã mcp-remote npm ããã±ãŒãžã®äœ¿çšãããããããŸãã
ã³ãã³ãã¯æ¬¡ã®ããã«ãªããŸãã
bunx mcp-remote --transport http-first https://some-domain.server.com/mcp
# or,
npx mcp-remote --transport http-first https://some-domain.server.com/mcp
--transport ãªãã·ã§ã³ã«ã¯ãããã€ãã®éžæè¢ããããŸãã
http-firstïŒããã©ã«ãïŒïŒãŸã HTTP ãã©ã³ã¹ããŒãã詊ããHTTP ã 404 ãšã©ãŒã§å€±æããå Žå㯠SSE ã«åãæ¿ããŸããsse-firstïŒãŸã SSE ãã©ã³ã¹ããŒãã詊ããSSE ã 405 ãšã©ãŒã§å€±æããå Žå㯠HTTP ã«åãæ¿ããŸããhttp-onlyïŒHTTP ãã©ã³ã¹ããŒãã®ã¿ã䜿çšããŸãããµãŒããŒã察å¿ããŠããªãå Žåã¯å€±æããŸããsse-onlyïŒSSE ãã©ã³ã¹ããŒãã®ã¿ã䜿çšããŸãããµãŒããŒã察å¿ããŠããªãå Žåã¯å€±æããŸãã
ã¡ã¢
src/app.stateless.tsã䜿ã£ãŠãµãŒããŒã® ã¹ããŒãã¬ã¹ çãèµ·åããå ŽåãSSE ãã©ã³ã¹ããŒãã¯å©çšã§ããªãããã--transport http-onlyã䜿çšããŠãã ããããã®ãšã³ããªãŒãã€ã³ãã§ã¯ãSSE ãã©ã³ã¹ããŒããåäœããããšã¯æ³å®ãããŠããŸããã
ãµãŒããŒããšãŒãžã§ã³ãã«æ¥ç¶ãã
StreamableHTTPClientTransport ã䜿ããšãã¹ããªãŒãã³ã°å¯èœãª HTTP ãµãŒããŒã JSïŒTS ã®ãšãŒãžã§ã³ãã«æ¥ç¶ã§ããŸãããã ãããã㯠OAuth ã§ä¿è·ããããµãŒããŒã§ã¯åäœããŸããã代ããã«ãã¯ã©ã€ã¢ã³ãåŽã§ Authorization ããããŒã䜿çšãããµãŒããŒåŽã§æå¹ãªã¢ã¯ã»ã¹ããŒã¯ã³ã䜿ã£ãŠãã ããã
ã¯ã©ã€ã¢ã³ãã¯ã¬ãã³ã·ã£ã«ãAPI ããŒãªã©ã䜿ã£ãŠå®è£ ã§ããŸãããã®ãã¿ãŒã³ã¯ãã®ãªããžããªã§ã¯ãµããŒããããŠããŸããããVercel AI SDK ã䜿ããšæ¬¡ã®ããã«ãªããŸãã
import { openai } from '@ai-sdk/openai';
import { experimental_createMCPClient as createMcpClient, generateText } from 'ai';
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const mcpClient = await createMcpClient({
transport: new StreamableHTTPClientTransport(
new URL("http://localhost:5050/mcp"), {
requestInit: {
headers: {
Authorization: "Bearer YOUR TOKEN HERE",
},
},
// TODO add OAuth client provider if you want
authProvider: undefined,
}),
});
const tools = await mcpClient.tools();
await generateText({
model: openai("gpt-4o"),
prompt: "Hello, world!",
tools: {
...(await mcpClient.tools())
}
});
ã³ã¡ã³ã
MCP ã¯åããŠã§ããïŒ
ãããã³ã«ã®æŠèŠããæåã®ãµãŒããŒã®å°å ¥ãŸã§ãããããçåã«ãŸãšããŠçããŸãã
AI ã¢ããªã±ãŒã·ã§ã³ãå€éšã®ããŒã«ãããŒã¿ãœãŒã¹ã«çµ±äžçãªæ¹æ³ã§æ¥ç¶ããããã®ãªãŒãã³ãªãããã³ã«ã§ããã¯ã©ã€ã¢ã³ãã¯ã¢ãã«ãšã®å¯Ÿè©±ãæ ããMCP ãµãŒããŒã¯ããŒã«ã»ãªãœãŒã¹ã»ããã³ãããã³ãã¬ãŒããæäŸããŸããæšæºã¡ãã»ãŒãžã§ããåãããããã1 ã€ã®ãµãŒããŒãè€æ°ã®ã¯ã©ã€ã¢ã³ãã§åå©çšã§ããŸãã