Skip to content

Commit 48c4b8d

Browse files
committed
feat: adding basic Starknet integration // WIP
1 parent 583b48b commit 48c4b8d

18 files changed

+2595
-103
lines changed

README.md

+62-29
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
# @mcpdotdirect/create-mcp-server
1+
# Starknet MCP Server
22

33
![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)
44
![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178C6)
55
![MCP](https://img.shields.io/badge/MCP-1.7+-green)
6+
![Starknet.js](https://img.shields.io/badge/Starknet.js-Latest-purple)
67

7-
A CLI tool to create a new Model Context Protocol (MCP) server project. This package provides a template for building custom MCP servers that can be used by AI agents to interact with external systems and data sources.
8+
An MCP (Model Context Protocol) server for the Starknet blockchain. This server provides AI agents with the ability to interact with Starknet networks, query blockchain data, manage wallets, and interact with smart contracts.
89

910
## 📋 Usage
1011

@@ -31,16 +32,17 @@ The template includes:
3132

3233
## ✨ Features
3334

34-
- **Dual Transport Support**: Run your MCP server over stdio or HTTP
35-
- **TypeScript**: Full TypeScript support for type safety
36-
- **MCP SDK**: Built on the official Model Context Protocol SDK
37-
- **Extensible**: Easy to add custom tools, resources, and prompts
35+
- **Starknet Integration**: Full Starknet blockchain integration using Starknet.js
36+
- **Network Support**: Supports both Mainnet and Sepolia testnet
37+
- **StarknetID Integration**: Resolution of Starknet IDs to addresses and vice versa
38+
- **Native Token Support**: Support for both ETH and STRK native tokens
39+
- **Smart Contract Interaction**: Call and query Starknet smart contracts
40+
- **Dual Transport**: Run as stdio server or HTTP server for different integration needs
41+
- **AI-Ready**: Designed to be used with Claude, GPT, and other AI assistants
3842

3943
## 🚀 Getting Started
4044

41-
After creating your project:
42-
43-
1. Install dependencies using your preferred package manager:
45+
1. Install dependencies:
4446
```bash
4547
# Using npm
4648
npm install
@@ -73,44 +75,75 @@ After creating your project:
7375
npm run dev:http
7476
```
7577

76-
> **Note**: The default scripts in package.json use Bun as the runtime (e.g., `bun run src/index.ts`). If you prefer to use a different package manager or runtime, you can modify these scripts in your package.json file to use Node.js or another runtime of your choice.
78+
## 🔧 Supported Features
79+
80+
### Blockchain Information
81+
- Query chain information (chain ID, latest block)
82+
- Explore block details
83+
- Search transactions
84+
- Get address information
85+
86+
### Native Token Operations
87+
- Get ETH and STRK balances
88+
- Transfer tokens
89+
90+
### Smart Contract Interaction
91+
- Call read-only contract functions
92+
- Get contract storage information
93+
- View ABIs and contract class information
94+
95+
### StarknetID
96+
- Resolve Starknet addresses to Starknet IDs
97+
- Resolve Starknet IDs to addresses
98+
- Get Starknet ID profiles
99+
100+
### NFT Operations
101+
- Check NFT ownership
102+
- Get NFT collection information
103+
104+
## 🔍 Usage with AI Assistants
105+
106+
When using this server with AI assistants like Claude or GPT:
107+
108+
1. Configure your AI assistant to use this MCP server
109+
2. The assistant can then use tools to interact with Starknet
110+
3. Example: "Look up the Starknet ID for address 0x123..."
111+
112+
## 📦 API Structure
77113

78-
## 🛠️ Adding Custom Tools and Resources
114+
The server provides:
79115

80-
When adding custom tools, resources, or prompts to your MCP server:
116+
- **Tools**: Direct function calls to perform blockchain operations
117+
- **Resources**: Structured data endpoints in the form of starknet://{network}/...
118+
- **Prompts**: Pre-built prompts to help AI agents explore the Starknet blockchain
119+
120+
## 🛠️ Development Conventions
121+
122+
When adding custom tools, resources, or prompts:
81123

82124
1. Use underscores (`_`) instead of hyphens (`-`) in all resource, tool, and prompt names
83125
```typescript
84126
// Good: Uses underscores
85127
server.tool(
86-
"my_custom_tool",
87-
"Description of my custom tool",
88-
{
89-
param_name: z.string().describe("Parameter description")
90-
},
91-
async (params) => {
92-
// Tool implementation
93-
}
94-
);
95-
96-
// Bad: Uses hyphens, may cause issues with Cursor
97-
server.tool(
98-
"my-custom-tool",
99-
"Description of my custom tool",
128+
"starknet_contract_call",
129+
"Description of the tool",
100130
{
101-
param-name: z.string().describe("Parameter description")
131+
contract_address: z.string().describe("The contract address")
102132
},
103133
async (params) => {
104134
// Tool implementation
105135
}
106136
);
107137
```
108138

109-
2. This naming convention ensures compatibility with Cursor and other AI tools that interact with your MCP server
139+
2. This naming convention ensures compatibility with Cursor and other AI tools
110140

111141
## 📚 Documentation
112142

113-
For more information about the Model Context Protocol, visit the [MCP Documentation](https://modelcontextprotocol.io/introduction).
143+
For more information about:
144+
- [Model Context Protocol](https://modelcontextprotocol.io/introduction)
145+
- [Starknet.js Documentation](https://www.starknetjs.com/)
146+
- [Starknet Documentation](https://docs.starknet.io/)
114147

115148
## 📄 License
116149

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
"ai",
5656
"agent"
5757
],
58-
"author": "mcpdotdirect",
58+
"author": "Etheral <[email protected]>",
5959
"license": "MIT",
6060
"engines": {
6161
"node": ">=18.0.0"

src/core/chains.ts

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* Defines supported Starknet networks with their RPC URLs
3+
*/
4+
5+
export type NetworkConfig = {
6+
name: string;
7+
chainId: string;
8+
rpcUrl: string;
9+
};
10+
11+
// Network configurations
12+
const networks: Record<string, NetworkConfig> = {
13+
mainnet: {
14+
name: 'mainnet',
15+
chainId: 'SN_MAIN',
16+
rpcUrl: 'https://starknet-mainnet.public.blastapi.io'
17+
},
18+
sepolia: {
19+
name: 'sepolia',
20+
chainId: 'SN_SEPOLIA',
21+
rpcUrl: 'https://starknet-sepolia.public.blastapi.io'
22+
}
23+
};
24+
25+
// Default network to use if none specified
26+
export const DEFAULT_NETWORK = 'mainnet';
27+
28+
/**
29+
* Get the network configuration for a given network name
30+
* @param networkName The network name (mainnet, sepolia)
31+
* @returns The network configuration
32+
*/
33+
export function getNetwork(networkName: string = DEFAULT_NETWORK): NetworkConfig {
34+
const network = networks[networkName.toLowerCase()];
35+
36+
if (!network) {
37+
throw new Error(`Network ${networkName} not supported. Available networks: ${Object.keys(networks).join(', ')}`);
38+
}
39+
40+
return network;
41+
}
42+
43+
/**
44+
* Get the RPC URL for a given network
45+
* @param networkName The network name
46+
* @returns The RPC URL for the network
47+
*/
48+
export function getRpcUrl(networkName: string = DEFAULT_NETWORK): string {
49+
return getNetwork(networkName).rpcUrl;
50+
}
51+
52+
/**
53+
* Get the chain ID for a given network
54+
* @param networkName The network name
55+
* @returns The chain ID for the network
56+
*/
57+
export function getChainId(networkName: string = DEFAULT_NETWORK): string {
58+
return getNetwork(networkName).chainId;
59+
}
60+
61+
/**
62+
* Get a list of all supported networks
63+
* @returns Array of network names
64+
*/
65+
export function getSupportedNetworks(): string[] {
66+
return Object.keys(networks);
67+
}

src/core/prompts.ts

+92-8
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,109 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
22
import { z } from "zod";
33

44
/**
5-
* Register all prompts with the MCP server
5+
* Register all Starknet-related prompts with the MCP server
66
* @param server The MCP server instance
77
*/
88
export function registerPrompts(server: McpServer) {
9-
// Example prompt
9+
// Basic block explorer prompt
1010
server.prompt(
11-
"greeting",
12-
"A simple greeting prompt",
11+
"explore_starknet_block",
12+
"Explore information about a specific Starknet block",
1313
{
14-
name: z.string().describe("Name to greet")
14+
blockNumber: z.string().optional().describe("Block number to explore. If not provided, latest block will be used."),
15+
network: z.string().optional().describe("Network name (e.g., 'mainnet', 'sepolia'). Defaults to Mainnet.")
1516
},
16-
(params: { name: string }) => ({
17+
({ blockNumber, network = "mainnet" }) => ({
1718
messages: [{
1819
role: "user",
1920
content: {
2021
type: "text",
21-
text: `Hello, ${params.name}! How can I help you today?`
22+
text: `I want to explore the Starknet blockchain. Please give me detailed information about ${blockNumber ? `block #${blockNumber}` : "the latest block"} on the ${network} network. Include data like timestamp, transactions count, and any other interesting metrics.`
2223
}
2324
}]
2425
})
2526
);
26-
}
27+
28+
// Address information prompt
29+
server.prompt(
30+
"explore_starknet_address",
31+
"Get information about a Starknet address",
32+
{
33+
address: z.string().describe("Starknet address to explore"),
34+
network: z.string().optional().describe("Network name (e.g., 'mainnet', 'sepolia'). Defaults to Mainnet.")
35+
},
36+
({ address, network = "mainnet" }) => ({
37+
messages: [{
38+
role: "user",
39+
content: {
40+
type: "text",
41+
text: `I'm researching the Starknet address ${address} on the ${network} network. Please provide me with detailed information about this address, including its ETH balance, any token balances if available, and transaction history if possible. Also check if it has a Starknet ID associated with it. Summarize what you find about this address.`
42+
}
43+
}]
44+
})
45+
);
46+
47+
// Transaction information prompt
48+
server.prompt(
49+
"explore_starknet_transaction",
50+
"Get information about a Starknet transaction",
51+
{
52+
txHash: z.string().describe("Transaction hash to explore"),
53+
network: z.string().optional().describe("Network name (e.g., 'mainnet', 'sepolia'). Defaults to Mainnet.")
54+
},
55+
({ txHash, network = "mainnet" }) => ({
56+
messages: [{
57+
role: "user",
58+
content: {
59+
type: "text",
60+
text: `I'm analyzing Starknet transaction ${txHash} on the ${network} network. Please provide me with detailed information about this transaction, including its status, block confirmation, timestamp, gas used, and any other relevant details. Also explain what this transaction did in plain language.`
61+
}
62+
}]
63+
})
64+
);
65+
66+
// Starknet ID lookup prompt
67+
server.prompt(
68+
"lookup_starknet_id",
69+
"Look up a Starknet ID or resolve an address to a Starknet ID",
70+
{
71+
identifier: z.string().describe("Either a Starknet ID (with or without .stark) or a Starknet address"),
72+
network: z.string().optional().describe("Network name (e.g., 'mainnet', 'sepolia'). Defaults to Mainnet.")
73+
},
74+
({ identifier, network = "mainnet" }) => {
75+
// Determine if this is an address or a Starknet ID
76+
const isLikelyAddress = identifier.startsWith('0x') || /^[0-9a-fA-F]{64}$/.test(identifier);
77+
78+
return {
79+
messages: [{
80+
role: "user",
81+
content: {
82+
type: "text",
83+
text: isLikelyAddress
84+
? `Please lookup the Starknet ID associated with the address ${identifier} on the ${network} network. If there's a profile available, provide details about it.`
85+
: `Please resolve the Starknet ID "${identifier}" to an address on the ${network} network. If this is a valid ID, provide information about the associated address.`
86+
}
87+
}]
88+
};
89+
}
90+
);
91+
92+
// Starknet ID profile prompt
93+
server.prompt(
94+
"explore_starknet_id_profile",
95+
"Explore a full Starknet ID profile",
96+
{
97+
address: z.string().describe("Starknet address to look up the profile for"),
98+
network: z.string().optional().describe("Network name (e.g., 'mainnet', 'sepolia'). Defaults to Mainnet.")
99+
},
100+
({ address, network = "mainnet" }) => ({
101+
messages: [{
102+
role: "user",
103+
content: {
104+
type: "text",
105+
text: `I'd like to explore the Starknet ID profile for address ${address} on the ${network} network. Please provide all available information, including the ID, profile picture, verifications, and any other associated data. Let me know if this address has a verified profile and what it can be used for.`
106+
}
107+
}]
108+
})
109+
);
110+
}

0 commit comments

Comments
 (0)