5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MCPサーバContext7を使って、もう古いSymbolSDKのコードをAIに書かせない。

Last updated at Posted at 2025-08-16

AIコーディングしてますか?便利ですよね。
でも、AIの吐き出すコードがどうにも古い…。
いまならもっと良い書き方がある、あ、こっちはもうDeprecatedなのに…。
あーいま公開されてるドキュメントを学習していてくれたらなー…。
そんな、あったらいいなをカタチにするMCPサーバが「Context7」です。

登録されているドキュメントの最新情報を適切に返却してくれるので、AIが学習している範囲や学習のカットオフを気にする必要もなくなります。

なお、Symbolのリポジトリが登録されていなかったので、とりあえず登録しておきました。
誰でもリポジトリURLを追加することができるようです。

context7-recently-added.png

claude codeへの追加

$ claude mcp add context7 -- npx --yes @upstash/context7-mcp

codexやgemini、その他のIDEを使っているひとはそれに従って導入してください。

導入の確認

$ claude /mcp
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Manage MCP servers                                                                                                               │
│                                                                                                                                  │
│ ❯ 1. context7  ✔ connected · Enter to view details

一覧の中にcontext7が表示されれば大丈夫でしょう。

Context7を使わない場合

SymbolSDKを用いた、シンプルなトランザクションのサンプルコードを書いて。

次はこのプロンプトで生成されたコードです。
どうみてもv2 SDKを用いたコードです。本当にありがとうございました。
ちなみに見た感じ動きそうですが、動作は確認していませんので、真面目に見なくてもいいです。

/**
 * Symbol SDK シンプルトランザクションサンプル
 * 
 * 設計ドキュメント参照: Symbol Developer Documentation
 * 関連クラス: Account, TransferTransaction, NetworkType, Mosaic, UInt64
 */

const {
    Account,
    Address,
    Deadline,
    NetworkType,
    PlainMessage,
    TransferTransaction,
    Mosaic,
    MosaicId,
    UInt64,
    TransactionHttp,
    RepositoryFactoryHttp
} = require('symbol-sdk');

/**
 * メイン処理
 * Symbol ネットワークへの XYM 送金トランザクションを作成・送信
 */
async function main() {
    try {
        // ネットワーク設定(テストネット)
        const networkType = NetworkType.TEST_NET;
        const nodeUrl = 'https://sym-test-03.opening-line.jp:3001';
        
        // 送信者アカウント(秘密鍵から生成)
        // 注意: 実際の使用時は環境変数等で秘密鍵を管理してください
        const privateKey = 'YOUR_PRIVATE_KEY_HERE'; // 64文字の16進数文字列
        const account = Account.createFromPrivateKey(privateKey, networkType);
        
        // 受信者アドレス
        const recipientAddress = Address.createFromRawAddress('TBIL6D6RURP45YQRWV6Q7YVWIIPLQGLZQFHWFEQ');
        
        // 送金額(マイクロXYM単位)
        const amount = UInt64.fromUint(1000000); // 1 XYM = 1,000,000 マイクロXYM
        
        // XYMモザイク
        const networkCurrencyMosaicId = new MosaicId('6BED913FA20223F8');
        const xymMosaic = new Mosaic(networkCurrencyMosaicId, amount);
        
        // トランザクション作成
        const transferTransaction = TransferTransaction.create(
            Deadline.create(2), // 2時間後の期限
            recipientAddress,
            [xymMosaic],
            PlainMessage.create('Symbol SDK サンプル送金'),
            networkType,
            UInt64.fromUint(2000000) // 手数料(マイクロXYM)
        );
        
        // トランザクション署名
        const signedTransaction = account.sign(transferTransaction, networkType);
        
        console.log('署名済みトランザクション:');
        console.log('ハッシュ:', signedTransaction.hash);
        console.log('ペイロード:', signedTransaction.payload);
        
        // ネットワークへ送信
        const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
        const transactionHttp = repositoryFactory.createTransactionRepository();
        
        const response = await transactionHttp.announce(signedTransaction).toPromise();
        console.log('トランザクション送信完了:', response.message);
        
        // トランザクション確認
        console.log('トランザクション確認URL:');
        console.log(`https://testnet.symbol.fyi/transactions/${signedTransaction.hash}`);
        
    } catch (error) {
        console.error('エラーが発生しました:', error);
    }
}

