Skip to main content
Glama

Story SDK MCP Server

by piplabs
conftest.py12.5 kB
""" Pytest fixtures for Story MCP Hub tests. """ import pytest import os from unittest.mock import Mock, MagicMock, patch import json from web3 import Web3 from mcp.server.fastmcp import FastMCP from dotenv import load_dotenv # Load test environment variables @pytest.fixture(scope="session", autouse=True) def load_env(): """Load .env.test file if it exists, otherwise load .env""" if os.path.exists(".env.test"): load_dotenv(".env.test", override=True) else: load_dotenv(override=True) # Set test mode environment variable os.environ["TESTING"] = "1" yield # Cleanup if "TESTING" in os.environ: del os.environ["TESTING"] # Web3 mocks @pytest.fixture def mock_web3(): """Create a mock Web3 instance with predefined responses""" mock_w3 = Mock(spec=Web3) # Mock eth module mock_w3.eth = Mock() mock_w3.eth.chain_id = 1315 # Story Protocol chain ID mock_w3.eth.get_balance = Mock(return_value=100000000000000000000) # 100 ETH in wei mock_w3.eth.get_transaction_count = Mock(return_value=0) mock_w3.eth.gas_price = 20000000000 # 20 gwei # Mock account module mock_account = Mock() mock_account.address = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" mock_w3.eth.account = Mock() mock_w3.eth.account.from_key = Mock(return_value=mock_account) # Helper methods mock_w3.to_wei = Web3.to_wei mock_w3.from_wei = Web3.from_wei mock_w3.to_checksum_address = Web3.to_checksum_address mock_w3.keccak = Web3.keccak # Mock connection status mock_w3.is_connected = Mock(return_value=True) return mock_w3 @pytest.fixture def mock_story_client(): """Create a mock Story Protocol client with predefined responses""" mock_client = Mock() # Mock License module mock_client.License = Mock() mock_client.License.getLicenseTerms = Mock(return_value=[ True, # transferable "0x1234567890123456789012345678901234567890", # royaltyPolicy 0, # defaultMintingFee 0, # expiration True, # commercialUse False, # commercialAttribution "0x0000000000000000000000000000000000000000", # commercializerChecker b'0x', # commercializerCheckerData 10, # commercialRevShare 0, # commercialRevCeiling True, # derivativesAllowed True, # derivativesAttribution False, # derivativesApproval True, # derivativesReciprocal 0, # derivativeRevCeiling "0x1514000000000000000000000000000000000000", # currency "ipfs://example", # uri ]) mock_client.License.mintLicenseTokens = Mock(return_value={ "txHash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", "licenseTokenIds": [1, 2, 3] }) # Mock IPAsset module mock_client.IPAsset = Mock() mock_client.IPAsset.mintAndRegisterIpAssetWithPilTerms = Mock(return_value={ "txHash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", "ipId": "0x9876543210abcdef9876543210abcdef98765432", "tokenId": 1, "licenseTermsIds": [1] }) mock_client.IPAsset.register = Mock(return_value={ "txHash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", "ipId": "0x9876543210abcdef9876543210abcdef98765432" }) mock_client.IPAsset.registerDerivative = Mock(return_value={ "txHash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890" }) # Mock Royalty module mock_client.Royalty = Mock() mock_client.Royalty.payRoyaltyOnBehalf = Mock(return_value={ "txHash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890" }) mock_client.Royalty.claimRevenue = Mock(return_value={ "txHash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", "claimableToken": 1000 }) return mock_client @pytest.fixture def mock_nft_client(): """Create a mock NFT client with predefined responses""" mock_nft_client = Mock() mock_nft_client.create_nft_collection = Mock(return_value={ "tx_hash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", "nft_contract": "0xabcdef1234567890abcdef1234567890abcdef1234" }) return mock_nft_client @pytest.fixture def mock_pinata_response(): """Create a mock response for Pinata API calls""" class MockResponse: def __init__(self, status_code=200, json_data=None): self.status_code = status_code self.json_data = json_data or {} self.text = json.dumps(self.json_data) self.content = b"mock image content" def json(self): return self.json_data return MockResponse(json_data={"IpfsHash": "QmXyZ123456789"}) # MCP server fixtures @pytest.fixture def mcp_test_server(): """Create a test MCP server instance""" mcp = FastMCP("Test MCP Server") return mcp # Storyscan API mock responses @pytest.fixture def mock_transaction_history_response(): """Mock response for transaction history endpoint""" return { "items": [ { "timestamp": "2025-03-15T12:00:00Z", "hash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", "block_number": 12345, "from_": {"hash": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"}, "to": {"hash": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"}, "value": "1000000000000000000", # 1 IP "fee": {"value": "21000000000000"}, "status": "ok", "method": "transfer", "transaction_types": ["token_transfer"], "gas_used": 21000, "gas_limit": 21000, "gas_price": "20000000000", # 20 gwei } ] } @pytest.fixture def mock_blockchain_stats_response(): """Mock response for blockchain stats endpoint""" return { "average_block_time": 2000, # 2 seconds in ms "total_blocks": 12345, "total_transactions": 67890, "transactions_today": 1234, "total_addresses": 5678, "coin_price": "1.25", "market_cap": "125000000", "network_utilization_percentage": 35, "gas_prices": { "slow": 20, "average": 30, "fast": 50 }, "gas_prices_update_in_seconds": 120, "gas_used_today": "500000000", "total_gas_used": "10000000000" } @pytest.fixture def mock_address_overview_response(): """Mock response for address overview endpoint""" return { "hash": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "coin_balance": "100000000000000000000", # 100 IP "exchange_rate": 1.25, "block_number_balance_updated_at": 12345, "is_contract": False, "is_verified": True, "is_scam": False, "ens_domain_name": "alice.ip", "has_tokens": True, "has_token_transfers": True, "has_logs": True, "has_beacon_chain_withdrawals": False, "has_validated_blocks": False, "has_decompiled_code": False, # This field may be missing in actual API responses "public_tags": [{"display_name": "Alice"}], "private_tags": [], "watchlist_names": [] } @pytest.fixture def mock_token_holdings_response(): """Mock response for token holdings endpoint""" return { "items": [ { "token": { "name": "Story Token", "symbol": "STORY", "decimals": "18", "type": "ERC-20", "address": "0xabcdef1234567890abcdef1234567890abcdef1234", "holders": "1000", "total_supply": "1000000000000000000000000", "exchange_rate": "0.5" }, "value": "10000000000000000000" # 10 STORY } ] } @pytest.fixture def mock_nft_holdings_response(): """Mock response for NFT holdings endpoint""" return { "items": [ { "token": { "name": "Story NFT Collection", "symbol": "SNFT", "type": "ERC-721", "address": "0xabcdef1234567890abcdef1234567890abcdef1234", "holders": "100", "total_supply": "1000" }, "id": "42", "token_type": "ERC-721", "value": "1", "image_url": "ipfs://QmXyZ123456789", "metadata": { "name": "Story NFT #42", "description": "A test NFT for Story Protocol", "attributes": [ {"trait_type": "Rarity", "value": "Legendary"}, {"trait_type": "Type", "value": "Artwork"} ] } } ] } @pytest.fixture def mock_transaction_interpretation_response(): """Mock response for transaction interpretation endpoint""" return { "summaries": [ { "summary_template": "{sender} transferred {amount} {token} to {receiver}", "summary_template_variables": { "sender": { "type": "address", "value": { "hash": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "name": "Alice" } }, "amount": { "type": "currency", "value": "1000000000000000000" }, "token": { "type": "token", "value": { "symbol": "IP", "name": "Story IP Token", "decimals": "18" } }, "receiver": { "type": "address", "value": { "hash": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", "name": "Bob" } } } } ], "data": { "debug_data": { "model_classification_type": "token_transfer", "summary_template": { "transfer": { "template_vars": { "token": { "name": "Story IP Token", "symbol": "IP", "type": "ERC-20", "address": "0x1234567890123456789012345678901234567890", "holders": "10000", "total_supply": "1000000000000000000000000000", "decimals": "18" }, "methodCalled": "transfer", "tokenTransfers": [ { "token": { "name": "Story IP Token", "symbol": "IP", "type": "ERC-20", "address": "0x1234567890123456789012345678901234567890", "holders": "10000", "total_supply": "1000000000000000000000000000", "decimals": "18" }, "from": {"hash": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"}, "to": {"hash": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"}, "total": {"value": "1000000000000000000"} } ] } } } } } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/piplabs/story-mcp-hub'

If you have feedback or need assistance with the MCP directory API, please join our Discord server