Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ agentkit/
│ ├── langchain-privy-chatbot/
│ ├── langchain-solana-chatbot/
│ ├── langchain-twitter-chatbot/
│ ├── model-context-protocol-cdp-server/
│ └── vercel-ai-sdk-cdp-chatbot/
├── python/
│ ├── coinbase-agentkit/
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ agentkit/
│ ├── langchain-privy-chatbot/
│ ├── langchain-solana-chatbot/
│ ├── langchain-twitter-chatbot/
│ ├── model-context-protocol-cdp-server/
│ └── vercel-ai-sdk-cdp-chatbot/
├── python/
│ ├── coinbase-agentkit/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"parser": "@typescript-eslint/parser",
"extends": ["../../.eslintrc.base.json"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
docs/
dist/
build/
coverage/
.github/
src/client
**/**/*.json
*.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": false,
"trailingComma": "all",
"bracketSpacing": true,
"arrowParens": "avoid",
"printWidth": 100,
"proseWrap": "never"
}
59 changes: 59 additions & 0 deletions typescript/examples/model-context-protocol-cdp-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# CDP AgentKit Model Context Protocol Examples - Chatbot Typescript

This example demonstrates an agent setup as a server for Model Context Protocol, allowing Claude Desktop access to the full set of CDP AgentKit actions.

## Ask the chatbot to engage in the Web3 ecosystem!

- "Transfer a portion of your ETH to a random address"
- "What is the price of BTC?"
- "Deploy an NFT that will go super viral!"
- "Deploy an ERC-20 token with total supply 1 billion"

## Prerequisites

### Checking Node Version

Before using the example, ensure that you have the correct version of Node.js installed. The example requires Node.js 18 or higher. You can check your Node version by running:

```bash
node --version
```

If you don't have the correct version, you can install it using [nvm](https://github.com/nvm-sh/nvm):

```bash
nvm install node
```

This will automatically install and use the latest version of Node.

### API Keys

You'll need the following API key:
- [CDP API Key](https://portal.cdp.coinbase.com/access/api)

You'll need to configure the Claude desktop config file with your CDP API keys. Copy the contents from `claude_desktop_config.json` to your Claude desktop config file and update the following:

1. Update the `args` path to match the location of your built index.js file
2. Set your CDP API keys in the `env` section:
- "CDP_API_KEY_NAME"
- "CDP_API_KEY_PRIVATE_KEY"

Then, navigate to the `claude_desktop_config.json` file found in your Claude Desktop apps' settings and update it's contents to the contents of our `claude_desktop_config.json` file.

## Running the example
Comment thread
CarsonRoscoe marked this conversation as resolved.

From the root directory, run:

```bash
npm install
npm run build
```

This will install the dependencies and build the packages locally. The chatbot example uses the local `@coinbase/agentkit-model-context-protocol` and `@coinbase/agentkit` packages. If you make changes to the packages, you can run `npm run build` from root again to rebuild the packages, and your changes will be reflected in the chatbot example.

To use the chatbot, simply open Claude desktop after configuring your API keys. The MCP server will run automatically when you interact with Claude.

## License

Apache-2.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"mcpServers": {
"agentkit": {
"command": "node",
"args": [
"/Users/YOUR_USER/YOUR_DIRECTORIES/agentkit/typescript/examples/model-context-protocol-cdp-server/dist/index.js"
],
"env": {
"CDP_API_KEY_NAME": "YOUR_CDP_API_KEY_NAME",
"CDP_API_KEY_PRIVATE_KEY": "YOUR_CDP_API_KEY_PRIVATE_KEY"
}
}
}
}
136 changes: 136 additions & 0 deletions typescript/examples/model-context-protocol-cdp-server/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { getMcpTools } from "@coinbase/agentkit-model-context-protocol";
import {
AgentKit,
CdpWalletProvider,
wethActionProvider,
walletActionProvider,
erc20ActionProvider,
erc721ActionProvider,
cdpApiActionProvider,
cdpWalletActionProvider,
pythActionProvider,
} from "@coinbase/agentkit";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";

