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
Making the Leap to Tech Lead
cromwellryan
135
10k
Fireside Chat
paigeccino
42
4k
Git: the NoSQL Database
bkeepers
PRO
432
67k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
880
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.5k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
960
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
220
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
Discover your Explorer Soul
emna__ayadi
2
1.2k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Information Architects: The Missing Link in Design Systems
soysaucechin
0
1k
Reality Check: Gamification 10 Years Later
codingconduct
0
2.2k
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
͋Γ͕ͱ͏͍͟͝·ͨ͠