MCPパワーでClaudeにCosenseを書いてもらう

スマホからCosense書きにくい問題

私は普段メモ用にCosenseを使っているが、スマホからCosenseを書くのは結構難しい。 上手いことインデントがかけられなかったり、カーソルの移動が難しかったりと、結構普段使うにはむずいところがある。 そこで、yosider/cosense-mcp-server: An MCP Server for Cosenseをインターネット越しに使えるようにすることで、スマホのClaudeからCosenseを読み書きできるようにする。

MCPサーバーの建立

CosenseにアクセスするためのMCPサーバーとして、yosider/cosense-mcp-serverを使う。

github.com

このMCPサーバーはローカル動作を前提としていて、stdioで通信するため、インターネット越しに使えるようにするためにはstdioをHTTPに載せるいい感じのプロキシを使うことになる。 この手のニーズは既にあるようで、今回はその中でもメジャーなsparfenyuk/mcp-proxyを使うことにする。

github.com

mcp-proxyの導入

Node.js、pnpm、Cloudflare Tunnelの導入が別途必要

$ pnpm install -g mcp-proxy

あとは、

$ COSENSE_PROJECT_NAME=your_project_name \
   COSENSE_SID=your_sid \
   mcp-proxy --port 8080 -- pnpm -s dlx @yosider/cosense-mcp-server

で動作する。

