Upgrade to Pro — share decks privately, control downloads, hide ads and more …

輸入実行関税率表をMCPサーバー化してみた

Avatar for Qlitre Qlitre
September 11, 2025
350

 輸入実行関税率表をMCPサーバー化してみた

Avatar for Qlitre

Qlitre

September 11, 2025
Tweet

Transcript

  1. ࣗݾ঺հ ͘Γͬͨʔ w 9 !LVSJ@UUFS ɹIUUQTRMJUSFNF w ࢓ࣄ w ߓ࿷෺ྲྀ૔ݿاۀ

    w ݱ৔؂ಜɺྫྷౚ૔ݿӦۀͳͲΛܦͯݱࡏ͸*5ௐୡ w ϓϩάϥϛϯά w झຯͰ)POP 1ZUIPOͳͲɻ w 8PSLFSTY)POP9ͰݸਓϒϩάͳͲެ։ ೥݄஑ାʹͯ
  2. ༌ೖ՟෺͕ྲྀ௨͢Δ·Ͱ ւ֎ อ੫஍Ҭ ʢ֎ࠃ՟෺Λஔ͚Δ৔ॴʣ ɾίϯςφϠʔυ ɾۭߓ ɾ෺ྲྀ૔ݿɹʜFUD ࠃ಺ ࢢ৔ ༌ૹɾൖೖ

    ൖग़ ༌ೖ ਃࠂ ੫ؔ ৹ࠪ ࠃ಺ ؔ੫ ೲ෇ ༌ೖ ڐՄ ͜͜Ͱར༻͢Δͷ͕༌ೖ࣮ߦؔ੫཰දʢλϦϑʣ ՙओʢ঎ࣾɾϝʔΧʔʣ͕ ෺ྲྀۀऀʹ༌ೖਃࠂखଓ͖ Λҕୗ͢Δͷ͕Ұൠతɻ
  3. w ༌ೖ͞ΕΔશͯͷ঎඼ʹ͍ͭ ͯɺܻ̕ͷ౷ܭ඼໨൪߸ͱؔ੫ ཰ΛఆΊͨҰཡද w ̓̕ΧςΰϦͰߏ੒ w ༌ೖਃࠂ࣌ʹඞཁͳؔ੫཰Λௐ ΂ΔͨΊͷඞਢπʔϧ w

    ੫ؔ8&#Ͱແྉެ։ɻ w ʮ༌ೖ࣮ߦؔ੫཰දʯͰ͙͙Δ ͱҰ൪্ʹग़ͯ͘Δ ༌ೖ࣮ߦؔ੫཰දʢλϦϑʣͱ͸ʁ IUUQTXXXDVTUPNTHPKQUBSJ ff @@JOEFYIUN
  4. ه࿥ͨ͠-&7&- ਂ͞ʣΛݩʹೖΕࢠɺ৿Λදݱɻ { "level": 0, "stat_code": "19.02", "desc": "ύελྨɾΫʔεΫʔε", "children":

    [ { "level": 1, "stat_code": "19.02", "desc": "ύελʢௐཧɾௐ੡͍ͯ͠ͳ͍΋ͷʣ", "children": [ { "level": 2, "stat_code": "1902.19", "desc": "ͦͷଞͷ΋ͷ", "children": [ { "level": 3, "stat_code": "1902.19", "desc": "ͦͷଞͷ΋ͷ", "children": [ { "level": 4, "desc": "ϚΧϩχٴͼεύήοςΟ", "children": [ { "level": 5, "stat_code": "1902.19", "hs_code": "093", "desc": "εύήοςΟ" } ] } ] } ] } ] } ] }
  5. )POPϓϩδΣΫτʹKTPOΛ഑ஔɻ γϯϓϧͳΩʔϫʔυݕࡧͰ)POPNDQͰ8PSLFSTʹσϓϩΠɻ DPOTUBQQOFX)POP  BQQBMM  BTZOD D \ DPOTUNDQ4FSWFSBXBJUHFU.DQ4FSWFS

    D  DPOTUUSBOTQPSUOFX4USFBNBCMF)5515SBOTQPSU  BXBJUNDQ4FSWFSDPOOFDU USBOTQPSU  SFUVSOUSBOTQPSUIBOEMF3FRVFTU D  ^  export const getMcpServer = async (c: Context<Env>) => { const server = new McpServer({ name: "japan-tariff-mcp", version: "0.0.1", }); server.tool( "searchTariffByKeywords", "Search tariff data by keywords (comma-separated)", { keywords: z.string().min(1) }, async ({ keywords }) => { const { results, hitCount } = await searchService.searchTariffData( keywords ); const limit = 30; let msg = ""; if (results.length > limit) { msg = `More than the maximum limit of ${limit} items were found. Please refer to hitCount and re-search if necessary.`; } return { content: [ { type: "text", text: JSON.stringify({ message: msg, hitCount: hitCount, results: results.slice(0, limit), }), }, ], }; } ); }; ۪௚ͳઢܗ୳ࡧɻݸͷKTPO ϑΝΠϧΛॱ൪ʹ։͖จࣈ͕ ؚ·ΕΔ͔൑ఆɻ )POPNDQͰ഑৴
  6. w ੈʹʮ8&#λϦϑʯͱݺ͹ΕΔެ ࣜݕࡧαΠτ͸ଘࡏ͢Δɻ w ঎඼໊͕ͦͷ··ࡌ͍ͬͯͳ͍έ ʔε΋ଟ͍ɻ w ྫ͑͹νϡʔϋΠͰݕࡧͯ͠΋ώ οτ͠ͳ͍ɻ w

    .$1͸νϡʔϋΠ মய Ξϧίʔ ϧҿྉͱʮΑ͠ͳʹʯྨޠݕࡧɻ w ݟ͔ͭΔ·ͰʮؤுΔʯɻ .$1ݕࡧπʔϧͷಛ௃ͱ௨ৗͱͷҧ͍
  7. w ΋ͱ΋ͱ୯ҰͷΩʔϫʔυͰ࣮૷ɻ w ݕࡧˠݟ͔ͭΒͳ͍ˠݕࡧʜͱ܁Γ ฦ͢ͷ͕৑௕ɻ w ΩʔϫʔυΛΧϯϚ۠੾ΓͰड͚औ ΔΑ͏ʹ஫ҙॻ͖ɻ w zνϡʔϋΠ

    মய Ξϧίʔϧҿྉz ͱ͍͏จࣈྻΛ"*͕౉ͯ͘͠ΕΔɻ w ϩδοΫଆͰTQMJUͯ͠Ұ୯ޠͣͭ൑ ఆɻࢼߦճ਺Λେ෯ʹ࡟ݮɻ ޻෉ᶃɹݕࡧΩʔϫʔυΛΧϯϚ۠੾ΓͰड͚औΔ server.tool( // ΧϯϚ۠੾ΓͰड͚औΔΑ͏ʹ͢Δ "searchTariffByKeywords", "Search tariff data by keywords (comma-separated)", { keywords: z.string().min(1) }, async ({ keywords }) => { // ϩδοΫଆͰsplitͯ͠ώοτ൑ఆ const { results, hitCount } = await searchService.searchTariffData( keywords ); ɹɹɹ…লུ );
  8. w ྫʣϑϥΠυνΩϯˠʮௐ੔ʯ͕ ݅ɺʮܲ೑ʯ͸݅ɻ ʢzௐ੔৯ྉ඼z͔Β࿈૝ʣ w Ωʔϫʔυ͝ͱͷώοτ݅਺Λه ࿥ͯ͠"*ʹฦ͢ɻ w ্ݶ஋Λ௒͑ͨΒɺ݅਺Λࢀߟʹ ࠶ݕࡧΛࢹ໺ʹೖΕΔɻ

    w ΠΠײ͡ʹيಓमਖ਼ͯ͠ߜΓ͜Μ Ͱ͘ΕΔΑ͏ʹͳͬͨɻ ޻෉ᶄɹҙਤ͠ͳ͍Ωʔϫʔυ͕ώοτͨ͠৔߹ͷيಓमਖ਼ server.tool( …ɹলུ async ({ keywords }) => { // ݕࡧΩʔϫʔυ͝ͱͷώοτ݅਺Λड͚औΔΑ͏ʹ͢Δ const { results, hitCount } = await searchService.searchTariffData( keywords ); // ώοτ਺ͷ্ݶΛઃఆ const limit = 30; let msg = ""; // ্ݶΛ௒͑ͯͨΒɺඞཁʹԠͯ͡࠶ݕࡧΛ͢Δ if (results.length > limit) { msg = `More than the maximum limit of ${limit} items were found. Please refer to hitCount and re-search if necessary.`; } return { // ϝοηʔδͱώοτ݅਺Λ݁Ռʹฦ͢ content: [ { type: "text", text: JSON.stringify({ message: msg, hitCount: hitCount, results: results.slice(0, limit), }), }, ], }; } );