@nomadamas/k-skill 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (350) hide show
  1. package/bin/k-skill.js +60 -0
  2. package/package.json +37 -0
  3. package/skills/assembly-bill-vote-search/instruction.md +111 -0
  4. package/skills/assembly-bill-vote-search/skill.json +10 -0
  5. package/skills/biz-health-check/instruction.md +69 -0
  6. package/skills/biz-health-check/scripts/biz_health_check.py +163 -0
  7. package/skills/biz-health-check/skill.json +10 -0
  8. package/skills/bok-ecos-stats/instruction.md +95 -0
  9. package/skills/bok-ecos-stats/scripts/bok_ecos.py +302 -0
  10. package/skills/bok-ecos-stats/skill.json +10 -0
  11. package/skills/building-register-search/instruction.md +69 -0
  12. package/skills/building-register-search/scripts/building_register.py +309 -0
  13. package/skills/building-register-search/scripts/building_register_xml.py +32 -0
  14. package/skills/building-register-search/skill.json +9 -0
  15. package/skills/bunjang-search/instruction.md +154 -0
  16. package/skills/bunjang-search/skill.json +10 -0
  17. package/skills/catchtable-sniper/instruction.md +270 -0
  18. package/skills/catchtable-sniper/skill.json +9 -0
  19. package/skills/cheap-gas-nearby/instruction.md +107 -0
  20. package/skills/cheap-gas-nearby/skill.json +10 -0
  21. package/skills/corporate-registration-consulting/instruction.md +117 -0
  22. package/skills/corporate-registration-consulting/scripts/fill_official_hwp.py +106 -0
  23. package/skills/corporate-registration-consulting/skill.json +8 -0
  24. package/skills/coupang-product-search/instruction.md +219 -0
  25. package/skills/coupang-product-search/scripts/coupang_partners_mcp.py +146 -0
  26. package/skills/coupang-product-search/skill.json +10 -0
  27. package/skills/court-auction-notice-search/instruction.md +201 -0
  28. package/skills/court-auction-notice-search/skill.json +9 -0
  29. package/skills/court-payment-order-assistant/instruction.md +120 -0
  30. package/skills/court-payment-order-assistant/skill.json +10 -0
  31. package/skills/d2b-notice-search/instruction.md +117 -0
  32. package/skills/d2b-notice-search/skill.json +10 -0
  33. package/skills/daangn-cars-search/instruction.md +91 -0
  34. package/skills/daangn-cars-search/scripts/daangn_cars.py +72 -0
  35. package/skills/daangn-cars-search/skill.json +9 -0
  36. package/skills/daangn-jobs-search/instruction.md +90 -0
  37. package/skills/daangn-jobs-search/scripts/daangn_jobs.py +98 -0
  38. package/skills/daangn-jobs-search/skill.json +9 -0
  39. package/skills/daangn-realty-search/instruction.md +114 -0
  40. package/skills/daangn-realty-search/scripts/daangn_detail_ld.py +76 -0
  41. package/skills/daangn-realty-search/scripts/daangn_realty.py +216 -0
  42. package/skills/daangn-realty-search/scripts/daangn_relay_store.py +174 -0
  43. package/skills/daangn-realty-search/skill.json +8 -0
  44. package/skills/daangn-used-goods-search/instruction.md +90 -0
  45. package/skills/daangn-used-goods-search/scripts/daangn_used_goods.py +80 -0
  46. package/skills/daangn-used-goods-search/skill.json +9 -0
  47. package/skills/daishin-report-search/instruction.md +138 -0
  48. package/skills/daishin-report-search/skill.json +10 -0
  49. package/skills/daiso-product-search/instruction.md +172 -0
  50. package/skills/daiso-product-search/skill.json +8 -0
  51. package/skills/danawa-price-search/instruction.md +183 -0
  52. package/skills/danawa-price-search/scripts/danawa_search.py +354 -0
  53. package/skills/danawa-price-search/skill.json +8 -0
  54. package/skills/delivery-tracking/instruction.md +358 -0
  55. package/skills/delivery-tracking/skill.json +8 -0
  56. package/skills/donation-place-search/instruction.md +129 -0
  57. package/skills/donation-place-search/skill.json +9 -0
  58. package/skills/emergency-room-beds/instruction.md +82 -0
  59. package/skills/emergency-room-beds/skill.json +8 -0
  60. package/skills/ev-charger-nearby/instruction.md +80 -0
  61. package/skills/ev-charger-nearby/scripts/ev_charger.py +222 -0
  62. package/skills/ev-charger-nearby/skill.json +10 -0
  63. package/skills/ev-subsidy-status/instruction.md +165 -0
  64. package/skills/ev-subsidy-status/skill.json +10 -0
  65. package/skills/express-bus-booking/instruction.md +207 -0
  66. package/skills/express-bus-booking/references/kobus-http-flow.md +159 -0
  67. package/skills/express-bus-booking/scripts/kobus_express_booking.py +243 -0
  68. package/skills/express-bus-booking/skill.json +8 -0
  69. package/skills/fine-dust-location/instruction.md +89 -0
  70. package/skills/fine-dust-location/skill.json +9 -0
  71. package/skills/flight-ticket-search/instruction.md +237 -0
  72. package/skills/flight-ticket-search/scripts/flight_ticket_search.py +501 -0
  73. package/skills/flight-ticket-search/skill.json +9 -0
  74. package/skills/foresttrip-vacancy/instruction.md +167 -0
  75. package/skills/foresttrip-vacancy/scripts/run_foresttrip_vacancy.py +549 -0
  76. package/skills/foresttrip-vacancy/skill.json +10 -0
  77. package/skills/fsc-corporate-info/instruction.md +57 -0
  78. package/skills/fsc-corporate-info/scripts/fsc_corporate_info.py +113 -0
  79. package/skills/fsc-corporate-info/skill.json +10 -0
  80. package/skills/g2b-order-plan-search/instruction.md +131 -0
  81. package/skills/g2b-order-plan-search/scripts/g2b_order_plan.py +158 -0
  82. package/skills/g2b-order-plan-search/skill.json +10 -0
  83. package/skills/g2b-sanctioned-supplier/instruction.md +61 -0
  84. package/skills/g2b-sanctioned-supplier/scripts/g2b_sanctioned_supplier.py +114 -0
  85. package/skills/g2b-sanctioned-supplier/skill.json +10 -0
  86. package/skills/gangnamunni-clinic-search/instruction.md +113 -0
  87. package/skills/gangnamunni-clinic-search/skill.json +9 -0
  88. package/skills/geeknews-search/instruction.md +69 -0
  89. package/skills/geeknews-search/scripts/geeknews_search.py +296 -0
  90. package/skills/geeknews-search/skill.json +8 -0
  91. package/skills/gongsijiga-search/instruction.md +128 -0
  92. package/skills/gongsijiga-search/skill.json +9 -0
  93. package/skills/gov-overseas-trip-report/instruction.md +488 -0
  94. package/skills/gov-overseas-trip-report/scripts/gov_overseas_trip_report.py +1206 -0
  95. package/skills/gov-overseas-trip-report/skill.json +9 -0
  96. package/skills/han-river-water-level/instruction.md +83 -0
  97. package/skills/han-river-water-level/skill.json +10 -0
  98. package/skills/highway-traffic-status/instruction.md +88 -0
  99. package/skills/highway-traffic-status/scripts/highway_traffic.py +315 -0
  100. package/skills/highway-traffic-status/skill.json +11 -0
  101. package/skills/hipass-receipt/instruction.md +97 -0
  102. package/skills/hipass-receipt/skill.json +10 -0
  103. package/skills/hola-poke-yeoksam/instruction.md +247 -0
  104. package/skills/hola-poke-yeoksam/skill.json +8 -0
  105. package/skills/household-waste-info/instruction.md +117 -0
  106. package/skills/household-waste-info/skill.json +10 -0
  107. package/skills/housing-official-price/instruction.md +177 -0
  108. package/skills/housing-official-price/skill.json +10 -0
  109. package/skills/hwp/instruction.md +206 -0
  110. package/skills/hwp/skill.json +8 -0
  111. package/skills/intercity-bus-booking/instruction.md +189 -0
  112. package/skills/intercity-bus-booking/references/tmoney-intercity-http-flow.md +126 -0
  113. package/skills/intercity-bus-booking/scripts/intercity_bus_search.py +381 -0
  114. package/skills/intercity-bus-booking/skill.json +8 -0
  115. package/skills/iros-registry-automation/instruction.md +229 -0
  116. package/skills/iros-registry-automation/scripts/iros_pdf_summary.py +249 -0
  117. package/skills/iros-registry-automation/scripts/upstream.pin +1 -0
  118. package/skills/iros-registry-automation/skill.json +9 -0
  119. package/skills/job-posting-match/instruction.md +130 -0
  120. package/skills/job-posting-match/scripts/job_posting_match.py +396 -0
  121. package/skills/job-posting-match/scripts/test_job_posting_match.py +54 -0
  122. package/skills/job-posting-match/skill.json +8 -0
  123. package/skills/jobkorea-talent-search/instruction.md +118 -0
  124. package/skills/jobkorea-talent-search/scripts/jobkorea_talent_models.py +27 -0
  125. package/skills/jobkorea-talent-search/scripts/jobkorea_talent_parse.py +186 -0
  126. package/skills/jobkorea-talent-search/scripts/jobkorea_talent_search.py +94 -0
  127. package/skills/jobkorea-talent-search/scripts/jobkorea_talent_search_condition.py +136 -0
  128. package/skills/jobkorea-talent-search/scripts/test_jobkorea_talent_search.py +76 -0
  129. package/skills/jobkorea-talent-search/skill.json +9 -0
  130. package/skills/joseon-sillok-search/instruction.md +76 -0
  131. package/skills/joseon-sillok-search/scripts/sillok_search.py +552 -0
  132. package/skills/joseon-sillok-search/skill.json +8 -0
  133. package/skills/k-dart/instruction.md +406 -0
  134. package/skills/k-dart/skill.json +8 -0
  135. package/skills/k-schoollunch-menu/instruction.md +109 -0
  136. package/skills/k-schoollunch-menu/skill.json +9 -0
  137. package/skills/k-skill-cleaner/instruction.md +80 -0
  138. package/skills/k-skill-cleaner/scripts/k_skill_cleaner.py +410 -0
  139. package/skills/k-skill-cleaner/skill.json +8 -0
  140. package/skills/k-skill-setup/instruction.md +253 -0
  141. package/skills/k-skill-setup/skill.json +11 -0
  142. package/skills/kakao-bar-nearby/instruction.md +76 -0
  143. package/skills/kakao-bar-nearby/skill.json +8 -0
  144. package/skills/kakao-map/instruction.md +176 -0
  145. package/skills/kakao-map/skill.json +10 -0
  146. package/skills/kakaotalk-mac/instruction.md +189 -0
  147. package/skills/kakaotalk-mac/skill.json +8 -0
  148. package/skills/kbl-results/instruction.md +89 -0
  149. package/skills/kbl-results/skill.json +9 -0
  150. package/skills/kbo-results/instruction.md +82 -0
  151. package/skills/kbo-results/skill.json +8 -0
  152. package/skills/keris-academic-search/instruction.md +81 -0
  153. package/skills/keris-academic-search/scripts/keris_academic.py +210 -0
  154. package/skills/keris-academic-search/skill.json +10 -0
  155. package/skills/kleague-results/instruction.md +92 -0
  156. package/skills/kleague-results/skill.json +8 -0
  157. package/skills/kopis-performance-search/instruction.md +109 -0
  158. package/skills/kopis-performance-search/skill.json +10 -0
  159. package/skills/korea-weather/instruction.md +93 -0
  160. package/skills/korea-weather/skill.json +10 -0
  161. package/skills/korean-character-count/instruction.md +87 -0
  162. package/skills/korean-character-count/scripts/korean_character_count.js +268 -0
  163. package/skills/korean-character-count/skill.json +8 -0
  164. package/skills/korean-cinema-search/instruction.md +177 -0
  165. package/skills/korean-cinema-search/skill.json +8 -0
  166. package/skills/korean-heritage-search/instruction.md +106 -0
  167. package/skills/korean-heritage-search/scripts/korean_heritage_search.py +321 -0
  168. package/skills/korean-heritage-search/skill.json +8 -0
  169. package/skills/korean-holiday-calendar/instruction.md +97 -0
  170. package/skills/korean-holiday-calendar/skill.json +9 -0
  171. package/skills/korean-humanizer/instruction.md +389 -0
  172. package/skills/korean-humanizer/references/ai-tell-taxonomy.md +147 -0
  173. package/skills/korean-humanizer/skill.json +8 -0
  174. package/skills/korean-jangbu-for/instruction.md +133 -0
  175. package/skills/korean-jangbu-for/scripts/install.sh +237 -0
  176. package/skills/korean-jangbu-for/scripts/upstream.pin +1 -0
  177. package/skills/korean-jangbu-for/skill.json +8 -0
  178. package/skills/korean-law-search/instruction.md +126 -0
  179. package/skills/korean-law-search/skill.json +10 -0
  180. package/skills/korean-marathon-schedule/instruction.md +111 -0
  181. package/skills/korean-marathon-schedule/skill.json +9 -0
  182. package/skills/korean-middle-korean/instruction.md +79 -0
  183. package/skills/korean-middle-korean/scripts/korean_middle_korean.js +214 -0
  184. package/skills/korean-middle-korean/skill.json +8 -0
  185. package/skills/korean-patent-search/instruction.md +79 -0
  186. package/skills/korean-patent-search/scripts/patent_search.py +409 -0
  187. package/skills/korean-patent-search/skill.json +9 -0
  188. package/skills/korean-privacy-terms/instruction.md +128 -0
  189. package/skills/korean-privacy-terms/scripts/install.sh +108 -0
  190. package/skills/korean-privacy-terms/scripts/upstream.pin +1 -0
  191. package/skills/korean-privacy-terms/skill.json +8 -0
  192. package/skills/korean-scholarship-search/instruction.md +317 -0
  193. package/skills/korean-scholarship-search/references/report-format.md +40 -0
  194. package/skills/korean-scholarship-search/references/school-discovery.md +61 -0
  195. package/skills/korean-scholarship-search/references/search-clues.md +58 -0
  196. package/skills/korean-scholarship-search/references/source-patterns.md +67 -0
  197. package/skills/korean-scholarship-search/scripts/scholarship_filter.py +811 -0
  198. package/skills/korean-scholarship-search/scripts/test_scholarship_filter.py +224 -0
  199. package/skills/korean-scholarship-search/scripts/university_search_plan.py +148 -0
  200. package/skills/korean-scholarship-search/skill.json +8 -0
  201. package/skills/korean-slang-writing/instruction.md +181 -0
  202. package/skills/korean-slang-writing/scripts/_slang_http.py +91 -0
  203. package/skills/korean-slang-writing/scripts/slang_lookup.py +291 -0
  204. package/skills/korean-slang-writing/scripts/slang_search.py +284 -0
  205. package/skills/korean-slang-writing/skill.json +8 -0
  206. package/skills/korean-spell-check/instruction.md +105 -0
  207. package/skills/korean-spell-check/scripts/korean_spell_check.py +523 -0
  208. package/skills/korean-spell-check/skill.json +9 -0
  209. package/skills/korean-stock-search/instruction.md +194 -0
  210. package/skills/korean-stock-search/skill.json +10 -0
  211. package/skills/korean-transit-route/instruction.md +113 -0
  212. package/skills/korean-transit-route/skill.json +10 -0
  213. package/skills/kosis-stats/instruction.md +232 -0
  214. package/skills/kosis-stats/references/kosis-openapi-guide.md +171 -0
  215. package/skills/kosis-stats/scripts/run_kosis_stats.py +896 -0
  216. package/skills/kosis-stats/skill.json +9 -0
  217. package/skills/kr-whois-lookup/instruction.md +107 -0
  218. package/skills/kr-whois-lookup/skill.json +10 -0
  219. package/skills/kstartup-search/instruction.md +186 -0
  220. package/skills/kstartup-search/scripts/run_kstartup.py +424 -0
  221. package/skills/kstartup-search/skill.json +11 -0
  222. package/skills/ktx-booking/instruction.md +244 -0
  223. package/skills/ktx-booking/skill.json +10 -0
  224. package/skills/lck-analytics/instruction.md +192 -0
  225. package/skills/lck-analytics/scripts/_lib.js +103 -0
  226. package/skills/lck-analytics/scripts/analyze-live-game.js +52 -0
  227. package/skills/lck-analytics/scripts/build-match-report.js +44 -0
  228. package/skills/lck-analytics/scripts/sync-oracle.js +50 -0
  229. package/skills/lck-analytics/skill.json +9 -0
  230. package/skills/lh-notice-search/instruction.md +206 -0
  231. package/skills/lh-notice-search/skill.json +10 -0
  232. package/skills/library-book-search/instruction.md +139 -0
  233. package/skills/library-book-search/skill.json +9 -0
  234. package/skills/local-election-candidate-search/instruction.md +77 -0
  235. package/skills/local-election-candidate-search/skill.json +8 -0
  236. package/skills/localdata-business-status/instruction.md +64 -0
  237. package/skills/localdata-business-status/scripts/localdata_business_status.py +206 -0
  238. package/skills/localdata-business-status/skill.json +8 -0
  239. package/skills/lotto-results/instruction.md +80 -0
  240. package/skills/lotto-results/skill.json +8 -0
  241. package/skills/lovebug-report/instruction.md +185 -0
  242. package/skills/lovebug-report/skill.json +9 -0
  243. package/skills/market-kurly-search/instruction.md +125 -0
  244. package/skills/market-kurly-search/skill.json +8 -0
  245. package/skills/mfds-drug-safety/instruction.md +86 -0
  246. package/skills/mfds-drug-safety/scripts/mfds_drug_safety.py +184 -0
  247. package/skills/mfds-drug-safety/skill.json +10 -0
  248. package/skills/mfds-food-safety/instruction.md +126 -0
  249. package/skills/mfds-food-safety/scripts/mfds_food_safety.py +281 -0
  250. package/skills/mfds-food-safety/skill.json +10 -0
  251. package/skills/myrealtrip-search/instruction.md +239 -0
  252. package/skills/myrealtrip-search/scripts/myrealtrip_mcp.py +194 -0
  253. package/skills/myrealtrip-search/scripts/test_myrealtrip_mcp.py +99 -0
  254. package/skills/myrealtrip-search/skill.json +9 -0
  255. package/skills/naming-house/instruction.md +146 -0
  256. package/skills/naming-house/skill.json +8 -0
  257. package/skills/national-pension-workplace/instruction.md +64 -0
  258. package/skills/national-pension-workplace/scripts/national_pension_workplace.py +113 -0
  259. package/skills/national-pension-workplace/skill.json +10 -0
  260. package/skills/naver-ad-performance/instruction.md +108 -0
  261. package/skills/naver-ad-performance/scripts/naver_ad_performance.py +240 -0
  262. package/skills/naver-ad-performance/skill.json +9 -0
  263. package/skills/naver-blog-research/instruction.md +128 -0
  264. package/skills/naver-blog-research/scripts/_naver_http.py +58 -0
  265. package/skills/naver-blog-research/scripts/naver_download_images.py +233 -0
  266. package/skills/naver-blog-research/scripts/naver_read.py +256 -0
  267. package/skills/naver-blog-research/scripts/naver_search.py +192 -0
  268. package/skills/naver-blog-research/skill.json +8 -0
  269. package/skills/naver-news-search/instruction.md +103 -0
  270. package/skills/naver-news-search/skill.json +10 -0
  271. package/skills/naver-shopping-search/instruction.md +94 -0
  272. package/skills/naver-shopping-search/skill.json +11 -0
  273. package/skills/nhis-care-checkup-search/instruction.md +116 -0
  274. package/skills/nhis-care-checkup-search/skill.json +10 -0
  275. package/skills/nts-business-registration/instruction.md +115 -0
  276. package/skills/nts-business-registration/scripts/nts_business_registration.py +215 -0
  277. package/skills/nts-business-registration/skill.json +10 -0
  278. package/skills/nts-tax-delinquency/instruction.md +54 -0
  279. package/skills/nts-tax-delinquency/scripts/nts_tax_delinquency.py +150 -0
  280. package/skills/nts-tax-delinquency/skill.json +8 -0
  281. package/skills/ohou-today-deal/instruction.md +182 -0
  282. package/skills/ohou-today-deal/scripts/ohou_today_deal.py +369 -0
  283. package/skills/ohou-today-deal/skill.json +9 -0
  284. package/skills/olive-young-search/instruction.md +154 -0
  285. package/skills/olive-young-search/skill.json +8 -0
  286. package/skills/parking-lot-search/instruction.md +96 -0
  287. package/skills/parking-lot-search/skill.json +9 -0
  288. package/skills/popbill/instruction.md +146 -0
  289. package/skills/popbill/scripts/popbill_cli.py +284 -0
  290. package/skills/popbill/scripts/popbill_registry.py +54 -0
  291. package/skills/popbill/scripts/popbill_safety.py +37 -0
  292. package/skills/popbill/scripts/popbill_templates.py +71 -0
  293. package/skills/popbill/skill.json +9 -0
  294. package/skills/public-restroom-nearby/instruction.md +89 -0
  295. package/skills/public-restroom-nearby/skill.json +9 -0
  296. package/skills/real-estate-search/instruction.md +172 -0
  297. package/skills/real-estate-search/skill.json +10 -0
  298. package/skills/rhwp-advanced/instruction.md +145 -0
  299. package/skills/rhwp-advanced/skill.json +8 -0
  300. package/skills/rhwp-edit/instruction.md +153 -0
  301. package/skills/rhwp-edit/skill.json +8 -0
  302. package/skills/s2b-notice-search/instruction.md +66 -0
  303. package/skills/s2b-notice-search/skill.json +9 -0
  304. package/skills/saju-fortune/instruction.md +177 -0
  305. package/skills/saju-fortune/skill.json +8 -0
  306. package/skills/saramin-talent-search/instruction.md +119 -0
  307. package/skills/saramin-talent-search/skill.json +9 -0
  308. package/skills/seoul-bike/instruction.md +83 -0
  309. package/skills/seoul-bike/scripts/seoul_bike.py +247 -0
  310. package/skills/seoul-bike/skill.json +10 -0
  311. package/skills/seoul-density/instruction.md +109 -0
  312. package/skills/seoul-density/scripts/seoul_density.py +271 -0
  313. package/skills/seoul-density/skill.json +10 -0
  314. package/skills/seoul-subway-arrival/instruction.md +85 -0
  315. package/skills/seoul-subway-arrival/skill.json +9 -0
  316. package/skills/sh-notice-search/instruction.md +150 -0
  317. package/skills/sh-notice-search/skill.json +9 -0
  318. package/skills/srt-booking/instruction.md +181 -0
  319. package/skills/srt-booking/scripts/srt_booking.py +272 -0
  320. package/skills/srt-booking/scripts/srt_seats.py +156 -0
  321. package/skills/srt-booking/skill.json +20 -0
  322. package/skills/subway-lost-property/instruction.md +93 -0
  323. package/skills/subway-lost-property/scripts/subway_lost_property.py +244 -0
  324. package/skills/subway-lost-property/skill.json +8 -0
  325. package/skills/ticket-availability/instruction.md +175 -0
  326. package/skills/ticket-availability/scripts/ticket_availability.py +430 -0
  327. package/skills/ticket-availability/skill.json +9 -0
  328. package/skills/toss-securities/instruction.md +116 -0
  329. package/skills/toss-securities/skill.json +9 -0
  330. package/skills/used-car-price-search/instruction.md +109 -0
  331. package/skills/used-car-price-search/skill.json +8 -0
  332. package/skills/yebigun-training/instruction.md +177 -0
  333. package/skills/yebigun-training/skill.json +9 -0
  334. package/skills/zipcode-search/instruction.md +159 -0
  335. package/skills/zipcode-search/scripts/zipcode_search.py +150 -0
  336. package/skills/zipcode-search/skill.json +8 -0
  337. package/src/assemble.js +134 -0
  338. package/src/detect.js +18 -0
  339. package/templates/action-account.md +4 -0
  340. package/templates/action-booking.md +5 -0
  341. package/templates/action-commerce.md +5 -0
  342. package/templates/action-communication.md +5 -0
  343. package/templates/action-submission.md +5 -0
  344. package/templates/browser.md +4 -0
  345. package/templates/core.md +5 -0
  346. package/templates/hard-boundary.md +3 -0
  347. package/templates/local.md +2 -0
  348. package/templates/lookup.md +2 -0
  349. package/templates/proxy.md +2 -0
  350. package/templates/vault.md +4 -0
