@andrewkimjoseph/celina 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +225 -0
  3. package/bin/cli.js +2 -0
  4. package/build/clients/celo-client.d.ts +14 -0
  5. package/build/clients/celo-client.js +58 -0
  6. package/build/clients/celo-client.js.map +1 -0
  7. package/build/config/chains.d.ts +932 -0
  8. package/build/config/chains.js +236 -0
  9. package/build/config/chains.js.map +1 -0
  10. package/build/config/env.d.ts +5 -0
  11. package/build/config/env.js +7 -0
  12. package/build/config/env.js.map +1 -0
  13. package/build/context/app-context.d.ts +16 -0
  14. package/build/context/app-context.js +17 -0
  15. package/build/context/app-context.js.map +1 -0
  16. package/build/crypto/wallet-key-crypto.d.ts +11 -0
  17. package/build/crypto/wallet-key-crypto.js +57 -0
  18. package/build/crypto/wallet-key-crypto.js.map +1 -0
  19. package/build/http.d.ts +2 -0
  20. package/build/http.js +14 -0
  21. package/build/http.js.map +1 -0
  22. package/build/index.d.ts +2 -0
  23. package/build/index.js +14 -0
  24. package/build/index.js.map +1 -0
  25. package/build/schemas/common.d.ts +4 -0
  26. package/build/schemas/common.js +16 -0
  27. package/build/schemas/common.js.map +1 -0
  28. package/build/server/create-http-app.d.ts +1 -0
  29. package/build/server/create-http-app.js +134 -0
  30. package/build/server/create-http-app.js.map +1 -0
  31. package/build/server/create-server.d.ts +2 -0
  32. package/build/server/create-server.js +21 -0
  33. package/build/server/create-server.js.map +1 -0
  34. package/build/server/instructions.d.ts +1 -0
  35. package/build/server/instructions.js +13 -0
  36. package/build/server/instructions.js.map +1 -0
  37. package/build/services/account.service.d.ts +13 -0
  38. package/build/services/account.service.js +23 -0
  39. package/build/services/account.service.js.map +1 -0
  40. package/build/services/blockchain.service.d.ts +40 -0
  41. package/build/services/blockchain.service.js +81 -0
  42. package/build/services/blockchain.service.js.map +1 -0
  43. package/build/services/token.service.d.ts +54 -0
  44. package/build/services/token.service.js +147 -0
  45. package/build/services/token.service.js.map +1 -0
  46. package/build/services/transaction.service.d.ts +33 -0
  47. package/build/services/transaction.service.js +126 -0
  48. package/build/services/transaction.service.js.map +1 -0
  49. package/build/tools/blockchain.tools.d.ts +3 -0
  50. package/build/tools/blockchain.tools.js +88 -0
  51. package/build/tools/blockchain.tools.js.map +1 -0
  52. package/build/tools/helpers.d.ts +3 -0
  53. package/build/tools/helpers.js +16 -0
  54. package/build/tools/helpers.js.map +1 -0
  55. package/build/tools/index.d.ts +5 -0
  56. package/build/tools/index.js +17 -0
  57. package/build/tools/index.js.map +1 -0
  58. package/build/tools/token.tools.d.ts +2 -0
  59. package/build/tools/token.tools.js +62 -0
  60. package/build/tools/token.tools.js.map +1 -0
  61. package/build/tools/transaction.tools.d.ts +2 -0
  62. package/build/tools/transaction.tools.js +68 -0
  63. package/build/tools/transaction.tools.js.map +1 -0
  64. package/build/tools/types.d.ts +5 -0
  65. package/build/tools/types.js +2 -0
  66. package/build/tools/types.js.map +1 -0
  67. package/build/tools/wallet.tools.d.ts +2 -0
  68. package/build/tools/wallet.tools.js +23 -0
  69. package/build/tools/wallet.tools.js.map +1 -0
  70. package/package.json +54 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Andrew Kim Joseph
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,225 @@
1
+ # Celina — Celo MCP Server
2
+
3
+ **Celina** is an open-source [Model Context Protocol](https://modelcontextprotocol.io) server that gives LLMs read + write access to **Celo mainnet** — balances, stablecoins, sends, swaps (quote stub), and chain reads.
4
+
5
+ Website: [celina.andrewkimjoseph.com](https://celina.andrewkimjoseph.com)
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm i @andrewkimjoseph/celina
11
+ ```
12
+
13
+ npm: [@andrewkimjoseph/celina](https://www.npmjs.com/package/@andrewkimjoseph/celina)
14
+
15
+ ## Quick start
16
+
17
+ **From npm** (stdio MCP server):
18
+
19
+ ```bash
20
+ npx @andrewkimjoseph/celina
21
+ ```
22
+
23
+ **From source** (development):
24
+
25
+ ```bash
26
+ npm install
27
+ npm run build
28
+ npm start
29
+ ```
30
+
31
+ ## Deploy to Render
32
+
33
+ This project includes a [Render Blueprint](render.yaml) for one-click deployment as a public Streamable HTTP MCP server.
34
+
35
+ ### 1. Generate an RSA key pair
36
+
37
+ ```bash
38
+ openssl genpkey -algorithm RSA -out private.pem -pkeyopt rsa_keygen_bits:2048
39
+ openssl rsa -pubout -in private.pem -out public.pem
40
+ ```
41
+
42
+ ### 2. Deploy
43
+
44
+ 1. Push this repo to GitHub
45
+ 2. Render Dashboard → **New → Blueprint** → connect the repo
46
+ 3. Set `WALLET_ENCRYPTION_PRIVATE_KEY` in the Render Environment tab (paste contents of `private.pem`)
47
+ 4. Your MCP endpoint will be at `https://celina.onrender.com/mcp`
48
+
49
+ > **Note:** Free Render services spin down after ~15 minutes of inactivity. Cold starts can take 30–60 seconds and may cause MCP client timeouts. Use a Starter plan for always-on hosting.
50
+
51
+ ## Cursor / Claude Desktop config
52
+
53
+ ### Remote (Render — recommended)
54
+
55
+ ```json
56
+ {
57
+ "mcpServers": {
58
+ "celina": {
59
+ "command": "npx",
60
+ "args": [
61
+ "-y",
62
+ "mcp-remote",
63
+ "https://celina.onrender.com/mcp",
64
+ "--transport",
65
+ "http-only"
66
+ ]
67
+ }
68
+ }
69
+ }
70
+ ```
71
+
72
+ Or with streamable HTTP directly:
73
+
74
+ ```json
75
+ {
76
+ "mcpServers": {
77
+ "celina": {
78
+ "type": "streamable-http",
79
+ "url": "https://celina.onrender.com/mcp"
80
+ }
81
+ }
82
+ }
83
+ ```
84
+
85
+ ### Local stdio (npm)
86
+
87
+ ```json
88
+ {
89
+ "mcpServers": {
90
+ "celina": {
91
+ "command": "npx",
92
+ "args": ["-y", "@andrewkimjoseph/celina"]
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ ### Local stdio (from source)
99
+
100
+ ```json
101
+ {
102
+ "mcpServers": {
103
+ "celina": {
104
+ "command": "node",
105
+ "args": ["/absolute/path/to/celina/build/index.js"]
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ For local write tools, add a funded mainnet wallet:
112
+
113
+ ```json
114
+ "env": {
115
+ "CELO_PRIVATE_KEY": "0x..."
116
+ }
117
+ ```
118
+
119
+ Never commit private keys. Use env vars only.
120
+
121
+ ## Write tools (hosted mode)
122
+
123
+ Write tools (`send_token`, `estimate_send`) accept an RSA-encrypted private key per request — never plaintext.
124
+
125
+ ### Flow
126
+
127
+ 1. Fetch the server's public key:
128
+ - MCP tool: `get_wallet_encryption_public_key`
129
+ - HTTP: `GET https://celina.onrender.com/public-key`
130
+ 2. Encrypt your key locally:
131
+
132
+ ```bash
133
+ npm run encrypt-key -- --url https://celina.onrender.com --key 0xYOUR_PRIVATE_KEY
134
+ ```
135
+
136
+ 3. Give the agent the encrypted blob (base64 output) along with your transaction details
137
+ 4. The agent calls `send_token` with the `encryptedPrivateKey` parameter
138
+
139
+ The server decrypts the key ephemerally to sign the transaction — it is not stored.
140
+
141
+ ## Environment variables
142
+
143
+ | Variable | Default | Description |
144
+ |----------|---------|-------------|
145
+ | `CELO_RPC_URL_MAINNET` | Forno public RPC | Override mainnet RPC |
146
+ | `CELO_PRIVATE_KEY` | — | Local stdio write tools only |
147
+ | `WALLET_ENCRYPTION_PRIVATE_KEY` | — | RSA private key PEM for HTTP write tools |
148
+ | `PORT` | `10000` | HTTP server port (set by Render) |
149
+
150
+ Copy `.env.example` to `.env` for local development.
151
+
152
+ ## Known tokens
153
+
154
+ All supported tokens live in a single registry (`src/config/chains.ts`):
155
+
156
+ | Category | Symbols |
157
+ |----------|---------|
158
+ | Native | `CELO` |
159
+ | Mento stablecoins | `USDm`, `EURm`, `BRLm`, `XOFm`, `KESm`, `PHPm`, `COPm`, `GBPm`, `CADm`, `AUDm`, `ZARm`, `GHSm`, `NGNm`, `JPYm`, `CHFm` |
160
+ | Bridged / third-party | `USDT`, `USDC`, `vEUR`, `vGBP`, `vCHF`, `USDM`, `USDA`, `EURA`, `USDGLO`, `BRLA`, `COPM` |
161
+ | GoodDollar | `GoodDollar`, `G$` (`0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A`) |
162
+
163
+ Token symbols are resolved case-insensitively. Legacy aliases `cUSD` and `cEUR` map to `USDm` and `EURm`. You can also pass any ERC-20 contract address directly.
164
+
165
+ - `get_celo_balances` — check specific tokens (defaults to `CELO` + `USDm`)
166
+ - `get_stablecoin_balances` — scan all registry stablecoins in one call (omits zero balances by default)
167
+
168
+ ## Tools (v0.2)
169
+
170
+ | Tool | Type | Description |
171
+ |------|------|-------------|
172
+ | `get_network_status` | read | Mainnet chain ID, block, gas price |
173
+ | `get_block` | read | Block by number/hash/latest |
174
+ | `get_latest_blocks` | read | Recent blocks |
175
+ | `get_transaction` | read | Tx + receipt |
176
+ | `get_account` | read | CELO balance, nonce |
177
+ | `get_celo_balances` | read | CELO + ERC-20 balances (default: CELO + USDm) |
178
+ | `get_stablecoin_balances` | read | All registry stablecoins including GoodDollar |
179
+ | `get_token_info` | read | Token metadata |
180
+ | `get_wallet_encryption_public_key` | read | RSA public key for encrypting private keys |
181
+ | `estimate_send` | read* | Gas estimate (*needs encrypted or env key) |
182
+ | `send_token` | write | Send CELO or ERC-20 |
183
+ | `get_swap_quote` | read | Swap preview (routing stub) |
184
+
185
+ ## Adding a new tool
186
+
187
+ 1. Create `src/tools/my-feature.tools.ts` implementing `ToolModule`:
188
+
189
+ ```typescript
190
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
191
+ import type { AppContext } from "../context/app-context.js";
192
+ import type { ToolModule } from "./types.js";
193
+
194
+ export const myFeatureTools: ToolModule = {
195
+ register(server, ctx) {
196
+ server.registerTool("my_tool", { /* ... */ }, async (args) => { /* ... */ });
197
+ },
198
+ };
199
+ ```
200
+
201
+ 2. Append to `toolModules` in `src/tools/index.ts`.
202
+ 3. Add domain logic in `src/services/` if needed.
203
+ 4. Rebuild: `npm run build`.
204
+
205
+ No changes to `src/index.ts` or server bootstrap required.
206
+
207
+ ## Roadmap
208
+
209
+ - [ ] Mento / DEX swap routing (`execute_swap`)
210
+ - [ ] Aave lending tools
211
+ - [ ] Self proof verification (`ai.self.xyz`)
212
+ - [ ] Self Agent ID check
213
+
214
+ ## Development
215
+
216
+ ```bash
217
+ npm run dev # watch TypeScript
218
+ npm run inspect # MCP Inspector UI (stdio)
219
+ npm run start:http # HTTP server on PORT (default 10000)
220
+ npm run encrypt-key # encrypt a private key for write tools
221
+ ```
222
+
223
+ ## License
224
+
225
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import "../build/index.js";
@@ -0,0 +1,14 @@
1
+ import { type PublicClient, type WalletClient } from "viem";
2
+ import type { AppConfig } from "../config/env.js";
3
+ export interface CeloClients {
4
+ public: PublicClient;
5
+ wallet?: WalletClient;
6
+ accountAddress?: `0x${string}`;
7
+ }
8
+ export declare class CeloClientFactory {
9
+ private readonly config;
10
+ private clients;
11
+ constructor(config: AppConfig);
12
+ getClients(): CeloClients;
13
+ getClientsForAccount(privateKey: `0x${string}`): CeloClients;
14
+ }
@@ -0,0 +1,58 @@
1
+ import { createPublicClient, createWalletClient, http, } from "viem";
2
+ import { privateKeyToAccount } from "viem/accounts";
3
+ import { CHAIN, DEFAULT_RPC_URL } from "../config/chains.js";
4
+ export class CeloClientFactory {
5
+ config;
6
+ clients = null;
7
+ constructor(config) {
8
+ this.config = config;
9
+ }
10
+ getClients() {
11
+ if (this.clients) {
12
+ return this.clients;
13
+ }
14
+ const rpcUrl = this.config.rpcUrl ?? DEFAULT_RPC_URL;
15
+ const transport = http(rpcUrl);
16
+ const publicClient = createPublicClient({
17
+ chain: CHAIN,
18
+ transport,
19
+ });
20
+ let wallet;
21
+ let accountAddress;
22
+ if (this.config.privateKey) {
23
+ const account = privateKeyToAccount(this.config.privateKey);
24
+ accountAddress = account.address;
25
+ wallet = createWalletClient({
26
+ account,
27
+ chain: CHAIN,
28
+ transport,
29
+ });
30
+ }
31
+ this.clients = {
32
+ public: publicClient,
33
+ wallet,
34
+ accountAddress,
35
+ };
36
+ return this.clients;
37
+ }
38
+ getClientsForAccount(privateKey) {
39
+ const rpcUrl = this.config.rpcUrl ?? DEFAULT_RPC_URL;
40
+ const transport = http(rpcUrl);
41
+ const publicClient = createPublicClient({
42
+ chain: CHAIN,
43
+ transport,
44
+ });
45
+ const account = privateKeyToAccount(privateKey);
46
+ const wallet = createWalletClient({
47
+ account,
48
+ chain: CHAIN,
49
+ transport,
50
+ });
51
+ return {
52
+ public: publicClient,
53
+ wallet,
54
+ accountAddress: account.address,
55
+ };
56
+ }
57
+ }
58
+ //# sourceMappingURL=celo-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"celo-client.js","sourceRoot":"","sources":["../../src/clients/celo-client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,IAAI,GAGL,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAQ7D,MAAM,OAAO,iBAAiB;IAGC;IAFrB,OAAO,GAAuB,IAAI,CAAC;IAE3C,YAA6B,MAAiB;QAAjB,WAAM,GAAN,MAAM,CAAW;IAAG,CAAC;IAElD,UAAU;QACR,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC,OAAO,CAAC;QACtB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,eAAe,CAAC;QACrD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/B,MAAM,YAAY,GAAG,kBAAkB,CAAC;YACtC,KAAK,EAAE,KAAK;YACZ,SAAS;SACV,CAAiB,CAAC;QAEnB,IAAI,MAAgC,CAAC;QACrC,IAAI,cAAyC,CAAC;QAE9C,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC5D,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;YACjC,MAAM,GAAG,kBAAkB,CAAC;gBAC1B,OAAO;gBACP,KAAK,EAAE,KAAK;gBACZ,SAAS;aACV,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,OAAO,GAAG;YACb,MAAM,EAAE,YAAY;YACpB,MAAM;YACN,cAAc;SACf,CAAC;QAEF,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,oBAAoB,CAAC,UAAyB;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,eAAe,CAAC;QACrD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/B,MAAM,YAAY,GAAG,kBAAkB,CAAC;YACtC,KAAK,EAAE,KAAK;YACZ,SAAS;SACV,CAAiB,CAAC;QACnB,MAAM,OAAO,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;QAEhD,MAAM,MAAM,GAAG,kBAAkB,CAAC;YAChC,OAAO;YACP,KAAK,EAAE,KAAK;YACZ,SAAS;SACV,CAAC,CAAC;QAEH,OAAO;YACL,MAAM,EAAE,YAAY;YACpB,MAAM;YACN,cAAc,EAAE,OAAO,CAAC,OAAO;SAChC,CAAC;IACJ,CAAC;CACF"}