Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
輸入実行関税率表をMCPサーバー化してみた
Search
Qlitre
September 11, 2025
510
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
輸入実行関税率表をMCPサーバー化してみた
Qlitre
September 11, 2025
Featured
See All Featured
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
390
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
220
Raft: Consensus for Rubyists
vanstee
141
7.6k
Context Engineering - Making Every Token Count
addyosmani
9
1k
Information Architects: The Missing Link in Design Systems
soysaucechin
0
1k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
340
Balancing Empowerment & Direction
lara
6
1.2k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
220
Automating Front-end Workflow
addyosmani
1370
210k
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
320
Between Models and Reality
mayunak
4
370
Transcript
!LVSJ@UUFSɹ ༌ೖ࣮ߦؔ੫දΛ .$1αʔόʔԽͯ͠Έͨ
ࣗݾհ ͘Γͬͨʔ w 9 !LVSJ@UUFS ɹIUUQTRMJUSFNF w ࣄ w ߓྲྀݿاۀ
w ݱಜɺྫྷౚݿӦۀͳͲΛܦͯݱࡏ*5ௐୡ w ϓϩάϥϛϯά w झຯͰ)POP 1ZUIPOͳͲɻ w 8PSLFSTY)POP9ͰݸਓϒϩάͳͲެ։ ݄ାʹͯ
࣍ w ༌ೖ࣮ߦؔ੫දʹ͍ͭͯ w .$1࣮֓ཁ w σϞ w ධՁ
༌ೖ࣮ߦؔ੫දʹ͍ͭͯ
༌ೖ՟͕ྲྀ௨͢Δ·Ͱ ւ֎ อ੫Ҭ ʢ֎ࠃ՟Λஔ͚Δॴʣ ɾίϯςφϠʔυ ɾۭߓ ɾྲྀݿɹʜFUD ࠃ ࢢ ༌ૹɾൖೖ
ൖग़ ༌ೖ ਃࠂ ੫ؔ ৹ࠪ ࠃ ؔ੫ ೲ ༌ೖ ڐՄ ͜͜Ͱར༻͢Δͷ͕༌ೖ࣮ߦؔ੫දʢλϦϑʣ ՙओʢࣾɾϝʔΧʔʣ͕ ྲྀۀऀʹ༌ೖਃࠂखଓ͖ Λҕୗ͢Δͷ͕Ұൠతɻ
w ༌ೖ͞ΕΔશͯͷʹ͍ͭ ͯɺܻ̕ͷ౷ܭ൪߸ͱؔ੫ ΛఆΊͨҰཡද w ̓̕ΧςΰϦͰߏ w ༌ೖਃࠂ࣌ʹඞཁͳؔ੫Λௐ ΔͨΊͷඞਢπʔϧ w
੫ؔ8&#Ͱແྉެ։ɻ w ʮ༌ೖ࣮ߦؔ੫දʯͰ͙͙Δ ͱҰ൪্ʹग़ͯ͘Δ ༌ೖ࣮ߦؔ੫දʢλϦϑʣͱʁ IUUQTXXXDVTUPNTHPKQUBSJ ff @@JOEFYIUN
ύελͷ༌ೖ੫൪Λಛఆ͢Δ߹ (15Ͱੜ
ύελখഴคͰग़དྷ͍ͯΔɻୈྨΛΈΔɻ
ʹʼʹ֘ɹؔ੫جຊԁLH850ՃໍࠃԁLH ੫ϦϯΫΛ։͘ͱIUNMςʔϒϧ͕͋Γɺৄࡉͳ͕ܝࡌ
w ίʔυ छྨఔ͋ΓɺਓྗͰͷಛఆ͚ͬ͜ ͏͕͔͔࣌ؒΔɻ w ༌ೖ݅૿Ճɻͷຊʹ͓͚Δ༌ೖਃࠂ݅ ɺߤۭɾւ্Λซͤԯ ສ݅ w ʢࢀߟɿIUUQTXXXOBDDTKQBSDIJWFTVOLZPV
TIJSZPQEGʣ ՝ͱϞνϕʔγϣϯ ϦϞʔτ.$1αʔόʔԽ͢Εͷಛఆޮ ԽͰ͖ͦ͏ͳؾ͕ͨ͠ɻ ॻ੶͋Δɻ ஈɿ ԁ
.$1࣮֓ཁ
༌ೖ࣮ߦؔ੫දΛσʔλԽ IPOPNDQϔϧύʔͰΩʔϫʔυݕࡧΛ࣮ $MPVE fl BSF8PSLFSTʹσϓϩΠ ࣮ͷ֓ཁ
ߏɻDTWΑΓKTPO
1ZUIPOͷ#FBVUJGVMTPVQͰ8&#εΫϨΠϐϯάͯ͠σʔλԽ UETUZMFlQBEEJOHMFGUFNzύελʢՃʹΑΔௐཧΛʜʣUE-&7&- UETUZMFlQBEEJOHMFGUFNͦͷଞͷͷUE-&7&- UETUZMFQBEEJOHMFGUFNͦͷଞͷͷUE-&7&- UETUZMFQBEEJOHMFGUFN - ϚΧϩχٴͼεύήοςΟUE-&7&- ࢠؔʢʹͷਂ͞ʣIUNMTUZMFͷQBEEJOHͷͱlzͰఆ def extract_level(td)
-> int: """style="padding-left:…em" ͔Β֊ϨϕϧΛͰฦ͢""" # paddingͷΛൈ͖ग़͢ m = re.search(r"padding-left\s*:\s*([\d.]+)\s*em", td.get("style", "")) level = int(float(m.group(1))) if m else 0 # - ͷΛ͑Δ cnt = 0 for c in td.text.strip(): if c == "−": cnt += 1 else: break return level + cnt
هͨ͠-&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": "εύήοςΟ" } ] } ] } ] } ] } ] }
̍ྨɿಈʢੜ͖͍ͯΔͷʹݶΔʣʙ̓̕ྨɿඒज़ɺऩूٴͼͭ͜ͱ͏
)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Ͱ৴
w ੈʹʮ8&#λϦϑʯͱݺΕΔެ ࣜݕࡧαΠτଘࡏ͢Δɻ w ໊͕ͦͷ··ࡌ͍ͬͯͳ͍έ ʔεଟ͍ɻ w ྫ͑νϡʔϋΠͰݕࡧͯ͠ώ οτ͠ͳ͍ɻ w
.$1νϡʔϋΠ মய Ξϧίʔ ϧҿྉͱʮΑ͠ͳʹʯྨޠݕࡧɻ w ݟ͔ͭΔ·ͰʮؤுΔʯɻ .$1ݕࡧπʔϧͷಛͱ௨ৗͱͷҧ͍
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 ); ɹɹɹ…লུ );
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), }), }, ], }; } );
None
σϞ
ධՁ
w γϯϓϧͳϓϩάϥϜ͕ͩɺް͍λϦϑදΛΊ͘Δखؒল͚Δ w ࣾͷ༗ࣝऀʢ௨ؔ࢜ʣʹͬͯΒͬͨͱ͜Ζײ৮ͩͬͨɻ w ˋٻΊͣௐࠪͷऔֻ͔ͬΓͰ͑Εे༗༻ɻ w ίετ΄΅͔͔Βͳ͍ͱࢥΘΕΔɻ ධՁ
w HJUIVCൃදݩͱͳͬͨιʔείʔυશจ w IUUQTHJUIVCDPNRMJUSFKBQBOUBSJ ff NDQ
͋Γ͕ͱ͏͍͟͝·ͨ͠