@@ -0,0 +1,87 @@
1
+ # 한국어 글자 수 세기
2
+
3
+ ## What this skill does
4
+
5
+ 자기소개서, 지원서, 자유서술형 폼처럼 **글자 수 제한이 중요한 한국어 텍스트**를 대상으로 LLM 추정 없이 결정론적으로 카운트한다.
6
+
7
+ - 기본 글자 수: `Intl.Segmenter` 기반 Unicode extended grapheme cluster
8
+ - 줄 수: `CRLF`, `LF`, `CR`, `U+2028`, `U+2029` 를 줄바꿈 1회로 계산
9
+ - 기본 byte 수: UTF-8 실제 인코딩 길이
10
+ - 호환 프로필: `neis` byte 규칙
11
+
12
+ ## When to use
13
+
14
+ - "이 자기소개서 1000자 넘는지 정확히 세줘"
15
+ - "이 텍스트를 UTF-8 byte 기준으로 계산해줘"
16
+ - "줄 수랑 byte 수도 같이 알려줘"
17
+ - "한글/영문/이모지 섞인 문장을 추정 말고 코드로 세줘"
18
+
19
+ ## Why this skill exists
20
+
21
+ - 글자 수 제한은 1자 차이도 민감하다.
22
+ - LLM이 글자 수를 눈대중으로 예측하면 재현성이 없다.
23
+ - 이 스킬은 **입력을 임의로 trim/정규화하지 않고**, 문서화된 계약으로만 센다.
24
+
25
+ ## Contracts
26
+
27
+ ### `default` profile
28
+
29
+ - characters: `Intl.Segmenter("ko", { granularity: "grapheme" })`
30
+ - bytes: `Buffer.byteLength(text, "utf8")`
31
+ - lines:
32
+ - empty string => `0`
33
+ - non-empty => 줄바꿈 시퀀스 수 + `1`
34
+ - `CRLF` 는 `2`줄바꿈이 아니라 `1`줄바꿈으로 센다.
35
+
36
+ ### `neis` profile
37
+
38
+ - characters: `default` 와 동일
39
+ - lines: `default` 와 동일
40
+ - bytes:
41
+ - 한글 grapheme => `3B`
42
+ - ASCII grapheme => `1B`
43
+ - Enter/줄바꿈 시퀀스 => `2B`
44
+ - 그 외 문자는 UTF-8 byte 길이로 fallback
45
+
46
+ ## Prerequisites
47
+
48
+ - `node` 18+
49
+ - 설치된 skill payload 안에 `scripts/korean_character_count.js` helper 포함
50
+ - 별도 API 키 없음
51
+
52
+ ## Workflow
53
+
54
+ 1. 텍스트를 직접 받거나 파일/STDIN으로 읽는다.
55
+ 2. `node scripts/korean_character_count.js` 로 결정론적 카운트를 실행한다.
56
+ 3. 필요한 프로필(`default`/`neis`)과 출력 형식(`json`/`text`)을 고른다.
57
+ 4. 결과를 그대로 반환하고, 어떤 계약으로 셌는지 함께 알려준다.
58
+
59
+ ## CLI examples
60
+
61
+ ```bash
62
+ node scripts/korean_character_count.js --text "가나다"
63
+ node scripts/korean_character_count.js --text $'첫 줄\r\n둘째 줄🙂'
64
+ node scripts/korean_character_count.js --text $'첫 줄\n둘째 줄🙂' --profile neis --format text
65
+ node scripts/korean_character_count.js --file ./essay.txt --profile default
66
+ cat essay.txt | node scripts/korean_character_count.js --stdin --profile neis
67
+ ```
68
+
69
+ ## Response policy
70
+
71
+ - 추정하지 말고 helper 결과를 그대로 쓴다.
72
+ - 어떤 profile로 셌는지 함께 보여준다.
73
+ - 기본값이 필요하면 `default` profile을 사용한다.
74
+ - 제출처가 NEIS/학교생활기록부 같은 별도 계약을 요구할 때만 `neis` 를 쓴다.
75
+
76
+ ## Done when
77
+
78
+ - 글자 수, 줄 수, byte 수가 함께 반환된다.
79
+ - `default` 와 `neis` 계약 차이가 문서에 명시된다.
80
+ - `node scripts/korean_character_count.js --help` 가 동작한다.
81
+ - 혼합 한국어/영문/공백/개행/emoji 입력에 대한 테스트가 있다.
82
+
83
+ ## Notes
84
+
85
+ - Unicode grapheme clusters: https://www.unicode.org/reports/tr29/
86
+ - WHATWG Encoding Standard: https://encoding.spec.whatwg.org/
87
+ - Node `Buffer.byteLength`: https://nodejs.org/api/buffer.html
@@ -0,0 +1,268 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const fs = require("node:fs");
5
+
6
+ const LINE_BREAK_PATTERN = /\r\n|[\n\r\u2028\u2029]/gu;
7
+ const HANGUL_OR_MARK_PATTERN = /^[\p{Script=Hangul}\p{Mark}]+$/u;
8
+ const HAS_HANGUL_PATTERN = /\p{Script=Hangul}/u;
9
+ const WHITESPACE_ONLY_PATTERN = /^\s+$/u;
10
+ const ASCII_ONLY_PATTERN = /^[\x00-\x7F]+$/;
11
+
12
+ function ensureSegmenter() {
13
+ if (!globalThis.Intl?.Segmenter) {
14
+ throw new Error("Intl.Segmenter is required. Use Node.js 18 or newer.");
15
+ }
16
+
17
+ return new Intl.Segmenter("ko", { granularity: "grapheme" });
18
+ }
19
+
20
+ function segmentGraphemes(text) {
21
+ return Array.from(ensureSegmenter().segment(text), ({ segment }) => segment);
22
+ }
23
+
24
+ function countUtf8Bytes(text) {
25
+ return Buffer.byteLength(text, "utf8");
26
+ }
27
+
28
+ function countLines(text) {
29
+ if (text.length === 0) {
30
+ return 0;
31
+ }
32
+
33
+ return Array.from(text.matchAll(LINE_BREAK_PATTERN)).length + 1;
34
+ }
35
+
36
+ function countNeisBytes(text) {
37
+ let total = 0;
38
+ let lastIndex = 0;
39
+
40
+ for (const match of text.matchAll(LINE_BREAK_PATTERN)) {
41
+ const breakIndex = match.index ?? 0;
42
+ total += countNeisChunkBytes(text.slice(lastIndex, breakIndex));
43
+ total += 2;
44
+ lastIndex = breakIndex + match[0].length;
45
+ }
46
+
47
+ total += countNeisChunkBytes(text.slice(lastIndex));
48
+ return total;
49
+ }
50
+
51
+ function countNeisChunkBytes(chunk) {
52
+ return segmentGraphemes(chunk).reduce((sum, grapheme) => sum + countNeisGraphemeBytes(grapheme), 0);
53
+ }
54
+
55
+ function countNeisGraphemeBytes(grapheme) {
56
+ if (!grapheme) {
57
+ return 0;
58
+ }
59
+
60
+ if (ASCII_ONLY_PATTERN.test(grapheme)) {
61
+ return 1;
62
+ }
63
+
64
+ if (HANGUL_OR_MARK_PATTERN.test(grapheme) && HAS_HANGUL_PATTERN.test(grapheme)) {
65
+ return 3;
66
+ }
67
+
68
+ return countUtf8Bytes(grapheme);
69
+ }
70
+
71
+ function createReport(text, profile = "default") {
72
+ const graphemes = segmentGraphemes(text);
73
+ const bytesUtf8 = countUtf8Bytes(text);
74
+ const bytesNeis = countNeisBytes(text);
75
+ const selectedBytes = profile === "neis" ? bytesNeis : bytesUtf8;
76
+
77
+ return {
78
+ profile,
79
+ contract: {
80
+ characters: "Unicode extended grapheme clusters via Intl.Segmenter",
81
+ bytes:
82
+ profile === "neis"
83
+ ? "NEIS-compatible bytes: Hangul grapheme=3B, ASCII grapheme=1B, each line break=2B, everything else falls back to UTF-8 bytes"
84
+ : "Actual UTF-8 encoded byte length",
85
+ lines:
86
+ "Empty string => 0 lines; otherwise count CRLF, LF, CR, U+2028, U+2029 as one line break each and add 1",
87
+ },
88
+ counts: {
89
+ characters: graphemes.length,
90
+ characters_without_whitespace: graphemes.filter((grapheme) => !WHITESPACE_ONLY_PATTERN.test(grapheme)).length,
91
+ code_points: Array.from(text).length,
92
+ utf16_code_units: text.length,
93
+ lines: countLines(text),
94
+ bytes: selectedBytes,
95
+ bytes_utf8: bytesUtf8,
96
+ bytes_neis: bytesNeis,
97
+ },
98
+ };
99
+ }
100
+
101
+ function parseArgs(argv, stdinIsTTY = process.stdin.isTTY) {
102
+ const options = {
103
+ format: "json",
104
+ inputMode: null,
105
+ profile: "default",
106
+ text: null,
107
+ };
108
+
109
+ for (let index = 0; index < argv.length; index += 1) {
110
+ const arg = argv[index];
111
+
112
+ if (arg === "--help" || arg === "-h") {
113
+ options.help = true;
114
+ continue;
115
+ }
116
+
117
+ if (arg === "--text") {
118
+ setInputMode(options, "text");
119
+ options.text = readNextValue(argv, ++index, arg);
120
+ continue;
121
+ }
122
+
123
+ if (arg === "--file") {
124
+ setInputMode(options, "file");
125
+ options.file = readNextValue(argv, ++index, arg);
126
+ continue;
127
+ }
128
+
129
+ if (arg === "--stdin") {
130
+ setInputMode(options, "stdin");
131
+ continue;
132
+ }
133
+
134
+ if (arg === "--profile") {
135
+ const value = readNextValue(argv, ++index, arg);
136
+
137
+ if (!["default", "neis"].includes(value)) {
138
+ throw new Error(`Unknown profile: ${value}`);
139
+ }
140
+
141
+ options.profile = value;
142
+ continue;
143
+ }
144
+
145
+ if (arg === "--format") {
146
+ const value = readNextValue(argv, ++index, arg);
147
+
148
+ if (!["json", "text"].includes(value)) {
149
+ throw new Error(`Unknown format: ${value}`);
150
+ }
151
+
152
+ options.format = value;
153
+ continue;
154
+ }
155
+
156
+ throw new Error(`Unknown option: ${arg}`);
157
+ }
158
+
159
+ if (options.help) {
160
+ return options;
161
+ }
162
+
163
+ if (!options.inputMode) {
164
+ if (stdinIsTTY) {
165
+ throw new Error("Provide exactly one input source with --text, --file, or --stdin.");
166
+ }
167
+
168
+ options.inputMode = "stdin";
169
+ }
170
+
171
+ return options;
172
+ }
173
+
174
+ function setInputMode(options, nextMode) {
175
+ if (options.inputMode) {
176
+ throw new Error("Provide exactly one input source with --text, --file, or --stdin.");
177
+ }
178
+
179
+ options.inputMode = nextMode;
180
+ }
181
+
182
+ function readNextValue(argv, index, flagName) {
183
+ const value = argv[index];
184
+
185
+ if (value == null) {
186
+ throw new Error(`Missing value after ${flagName}`);
187
+ }
188
+
189
+ return value;
190
+ }
191
+
192
+ function readInput(options) {
193
+ if (options.inputMode === "text") {
194
+ return options.text ?? "";
195
+ }
196
+
197
+ if (options.inputMode === "file") {
198
+ return fs.readFileSync(options.file, "utf8");
199
+ }
200
+
201
+ return fs.readFileSync(0, "utf8");
202
+ }
203
+
204
+ function formatTextReport(report) {
205
+ return [
206
+ `profile: ${report.profile}`,
207
+ `characters: ${report.counts.characters}`,
208
+ `characters_without_whitespace: ${report.counts.characters_without_whitespace}`,
209
+ `code_points: ${report.counts.code_points}`,
210
+ `utf16_code_units: ${report.counts.utf16_code_units}`,
211
+ `lines: ${report.counts.lines}`,
212
+ `bytes: ${report.counts.bytes}`,
213
+ `bytes_utf8: ${report.counts.bytes_utf8}`,
214
+ `bytes_neis: ${report.counts.bytes_neis}`,
215
+ `character_contract: ${report.contract.characters}`,
216
+ `byte_contract: ${report.contract.bytes}`,
217
+ `line_contract: ${report.contract.lines}`,
218
+ ].join("\n");
219
+ }
220
+
221
+ function printHelp() {
222
+ console.log(`Usage: node scripts/korean_character_count.js [--text <text> | --file <path> | --stdin] [--profile default|neis] [--format json|text]
223
+
224
+ Deterministically count Korean text characters, lines, and bytes.
225
+
226
+ Options:
227
+ --text <text> Count the provided text
228
+ --file <path> Read UTF-8 text from a file
229
+ --stdin Read UTF-8 text from stdin
230
+ --profile <name> default (grapheme + UTF-8) or neis
231
+ --format <name> json (default) or text
232
+ --help, -h Show this help text
233
+ `);
234
+ }
235
+
236
+ function main(argv = process.argv.slice(2)) {
237
+ const options = parseArgs(argv);
238
+
239
+ if (options.help) {
240
+ printHelp();
241
+ return;
242
+ }
243
+
244
+ const report = createReport(readInput(options), options.profile);
245
+ const output = options.format === "text" ? formatTextReport(report) : JSON.stringify(report, null, 2);
246
+
247
+ console.log(output);
248
+ }
249
+
250
+ if (require.main === module) {
251
+ try {
252
+ main();
253
+ } catch (error) {
254
+ console.error(error.message);
255
+ process.exitCode = 1;
256
+ }
257
+ }
258
+
259
+ module.exports = {
260
+ countLines,
261
+ countNeisBytes,
262
+ countUtf8Bytes,
263
+ createReport,
264
+ formatTextReport,
265
+ main,
266
+ parseArgs,
267
+ segmentGraphemes,
268
+ };
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "korean-character-count",
3
+ "description": "Count Korean text deterministically with exact grapheme, line, and byte contracts for self-intros and form limits.",
4
+ "profiles": [
5
+ "local"
6
+ ],
7
+ "frontmatter": "name: korean-character-count\ndescription: Count Korean text deterministically with exact grapheme, line, and byte contracts for self-intros and form limits.\nlicense: MIT\nmetadata:\n category: writing\n locale: ko-KR\n phase: v1"
8
+ }
@@ -0,0 +1,177 @@
1
+ # Korean Cinema Search
2
+
3
+ ## What this skill does
4
+
5
+ upstream 원본 [`hmmhmmhm/daiso-mcp`](https://github.com/hmmhmmhm/daiso-mcp) 와 npm package [`daiso`](https://www.npmjs.com/package/daiso) 를 사용해 **CGV, 메가박스, 롯데시네마 영화관 검색, 상영작, 시간표, 잔여석 조회**를 안내한다.
6
+
7
+ 이 저장소는 upstream 코드를 vendoring 하지 않는다. 기본 경로는 **MCP 서버를 직접 설치하지 않고 CLI로 먼저 확인하는 방식**이다.
8
+
9
+ 핵심 조회 경로:
10
+
11
+ - CGV: `/api/cgv/theaters`, `/api/cgv/movies`, `/api/cgv/timetable`
12
+ - 메가박스: `/api/megabox/theaters`, `/api/megabox/movies`, `/api/megabox/seats`
13
+ - 롯데시네마: `/api/lottecinema/theaters`, `/api/lottecinema/movies`, `/api/lottecinema/seats`
14
+ - health check: `npx --yes daiso health`
15
+
16
+ ## When to use
17
+
18
+ - "강남 근처 CGV 찾아줘"
19
+ - "오늘 메가박스 코엑스 상영작 알려줘"
20
+ - "롯데시네마 월드타워 잔여석 확인해줘"
21
+ - "주변 영화관 시간표 비교해줘"
22
+
23
+ ## When not to use
24
+
25
+ - 예매, 결제, 좌석 선점, 로그인 자동화
26
+ - 영화관 계정이나 멤버십 권한이 필요한 기능
27
+ - upstream 서버 코드를 이 저장소에 복사해서 유지하려는 경우
28
+
29
+ ## Prerequisites
30
+
31
+ - 인터넷 연결
32
+ - `node` 20 권장
33
+ - `npx` 또는 `npm`
34
+ - 필요하면 `git`
35
+
36
+ ## Preferred setup: CLI first
37
+
38
+ 먼저 MCP 연결이 아니라 upstream CLI로 공개 endpoint를 확인한다.
39
+
40
+ 날짜가 있는 요청은 Asia/Seoul 기준 `YYYYMMDD` 로 정규화하고 `--playDate <YYYYMMDD>` 를 항상 붙인다. 사용자가 오늘이라고 말하거나 날짜를 생략하면 KST 오늘 날짜를 계산한다.
41
+
42
+ ```bash
43
+ npx --yes daiso health
44
+ npx --yes daiso get /api/cgv/theaters --keyword 강남 --limit 5 --json
45
+ npx --yes daiso get /api/cgv/movies --keyword 강남 --playDate <YYYYMMDD> --json
46
+ npx --yes daiso get /api/cgv/timetable --keyword 강남 --playDate <YYYYMMDD> --json
47
+ npx --yes daiso get /api/megabox/theaters --keyword 코엑스 --limit 5 --json
48
+ npx --yes daiso get /api/megabox/movies --keyword 코엑스 --playDate <YYYYMMDD> --json
49
+ npx --yes daiso get /api/megabox/seats --keyword 코엑스 --playDate <YYYYMMDD> --limit 10 --json
50
+ npx --yes daiso get /api/lottecinema/theaters --keyword 월드타워 --limit 5 --json
51
+ npx --yes daiso get /api/lottecinema/movies --keyword 월드타워 --playDate <YYYYMMDD> --json
52
+ npx --yes daiso get /api/lottecinema/seats --keyword 월드타워 --playDate <YYYYMMDD> --limit 10 --json
53
+ ```
54
+
55
+ 반복 사용이면 전역 설치도 가능하다.
56
+
57
+ ```bash
58
+ npm install -g daiso
59
+ export NODE_PATH="$(npm root -g)"
60
+ daiso health
61
+ ```
62
+
63
+ ## Fallback: clone the original repository
64
+
65
+ public endpoint 재시도나 버전 고정이 필요하면 원본 저장소를 clone 해서 build 결과물 `dist/bin.js` 를 직접 실행한다.
66
+
67
+ ```bash
68
+ git clone https://github.com/hmmhmmhm/daiso-mcp.git
69
+ cd daiso-mcp
70
+ npm install
71
+ npm run build
72
+ node dist/bin.js health
73
+ node dist/bin.js get /api/cgv/theaters --keyword 강남 --limit 5 --json
74
+ node dist/bin.js get /api/cgv/timetable --keyword 강남 --playDate <YYYYMMDD> --json
75
+ node dist/bin.js get /api/megabox/seats --keyword 코엑스 --playDate <YYYYMMDD> --limit 10 --json
76
+ node dist/bin.js get /api/lottecinema/seats --keyword 월드타워 --playDate <YYYYMMDD> --limit 10 --json
77
+ ```
78
+
79
+ ## Required inputs
80
+
81
+ ### 1. Cinema chain
82
+
83
+ 체인이 없으면 먼저 묻는다.
84
+
85
+ - 권장 질문: `어느 영화관을 볼까요? CGV, 메가박스, 롯데시네마 중 하나를 알려주세요.`
86
+
87
+ ### 2. Theater or area keyword
88
+
89
+ 지역이나 지점명이 없으면 바로 조회하지 말고 기준 위치를 받는다.
90
+
91
+ - 권장 질문: `어느 지역이나 지점을 기준으로 볼까요? 예: 강남, 코엑스, 월드타워`
92
+
93
+ ### 3. Movie title when seats are requested
94
+
95
+ 잔여석 질문인데 영화명이 없으면 먼저 영화 후보를 조회하거나 영화명을 물어본다.
96
+
97
+ ### 4. Date
98
+
99
+ 사용자가 날짜를 말하면 그 날짜를 우선한다. 날짜가 없으면 Asia/Seoul 기준 오늘을 `YYYYMMDD` 로 계산해 `--playDate <YYYYMMDD>` 로 넘긴다.
100
+
101
+ | 체인 | 후보 조회 | 상영작 | 시간표 또는 잔여석 | 날짜 |
102
+ | --- | --- | --- | --- | --- |
103
+ | CGV | `keyword`, 선택 `limit` | `keyword` 또는 `theaterId`, `playDate` | `keyword` 또는 `theaterId`, `movieId`, `playDate` | 필수로 명시 |
104
+ | 메가박스 | `keyword`, 선택 `limit` | `keyword` 또는 `theaterId`, `playDate` | `keyword` 또는 `theaterId`, `movieId`, `playDate` | 필수로 명시 |
105
+ | 롯데시네마 | `keyword`, 선택 `limit` | `keyword` 또는 `theaterId`, `playDate` | `keyword` 또는 `theaterId`, `movieId`, `playDate` | 필수로 명시 |
106
+
107
+ ## Workflow
108
+
109
+ ### 1. Check server health
110
+
111
+ ```bash
112
+ npx --yes daiso health
113
+ ```
114
+
115
+ ### 2. Resolve theater candidates
116
+
117
+ ```bash
118
+ npx --yes daiso get /api/cgv/theaters --keyword 강남 --limit 5 --json
119
+ ```
120
+
121
+ 후보가 여러 개면 상위 2개에서 3개만 요약하고 다시 확인받는다.
122
+
123
+ ### 3. Resolve movie candidates
124
+
125
+ ```bash
126
+ npx --yes daiso get /api/cgv/movies --keyword 강남 --playDate <YYYYMMDD> --json
127
+ ```
128
+
129
+ 영화 후보가 많으면 제목과 등급만 짧게 정리한다.
130
+
131
+ ### 4. Check timetable or seats
132
+
133
+ CGV는 시간표 중심으로 본다.
134
+
135
+ ```bash
136
+ npx --yes daiso get /api/cgv/timetable --keyword 강남 --playDate <YYYYMMDD> --json
137
+ ```
138
+
139
+ 메가박스와 롯데시네마는 잔여석 endpoint를 사용할 수 있다.
140
+
141
+ ```bash
142
+ npx --yes daiso get /api/megabox/seats --keyword 코엑스 --playDate <YYYYMMDD> --limit 10 --json
143
+ npx --yes daiso get /api/lottecinema/seats --keyword 월드타워 --playDate <YYYYMMDD> --limit 10 --json
144
+ ```
145
+
146
+ ### 5. Respond conservatively
147
+
148
+ 최종 응답은 짧게 정리한다.
149
+
150
+ - 영화관 체인
151
+ - 기준 지역이나 지점
152
+ - 상영작 또는 선택 영화
153
+ - 시간표와 잔여석
154
+ - 조회 시각과 공개 endpoint 특성상 변동 가능하다는 점
155
+
156
+ 예매와 결제는 자동화하지 않는다.
157
+
158
+ ## Done when
159
+
160
+ - `hmmhmmhm/daiso-mcp` 원본 repo와 `daiso` CLI 사용 경로를 명시했다.
161
+ - MCP 서버를 직접 설치하는 대신 CLI first 흐름을 제시했다.
162
+ - CGV, 메가박스, 롯데시네마 조회 범위를 구분했다.
163
+ - 영화관 검색, 상영작, 시간표, 잔여석 중 필요한 호출을 실제로 안내했다.
164
+ - 예매와 결제 자동화가 범위 밖임을 명시했다.
165
+
166
+ ## Failure modes
167
+
168
+ - public endpoint는 upstream 상태에 따라 간헐적인 5xx를 줄 수 있다.
169
+ - 지역 키워드가 넓으면 다른 지점이 섞일 수 있다.
170
+ - 시간표와 잔여석은 시점에 따라 달라진다.
171
+ - 일부 체인은 상영작, 시간표, 잔여석 endpoint의 입력값이 다르므로 theaterId, movieId가 있으면 그 값을 우선 사용한다.
172
+
173
+ ## Notes
174
+
175
+ - 원본 프로젝트: `https://github.com/hmmhmmhm/daiso-mcp`
176
+ - npm package: `https://www.npmjs.com/package/daiso`
177
+ - 이 저장소는 upstream 코드를 vendoring 하지 않고 skill/docs만 유지한다.
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "korean-cinema-search",
3
+ "description": "CGV, 메가박스, 롯데시네마 영화관 검색, 상영작, 시간표, 잔여석 조회가 필요할 때 사용한다. 돌쇠에서는 공식 표면을 통한 후속 액션까지 진행한다.",
4
+ "profiles": [
5
+ "action:booking"
6
+ ],
7
+ "frontmatter": "name: korean-cinema-search\ndescription: CGV, 메가박스, 롯데시네마 영화관 검색, 상영작, 시간표, 잔여석 조회가 필요할 때 사용한다. 돌쇠에서는 공식 표면을 통한 후속 액션까지 진행한다.\nlicense: MIT\nmetadata:\n category: entertainment\n locale: ko-KR\n phase: v1"
8
+ }
@@ -0,0 +1,106 @@
1
+ # 한국 국가유산 검색
2
+
3
+ ## What this skill does
4
+
5
+ 국가유산청(현 국가유산청 영문 Korea Heritage Service)의 공식 Open API에서 국가유산 목록·상세정보와 월별 국가유산 활용 행사를 조회한다.
6
+
7
+ v1은 공식 XML API를 직접 호출하며, 별도 API key·로그인·프록시가 필요 없다.
8
+
9
+ - 국가유산명·지역 기준 검색
10
+ - 국가유산 상세 설명·주소·좌표·이미지 조회
11
+ - 연도·월별 국가유산 행사 조회
12
+
13
+ ## When to use
14
+
15
+ - "경복궁 관련 국가유산 찾아줘"
16
+ - "서울 국보 목록 보여줘"
17
+ - "숭례문 역사와 주소 알려줘"
18
+ - "이번 달 국가유산 행사 알려줘"
19
+ - "전주 지역 국가유산을 검색해줘"
20
+
21
+ ## When not to use
22
+
23
+ - 현재 입장 가능 여부, 운영시간, 입장료를 확정해야 하는 경우
24
+ - 실시간 통제·혼잡도·주차 가능 여부가 필요한 경우
25
+ - 예매·결제·행사 신청을 자동화해야 하는 경우
26
+
27
+ ## Prerequisites
28
+
29
+ - 인터넷 연결
30
+ - Python 3.10+
31
+ - 설치된 skill payload 안에 `scripts/korean_heritage_search.py` helper가 포함되어 있다.
32
+ - 별도 API key나 로그인은 필요 없다.
33
+
34
+ ## Inputs
35
+
36
+ ### Search
37
+
38
+ - 선택: 국가유산명 검색어
39
+ - 선택: 시도명 또는 시도 코드
40
+ - 선택: 페이지 번호
41
+ - 선택: 결과 수(1~100)
42
+
43
+ 지원 지역명: 서울, 부산, 대구, 인천, 광주, 대전, 울산, 경기, 강원, 충북, 충남, 전북, 전남, 경북, 경남, 제주, 세종.
44
+
45
+ ### Detail
46
+
47
+ 목록 결과에서 받은 다음 세 식별자가 필요하다.
48
+
49
+ - `ccbaKdcd`
50
+ - `ccbaAsno`
51
+ - `ccbaCtcd`
52
+
53
+ ### Events
54
+
55
+ - 필수: 연도(`YYYY`)
56
+ - 필수: 월(`1~12`)
57
+ - 선택: 시도명·시군구명 부분 필터
58
+
59
+ ## Workflow
60
+
61
+ 1. 국가유산명과 지역을 확인한다. 모호한 요청이면 먼저 검색 결과를 보여주고 상세 대상을 선택하게 한다.
62
+ 2. 공식 `SearchKindOpenapiList.do`에서 목록을 조회한다.
63
+ 3. 목록 결과의 `ccbaKdcd`, `ccbaAsno`, `ccbaCtcd`를 사용해 `SearchKindOpenapiDt.do` 상세를 조회한다.
64
+ 4. 행사 요청이면 `selectEventListOpenapi.do`에 연도·월을 넣고, 반환된 지역·기간·행사명·공식 링크를 정리한다.
65
+ 5. 결과에 공식 출처 URL과 조회 시각을 포함한다.
66
+ 6. 입장료·운영시간·현재 행사 진행 여부처럼 변동 가능성이 있는 정보는 상세 API의 사실과 별도로 표시하고, 공식 안내 페이지를 확인하도록 안내한다.
67
+
68
+ ## CLI examples
69
+
70
+ ```bash
71
+ python3 scripts/korean_heritage_search.py search --query "경복궁" --region 서울 --limit 5
72
+ python3 scripts/korean_heritage_search.py search --region 전북 --limit 10
73
+ python3 scripts/korean_heritage_search.py detail --ccba-kdcd 11 --ccba-asno 0000010000000 --ccba-ctcd 11
74
+ python3 scripts/korean_heritage_search.py events --year 2026 --month 7 --region 서울 --limit 10
75
+ ```
76
+
77
+ ## Response policy
78
+
79
+ - 국가유산명, 유형, 지역, 주소, 좌표, 지정일, 설명, 관리기관을 공식 응답 그대로 요약한다.
80
+ - 상세 조회에서 받은 `content`는 역사 설명으로 표시하고, 현재 운영 상태로 해석하지 않는다.
81
+ - 행사 응답의 `subContent`는 HTML을 제거한 텍스트로 정리하되, 원문 링크(`subPath`)를 함께 제공한다.
82
+ - 결과가 없으면 다른 국가유산명 표기나 지역 조건을 제안한다.
83
+ - API에 없는 입장료·운영시간·통제 상태를 추정하지 않는다.
84
+
85
+ ## Done when
86
+
87
+ - 검색 요청이면 공식 목록 결과와 `total_results`가 정리되어 있다.
88
+ - 상세 요청이면 공식 식별자와 설명·주소·좌표·이미지가 정리되어 있다.
89
+ - 행사 요청이면 연도·월, 행사명, 기간, 지역, 공식 링크가 정리되어 있다.
90
+ - 응답에 공식 출처와 조회 시각이 포함되어 있다.
91
+
92
+ ## Failure modes
93
+
94
+ - 국가유산명·지역 조건에 해당하는 결과가 없음
95
+ - `ccbaKdcd`, `ccbaAsno`, `ccbaCtcd` 조합이 유효하지 않음
96
+ - 국가유산청 API의 일시적 timeout, HTTP 오류, XML 오류
97
+ - 행사 데이터의 설명 HTML 또는 기간 문자열이 불완전함
98
+ - 오래된 API 응답으로 이미지 URL 또는 일부 필드가 비어 있음
99
+
100
+ ## Notes
101
+
102
+ - 목록 API: `https://www.khs.go.kr/cha/SearchKindOpenapiList.do`
103
+ - 상세 API: `https://www.khs.go.kr/cha/SearchKindOpenapiDt.do`
104
+ - 행사 API: `https://www.khs.go.kr/cha/openapi/selectEventListOpenapi.do`
105
+ - 공식 Open API 안내: `https://www.khs.go.kr/html/HtmlPage.do?mn=NS_04_04_03&pg=%2Fpublicinfo%2Fpbinfo3_0201.jsp`
106
+ - 이 기능은 검색·조회 전용이며 예약, 결제, 신청을 수행하지 않는다.