your_project_nameは操作対象のプロジェクト名(例えばhttps://scrapbox.io/taiseiue なら"taiseiue")、your_sidはCosenseのセッションIDで置換する。 セッションIDはChromeでCosenseを開いて、以下の画像のように開発者ツールから値を取得する。

sidの取得

systemdで管理する

毎回コマンドを叩くのは面倒なので、サービスにしてsystemdで管理するようにする。

/etc/systemd/system/cosense-mcp.serviceに以下のように書く。your_usernameとyour_project_name、your_sidは各自置換されたい。

[Unit]
Description=Cosense MCP Server (mcp-proxy)
After=network.target

[Service]
Type=simple
User=your_username
WorkingDirectory=/home/your_username

Environment=COSENSE_PROJECT_NAME=your_project_name
Environment=COSENSE_SID=your_sid

ExecStart=mcp-proxy --port 8080 -- pnpm -s dlx @yosider/cosense-mcp-server

Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

後はインストールする

$ sudo systemctl daemon-reload
# 起動する
$ sudo systemctl start cosense-mcp

# ログを眺める
$ sudo journalctl -u cosense-mcp -f
Feb 25 13:23:26 lily systemd[1]: cosense-mcp.service: Scheduled restart job, restart counter is at 25.
Feb 25 13:23:26 lily systemd[1]: Started cosense-mcp.service - Cosense MCP Server (mcp-proxy).
Feb 25 13:23:26 lily systemd[1]: cosense-mcp.service: Main process exited, code=exited, status=203/EXEC
Feb 25 13:23:26 lily systemd[1]: cosense-mcp.service: Failed with result 'exit-code'.

パスが通っていなさそうなので、/etc/systemd/system/cosense-mcp.serviceにPATHを追加する。

[Service]
+ Environment=PATH=/usr/local/bin:/usr/bin:/bin:/home/your_username/.local/share/pnpm:/home/your_username/.local/share/mcp-proxy

その後、

$ sudo systemctl daemon-reload
$ sudo systemctl start cosense-mcp

$ sudo journalctl -u cosense-mcp -f

これで動作したので最後に以下のようにOS起動時に自動起動させる。

$ sudo systemctl enable cosense-mcp

Cloudflare Tunnelで公開する

動かしたMCPサーバーをCloudflare Tunnelで公開する。タダ乗りされると嫌なのでCloudflare Accessで認証も行う。

Cloudflare Tunnelでの公開は各自されたい。Cloudflare ZeroTrust>ネットワーク>トンネルから行える。

Cluodflare Accessで認証を設定する。まずはサービス資格情報を作成する。ここで生成された認証情報がOAuthトークンとシークレットになる。

サービス資格情報を作成する

次にポリシーから、先ほど作成した認証情報で認証を行うポリシーを作成する。

ポリシーの作成

最後にAccessアプリケーションを、セルフホスト用テンプレートで作成する。

アプリケーションの作成

これでMCPサーバーの構築は完了。

ClaudeにMCPサーバーを接続する

ClaudeのカスタマイズからMCPサーバーを接続する。

MCPサーバーの追加

上手く接続できるとこのようになる。

接続後の様子

試してみる

Cosenseの中身をリストさせている

Skillsの設定

Cosense記法はMarkdownと違うが、なかなかAIはMarkdown記法を使いたがるので、記法をSkillsに入れるようにした。 以下のページをExport for AIしてそれを読ませることでCosense記法をマスターしてもらう。

scrapbox.io

最終的にはこういうSkillsになった。

cosence-notation-skill.md · GitHub

自分で触った箇所としては、以下のようにClaudeが作成したこと、人間が見ていないことを識別できるようにタグを作成させるようにした。

##必須タグ
Claudeがコンテンツを作成・編集する際は、**必ずページの末尾に以下のタグを追加すること**:

#author:claude #waiting-review

- このタグはClaudeが作成・編集したことを示し、レビュー待ちを意味する
- ページの2行目に単独で記述する
- 省略不可

試してみる

例えば外出先でCosenseに面白いジョーク集を作りたくなった時に以下のようにやってもらえる。

iPhoneのClaudeアプリで書いてもらっている様子

より実践的な例だと、今日の日記を書いておいてもらえる。

日記もとい日報を書いてもらっている様子

どちらもそこそこちゃんと書けている。日報については、書きかたも空気を読んでいてくれていい感じ。

感想

そこそこ便利だと思ったけど、自分のメモ帳に知らない人が追記しているみたいな感覚でやや不気味だと思った。 ページだけ作っておいて、「あれ結局どういうことやったん」とか聞く分には便利かも。

JANOG57 NOCでログ班として活動していました

こんにちは。id:taiseiueです。 2/11~13に大阪で開催されていた、「JANOG57」にNOCとして参加していました。

私はサーバーチーム所属でログ班として、主にログの収集分析を担当していました。 この記事ではログ班の活動の様子を書いていきます。

構成

今回の構成は以下のような感じです。

ログの配送構成図

左側が受信形式、右側が配送先、中央がルーティングを行っている部分となります。

配送先にはGrafanaでアラートを発報したりダッシュボードを表示するためのGrafana Lokiに加え、OpenRoamingおよびeduroamを提供するにあたってのログ保存義務を全うするためにさくらのクラウドにあるさくらのログストレージに配送し、ログを保存しています。

また、Ciscoさまより提供いただいたSplunkにも配送することで、ログ分析を行いました。

様々なsyslog

今回、ログ配送にはGrafana Alloyを使用することにしました。 これは、promtailの後継として開発され、標準的な"整理された"syslog形式であるRFC5424を処理できます。また、ログのパースやラベル付けも可能です。

しかし、世間には様々なsyslogの形式があります。 今回のJANOGでは、以下のような形式のsyslogを受け取りました。

RFC3164: <PRI>TIMESTAMP HOSTNAME TAG: MSG
RFC5424: <PRI>VERSION TIMESTAMP HOSTNAME APP-NAME PROCID MSGID [STRUCTURED-DATA] MSG
YAMAHA: <PRI>MSG

RFC3164

RFC3164(BSD Syslog)は古くから存在するsyslogの形式です。 ネットワーク機器などでは、デフォルトでこれを送信するものが存在し、このためGrafana Alloyに直接送信させず、rsyslogで受け取りそれをrsyslogからGrafana Alloyに配送することで、RFC3164->RFC5424の変換を行いました。

具体的には、PRIの次のセクションに、TIMESTAMPが来るかVERSIONが来るかでsyslogの種類を識別し、正規表現の置換を使ってそれぞれを再配置していきました。

具体的には、以下のような処理を書いています。

janog57-noc/janog57-infra/ansible/roles/log/templates/rsyslog/20-generic.conf#L25-L38

YAMAHA形式

今回使用したYAMAHA製のルーターは、デフォルトではYAMAHA形式という独自のsyslog形式でログを送信するようでした。このため、こちらもrsyslogに一度送信し、YAMAHA->RFC5424の変換を行いました。

# YAMAHA形式(再掲)
<PRI>MSG

YAMAHA形式は、このようにVERSIONやTIMESTAMPがなくそのままメッセージセクションで始まるのが特徴です。このため、VERSIONもTIMESTAMPもない場合にYAMAHA形式として処理を行うようにしました。

具体的には、以下のような処理を書いています。

janog57-noc/janog57-infra/ansible/roles/log/templates/rsyslog/20-generic.conf#L39-L54

ログストレージ送信時のレート制限対策

次に、ログの送信先についてです。 先述の通り、今回はOpenRoamingおよびeduroamを提供するにあたってのログ保存義務を全うするためにさくらのクラウドにあるさくらのログストレージに配送していますが、さくらのログストレージには1000行/secのレート制限が存在します。 仮に5000台のクライアントが接続していて、同時にDHCP割り当てが起きた場合、余裕でレート制限に到達してしまう換算です。(このシナリオはDHCPサーバーの障害などで再割り当てを実行する必要があるときなどにありうる)

このため、一度ログをキューに保存し、1秒毎(実際には念のため1100ms)に1000行を上限にバッチ送信する作戦をとりました。キューは6000行設定しています。キューが溢れた分のログは破棄されます。

この値は負荷試験を実施して得ましたが、今考えると参加登録人数が6000人超で、ひとり2台(PC+スマホ)、1000行は処理できることを考えると、6000 * 2 -1000 = 11000、1万1000行程度は確保できるとよかったのかなと思います。

この部分は以下のコードのように定義しています。

janog57-noc/janog57-infra/ansible/roles/log/templates/alloy/config.alloy#L142-L172

ダッシュボード

前述の通りログのキューがあふれるとログの破棄が起きてしまい問題となるため、Grafana Alloyのメトリクスをscrape可能にし、メトリクス班のid:nekoy3さんがダッシュボードを作成してくださりました。

Grafana Alloyのダッシュボード

心配していたAlloyのキューですが、会期中は一度もあふれることなく、使用率も1%以下になっていました。

Alloyの送信キュー推移

定期的にスパイクしている箇所に朝が多いことから、接続時にDHCP割り当てなどのログが増加していることが推測できます。

障害対応フロー

ログが保存できていないことが発覚した場合、OpenRoamingとeduroamを復旧するまで停波してもらう必要があるため、ログ班では障害対応フローを策定しました。ちょっと長いですがこんな感じです。

#j57-noc-server で共有する > みんな

@channel ログで障害が発生中です。${その時点でわかっていることをここに書く}。

担当者は {障害対応フローへのリンク} を確認して対応にあたりましょう。

チームリーダー> @チームリーダー

ログ班> @ログ班

トリアージ > ログ班

各種状態確認

AlloyのGrafanaダッシュボード / Loki / さくらのログストレージ / Splunk (それぞれのリンク)

以下のどれか

  1. ログの受信ができていない
  2. ログの受信はできていて、Lokiとさくらのストレージのどちらにも送信できていない

    =>ログの収集が停止している

    eduroam,OpenRoamingを停波してもらう必要がある

  3. ログの受信はできていて、さくらのストレージまたはSplunkにログが送信できていない

    => ログの収集はできている

エスカレーション

eduroam,OpenRoamingを停波してもらう必要があるとき実施

全体周知

@channel サーバーチームのログ担当です。

ログが受信/保存できなくなっている疑いがあり対応中です。 この後ログの保存が必要なeduroamとOpenRoamingを停波していただきます。

会場: ${ここにスレッドのリンク}

APチーム

@channel サーバーチームのログ担当です。

ログが受信/保存できなくなっている疑いがあり、eduroamとOpenRoamingを一時的に停波していただきたいです。

会場: ${ここにスレッドのリンク}

告知 > 大人と相談

障害が起きはじめた時間を特定する

AlloyのGrafanaダッシュボード を見て決める

リーダーに続報を報告

復旧したら

eduroamとOpenRoamingを再開してもらう必要があるため、APチームに連絡する

会期後

logcliを使ってさくらのストレージに送れなかったログを調べる必要があるため、本番サーバーで下記コマンド実行

docker run --rm -it \
  --network monitoring_network
  -e LOKI_ADDR="http://loki:3100" \
  grafana/logcli:latest query '{job="syslog"}' --limit=0 --output=jsonl \
  --from="2026-02-09T00:00:00+09:00"  --to="2026-02-09T01:00:00+09:00"

開発環境改善

今回、Grafana Alloyとrsyslogの設定ファイルを書く機会が非常に多かったため、コードレビュー前に気付き、レビュー漏れをなくすためにCIとしてGitHubActions上で設定ファイルをdry-runするようにしました。

GrafanaAlloyはalloy validateという専用コマンドを、rsyslogは-N1という検証用のオプションを付けて実行しています。

最後に

チーム結成から会期中まで、学生リーダーのid:crashrtさんを始めチームのみなさんに非常にお世話になりました!特に最初の頃はAnsibleまったくわからんところから始まり、様々お手伝いしていただいたり沢山コードレビューをお願いしていました。 今回得た学びは今後のNOC活動にぜひ活かしていきたいと思います。

nixのhome-managerで入れたffmpegをAudacityで使う

Audacityでm4aなどを開きたくなったのでメモ。

Audacityでは、mp3やwav以外のファイルを開きたい場合はffmpegのライブラリ(具体的にはavformat-*.dylib)を使う必要がある。 しかし、普通にffmpegをhome-managerで入れると、ffmpegの実行バイナリしか出力されず、ライブラリが使えない。

解決

こう書く。

 home.packages = pkgs.lib.flatten (
    (with pkgs; [
    ffmpeg
    ffmpeg.lib
    ]));

こうすることで、ffmpegで使っているライブラリを~/.nix-profile/libで使うことができる。

Audacityの環境設定でffmpegの場所を手動で「~/.nix-profile/lib/」に設定する

余談

Nixで入れたAudacityはなぜか環境設定からffmpegライブラリの場所をえらべないので、brew caskなどで入れたもので設定するといい。

Nixで入れたAudacityの環境設定

brew casksで入れたAudacityの環境設定

NextcloudのジョブをGrafanaで監視できるようにする

こんにちは、id:taiseiueです。 この記事は、はてなエンジニア Advent Calendar 2025 - Hatena Developer Blogの45日目の記事です。

昨日の記事は、id:tunacookさんによるNaninovelのシナリオ文字カウントをするVSCode拡張を作った - ツナサンド定食でした。

今日の記事では、Nextcloudのジョブの状態を監視できるようにしてみます。

Nextcloudのジョブが実行されない問題

1年前くらいから、知人とDJスタジオを運営しており、その一環でDJプレイ中の録画を保管しておくためのNextcloudをRaspberry Pi 5で稼動しています。

普段の使用(アクティブユーザー>5くらい)までであれば問題なく動作するんですが、アクセスが集中したり、大容量の録画のプレビューを生成したりすると、上手くバックグラウンドジョブが実行されずに通知が送信されなかったり、管理画面で警告が表示されたりします。

そこで、今回はNextcloudのジョブの状態をGrafanaで監視できるようにすることをゴールにします。

Nextcloudのジョブはどう管理されているか

Nextcloudでジョブはoc_jobsテーブルで管理されています。 Nextcloud Version 32.0.3でのテーブルの構造はこんな感じでした。

MariaDB [nextcloud]> DESCRIBE `oc_jobs`;
+--------------------+---------------------+------+-----+---------+----------------+
| Field              | Type                | Null | Key | Default | Extra          |
+--------------------+---------------------+------+-----+---------+----------------+
| id                 | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| class              | varchar(255)        | NO   | MUL |         |                |
| argument           | varchar(4000)       | NO   |     |         |                |
| last_run           | int(11)             | YES  |     | 0       |                |
| last_checked       | int(11)             | YES  | MUL | 0       |                |
| reserved_at        | int(11)             | YES  |     | 0       |                |
| execution_duration | int(11)             | YES  |     | 0       |                |
| argument_hash      | varchar(64)         | YES  |     | NULL    |                |
| time_sensitive     | smallint(6)         | NO   | MUL | 1       |                |
+--------------------+---------------------+------+-----+---------+----------------+

last_runはそのジョブが最後に実行された Unix timestamp、execution_durationは直近実行時の処理時間が入っています。 この中のlast_runなどをメトリクスとしてPrometheusに送信できればいいわけですね。

ジョブの状態をPrometheusに送信する

作戦として、今回はexporterを自作するのではなく、cronで定期的にデータベースにジョブの状態を見に行ってテキストファイルに出力し、それをnode_exporterでPrometheusに送信するという素朴な方法を選んでみました。

cronでジョブの状態を見に行く

こんな感じのスクリプトを書いて、データベースにジョブの状態を引きに行ってprom形式で出力してあげます。

gist.github.com

あとはcronにスクリプトを毎分実行するように登録しておきます。

* * * * * /usr/local/bin/nc-jobs-textfile.sh 2>&1

これでしばらくたつと/var/lib/node_exporter/textfile/nextcloud_jobs.promにメトリクスが出力されてきます。

Prometheusに送る

sudo systemctl edit prometheus-node-exporterで/var/lib/node_exporter/textfileを収集するようにします。

[Service]
ExecStart=
ExecStart=/usr/bin/prometheus-node-exporter \
  --collector.textfile.directory=/var/lib/node_exporter/textfile

上手くいけばPrometheusにnextcloud_job_execution_duration_secondsなどのメトリクスが送られているはずです。

メトリクスの様子

Grafanaで眺める

ダッシュボードの様子

Grafanaで、最後のジョブからの経過時間を可視化できるようにしてみました。 Nextcloudのジョブは基本的に5分おきに走るので、最後のジョブからの経過時間が5分を越えると遅れ気味だというわけです。 min(time() - nextcloud_job_last_run_timestamp_seconds)というPromQLで取得しています。

ついでにいつ、どのジョブが走っているかも見れるようにしています。

走っているジョブの様子
こうして見ると毎回実行されるジョブもあればアップロード後に走ってそうなのもあっておもしろいですね。

おわりに

いかがでしたか。これを期に身の周りのジョブを可視化してみたくなりましたか。 この記事は、はてなエンジニア Advent Calendar 2025 - Hatena Developer Blogの45日目の記事でした。 明日(1月14日)はid:masayosuさんです。よろしくお願いします。

YAPC::Fukuoka 2025 に行きました

id:taiseiueです。11/14〜15に九州は福岡工業大学で開催されていた「YAPC::Fukuoka 2025」に参加しました。

yapcjapan.org

参加にあたっては、学生旅費支援で宿泊費と旅費を支援していただきました。 このような機会をくださった運営の方々に感謝しています。

blog.yapcjapan.org

以下は懇親会で楽しそうなid:taiseiue と仲間達です。

インフルでした

帰って早々インフルになっていました。ブログを書くのがだいぶ遅れたのはこれです..

トーク&踊り場

ここからは、聴講させていただいたトークや参加した踊り場の感想を書いていきます。

2025年秋のPerl by charsbar

speakerdeck.com

今ドキの最新Perlの話でした。all/any演算子が入って便利に使えそう。use feature 'all'ではなくてuse feature 'keyword_all'と書くのは全機能を有効化してしまいそうな感じがするからでしょうか。あと、:readerと:writerが個人的便利そう。

大規模OSSに一人で立ち向かうには by Sosuke Suzuki

speakerdeck.com

いい話でした。何かに莫大な情熱を持っている人をエミュレートするには、「時間を可能な限り捻出して、可能な限り集中して使うこと」。この点が言語化されて実感が持てました。他にも、「手を動かしてメンタルモデルを得ること」、「教科書を読むこと」は日常生活の中でも役立ちそうです。

とりあえず散歩に行きます。

「バイブス静的解析」でレガシーコードを分析・改善しよう by hitode909

speakerdeck.com

id:hitode909 さんの発表には特有の凄みがあると思います。何か自然に場の空気を支配される感じ。 今まで画面越しに見ていたそれを生でみられてよかったです。

静的解析をLLMに助けてもらう、確かにVibeCodingよりも相当安心感がありますね。うちのプロジェクトもデッドコードを削除するところからやってもらおうかな。

Perl ブートキャンプ by Takafumi ONAKA

speakerdeck.com

Perlって何??となったので。manみたいにperldocが整備されているの、当たり前に思ってるけど良いですね。 「非常に高い後方互換性」について、確かに互換性を失なった先は狂気ではあるけどバグとの兼ね合いが難しすぎる...という気持ちになっていました。 私もしがないプログラミング言語をメンテナンスしているので、ここは気持ちがわかる気がします。

これは何度も言っているのですが、データにパッケージを紐付けてオブジェクトとするの、原野的な感じがしてすごくいい(語彙力)。

SREのためのテレメトリー技術の探究 — モニタリングSaaS開発からAIOps・AIインフラまで by yuuk1

speakerdeck.com

時系列基盤モデル、初めて聞いた概念だったのですがなかなか便利そう。MackerelでChatOpsから入って、AIOpsへと時代とともに要求が難しくなっていく のにはヒエエとなりました。基盤モデルを作ろうにもデータセットを得るのが難しい、そりゃそうやなとなりました。

OSS開発者なら学生たくさん連れてこれる説 by id:moznion

つれてこられました。尊敬する OSS 開発者の皆さんが横に並んでいて迫力がありました。 OSSコントリビュートするノウハウや継続するコツなど、様々な話が聞けてよかったです。

教科書では知れない令和最新 Perl ワード解説バトル by id:rokuokun

バトルですね。激闘でした。

slidoで素朴なPerlの疑問を賢者の方々に投げかけれるのかなりよかったです。 CPAN Testersが有志でCI(のようなもの)を周してくれている様子には迫力がありました。 Mojoliciousが最近は良いと聞いたので、何かつくるときに使ってみます。

id:rokuokun は司会おつかれさまです!

キーノート by P山

speakerdeck.com

スライドが良かったです。章立てされていて、セクションごとに画像は入っている感じは洋書に近いものを感じました。

"Hacker"であり続けるために、継続的に、よく考えつづける必要があると思いました。精進します。

牛すき鍋御膳を食べた

今宮通を北大路から堀川まで歩いた。行き先は堀川今宮のすき家に行くためだ。 例年この時期のすき家は牛すき鍋御膳を販売してくれる。平たく言えばすき焼き鍋セットである。

このシーンはちょうど2年前の今頃にもあった。あの頃は確か大学入試の願書だったかをギリギリまで書いていて、提出先の大学の配送担当の北郵便局に持って行ったのを覚えている。あの頃から無計画性はあまり変わらないようだ。

提供を待っていると、あのころ歩きながら聴いていた曲が有線から流れてきたのには驚いた。驚いただけで何の関連もない。

beautiful glider

beautiful glider

セットが来た。 自分なりのおすすめの食べ方は、まず伸びる前早々にうどんを小皿へと退避させ、煮切れそうになったらコップの水を入れて冷ます。こうすることで長いこと楽しめる。ああ、卵はふたつ頼んでおくといい。猫舌に鍋は熱すぎるから。

前回ここに来た頃からするといくらか美味しくなった気がする。それは多分体感の問題だ。あの頃は(当時の自分からすると)失意の地底から上がってきてすぐだったから。 次来たときはもっと美味しく感じられるといいなあ。

食後、調子に乗ってSukiシェイクも頼んでしまった。バニラ味。この手のものはバニラ味が一番、牧歌的で美味しい。

今、まだシェイクをすすりながらこれを書いている。

そんな私です。

MacBookを初期化した

今日、手元のMacBookを初期化した。2024年の春から使っていて、ちょうど1年半。 それなりに思い入れや愛着も湧いてきていたが、HomebrewやMacPortsなど、様々なパッケージマネージャーを試したり、種々のドライバ、ソフトウェアをインストールしてきたことで、ジャンクファイルでいっぱいになり挙動も怪しくなったからだ。

ついでにOSも最新のmacOS Tahoeにアップデートしておいた。 この過程で、当然macOSのセットアップを行ったわけだが、ここにこそコンピューターと向き合うことの"楽しさ"があることを思い出した。 コンピューターを手にして、それを自分好みにカスタマイズすること、これからコンピューターを使ってできる無限の可能性が、セットアップという手順に凝縮されている。

これから私は、また (愚かにも) このマシンを使い倒し、様々なソフトウェアをインストールし、環境を肥大化させていくだろう。 しかし、それはそれでよかろう。なぜなら、私はそうやってコンピューターと一体化していくことが好きだからだ。 使えば使うほど、コンピューターは自分の行動に即した提案をしてくれ(時に行動を補完することすらあるが)、今に自分自身の思考に最も近くなる。

先日、情報学を学んではいるが、コンピューターと仲良くなれない、という友人と話す機会があった。 できれば私のように、コンピューターと一体化していく体験をしてほしいと思う。