/**
* Validates that required environment variables are set
*/
function validateEnvironment(): void {
const requiredVars = ["CDP_API_KEY_NAME", "CDP_API_KEY_PRIVATE_KEY"];
const missingVars = requiredVars.filter(varName => !process.env[varName]);

if (missingVars.length > 0) {
console.error("Error: Required environment variables are not set:");
missingVars.forEach(varName => {
console.error(`${varName}=your_${varName.toLowerCase()}_here`);
});
process.exit(1);
}

if (!process.env.NETWORK_ID) {
console.warn("Warning: NETWORK_ID not set, defaulting to base-sepolia testnet");
}
}

/**
* This function creates a new server instance with the capabilities to handle MCP requests.
* It configures the CDP Wallet Provider with the provided API keys and network ID.
* It then initializes the AgentKit with the configured wallet provider and action providers.
*
* @returns {Promise<Server>} The initialized MCP server
*/
async function initializeServer() {
try {
// Create server instance with capabilities
const server = new Server(
{
name: "cdp-agentkit",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
},
);

// Configure CDP Wallet Provider
const config = {
apiKeyName: process.env.CDP_API_KEY_NAME!,
apiKeyPrivateKey: process.env.CDP_API_KEY_PRIVATE_KEY!,
networkId: process.env.NETWORK_ID || "base-sepolia",
};

const walletProvider = await CdpWalletProvider.configureWithWallet(config);

// Initialize AgentKit
const agentkit = await AgentKit.from({
walletProvider,
actionProviders: [
wethActionProvider(),
pythActionProvider(),
walletActionProvider(),
erc20ActionProvider(),
erc721ActionProvider(),
cdpApiActionProvider({
apiKeyName: config.apiKeyName,
apiKeyPrivateKey: config.apiKeyPrivateKey,
}),
cdpWalletActionProvider({
apiKeyName: config.apiKeyName,
apiKeyPrivateKey: config.apiKeyPrivateKey,
}),
],
});

// Get MCP tools from AgentKit
const { tools, toolHandler } = await getMcpTools(agentkit);

// Set up request handlers
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools,
};
});

server.setRequestHandler(CallToolRequestSchema, async request => {
try {
return await toolHandler(request.params.name, request.params.arguments);
} catch (error) {
console.error(`Error executing tool ${request.params.name}:`, error);
throw new Error(`Tool ${request.params.name} failed: ${error}`);
}
});

return server;
} catch (error) {
console.error("Failed to initialize server:", error);
throw error;
}
}

/**
* Main function to run the MCP server
*/
async function main() {
validateEnvironment();

try {
const server = await initializeServer();
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("CDP AgentKit MCP Server running on stdio");
} catch (error) {
console.error("Fatal error:", error);
process.exit(1);
}
}

if (require.main === module) {
main().catch(error => {
console.error("Fatal error in main():", error);
process.exit(1);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "@coinbase/cdp-model-context-protocol-server",
"description": "Coinbase AgentKit Example Model Context Protocol Server",
"version": "1.0.0",
"private": true,
"author": "Coinbase Inc.",
"license": "Apache-2.0",
"bin": {
"agentkit": "./dist/index.js"
},
"scripts": {
"build": "tsc && node -e \"require('fs').chmodSync('dist/index.js', '755')\"",
"lint": "eslint -c .eslintrc.json *.ts",
"lint:fix": "eslint -c .eslintrc.json *.ts --fix",
"format": "prettier --write \"**/*.{ts,js,cjs,json,md}\"",
"format:check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\""
},
"dependencies": {
"@coinbase/agentkit": "^0.2.3",
"@coinbase/agentkit-model-context-protocol": "^0.1.0",
"@modelcontextprotocol/sdk": "^1.6.1",
"zod": "^3.22.4"
},
"devDependencies": {
"nodemon": "^3.1.0",
"ts-node": "^10.9.2"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"preserveSymlinks": true,
"outDir": "./dist",
"rootDir": ".",
"module": "Node16"
},
"include": ["*.ts"]
}
Loading