ããã«ã¡ã¯ã ãã¡ã€ã³ãã£æ ªåŒäŒç€Ÿ ã§ Tech Lead ãããããŠããã£ãŠãæžç°ã§ãã çŸåšã®ãœãããŠã§ã¢éçºã®äžçã¯ãçæAIã®ç»å Žã«ãã倧ããªè»¢æç¹ãè¿ããŠããŸãã GitHub CopilotãClaude Codeãªã©çæAIãæŽ»çšããéçºæ¯æŽããŒã«ã次ã
ãšç»å Žããéçºè
ã®æ¥åžžçãªã¯ãŒã¯ãããŒã«çµã¿èŸŒãŸãã€ã€ãããŸãã ãã®ãããªç¶æ³ã®äžã§å
æ¥ãåŒç€Ÿããæ°ãµãŒãã¹ã®Findy AI+ããªãªãŒã¹ãããŸããã Findy AI+ã®Î±çã¯ãªã¢ãŒãMCPãµãŒããŒã§æäŸããŠããã以åã®èšäºã§ã玹ä»ãããŠããã ããŸããã tech.findy.co.jp äžè¬çãªWebãµãŒãã¹ã§ã¯ããŠãŒã¶ãŒåŽã®ã¢ããªã±ãŒã·ã§ã³ã®ä»ã«ã管çè
çšã®ã¢ããªã±ãŒã·ã§ã³ãçšæããããšãå€ããããŸãã Findy AI+ã§ã管çè
çšã®ã¢ããªã±ãŒã·ã§ã³ãçšæããŸããããä»åã¯ç®¡çè
çšã®MCPãµãŒããŒãšããŠå®è£
ããããšã§ãå°çšã®ç»é¢ãå¿
èŠãšãããèªç¶èšèªã§ç®¡çæ©èœãå®è¡ã§ããããã«ããŸããã ããã§ä»åã¯ããã®ç®¡çè
çšã®MCPãµãŒããŒã«ã€ããŠæ·±å ã£ãŠè§£èª¬ããŠãããŸãã ããã§ã¯èŠãŠãããŸãããïŒ Findy AI+ãšã¯ Local MCP Server for Administrator ã¢ãŒããã¯ã㣠èªèšŒ å©ç𿹿³ã®çµ±äž Elicitation ãŸãšã Findy AI+ãšã¯ Findy AI+ã¯GitHub飿ºã»ããã³ããæç€ºã§çæAIã¢ã¯ãã£ããã£ãå¯èŠåããçæAIã®å©æŽ»çšåäžãæ¯æŽãããµãŒãã¹ã§ãã人ãšçæAIã®ååãåŸæŒãããŠãéçºçµç¹ã®å€é©ããµããŒãããŸãã GitHub Copilot / Claude Code / Devin / Codexã«å¯Ÿå¿ããŠãããçæAIã¢ã¯ãã£ããã£ãå¯èŠåããçæAI婿޻çšã®ããã«ããã¯çºèŠã»å©æŽ»çšæšé²ããµããŒãããŸãã ãŸãããŠãŒã¶ãŒãããã³ããã§æç€ºããŠãFindy AI+ã®MCPãµãŒããŒçµç±ã§çæAIã®å©æŽ»çšç¶æ³ãå®éã»å®æ§äž¡é¢ããèªåååŸããŸãã Local MCP Server for Administrator ãµãŒãã¹ããããã¯ããæäŸããå ŽåããŠãŒã¶ãŒåãã®æ©èœã ãã§ã¯ãªãããµãŒãã¹ã®ç®¡çè
åŽã®æ©èœãå¿
èŠã«ãªãããšããããŸãã ãã®ãããªå Žåã管çè
çšã®ç»é¢ãçšæããã®ãäžè¬çã§ãããããFindy AI+ã§ã¯ç®¡çç»é¢ãäœãããLocal MCP Serverãä»ããŠç®¡çè
çšã®APIãå®è¡åºæ¥ãããã«ç°å¢æ§ç¯ãè¡ããŸããã æšä»ã®Webããã³ããšã³ãã®ç»é¢ã¯ããã¶ã€ã³ããHTML/CSSãèªèšŒãããŒã¿éä¿¡ãªã©ã1ç»é¢ãäœãããã«å¿
èŠãªèŠçŽ ãå€å²ã«æž¡ããããæ³å®ä»¥äžã«æéãšã³ã¹ããæããããšããããŸãã ãããããã®ä»çµã¿ã«ããããšã§ç®¡çè
çšã®ç»é¢ã®ãã¶ã€ã³ãå®è£
ãããå¿
èŠããªããæäœéã®APIãšMCPãµãŒããŒã®å®è£
ãããã ãã§ç®¡çæ©èœãçšæã§ããããã«ãªããŸããã ã¢ãŒããã¯ã㣠ã¢ãŒããã¯ãã£ã¯éåžžã«ã·ã³ãã«ã§ãã ãŸãFindy AI+ã®å©çšè
ãRemote MCP Serverã«æ¥ç¶ããŠãããããFindy AI+ããGitHubãDevinãªã©ãšãã£ãå€éšAPIãå®è¡ããŸãã Findy AI+ã®ç®¡çæ©èœã¯ç»é¢ãRemote MCP Serverã§ã¯ãªããéå¶ã¡ã³ããŒã®PCã«Local MCP ServerãçšæããŠæäŸããŸããLocal MCP ServerããFindy AI+ã®APIãå®è¡ããŸãã ãã®æãå©çšè
åŽãšç®¡çè
åŽã®APIã¯ãšã³ããã€ã³ãã¬ãã«ã§åããŠãããå©çšè
åŽãã管çè
çšã®APIãå®è¡åºæ¥ãªãããã«ãªã£ãŠããŸãã ãã®ä»çµã¿ãå®çŸããããšã§ãç®¡çæ©èœãå®è£
ããã³ã¹ããAPIã®å®è£
ãšLocal MCP Serverã®å®è£
ã³ã¹ãã ãã«ãªããéçºã³ã¹ãã倧å¹
ã«åæžããŸããã èªèšŒ 管çè
åãã®Local MCP Serverã®èªèšŒãéåžžã«ã·ã³ãã«ã§ãã éå¶ã¡ã³ããŒã®PCã§åããããMCPãµãŒããŒã®èµ·åæã«ç®¡çè
çšAPIã®å®è¡æš©éãæãããã¢ã¯ã»ã¹ããŒã¯ã³ãç°å¢å€æ°ã«ä»äžããŸãããŸããAPIã®å®è¡å
ãéçºçšãšãã以å€ã§åãæ¿ãã§ããããã«ãããŸãã { " inputs ": [ { " type ": " promptString ", " id ": " ACCESS_TOKEN ", " description ": " MCP Access Token for Findy AI+ Admin ", " password ": true } , { " type ": " promptString ", " id ": " ENV ", " description ": " production or staging or local ", " password ": false } ] , " servers ": { " admin ": { " command ": " node ", " args ": [ " /User/hoge/dist/apps/admin/main.js " ] , " env ": { " ACCESS_TOKEN ": " ${input:ACCESS_TOKEN} ", " ENV ": " ${input:ENV} " } } } } MCPãµãŒããŒãã管çè
çšã®APIãå®è¡ããéã«ããã®ã¢ã¯ã»ã¹ããŒã¯ã³ãhttp headerã«ä»äžããAPIåŽã§èªèšŒã確èªããŸãã import * as https from 'https' ; import createFetchClient from 'openapi-fetch' ; import type { paths } from './__generated__/schema.js' ; const adminApiEnv = process .env[ 'ENV' ] || 'local' ; const baseUrl = adminApiEnv === 'production' ? 'https://production.hoge.com' : adminApiEnv === 'staging' ? 'https://stg.hoge.com' : 'https://localhost:8000' ; const apiClient = createFetchClient< paths >( { baseUrl , credentials : 'include' , } ); const httpsAgent = new https.Agent( { rejectUnauthorized : false } ); await apiClient.POST( '/api/admin/hoge' , { params : { header : { Authorization : `Bearer ${ process .env[ 'ACCESS_TOKEN' ] } ` , } , } , body : { text : 'test' } , httpsAgent , } ); ãã®ããã«ãAPIã®å®è¡å
ã®åãæ¿ããšã¢ã¯ã»ã¹ããŒã¯ã³ããéå¶ã¡ã³ããŒã®ããŒã«ã«ç°å¢ã®ç°å¢å€æ°ã«æãããããšã§ãå®å
šã«ç®¡çéå¶ã§ããããã«æŽåããŸããã å©ç𿹿³ã®çµ±äž èªç¶èšèªãå©çšããŠãMCPãµãŒããŒçµç±ã§ç®¡çæ©èœãå©çšããããšã«ãªããŸãããããã§1ã€åé¡ãåºãŠããŸãã MCPãµãŒããŒãå®è¡ããéã«ãéå¶ã¡ã³ããŒãæå³ããæåãããããã³ãããå
¥ååºæ¥ãªãã±ãŒã¹ãæ³å®ãããŸãã ãã®åé¡ã解決ããããã«ãMCPãµãŒããŒã®PromptsãæŽ»çšããããšã«ããŸãããPromptsãå©çšããããšã§ãå®åæã䜿ã£ãŠåçã«ããã³ãããäœæããããšãå¯èœã«ãªããŸãã modelcontextprotocol.io äŸãã°ãæ°ããå¥çŽããŠé ããäŒæ¥æ
å ±ã远å ãããšããŸãããã®å Žåãæ¬¡ã®ãããªã³ãŒãã§ããã³ãããã®ãã®ãåçã«äœæã§ããŸãã import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js' ; import { z } from 'zod' ; const mcpServer = new McpServer( { name : 'Findy AI+ Admin MCP Server' , version : '0.0.1' , } ); mcpServer. prompt ( 'add_organization' , 'Add organization to Findy AI+' , { last_name : z.string().describe( 'Last Name(Family Name)' ), first_name : z.string().describe( 'First Name' ), email : z.string().email().describe( 'Email address' ), org_name : z.string().describe( 'Organization name' ), } , async ( { last_name , first_name , email , org_name } ) => { return { messages : [ { role : 'user' , content : { type : 'text' , text : `Findy AI+ã«çµç¹ã远å ããŠãã ããã ãã©ã¡ãŒã¿: - 管çè
å: ${ last_name } ${ first_name } - 管çè
ã¡ãŒã«ã¢ãã¬ã¹: ${ email } - çµç¹å: ${ org_name } ` , } , } , ] , } ; } ); å®éã«å®è¡ãããšãããã³ãããäœãããã«å¿
èŠãªæ
å ±ãèãããŸãã æç€ºã«åŸã£ãŠå
容ãå
¥åããŠãããšãæçµçã«åçãªããã³ãããäœæãããŸãã ããšã¯ãã®ãŸãŸå®è¡ããã ãã§ã誰ãå®è¡ããŠãåãçµæã«ãªããŸãã Elicitation MCPãµãŒããŒã§ç®¡çæ©èœãå®çŸããããã§é¿ããŠéããªãåé¡ããã1ã€ãããŸããåºæ¬çã«MCPãµãŒããŒãšã®ããåãã¯äžæ¹éè¡ã ãšããããšã§ãã MCPãµãŒããŒãšã®ããåãã®åºæ¬çãªã·ãŒã±ã³ã¹å³ã¯ãããªããŸãã ãã®ã·ãŒã±ã³ã¹å³ããåããéãããªã¯ãšã¹ããæãããã¬ã¹ãã³ã¹ãè¿ã£ãŠãããšãã£ããäžè¬çãªæµãã§ãã ãããå
¥åããäŒæ¥åãééã£ãŠãããŸãŸããã³ãããå®è¡ããŠããŸã£ãå Žåãééã£ãæ
å ±ã®ãŸãŸã§APIãå®è¡ãããŠããŸãã®ãæ¢ããææ®µããããŸããã ããã§æŽ»èºããã®ãã以åã«ä»ã®èšäºã§ã玹ä»ããMCPã®Elicitationãšããæ©èœã§ãã tech.findy.co.jp Elicitationãå©çšããããšã§ãMCPãµãŒããŒãšã®ããåãã®ã·ãŒã±ã³ã¹å³ã¯æ¬¡ã®ããã«å€ãããŸãã confirmãšapproveã®ãããŒãå¢ããŠããã®ãåããããšæããŸããMCPãµãŒããŒãšMCPã¯ã©ã€ã¢ã³ãã®éä¿¡äžã«ããŠãŒã¶ãŒã«è¿œå æ
å ±ãèŠæ±ã§ããããã«ãªãã®ã§ãã Elicitationã䜿ã£ã確èªãããŒã®å®è£
äŸã¯æ¬¡ã®ããã«ãªããŸãã import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js' ; import { apiClient } from '@admin/api-client' ; import * as https from 'https' ; import { z } from 'zod' ; const mcpServer = new McpServer( { name : 'Findy AI+ Admin MCP Server' , version : '0.0.1' , } ); mcpServer.tool( 'create_org' , 'Create a new organization' , { org_name : z.string().describe( 'Organization name' ), email : z.string().email().describe( 'Email address' ), last_name : z.string().describe( 'Last name(Family name)' ), first_name : z.string().describe( 'First name' ), } , { title : 'Create Organization Tool' , } , async ( { org_name , email , last_name , first_name } ) => { const confirmation = await mcpServer.server.elicitInput( { message : `çµç¹ " ${ org_name } " ãäœæããŸããïŒ \n 管çè
: ${ last_name } ${ first_name } ( ${ email } )` , requestedSchema : { type : 'object' , properties : { confirm : { type : 'string' , title : '確èª' , description : 'Type "yes" to confirm or "no" to cancel' , enum : [ 'yes' , 'no' ] , } , } , required : [ 'confirm' ] , } , } , { timeout : 30000 } ); if ( confirmation. action !== 'accept' || confirmation.content?. [ 'confirm' ] !== 'yes' ) { return { content : [ { type : 'text' , text : 'Organization creation cancelled by user.' , } , ] , } ; } const httpsAgent = new https.Agent( { rejectUnauthorized : false } ); const { response , data } = await apiClient.POST( '/api/admin/hoge' , { params : { header : { Authorization : `Bearer ${ process .env[ 'ACCESS_TOKEN' ] } ` , } , } , body : { org_name , email , last_name , first_name , } , httpsAgent , } ); if (response. status !== 201 || !data) { return { content : [ { type : 'text' , text : `Error: Unexpected response status ${ response. status} ` , } , ] , } ; } const { id , name , user_id , user_first_name , user_last_name , user_email } = data; return { content : [ { type : 'text' , text : `Organization created successfully: - ID: ${ id } - Name: ${ name } - User ID: ${ user_id } - User Name: ${ user_last_name } ${ user_first_name } - User Email: ${ user_email } ` , } , ] , } ; } ); å®éã«GitHub Copilot Chatã§Elicitationãå®è¡ããæ§åãèŠãŠã¿ãŸãããã ãŸãã¯å
çšç޹ä»ããããã³ãããå®è¡ããŸããToolã®å®è¡èš±å¯ãå°ããããã®ã§èš±å¯ããŸãããã ãããšã次ã®ãããªç¢ºèªã¹ããããåºåãããŸãã ãã®Respondãã¿ã³ãæŒäžãããšã次ã®ãããªç¢ºèªã¢ãŒãã«ã衚瀺ãããŸãã ä»åã®ã±ãŒã¹ã ãšyesãéžæãããšAPIãå®è¡ãããnoãéžæãããšããã§åŠçãçµäºãšãªããŸãã ãã®ããã«ãMCPãµãŒããŒãšã®éä¿¡äžã«ãŠãŒã¶ãŒã«éžæè¢ãèŠæ±ããŠåŠçãåå²ãããæã«Elicitationã¯å€§ããªåšåãçºæ®ããŸãã ãŸãšã ãããã§ããã§ããããïŒ ä»åã®å
容ã¯å
æ¥éå¬ãã Findy AI Meetup in Fukuoka #2 ã§ã玹ä»ãããŠããããŸããã ãã¡ãããã®æã®è³æãšãªããŸããæ¯éåèã«ããŠã¿ãŠãã ããã ãã¡ã€ã³ãã£ã§ã¯MCPã®æçšæ§ã«ãã¡æ©ãæ°ã¥ããæ€èšŒãç¶ããŠããŸããã ãã®çµæãéçºå¹çãäžããã ãã§ã¯ãªããä»å玹ä»ããããã«ãµãŒãã¹ã«åã蟌ãã ãããããã¯ãã®äœãæ¹ãæäŸã®ä»æ¹ãŸã§ãã倧ããå€ãããŸããã MCPã®å¯èœæ§ã¯ã©ãã©ãåºãã£ãŠããŸããæ¯éã¿ãªããã®MCPæŽ»çšæ³ãæããŠãã ããã çŸåšããã¡ã€ã³ãã£ã§ã¯äžç·ã«åãã¡ã³ããŒãåéäžã§ãã èå³ãããæ¹ã¯ãã¡ããã â herp.careers