@gitgrant/mcp 0.1.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.
- package/.env.example +13 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +192 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/tools.d.ts +23 -0
- package/dist/tools.js +215 -0
- package/dist/tools.js.map +1 -0
- package/package.json +31 -0
package/.env.example
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# GitGrant MCP Server Configuration
|
|
2
|
+
|
|
3
|
+
# API endpoint of the GitGrant bot (required)
|
|
4
|
+
GITGRANT_API_URL=https://api.gitgrant.app
|
|
5
|
+
|
|
6
|
+
# Chain RPC URL (default: Base Sepolia)
|
|
7
|
+
RPC_URL=https://sepolia.base.org
|
|
8
|
+
|
|
9
|
+
# Escrow contract address on the target chain
|
|
10
|
+
ESCROW_ADDRESS=0x0000000000000000000000000000000000000000
|
|
11
|
+
|
|
12
|
+
# Chain ID (default: 84532 = Base Sepolia)
|
|
13
|
+
CHAIN_ID=84532
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "dotenv/config";
|
|
3
|
+
import { readFileSync, existsSync } from "fs";
|
|
4
|
+
import { join, dirname } from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { GitGrantClient, computeBountyId, parseIssueUri, statusEmoji, formatWeiToEth } from "@gitgrant/sdk";
|
|
7
|
+
const API_URL = process.env.GITGRANT_API_URL || "https://api.gitgrant.app";
|
|
8
|
+
const RPC_URL = process.env.RPC_URL || "https://mainnet.base.org";
|
|
9
|
+
const ESCROW_ADDRESS = process.env.ESCROW_ADDRESS || "0xFa59AeA9A35880716bC17455d101871Ba2D274a7";
|
|
10
|
+
const CHAIN_ID = Number(process.env.CHAIN_ID || 8453);
|
|
11
|
+
const CHAIN_NAMES = { 8453: "Base Mainnet", 84532: "Base Sepolia", 31337: "Local" };
|
|
12
|
+
const client = new GitGrantClient({ baseUrl: API_URL });
|
|
13
|
+
// Resolve ASCII art from src/ (dev via tsx) or from a sibling file (compiled dist/)
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const asciiPath = existsSync(join(__dirname, "ascii-text-art.txt"))
|
|
16
|
+
? join(__dirname, "ascii-text-art.txt")
|
|
17
|
+
: join(__dirname, "..", "src", "ascii-text-art.txt");
|
|
18
|
+
const ASCII = readFileSync(asciiPath, "utf-8");
|
|
19
|
+
const G = "\x1b[38;2;139;92;246m";
|
|
20
|
+
const R = "\x1b[0m";
|
|
21
|
+
const B = "\x1b[1m";
|
|
22
|
+
const D = "\x1b[2m";
|
|
23
|
+
const WELCOME = `
|
|
24
|
+
${G}${ASCII}${R}
|
|
25
|
+
|
|
26
|
+
${B}GitGrant CLI${R} — onchain bounties for open source
|
|
27
|
+
${D}API: ${API_URL} • Chain: ${CHAIN_NAMES[CHAIN_ID]} (${CHAIN_ID})${R}
|
|
28
|
+
|
|
29
|
+
${B}Commands:${R}
|
|
30
|
+
list List all bounties
|
|
31
|
+
active List active bounties (Open + Claimed)
|
|
32
|
+
get Get bounty detail by ID or issue URI
|
|
33
|
+
stats Show platform statistics
|
|
34
|
+
id Compute bounty ID from an issue URI
|
|
35
|
+
parse Parse an issue URI into components
|
|
36
|
+
chain Show chain info
|
|
37
|
+
|
|
38
|
+
${B}Options${R} (list/active):
|
|
39
|
+
--status Filter by status (comma-separated)
|
|
40
|
+
--repo Filter by repo (owner/repo)
|
|
41
|
+
--limit Max results (default 20)
|
|
42
|
+
--offset Pagination offset
|
|
43
|
+
|
|
44
|
+
${B}Examples:${R}
|
|
45
|
+
gitgrant list
|
|
46
|
+
gitgrant list --status Open --repo owner/repo
|
|
47
|
+
gitgrant active
|
|
48
|
+
gitgrant get github:owner/repo#123
|
|
49
|
+
gitgrant stats
|
|
50
|
+
gitgrant id github:owner/repo#123
|
|
51
|
+
gitgrant chain
|
|
52
|
+
`;
|
|
53
|
+
function parseArgs(argv) {
|
|
54
|
+
const opts = {};
|
|
55
|
+
for (let i = 0; i < argv.length; i++) {
|
|
56
|
+
if (argv[i].startsWith("--")) {
|
|
57
|
+
const key = argv[i].slice(2);
|
|
58
|
+
const val = argv[i + 1] && !argv[i + 1].startsWith("--") ? argv[++i] : "true";
|
|
59
|
+
opts[key] = val;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return opts;
|
|
63
|
+
}
|
|
64
|
+
function daysAgo(iso) {
|
|
65
|
+
return Math.floor((Date.now() - new Date(iso).getTime()) / 86400000);
|
|
66
|
+
}
|
|
67
|
+
function shortAddr(addr) {
|
|
68
|
+
return addr.length < 10 ? addr : `${addr.slice(0, 6)}...${addr.slice(-4)}`;
|
|
69
|
+
}
|
|
70
|
+
async function cmdList(args) {
|
|
71
|
+
const opts = parseArgs(args);
|
|
72
|
+
const status = opts.status?.split(",").map((s) => s.trim());
|
|
73
|
+
const result = await client.listBounties({
|
|
74
|
+
status,
|
|
75
|
+
repo: opts.repo,
|
|
76
|
+
limit: Number(opts.limit) || 20,
|
|
77
|
+
offset: Number(opts.offset) || 0,
|
|
78
|
+
});
|
|
79
|
+
if (result.bounties.length === 0)
|
|
80
|
+
return console.log("No bounties found.");
|
|
81
|
+
for (const b of result.bounties) {
|
|
82
|
+
const age = daysAgo(b.createdAt);
|
|
83
|
+
console.log(`${statusEmoji(b.status)} [${b.status}] ${b.repo}#${b.issueNumber}`);
|
|
84
|
+
console.log(` ID: ${b.bountyId}`);
|
|
85
|
+
console.log(` Creator: ${b.creatorGithub ?? shortAddr(b.creatorWallet)} | ${age}d ago`);
|
|
86
|
+
console.log(` Amount: ${formatWeiToEth(b.amountWei)} ETH`);
|
|
87
|
+
console.log();
|
|
88
|
+
}
|
|
89
|
+
console.log(`${result.bounties.length} bounties | chain=${result.chain.chainId}`);
|
|
90
|
+
}
|
|
91
|
+
async function cmdActive(args) {
|
|
92
|
+
const opts = parseArgs(args);
|
|
93
|
+
const result = await client.listBounties({
|
|
94
|
+
status: ["Open", "Claimed"],
|
|
95
|
+
repo: opts.repo,
|
|
96
|
+
limit: Number(opts.limit) || 20,
|
|
97
|
+
});
|
|
98
|
+
if (result.bounties.length === 0)
|
|
99
|
+
return console.log("No active bounties.");
|
|
100
|
+
for (const b of result.bounties) {
|
|
101
|
+
const age = daysAgo(b.createdAt);
|
|
102
|
+
console.log(`${statusEmoji(b.status)} [${b.status}] ${b.repo}#${b.issueNumber}`);
|
|
103
|
+
console.log(` ID: ${b.bountyId}`);
|
|
104
|
+
console.log(` Creator: ${b.creatorGithub ?? shortAddr(b.creatorWallet)} | ${age}d ago`);
|
|
105
|
+
console.log(` Amount: ${formatWeiToEth(b.amountWei)} ETH`);
|
|
106
|
+
console.log();
|
|
107
|
+
}
|
|
108
|
+
console.log(`${result.bounties.length} active bounties`);
|
|
109
|
+
}
|
|
110
|
+
async function cmdGet(identifier) {
|
|
111
|
+
let bountyId = identifier;
|
|
112
|
+
if (identifier.startsWith("github:") || identifier.startsWith("gitlab:")) {
|
|
113
|
+
bountyId = computeBountyId(identifier);
|
|
114
|
+
}
|
|
115
|
+
const result = await client.getBounty(bountyId);
|
|
116
|
+
const b = result.bounty;
|
|
117
|
+
console.log(`${statusEmoji(b.status)} ${b.status} — ${b.repo}#${b.issueNumber}`);
|
|
118
|
+
console.log(`ID: ${b.bountyId}`);
|
|
119
|
+
console.log(`Issue: ${b.issueUri}`);
|
|
120
|
+
console.log(`Amount: ${formatWeiToEth(b.amountWei)} ETH (${b.amountWei} wei)`);
|
|
121
|
+
console.log(`Creator: ${b.creatorGithub ?? b.creatorWallet}`);
|
|
122
|
+
console.log(`Claimant: ${b.claimantGithub ?? b.claimantWallet ?? "(none)"}`);
|
|
123
|
+
console.log(`Created: ${b.createdAt}`);
|
|
124
|
+
console.log(`Deadline: ${b.deadline}`);
|
|
125
|
+
console.log(`Create tx: ${b.createTx ?? "—"}`);
|
|
126
|
+
console.log(`Claim tx: ${b.claimTx ?? "—"}`);
|
|
127
|
+
console.log(`Submit tx: ${b.submitTx ?? "—"}`);
|
|
128
|
+
console.log(`Release tx: ${b.releaseTx ?? "—"}`);
|
|
129
|
+
}
|
|
130
|
+
async function cmdStats() {
|
|
131
|
+
const result = await client.getStats();
|
|
132
|
+
const s = result.stats;
|
|
133
|
+
console.log(`Total: ${s.total}`);
|
|
134
|
+
console.log(`Open: ${s.open}`);
|
|
135
|
+
console.log(`Claimed: ${s.claimed}`);
|
|
136
|
+
console.log(`Submitted: ${s.submitted}`);
|
|
137
|
+
console.log(`Completed: ${s.completed}`);
|
|
138
|
+
console.log(`Escrowed: ${formatWeiToEth(s.totalEscrowedWei)} ETH`);
|
|
139
|
+
console.log(`Paid: ${formatWeiToEth(s.totalPaidWei)} ETH`);
|
|
140
|
+
}
|
|
141
|
+
async function cmdId(uri) {
|
|
142
|
+
const id = computeBountyId(uri);
|
|
143
|
+
const parsed = parseIssueUri(uri);
|
|
144
|
+
console.log(`URI: ${uri}`);
|
|
145
|
+
console.log(`ID: ${id}`);
|
|
146
|
+
if (parsed) {
|
|
147
|
+
console.log(`Repo: ${parsed.repo}`);
|
|
148
|
+
console.log(`Issue: #${parsed.issueNumber}`);
|
|
149
|
+
console.log(`URL: https://github.com/${parsed.repo}/issues/${parsed.issueNumber}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async function cmdParse(uri) {
|
|
153
|
+
const parsed = parseIssueUri(uri);
|
|
154
|
+
if (!parsed) {
|
|
155
|
+
console.log(`Invalid URI: ${uri}`);
|
|
156
|
+
console.log("Expected format: github:owner/repo#123");
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
|
159
|
+
console.log(`Platform: github`);
|
|
160
|
+
console.log(`Repo: ${parsed.repo}`);
|
|
161
|
+
console.log(`Issue: #${parsed.issueNumber}`);
|
|
162
|
+
console.log(`URL: https://github.com/${parsed.repo}/issues/${parsed.issueNumber}`);
|
|
163
|
+
}
|
|
164
|
+
function cmdChain() {
|
|
165
|
+
const name = CHAIN_NAMES[CHAIN_ID] ?? `Chain ${CHAIN_ID}`;
|
|
166
|
+
console.log(`Chain: ${name} (${CHAIN_ID})`);
|
|
167
|
+
console.log(`RPC: ${RPC_URL}`);
|
|
168
|
+
console.log(`Escrow: ${ESCROW_ADDRESS}`);
|
|
169
|
+
}
|
|
170
|
+
// ─── Main ──────────────────────────────────────────────────────────────
|
|
171
|
+
const [, , cmd, ...args] = process.argv;
|
|
172
|
+
async function main() {
|
|
173
|
+
switch (cmd) {
|
|
174
|
+
case "list": return cmdList(args);
|
|
175
|
+
case "active": return cmdActive(args);
|
|
176
|
+
case "get": return cmdGet(args[0] || "");
|
|
177
|
+
case "stats": return cmdStats();
|
|
178
|
+
case "id": return cmdId(args[0] || "");
|
|
179
|
+
case "parse": return cmdParse(args[0] || "");
|
|
180
|
+
case "chain": return cmdChain();
|
|
181
|
+
default:
|
|
182
|
+
console.log(WELCOME);
|
|
183
|
+
if (cmd)
|
|
184
|
+
console.log(`Unknown command: ${cmd}`);
|
|
185
|
+
process.exit(cmd ? 1 : 0);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
main().catch((err) => {
|
|
189
|
+
console.error(`Error: ${err.message}`);
|
|
190
|
+
process.exit(1);
|
|
191
|
+
});
|
|
192
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "dotenv/config";
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import { createToolDefinitions } from "./tools.js";
|
|
6
|
+
const GITGRANT_API_URL = process.env.GITGRANT_API_URL || "https://api.gitgrant.app";
|
|
7
|
+
const RPC_URL = process.env.RPC_URL || "https://sepolia.base.org";
|
|
8
|
+
const ESCROW_ADDRESS = process.env.ESCROW_ADDRESS || "0x0000000000000000000000000000000000000000";
|
|
9
|
+
const CHAIN_ID = Number(process.env.CHAIN_ID || 84532);
|
|
10
|
+
const server = new McpServer({
|
|
11
|
+
name: "gitgrant",
|
|
12
|
+
version: "0.1.0",
|
|
13
|
+
description: "GitGrant — onchain bounties for open source. Create, claim, submit, and release bounties directly from AI agents.",
|
|
14
|
+
});
|
|
15
|
+
const tools = createToolDefinitions({
|
|
16
|
+
apiUrl: GITGRANT_API_URL,
|
|
17
|
+
rpcUrl: RPC_URL,
|
|
18
|
+
escrowAddress: ESCROW_ADDRESS,
|
|
19
|
+
chainId: CHAIN_ID,
|
|
20
|
+
});
|
|
21
|
+
for (const tool of tools) {
|
|
22
|
+
server.registerTool(tool.name, tool.config, tool.handler);
|
|
23
|
+
}
|
|
24
|
+
async function main() {
|
|
25
|
+
const transport = new StdioServerTransport();
|
|
26
|
+
await server.connect(transport);
|
|
27
|
+
console.error(`GitGrant MCP server started (api=${GITGRANT_API_URL}, chain=${CHAIN_ID})`);
|
|
28
|
+
}
|
|
29
|
+
main().catch((err) => {
|
|
30
|
+
console.error("Fatal: failed to start GitGrant MCP server", err);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
});
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnD,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,0BAA0B,CAAC;AACpF,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,0BAA0B,CAAC;AAClE,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,4CAA4C,CAAC;AAClG,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC;AAEvD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;IAChB,WAAW,EACT,mHAAmH;CACtH,CAAC,CAAC;AAEH,MAAM,KAAK,GAAG,qBAAqB,CAAC;IAClC,MAAM,EAAE,gBAAgB;IACxB,MAAM,EAAE,OAAO;IACf,aAAa,EAAE,cAA+B;IAC9C,OAAO,EAAE,QAAQ;CAClB,CAAC,CAAC;AAEH,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;IACzB,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAc,CAAC,CAAC;AACnE,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,oCAAoC,gBAAgB,WAAW,QAAQ,GAAG,CAAC,CAAC;AAC5F,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE,GAAG,CAAC,CAAC;IACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export interface ToolContext {
|
|
3
|
+
apiUrl: string;
|
|
4
|
+
rpcUrl: string;
|
|
5
|
+
escrowAddress: `0x${string}`;
|
|
6
|
+
chainId: number;
|
|
7
|
+
}
|
|
8
|
+
type Handler = (args: Record<string, unknown>) => Promise<{
|
|
9
|
+
content: Array<{
|
|
10
|
+
type: "text";
|
|
11
|
+
text: string;
|
|
12
|
+
}>;
|
|
13
|
+
}>;
|
|
14
|
+
export interface ToolDef {
|
|
15
|
+
name: string;
|
|
16
|
+
config: {
|
|
17
|
+
description: string;
|
|
18
|
+
inputSchema: Record<string, z.ZodTypeAny>;
|
|
19
|
+
};
|
|
20
|
+
handler: Handler;
|
|
21
|
+
}
|
|
22
|
+
export declare function createToolDefinitions(ctx: ToolContext): ToolDef[];
|
|
23
|
+
export {};
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { GitGrantClient, computeBountyId, parseIssueUri } from "@gitgrant/sdk";
|
|
3
|
+
let _client = null;
|
|
4
|
+
function getClient(ctx) {
|
|
5
|
+
if (!_client)
|
|
6
|
+
_client = new GitGrantClient({ baseUrl: ctx.apiUrl });
|
|
7
|
+
return _client;
|
|
8
|
+
}
|
|
9
|
+
export function createToolDefinitions(ctx) {
|
|
10
|
+
const client = () => getClient(ctx);
|
|
11
|
+
return [
|
|
12
|
+
// ── list_bounties ───────────────────────────────────────────────
|
|
13
|
+
{
|
|
14
|
+
name: "list_bounties",
|
|
15
|
+
config: {
|
|
16
|
+
description: "List all bounties on GitGrant. Supports filtering by status (Open, Claimed, Submitted, Completed, Disputed, Expired, Cancelled), repo (e.g. 'owner/repo'), and pagination with limit/offset.",
|
|
17
|
+
inputSchema: {
|
|
18
|
+
status: z.string().optional().describe("Filter by status. Use comma for multiple, e.g. 'Open,Claimed'."),
|
|
19
|
+
repo: z.string().optional().describe("Filter by GitHub repo, e.g. 'owner/repo'."),
|
|
20
|
+
limit: z.number().optional().describe("Max results (1-200, default 50)."),
|
|
21
|
+
offset: z.number().optional().describe("Pagination offset (default 0)."),
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
handler: async (args) => {
|
|
25
|
+
const result = await client().listBounties({
|
|
26
|
+
status: args.status ? args.status.split(",").map((s) => s.trim()) : undefined,
|
|
27
|
+
repo: args.repo,
|
|
28
|
+
limit: args.limit,
|
|
29
|
+
offset: args.offset,
|
|
30
|
+
});
|
|
31
|
+
const lines = result.bounties.map((b) => {
|
|
32
|
+
const age = daysAgo(b.createdAt);
|
|
33
|
+
return `- [${b.status}] \`${b.bountyId.slice(0, 10)}...\` | ${b.repo}#${b.issueNumber} | ${b.creatorGithub ?? shortAddr(b.creatorWallet)} | ${age}d ago`;
|
|
34
|
+
});
|
|
35
|
+
return {
|
|
36
|
+
content: [{ type: "text", text: `Found ${result.bounties.length} bounties (chain=${result.chain.chainId}, escrow=${result.chain.escrowAddress}):\n\n${lines.join("\n") || "(none)"}` }],
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
// ── get_bounty ──────────────────────────────────────────────────
|
|
41
|
+
{
|
|
42
|
+
name: "get_bounty",
|
|
43
|
+
config: {
|
|
44
|
+
description: "Get full details for a single bounty by its ID (bytes32 hex) or by its issue URI (e.g. 'github:owner/repo#123').",
|
|
45
|
+
inputSchema: {
|
|
46
|
+
idOrUri: z.string().describe("Bounty ID (0x... bytes32) or issue URI (github:owner/repo#123)."),
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
handler: async (args) => {
|
|
50
|
+
let bountyId = args.idOrUri;
|
|
51
|
+
if (bountyId.startsWith("github:") || bountyId.startsWith("gitlab:")) {
|
|
52
|
+
bountyId = computeBountyId(bountyId);
|
|
53
|
+
}
|
|
54
|
+
const result = await client().getBounty(bountyId);
|
|
55
|
+
const b = result.bounty;
|
|
56
|
+
return {
|
|
57
|
+
content: [{
|
|
58
|
+
type: "text",
|
|
59
|
+
text: [
|
|
60
|
+
`**Bounty ${b.bountyId}**`,
|
|
61
|
+
`- Issue: ${b.issueUri} (${b.repo}#${b.issueNumber})`,
|
|
62
|
+
`- Status: ${b.status}`,
|
|
63
|
+
`- Amount: ${b.amountWei} wei`,
|
|
64
|
+
`- Creator: ${b.creatorGithub ?? b.creatorWallet}`,
|
|
65
|
+
`- Claimant: ${b.claimantGithub ?? b.claimantWallet ?? "(none)"}`,
|
|
66
|
+
`- Created: ${b.createdAt}`,
|
|
67
|
+
`- Deadline: ${b.deadline}`,
|
|
68
|
+
`- Tx: create=${b.createTx ?? "—"}, claim=${b.claimTx ?? "—"}, submit=${b.submitTx ?? "—"}, release=${b.releaseTx ?? "—"}`,
|
|
69
|
+
].join("\n"),
|
|
70
|
+
}],
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
// ── get_stats ───────────────────────────────────────────────────
|
|
75
|
+
{
|
|
76
|
+
name: "get_stats",
|
|
77
|
+
config: {
|
|
78
|
+
description: "Get aggregate GitGrant platform statistics (total, per-status counts, total value escrowed and paid).",
|
|
79
|
+
inputSchema: {},
|
|
80
|
+
},
|
|
81
|
+
handler: async () => {
|
|
82
|
+
const result = await client().getStats();
|
|
83
|
+
const s = result.stats;
|
|
84
|
+
return {
|
|
85
|
+
content: [{
|
|
86
|
+
type: "text",
|
|
87
|
+
text: [
|
|
88
|
+
`**GitGrant Platform Stats**`,
|
|
89
|
+
`- Total bounties: ${s.total}`,
|
|
90
|
+
`- Open: ${s.open}`,
|
|
91
|
+
`- Claimed: ${s.claimed}`,
|
|
92
|
+
`- Submitted: ${s.submitted}`,
|
|
93
|
+
`- Completed: ${s.completed}`,
|
|
94
|
+
`- Total escrowed: ${s.totalEscrowedWei} wei`,
|
|
95
|
+
`- Total paid: ${s.totalPaidWei} wei`,
|
|
96
|
+
].join("\n"),
|
|
97
|
+
}],
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
// ── compute_bounty_id ───────────────────────────────────────────
|
|
102
|
+
{
|
|
103
|
+
name: "compute_bounty_id",
|
|
104
|
+
config: {
|
|
105
|
+
description: "Compute the deterministic bytes32 bounty ID from an issue URI. Format: 'github:owner/repo#issueNumber'.",
|
|
106
|
+
inputSchema: {
|
|
107
|
+
issueUri: z.string().describe("Issue URI, e.g. 'github:owner/repo#123'."),
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
handler: async (args) => {
|
|
111
|
+
const uri = args.issueUri;
|
|
112
|
+
const id = computeBountyId(uri);
|
|
113
|
+
const parsed = parseIssueUri(uri);
|
|
114
|
+
return {
|
|
115
|
+
content: [{
|
|
116
|
+
type: "text",
|
|
117
|
+
text: parsed
|
|
118
|
+
? `**Bounty ID:** \`${id}\`\n- Repo: ${parsed.repo}\n- Issue: #${parsed.issueNumber}\n- URL: https://github.com/${parsed.repo}/issues/${parsed.issueNumber}`
|
|
119
|
+
: `**Bounty ID:** \`${id}\`\n- URI: ${uri}`,
|
|
120
|
+
}],
|
|
121
|
+
};
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
// ── parse_issue_uri ─────────────────────────────────────────────
|
|
125
|
+
{
|
|
126
|
+
name: "parse_issue_uri",
|
|
127
|
+
config: {
|
|
128
|
+
description: "Parse a GitGrant issue URI into components (platform, repo, issue number). Supports github: and gitlab: prefixes.",
|
|
129
|
+
inputSchema: {
|
|
130
|
+
issueUri: z.string().describe("Issue URI, e.g. 'github:owner/repo#123'."),
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
handler: async (args) => {
|
|
134
|
+
const uri = args.issueUri;
|
|
135
|
+
const parsed = parseIssueUri(uri);
|
|
136
|
+
if (!parsed) {
|
|
137
|
+
return {
|
|
138
|
+
content: [{ type: "text", text: `Invalid issue URI: "${uri}". Expected format: github:owner/repo#123` }],
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
content: [{
|
|
143
|
+
type: "text",
|
|
144
|
+
text: `- Platform: github\n- Repo: ${parsed.repo}\n- Issue: #${parsed.issueNumber}\n- URL: https://github.com/${parsed.repo}/issues/${parsed.issueNumber}`,
|
|
145
|
+
}],
|
|
146
|
+
};
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
// ── get_chain_info ──────────────────────────────────────────────
|
|
150
|
+
{
|
|
151
|
+
name: "get_chain_info",
|
|
152
|
+
config: {
|
|
153
|
+
description: "Get the current chain configuration (chain ID, RPC URL, escrow contract address).",
|
|
154
|
+
inputSchema: {},
|
|
155
|
+
},
|
|
156
|
+
handler: async () => {
|
|
157
|
+
const chainNames = {
|
|
158
|
+
8453: "Base Mainnet",
|
|
159
|
+
84532: "Base Sepolia (testnet)",
|
|
160
|
+
31337: "Local / Foundry",
|
|
161
|
+
};
|
|
162
|
+
const name = chainNames[ctx.chainId] ?? `Chain ${ctx.chainId}`;
|
|
163
|
+
return {
|
|
164
|
+
content: [{
|
|
165
|
+
type: "text",
|
|
166
|
+
text: [
|
|
167
|
+
`**Chain:** ${name} (${ctx.chainId})`,
|
|
168
|
+
`- RPC: ${ctx.rpcUrl}`,
|
|
169
|
+
`- Escrow contract: ${ctx.escrowAddress}`,
|
|
170
|
+
].join("\n"),
|
|
171
|
+
}],
|
|
172
|
+
};
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
// ── list_active_bounties ────────────────────────────────────────
|
|
176
|
+
{
|
|
177
|
+
name: "list_active_bounties",
|
|
178
|
+
config: {
|
|
179
|
+
description: "List only active (workable) bounties — those with status Open or Claimed. These are bounties contributors can still engage with.",
|
|
180
|
+
inputSchema: {
|
|
181
|
+
repo: z.string().optional().describe("Filter by GitHub repo, e.g. 'owner/repo'."),
|
|
182
|
+
limit: z.number().optional().describe("Max results (default 50)."),
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
handler: async (args) => {
|
|
186
|
+
const result = await client().listBounties({
|
|
187
|
+
status: ["Open", "Claimed"],
|
|
188
|
+
repo: args.repo,
|
|
189
|
+
limit: args.limit,
|
|
190
|
+
});
|
|
191
|
+
const lines = result.bounties.map((b) => {
|
|
192
|
+
const age = daysAgo(b.createdAt);
|
|
193
|
+
return `- [${b.status}] ${b.repo}#${b.issueNumber} | ${b.creatorGithub ?? shortAddr(b.creatorWallet)} | ${age}d ago | \`${b.bountyId.slice(0, 10)}...\``;
|
|
194
|
+
});
|
|
195
|
+
return {
|
|
196
|
+
content: [{
|
|
197
|
+
type: "text",
|
|
198
|
+
text: `${result.bounties.length} active bounties:\n\n${lines.join("\n") || "(none)"}`,
|
|
199
|
+
}],
|
|
200
|
+
};
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
];
|
|
204
|
+
}
|
|
205
|
+
// ─── Helpers ───────────────────────────────────────────────────────────
|
|
206
|
+
function daysAgo(iso) {
|
|
207
|
+
const diff = Date.now() - new Date(iso).getTime();
|
|
208
|
+
return Math.floor(diff / (1000 * 60 * 60 * 24));
|
|
209
|
+
}
|
|
210
|
+
function shortAddr(addr) {
|
|
211
|
+
if (addr.length < 10)
|
|
212
|
+
return addr;
|
|
213
|
+
return `${addr.slice(0, 6)}...${addr.slice(-4)}`;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gitgrant/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "GitGrant CLI & MCP server — onchain bounties for open source",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"gitgrant": "./dist/cli.js",
|
|
9
|
+
"gitgrant-mcp": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"dev": "tsx src/index.ts",
|
|
14
|
+
"start": "node dist/index.js",
|
|
15
|
+
"typecheck": "tsc --noEmit"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@gitgrant/sdk": "^0.2.0",
|
|
19
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
20
|
+
"dotenv": "^16.4.0",
|
|
21
|
+
"viem": "^2.23.0",
|
|
22
|
+
"zod": "^3.24.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "^22.10.0",
|
|
26
|
+
"tsx": "^4.19.0",
|
|
27
|
+
"typescript": "^5.7.0"
|
|
28
|
+
},
|
|
29
|
+
"keywords": ["gitgrant", "mcp", "ai-agent", "bounty", "web3"],
|
|
30
|
+
"license": "MIT"
|
|
31
|
+
}
|