/**
 * アカウント残高確認のサンプル関数
 */
async function checkBalance(address, nodeUrl = 'https://sym-test-03.opening-line.jp:3001') {
    try {
        const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
        const accountHttp = repositoryFactory.createAccountRepository();
        
        const accountInfo = await accountHttp.getAccountInfo(Address.createFromRawAddress(address)).toPromise();
        
        console.log('アカウント情報:');
        console.log('アドレス:', accountInfo.address.pretty());
        console.log('モザイク一覧:');
        
        accountInfo.mosaics.forEach(mosaic => {
            console.log(`  モザイクID: ${mosaic.id.toHex()}`);
            console.log(`  残高: ${mosaic.amount.toString()}`);
        });
        
    } catch (error) {
        console.error('残高確認でエラーが発生しました:', error);
    }
}

// 実行
if (require.main === module) {
    main();
}

module.exports = {
    main,
    checkBalance
};

プロンプトでv3を使うことを指定したり、同じプロンプトでも偶然v3のコードを出してくれる可能性もありますが、とりあえずこのような結果が出力されました。

Context7を使った場合

SymbolSDKを用いた、シンプルなトランザクションのサンプルコードを書いて。 use context7 symbol/symbol

同じプロンプトに「use context7 symbol/symbol」という文を付け足します。これでMCPサーバを使ってくれます。

「symbol/symbol」というのは本当は省けるのですが、context7がうまくリポジトリ名を発見できないケースがあったため、登録したリポジトリ名を渡すようにしています

⏺ Symbol monorepoが見つかりました!これを使用してドキュメントを取得します。

⏺ context7 - get-library-docs (MCP)(context7CompatibleLibraryID: "/symbol/symbol", topic: "transaction sample", tokens: 5000)
  ⎿  ========================
     CODE SNIPPETS
     ========================
     … +1278 lines (ctrl+r to expand)

いいですね。ツッコミを入れたい部分はたくさんありますが、v3のコードで生成されました。
こちらも動作確認はしていないので、真面目に見なくてもいいです。

/**
 * Symbol転送トランザクションのサンプルコード
 * 
 * 設計ドキュメント参照: Symbol SDK (/symbol/symbol)
 * 関連クラス: SymbolFacade, TransactionFactory
 */

import { SymbolFacade } from 'symbol-sdk';

// ネットワーク設定
const SYMBOL_API_ENDPOINT = 'https://sym-test-04.opening-line.jp:3001';  // テストネット
const NETWORK_TYPE = 'testnet';

/**
 * シンプルな転送トランザクションを作成・送信
 */
