MCP Solana Internet
by waifuai
This project is a proof-of-concept MCP server that integrates with the Solana blockchain to enable paid access to digital content using direct SOL payments. It showcases how MCP can be combined with a blockchain to create decentralized access control systems.
Last updated: N/A
MCP Solana Internet: Direct SOL Payments for Content Access
This project demonstrates a proof-of-concept implementation of an MCP server that integrates with the Solana blockchain to enable paid access to digital content and resources using direct SOL payments. It showcases how MCP can be combined with a blockchain to create decentralized, permissionless access control systems.
Overview
The project consists of two main components:
- MCP Server (
server.py
): This is the core MCP server, built using thefastmcp
library. It handles MCP requests, manages resource access, and interacts with the Solana blockchain. - Payment API (
payments.py
): A Flask-based API that handles the creation of payment transactions. This is integrated within the MCP server itself (using Flask blueprints), simplifying deployment and interaction. This approach makes it easy to create "solana-action:" URIs, as described in the MCP specification.
The server exposes an MCP resource (access://check
) that checks if a user has paid for access to a given resource. If payment is required, it returns a solana-action:
URL that the MCP client can use to initiate a payment transaction. The process_payment
tool allows an MCP client to submit a signed Solana transaction, completing the payment.
Features
- Direct SOL Payments: Users pay directly in SOL to access resources, eliminating intermediaries.
- Decentralized Access Control: The Solana blockchain acts as a transparent and immutable ledger for payment verification.
- MCP Integration: Leverages the MCP for standardized resource access requests and payment initiation.
- Flask-Based Payment API: Provides a simple and well-defined API for generating unsigned Solana payment transactions.
- Solana Interaction: Uses the
solders
library for efficient and idiomatic interaction with the Solana blockchain. - Test Coverage: Includes integration tests using
pytest
andpytest-asyncio
to verify basic functionality. - Extensible Design: Provides a foundation for building more complex paid content systems on Solana and MCP.
Installation
-
Prerequisites:
- Python 3.11+
- Poetry (for dependency management)
- Solana CLI (version 1.16 or later)
solana-test-validator
(for local testing)
-
Clone the Repository:
git clone <repository_url> cd mcp-solana-internet
-
Install Dependencies:
poetry install
-
Environment Setup:
-
Create a
.env
file in themcp_solana_internet
directory:touch mcp_solana_internet/.env
-
Edit the
.env
file and set the following variables:RPC_ENDPOINT="http://localhost:8899" # Or your Solana cluster endpoint PAYMENT_WALLET_SEED="1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1" # ^^^ **IMPORTANT:** This is a placeholder for demonstration purposes ONLY. # In a production environment, you MUST use a secure key management solution # (e.g., AWS KMS, HashiCorp Vault, or a hardware wallet). Never store private # keys or seeds directly in code or configuration files. This seed generates # the wallet address.
RPC_ENDPOINT
: The URL of your Solana RPC endpoint. For local development, you can usehttp://localhost:8899
if you're runningsolana-test-validator
. For testing against devnet, usehttps://api.devnet.solana.com
.PAYMENT_WALLET_SEED
: A comma-separated list of 32 integers representing the seed for the payment wallet. This wallet will receive the SOL payments. Again, this is insecure and for demonstration only.
-
Usage
-
Start the Solana Test Validator (for local testing):
solana-test-validator
This starts a local Solana cluster that you can use for testing.
-
Start the MCP Server:
poetry run python mcp_solana_internet/server.py
The server will start listening for MCP requests on
stdin
andstdout
(stdio transport). It also starts the Flask payment API on port 5001. -
Interacting with the Server (Conceptual Example):
An MCP client would interact with the server as follows:
-
Check Access: The client sends an MCP request to
access://check
with the user's public key and the resource ID. -
Payment Required: If the user hasn't paid, the server responds with a JSON object containing:
access
:false
message
: "Payment required."payment_url
: Asolana-action:
URI pointing to the/process_payment_action
endpoint, including the required amount and resource ID as query parameters (e.g.,solana-action:/process_payment_action?amount_sol=0.1&resource_id=resource_1
).
-
Payment Transaction Creation:
- The client extracts the
payment_url
from the previous response. This url includes the amount and resource_id. - The client makes a
POST
request to/process_payment_action
including the user's public key,amount_sol
andresource_id
. - The payment API constructs an unsigned Solana transaction for a direct SOL transfer from the user's wallet to the
PAYMENT_WALLET
. The API returns the serialized, unsigned transaction as a hex string.
- The client extracts the
-
Transaction Signing (Client-Side): The client (e.g., the user's wallet software) must sign the transaction using the user's private key. This signing step is crucial for security and is not handled by the server.
-
Submit Payment: The client sends the signed transaction to the Solana network. This can be achieved with the
solana
cli tool, or programatically through libraries likesolana-py
orsolders
. -
The client then calls the
process_payment
tool on the MCP server, passing in the transaction signature (not the full transaction) as thepayment_transaction
parameter, along with theamount_sol
,client_ip
andresource_id
. The server validates this signature by retrieving the full transaction from the blockchain, checking the amount, destination, etc. -
Re-check Access: After the payment is confirmed, the client can again send an MCP request to
access://check
. This time, if the payment has been processed, the server should respond with{"access": true}
.
-
Code Structure
mcp_solana_internet/
:server.py
: The main MCP server implementation.payments.py
: The Flask API for handling payment transaction creation.utils.py
: (Currently empty) A placeholder for utility functions.tests/
:integration/
: Integration tests for the server.
pyproject.toml
: Project metadata and dependencies (managed by Poetry).pytest.ini
: Configuration for pytest.
.gitignore
: Specifies files and directories to be ignored by Git.README.md
: This file.
Key Files and Functions Explained
server.py
RPC_ENDPOINT
: The Solana RPC endpoint URL.PAYMENT_WALLET
: TheKeypair
object representing the wallet that receives payments.LAMPORTS_PER_SOL
: The conversion factor between SOL and Lamports (the smallest unit of SOL).get_resource_price(resource_id)
: A helper function that returns the price (in SOL) for a given resource ID. This is a placeholder and should be replaced with a more robust pricing mechanism (e.g., fetching prices from a database or an oracle).has_paid_for_access(user_pubkey, resource_id)
: A placeholder function that checks if a user has paid for access to a resource. In a real application, this would involve querying a database of payment records.@mcp.resource("access://check")
: The MCP resource handler for checking access. It takes the user's public key and the resource ID as input.@mcp.tool()
: Defines theprocess_payment
tool which validates the user's payment transaction signature.- Flask Blueprint Integration:
mcp.flask_app.register_blueprint(payments_blueprint)
integrates the Flask payment API directly into the MCP server.
payments.py
payment_app
: The Flask application (blueprint) for the payment API./process_payment_action
(GET): An endpoint that returns metadata describing the payment action, conforming to the MCP action format./process_payment_action
(POST): An endpoint that takes the amount, resource ID, and user's public key as input, and returns a serialized, unsigned Solana transaction for a direct SOL transfer.- CORS Handling: Includes CORS headers to allow requests from different origins (e.g., a web-based wallet).
tests/integration/test_server.py
test_access_check_no_payment
: Tests theaccess://check
resource when the user has not paid.test_access_check_invalid_pubkey
: Tests theaccess://check
resource with an invalid public key.test_access_check_paid
: Simulates a paid user (currently,has_paid_for_access
always returnsFalse
, so this test expects access to be denied).
Improvements and Future Work
- Database Integration: Replace the placeholder
has_paid_for_access
function with a database query to store and retrieve payment records. This would involve:- Choosing a database (e.g., PostgreSQL, MySQL, or a NoSQL database).
- Creating a table to store payment information (user public key, resource ID, amount, timestamp, transaction signature).
- Implementing functions to insert and query payment records.
- Robust Transaction Validation: Enhance the
process_payment
tool to perform more thorough validation of the payment transaction, including:- Checking for double-spending.
- Verifying the transaction's recent blockhash.
- Checking for any other potential issues.
- Error Handling: Improve error handling throughout the code to provide more informative error messages to the client.
- Security:
- Implement a secure key management solution for the
PAYMENT_WALLET
. - Consider using a more secure method for handling the user's public key in the
payments.py
API (e.g., requiring a signed message from the user).
- Implement a secure key management solution for the
- Asynchronous Operations: Use asynchronous database operations to improve performance.
- Token Payments: Extend the system to support payments with SPL tokens in addition to SOL.
- Subscription Model: Implement a subscription model where users can pay for recurring access to resources.
- Dynamic Pricing: Integrate with an oracle or a dynamic pricing mechanism to fetch resource prices in real-time.
- More Tests: Add more unit and integration tests to cover all aspects of the code.
- Refactor process_payment: Separate the transaction fetching and validation from the MCP tool, which is mainly an interface.
This README provides a comprehensive overview of the project, its features, installation instructions, usage examples, and potential improvements. It aims to be informative and helpful for developers interested in understanding and extending the project. The emphasis on security and the clear distinction between placeholder implementations and production-ready solutions are also crucial.