async function createSimpleTransferTransaction() {
    // Symbol Facadeを初期化
    const facade = new SymbolFacade(NETWORK_TYPE);
    
    // 送信者の秘密鍵(実際の利用時は安全に管理してください)
    const privateKey = 'YOUR_PRIVATE_KEY_HERE';
    const keyPair = facade.KeyPair(facade.PrivateKey(privateKey));
    
    // 送信者アドレス
    const senderAddress = facade.network.publicKeyToAddress(keyPair.publicKey);
    console.log(`送信者アドレス: ${senderAddress}`);
    
    // 受信者アドレス
    const recipientAddress = 'TCHBDENCLKEBILBPWP3JPB2XNY64OE7PYHHE32I';
    
    // 現在のネットワーク時間を取得し、2時間後をデッドラインに設定
    const networkTime = await getNetworkTime();
    const deadline = networkTime.addHours(2);
    
    // 転送トランザクションを作成
    const transaction = facade.transactionFactory.create({
        type: 'transfer_transaction_v1',
        signerPublicKey: keyPair.publicKey,
        deadline: deadline.timestamp,
        recipientAddress: recipientAddress,
        mosaics: [
            {
                mosaicId: 0x7CDF3B117A3C40CCn,  // XYMのモザイクID
                amount: 1000000n                 // 1 XYM (6桁の小数点)
            }
        ],
        message: new TextEncoder().encode('Hello Symbol!')  // メッセージ(オプション)
    });
    
    // 手数料を設定(トランザクションサイズに基づく)
    transaction.fee = 100n * BigInt(transaction.size);
    
    // トランザクションに署名
    const signature = facade.signTransaction(keyPair, transaction);
    const jsonPayload = facade.transactionFactory.attachSignature(transaction, signature);
    
    // トランザクションハッシュを計算
    const transactionHash = facade.hashTransaction(transaction);
    console.log(`トランザクションハッシュ: ${transactionHash}`);
    
    // 署名済みトランザクションを表示
    console.log('署名済みトランザクション:', transaction);
    
    // ネットワークにトランザクションを送信
    try {
        const response = await fetch(`${SYMBOL_API_ENDPOINT}/transactions`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json'
            },
            body: jsonPayload
        });
        
        const result = await response.json();
        console.log('送信結果:', result);
        
        // トランザクションの確認を待機
        await waitForTransactionStatus(transactionHash, 'confirmed');
        console.log('トランザクションが確認されました!');
        
    } catch (error) {
        console.error('トランザクション送信エラー:', error);
    }
}

/**
 * ネットワーク時間を取得
 */
async function getNetworkTime() {
    const response = await fetch(`${SYMBOL_API_ENDPOINT}/network/time`);
    const data = await response.json();
    return {
        timestamp: BigInt(data.receiveTimeStamp),
        addHours: (hours) => ({
            timestamp: BigInt(data.receiveTimeStamp) + BigInt(hours * 60 * 60 * 1000)
        })
    };
}

/**
 * トランザクションの状態確認を待機
 */
async function waitForTransactionStatus(hash, expectedStatus, maxRetries = 30) {
    for (let i = 0; i < maxRetries; i++) {
        try {
            const response = await fetch(`${SYMBOL_API_ENDPOINT}/transactionStatus/${hash}`);
            const status = await response.json();
            
            if (status.group === expectedStatus) {
                return status;
            }
            
            // 2秒待機してリトライ
            await new Promise(resolve => setTimeout(resolve, 2000));
        } catch (error) {
            console.log(`状態確認中... (${i + 1}/${maxRetries})`);
            await new Promise(resolve => setTimeout(resolve, 2000));
        }
    }
    
    throw new Error(`トランザクション ${hash} の確認がタイムアウトしました`);
}

// 実行例
createSimpleTransferTransaction()
    .then(() => console.log('完了'))
    .catch(error => console.error('エラー:', error));

まとめ

そもそも、もう少し詳細に指示を出したほうがいいのはもちろん、数回程度しか試していないので、有効性の検証としては甘いのですが、ちゃんとv3 SDKが使われました。

context7がより効果的な結果を返せるように、メタな情報をもたせるフォーマットがあるので、これに従った情報をリポジトリに追加すると、より意図に近い情報が取得できるように、便利になるかもしれません。

Symbol SDKはv2版の情報がとても豊富ですが、今となっては過去のものです。
v3版も十分成熟しているので、正直なところ今更v2の情報やスニペットが邪魔になってしまうこともあります。

時間が経てば古い情報をAIが返してこなくなるかもしれませんし、新しい情報についても、この先Context7を使わなくてもいいような手段が現れるかも知れませんが、現時点では新しい情報を取り入れたAIコーディングをさせるには良い選択肢だと思います。

この課題はSymbolだけでなく、一般的な課題ですので、Symbolを用いたアプリケーション開発を加速させていくためにも、context7のような仕組みはどんどん使いこなしていきたいですね。

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?