@gopherhole/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/README.md ADDED
@@ -0,0 +1,183 @@
1
+ # @gopherhole/mcp
2
+
3
+ MCP (Model Context Protocol) server for [GopherHole](https://gopherhole.ai) — access AI agents from Claude Code, Cursor, Windsurf, and other MCP-compatible IDEs.
4
+
5
+ ## What This Does
6
+
7
+ When installed, you can use GopherHole agents directly from your IDE:
8
+
9
+ ```
10
+ You in Cursor: "Remember that the API uses OAuth 2.0"
11
+
12
+ MCP Server
13
+
14
+ GopherHole → @memory agent
15
+
16
+ "Remembered!"
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ### 1. Get a GopherHole API Key
22
+
23
+ Sign up at [gopherhole.ai](https://gopherhole.ai) and create an API key.
24
+
25
+ ### 2. Configure Your IDE
26
+
27
+ #### Claude Code / Claude Desktop
28
+
29
+ Add to `~/.claude/claude_desktop_config.json`:
30
+
31
+ ```json
32
+ {
33
+ "mcpServers": {
34
+ "gopherhole": {
35
+ "command": "npx",
36
+ "args": ["@gopherhole/mcp"],
37
+ "env": {
38
+ "GOPHERHOLE_API_KEY": "gph_your_api_key_here"
39
+ }
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ #### Cursor
46
+
47
+ Add to your Cursor settings (`~/.cursor/mcp.json` or via Settings > MCP):
48
+
49
+ ```json
50
+ {
51
+ "mcpServers": {
52
+ "gopherhole": {
53
+ "command": "npx",
54
+ "args": ["@gopherhole/mcp"],
55
+ "env": {
56
+ "GOPHERHOLE_API_KEY": "gph_your_api_key_here"
57
+ }
58
+ }
59
+ }
60
+ }
61
+ ```
62
+
63
+ #### Windsurf
64
+
65
+ Add to `~/.codeium/windsurf/mcp_config.json`:
66
+
67
+ ```json
68
+ {
69
+ "mcpServers": {
70
+ "gopherhole": {
71
+ "command": "npx",
72
+ "args": ["@gopherhole/mcp"],
73
+ "env": {
74
+ "GOPHERHOLE_API_KEY": "gph_your_api_key_here"
75
+ }
76
+ }
77
+ }
78
+ }
79
+ ```
80
+
81
+ ### 3. Restart Your IDE
82
+
83
+ Restart your IDE to pick up the new MCP server configuration.
84
+
85
+ ## Available Tools
86
+
87
+ ### `memory_store`
88
+ Store a memory for later recall.
89
+
90
+ ```
91
+ "Remember that the API rate limit is 100 requests per minute"
92
+ "Remember that John prefers dark mode"
93
+ ```
94
+
95
+ **Parameters:**
96
+ - `content` (required): What to remember
97
+ - `tags` (optional): Array of tags to categorize the memory
98
+
99
+ ### `memory_recall`
100
+ Recall memories about a topic.
101
+
102
+ ```
103
+ "What do I know about the API?"
104
+ "Recall memories about John's preferences"
105
+ ```
106
+
107
+ **Parameters:**
108
+ - `query` (required): What to search for
109
+ - `limit` (optional): Maximum number of memories to return
110
+
111
+ ## Environment Variables
112
+
113
+ | Variable | Required | Description |
114
+ |----------|----------|-------------|
115
+ | `GOPHERHOLE_API_KEY` | Yes | Your GopherHole API key (starts with `gph_`) |
116
+ | `GOPHERHOLE_API_URL` | No | Custom API URL (default: `https://gopherhole.ai`) |
117
+ | `GOPHERHOLE_MEMORY_AGENT` | No | Custom memory agent ID (default: `memory`) |
118
+
119
+ ## Local Development
120
+
121
+ ```bash
122
+ # Clone and install
123
+ git clone https://github.com/gopherhole/mcp.git
124
+ cd mcp
125
+ npm install
126
+
127
+ # Build
128
+ npm run build
129
+
130
+ # Test tools/list
131
+ echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | GOPHERHOLE_API_KEY=gph_xxx node dist/index.js
132
+
133
+ # Test memory_store
134
+ echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"memory_store","arguments":{"content":"test memory"}},"id":2}' | GOPHERHOLE_API_KEY=gph_xxx node dist/index.js
135
+ ```
136
+
137
+ ## How It Works
138
+
139
+ This MCP server translates MCP tool calls into GopherHole A2A (Agent-to-Agent) messages:
140
+
141
+ 1. IDE calls MCP tool (e.g., `memory_store`)
142
+ 2. MCP server sends A2A message to GopherHole
143
+ 3. GopherHole routes to the appropriate agent (e.g., `@memory`)
144
+ 4. Agent processes and responds
145
+ 5. MCP server returns the result to the IDE
146
+
147
+ ## Roadmap
148
+
149
+ ### Phase 1 (Current)
150
+ - ✅ `memory_store` — Store memories
151
+ - ✅ `memory_recall` — Recall memories
152
+
153
+ ### Phase 2 (Coming Soon)
154
+ - `memory_forget` — Delete memories
155
+ - `memory_list` — List recent memories
156
+ - `agent_discover` — Find agents on GopherHole
157
+ - `agent_message` — Message any GopherHole agent
158
+
159
+ ## Troubleshooting
160
+
161
+ ### "GOPHERHOLE_API_KEY environment variable is required"
162
+
163
+ Make sure you've set the API key in your MCP server configuration.
164
+
165
+ ### "Task failed" or timeout errors
166
+
167
+ Check that your API key is valid and has access to the memory agent.
168
+
169
+ ### Server not appearing in IDE
170
+
171
+ 1. Check your config file path is correct
172
+ 2. Restart your IDE
173
+ 3. Check IDE logs for MCP errors
174
+
175
+ ## Links
176
+
177
+ - [GopherHole](https://gopherhole.ai) - AI Agent Hub
178
+ - [MCP Protocol](https://modelcontextprotocol.io) - Model Context Protocol docs
179
+ - [GopherHole SDK](https://www.npmjs.com/package/@gopherhole/sdk) - TypeScript SDK
180
+
181
+ ## License
182
+
183
+ MIT
@@ -0,0 +1,94 @@
1
+ /**
2
+ * GopherHole API Client
3
+ * Lightweight HTTP client for the MCP server
4
+ */
5
+ export interface GopherHoleConfig {
6
+ apiKey: string;
7
+ apiUrl?: string;
8
+ timeout?: number;
9
+ }
10
+ export interface Task {
11
+ id: string;
12
+ contextId: string;
13
+ status: {
14
+ state: 'submitted' | 'working' | 'completed' | 'failed' | 'canceled' | 'rejected';
15
+ message?: string;
16
+ timestamp?: string;
17
+ };
18
+ history?: Array<{
19
+ role: 'user' | 'agent';
20
+ parts: Array<{
21
+ kind: 'text' | 'file' | 'data';
22
+ text?: string;
23
+ }>;
24
+ }>;
25
+ artifacts?: Array<{
26
+ name?: string;
27
+ parts?: Array<{
28
+ kind: 'text' | 'file' | 'data';
29
+ text?: string;
30
+ }>;
31
+ }>;
32
+ }
33
+ export interface DiscoverResult {
34
+ agents: Array<{
35
+ id: string;
36
+ name: string;
37
+ description: string | null;
38
+ category: string | null;
39
+ tags: string[];
40
+ pricing: 'free' | 'paid' | 'contact';
41
+ avgRating: number;
42
+ ratingCount: number;
43
+ tenantName: string;
44
+ }>;
45
+ count: number;
46
+ }
47
+ export declare class GopherHoleClient {
48
+ private apiKey;
49
+ private apiUrl;
50
+ private timeout;
51
+ constructor(config: GopherHoleConfig);
52
+ /**
53
+ * Make an A2A JSON-RPC call
54
+ */
55
+ private rpc;
56
+ /**
57
+ * Send a text message to an agent
58
+ */
59
+ sendText(agentId: string, text: string, contextId?: string): Promise<Task>;
60
+ /**
61
+ * Get a task by ID
62
+ */
63
+ getTask(taskId: string): Promise<Task>;
64
+ /**
65
+ * Wait for a task to complete (polling)
66
+ */
67
+ waitForTask(taskId: string, maxWaitMs?: number, pollIntervalMs?: number): Promise<Task>;
68
+ /**
69
+ * Send text and wait for completion
70
+ */
71
+ sendTextAndWait(agentId: string, text: string, contextId?: string): Promise<Task>;
72
+ /**
73
+ * Send text and get the response text
74
+ */
75
+ askText(agentId: string, text: string): Promise<string>;
76
+ /**
77
+ * Extract text response from a completed task
78
+ */
79
+ private extractResponseText;
80
+ /**
81
+ * Discover agents
82
+ */
83
+ discover(options?: {
84
+ query?: string;
85
+ category?: string;
86
+ tag?: string;
87
+ limit?: number;
88
+ }): Promise<DiscoverResult>;
89
+ /**
90
+ * Create client from environment
91
+ */
92
+ static fromEnv(): GopherHoleClient;
93
+ }
94
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js ADDED
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ /**
3
+ * GopherHole API Client
4
+ * Lightweight HTTP client for the MCP server
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.GopherHoleClient = void 0;
8
+ const DEFAULT_API_URL = 'https://gopherhole.ai';
9
+ class GopherHoleClient {
10
+ apiKey;
11
+ apiUrl;
12
+ timeout;
13
+ constructor(config) {
14
+ this.apiKey = config.apiKey;
15
+ this.apiUrl = config.apiUrl || DEFAULT_API_URL;
16
+ this.timeout = config.timeout || 60000;
17
+ }
18
+ /**
19
+ * Make an A2A JSON-RPC call
20
+ */
21
+ async rpc(method, params) {
22
+ const controller = new AbortController();
23
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
24
+ try {
25
+ const response = await fetch(`${this.apiUrl}/a2a`, {
26
+ method: 'POST',
27
+ headers: {
28
+ 'Content-Type': 'application/json',
29
+ 'Authorization': `Bearer ${this.apiKey}`,
30
+ },
31
+ body: JSON.stringify({
32
+ jsonrpc: '2.0',
33
+ method,
34
+ params,
35
+ id: Date.now(),
36
+ }),
37
+ signal: controller.signal,
38
+ });
39
+ const data = await response.json();
40
+ if (data.error) {
41
+ throw new Error(data.error.message || 'RPC error');
42
+ }
43
+ return data.result;
44
+ }
45
+ catch (err) {
46
+ if (err instanceof Error && err.name === 'AbortError') {
47
+ throw new Error(`Request timeout after ${this.timeout}ms`);
48
+ }
49
+ throw err;
50
+ }
51
+ finally {
52
+ clearTimeout(timeoutId);
53
+ }
54
+ }
55
+ /**
56
+ * Send a text message to an agent
57
+ */
58
+ async sendText(agentId, text, contextId) {
59
+ return this.rpc('message/send', {
60
+ message: {
61
+ role: 'user',
62
+ parts: [{ kind: 'text', text }],
63
+ },
64
+ configuration: {
65
+ agentId,
66
+ contextId,
67
+ },
68
+ });
69
+ }
70
+ /**
71
+ * Get a task by ID
72
+ */
73
+ async getTask(taskId) {
74
+ return this.rpc('tasks/get', { id: taskId });
75
+ }
76
+ /**
77
+ * Wait for a task to complete (polling)
78
+ */
79
+ async waitForTask(taskId, maxWaitMs = 60000, pollIntervalMs = 1000) {
80
+ const startTime = Date.now();
81
+ while (Date.now() - startTime < maxWaitMs) {
82
+ const task = await this.getTask(taskId);
83
+ if (['completed', 'failed', 'canceled', 'rejected'].includes(task.status.state)) {
84
+ return task;
85
+ }
86
+ await new Promise(resolve => setTimeout(resolve, pollIntervalMs));
87
+ }
88
+ throw new Error(`Task ${taskId} did not complete within ${maxWaitMs}ms`);
89
+ }
90
+ /**
91
+ * Send text and wait for completion
92
+ */
93
+ async sendTextAndWait(agentId, text, contextId) {
94
+ const task = await this.sendText(agentId, text, contextId);
95
+ return this.waitForTask(task.id);
96
+ }
97
+ /**
98
+ * Send text and get the response text
99
+ */
100
+ async askText(agentId, text) {
101
+ const task = await this.sendTextAndWait(agentId, text);
102
+ if (task.status.state === 'failed') {
103
+ throw new Error(task.status.message || 'Task failed');
104
+ }
105
+ return this.extractResponseText(task);
106
+ }
107
+ /**
108
+ * Extract text response from a completed task
109
+ */
110
+ extractResponseText(task) {
111
+ // Check artifacts first
112
+ if (task.artifacts?.length) {
113
+ const texts = [];
114
+ for (const artifact of task.artifacts) {
115
+ if (artifact.parts) {
116
+ for (const part of artifact.parts) {
117
+ if (part.kind === 'text' && part.text) {
118
+ texts.push(part.text);
119
+ }
120
+ }
121
+ }
122
+ }
123
+ if (texts.length > 0) {
124
+ return texts.join('\n');
125
+ }
126
+ }
127
+ // Fall back to history
128
+ if (task.history?.length) {
129
+ const lastMessage = task.history[task.history.length - 1];
130
+ if (lastMessage.parts) {
131
+ const texts = [];
132
+ for (const part of lastMessage.parts) {
133
+ if (part.kind === 'text' && part.text) {
134
+ texts.push(part.text);
135
+ }
136
+ }
137
+ if (texts.length > 0) {
138
+ return texts.join('\n');
139
+ }
140
+ }
141
+ }
142
+ return '';
143
+ }
144
+ /**
145
+ * Discover agents
146
+ */
147
+ async discover(options) {
148
+ const params = new URLSearchParams();
149
+ if (options?.query)
150
+ params.set('q', options.query);
151
+ if (options?.category)
152
+ params.set('category', options.category);
153
+ if (options?.tag)
154
+ params.set('tag', options.tag);
155
+ if (options?.limit)
156
+ params.set('limit', String(options.limit));
157
+ const response = await fetch(`${this.apiUrl}/api/discover/agents?${params}`, {
158
+ headers: {
159
+ 'Authorization': `Bearer ${this.apiKey}`,
160
+ },
161
+ });
162
+ if (!response.ok) {
163
+ throw new Error(`Discovery failed: ${response.statusText}`);
164
+ }
165
+ return response.json();
166
+ }
167
+ /**
168
+ * Create client from environment
169
+ */
170
+ static fromEnv() {
171
+ const apiKey = process.env.GOPHERHOLE_API_KEY;
172
+ if (!apiKey) {
173
+ throw new Error('GOPHERHOLE_API_KEY environment variable is required');
174
+ }
175
+ return new GopherHoleClient({
176
+ apiKey,
177
+ apiUrl: process.env.GOPHERHOLE_API_URL,
178
+ });
179
+ }
180
+ }
181
+ exports.GopherHoleClient = GopherHoleClient;
182
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,MAAM,eAAe,GAAG,uBAAuB,CAAC;AAyChD,MAAa,gBAAgB;IACnB,MAAM,CAAS;IACf,MAAM,CAAS;IACf,OAAO,CAAS;IAExB,YAAY,MAAwB;QAClC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,eAAe,CAAC;QAC/C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC;IACzC,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,GAAG,CAAI,MAAc,EAAE,MAA+B;QAClE,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAErE,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,MAAM,EAAE;gBACjD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,eAAe,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;iBACzC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,MAAM;oBACN,MAAM;oBACN,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;iBACf,CAAC;gBACF,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAiD,CAAC;YAElF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,WAAW,CAAC,CAAC;YACrD,CAAC;YAED,OAAO,IAAI,CAAC,MAAW,CAAC;QAC1B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBACtD,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;YAC7D,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,SAAS,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,OAAe,EAAE,IAAY,EAAE,SAAkB;QAC9D,OAAO,IAAI,CAAC,GAAG,CAAO,cAAc,EAAE;YACpC,OAAO,EAAE;gBACP,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;aAChC;YACD,aAAa,EAAE;gBACb,OAAO;gBACP,SAAS;aACV;SACF,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,MAAc;QAC1B,OAAO,IAAI,CAAC,GAAG,CAAO,WAAW,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACrD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,MAAc,EAAE,SAAS,GAAG,KAAK,EAAE,cAAc,GAAG,IAAI;QACxE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,SAAS,EAAE,CAAC;YAC1C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAExC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;gBAChF,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,QAAQ,MAAM,4BAA4B,SAAS,IAAI,CAAC,CAAC;IAC3E,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,OAAe,EAAE,IAAY,EAAE,SAAkB;QACrE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,OAAe,EAAE,IAAY;QACzC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAEvD,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,aAAa,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IAED;;OAEG;IACK,mBAAmB,CAAC,IAAU;QACpC,wBAAwB;QACxB,IAAI,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACtC,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;oBACnB,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;wBAClC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;4BACtC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;wBACxB,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,uBAAuB;QACvB,IAAI,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;YACzB,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC1D,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;gBACtB,MAAM,KAAK,GAAa,EAAE,CAAC;gBAC3B,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;oBACrC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;wBACtC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACxB,CAAC;gBACH,CAAC;gBACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACrB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,EAAE,CAAC;IACZ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,OAKd;QACC,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,OAAO,EAAE,KAAK;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QACnD,IAAI,OAAO,EAAE,QAAQ;YAAE,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QAChE,IAAI,OAAO,EAAE,GAAG;YAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QACjD,IAAI,OAAO,EAAE,KAAK;YAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAE/D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,wBAAwB,MAAM,EAAE,EAAE;YAC3E,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;aACzC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAA6B,CAAC;IACpD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,OAAO;QACZ,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;QAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;QAED,OAAO,IAAI,gBAAgB,CAAC;YAC1B,MAAM;YACN,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;SACvC,CAAC,CAAC;IACL,CAAC;CACF;AApMD,4CAoMC"}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * GopherHole MCP Server
4
+ *
5
+ * Exposes GopherHole agents as MCP tools for Claude Code, Cursor, and other
6
+ * MCP-compatible IDEs.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG"}
package/dist/index.js ADDED
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * GopherHole MCP Server
5
+ *
6
+ * Exposes GopherHole agents as MCP tools for Claude Code, Cursor, and other
7
+ * MCP-compatible IDEs.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
11
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
12
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
13
+ const client_js_1 = require("./client.js");
14
+ const tools_js_1 = require("./tools.js");
15
+ // Default memory agent ID (can be overridden via env)
16
+ const MEMORY_AGENT_ID = process.env.GOPHERHOLE_MEMORY_AGENT || 'memory';
17
+ /**
18
+ * Format tags for the memory store message
19
+ */
20
+ function formatStoreMessage(content, tags) {
21
+ let message = `Remember this:\n\n${content}`;
22
+ if (tags?.length) {
23
+ message += `\n\nTags: ${tags.join(', ')}`;
24
+ }
25
+ return message;
26
+ }
27
+ /**
28
+ * Format search query for memory recall
29
+ */
30
+ function formatRecallMessage(query, limit) {
31
+ let message = `Search memories for: ${query}`;
32
+ if (limit) {
33
+ message += ` (limit: ${limit})`;
34
+ }
35
+ return message;
36
+ }
37
+ /**
38
+ * Main entry point
39
+ */
40
+ async function main() {
41
+ // Initialize GopherHole client
42
+ let client;
43
+ try {
44
+ client = client_js_1.GopherHoleClient.fromEnv();
45
+ }
46
+ catch (error) {
47
+ console.error('Error: GOPHERHOLE_API_KEY environment variable is required');
48
+ console.error('Get your API key at https://gopherhole.ai');
49
+ process.exit(1);
50
+ }
51
+ // Create MCP server
52
+ const server = new index_js_1.Server({
53
+ name: 'gopherhole',
54
+ version: '0.1.0',
55
+ }, {
56
+ capabilities: {
57
+ tools: {},
58
+ },
59
+ });
60
+ // Handle tools/list
61
+ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
62
+ return { tools: tools_js_1.ALL_TOOLS };
63
+ });
64
+ // Handle tools/call
65
+ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
66
+ const { name, arguments: args } = request.params;
67
+ try {
68
+ switch (name) {
69
+ case 'memory_store': {
70
+ const content = args?.content;
71
+ const tags = args?.tags;
72
+ if (!content) {
73
+ return {
74
+ content: [{ type: 'text', text: 'Error: content is required' }],
75
+ isError: true,
76
+ };
77
+ }
78
+ const message = formatStoreMessage(content, tags);
79
+ const response = await client.askText(MEMORY_AGENT_ID, message);
80
+ return {
81
+ content: [{ type: 'text', text: response || 'Memory stored successfully' }],
82
+ };
83
+ }
84
+ case 'memory_recall': {
85
+ const query = args?.query;
86
+ const limit = args?.limit;
87
+ if (!query) {
88
+ return {
89
+ content: [{ type: 'text', text: 'Error: query is required' }],
90
+ isError: true,
91
+ };
92
+ }
93
+ const message = formatRecallMessage(query, limit);
94
+ const response = await client.askText(MEMORY_AGENT_ID, message);
95
+ return {
96
+ content: [{ type: 'text', text: response || 'No memories found' }],
97
+ };
98
+ }
99
+ case 'memory_forget': {
100
+ const query = args?.query;
101
+ const confirmDelete = args?.confirmDelete;
102
+ if (!query || !confirmDelete) {
103
+ return {
104
+ content: [{ type: 'text', text: 'Error: query and confirmDelete=true are required' }],
105
+ isError: true,
106
+ };
107
+ }
108
+ const response = await client.askText(MEMORY_AGENT_ID, `Forget memories matching: ${query}`);
109
+ return {
110
+ content: [{ type: 'text', text: response || 'Memories deleted' }],
111
+ };
112
+ }
113
+ case 'memory_list': {
114
+ const limit = args?.limit || 20;
115
+ const offset = args?.offset || 0;
116
+ const response = await client.askText(MEMORY_AGENT_ID, `List my recent memories (limit: ${limit}, offset: ${offset})`);
117
+ return {
118
+ content: [{ type: 'text', text: response || 'No memories found' }],
119
+ };
120
+ }
121
+ case 'agent_discover': {
122
+ const query = args?.query;
123
+ const category = args?.category;
124
+ const limit = args?.limit;
125
+ const result = await client.discover({ query, category, limit });
126
+ if (result.agents.length === 0) {
127
+ return {
128
+ content: [{ type: 'text', text: 'No agents found matching your criteria' }],
129
+ };
130
+ }
131
+ const agentList = result.agents.map(a => `• **${a.name}** (${a.id})\n ${a.description || 'No description'}\n Rating: ${a.avgRating.toFixed(1)} ⭐ (${a.ratingCount} reviews)`).join('\n\n');
132
+ return {
133
+ content: [{ type: 'text', text: `Found ${result.count} agents:\n\n${agentList}` }],
134
+ };
135
+ }
136
+ case 'agent_message': {
137
+ const agentId = args?.agentId;
138
+ const message = args?.message;
139
+ if (!agentId || !message) {
140
+ return {
141
+ content: [{ type: 'text', text: 'Error: agentId and message are required' }],
142
+ isError: true,
143
+ };
144
+ }
145
+ const response = await client.askText(agentId, message);
146
+ return {
147
+ content: [{ type: 'text', text: response || 'No response from agent' }],
148
+ };
149
+ }
150
+ default:
151
+ return {
152
+ content: [{ type: 'text', text: `Unknown tool: ${name}` }],
153
+ isError: true,
154
+ };
155
+ }
156
+ }
157
+ catch (error) {
158
+ const errorMessage = error instanceof Error ? error.message : String(error);
159
+ return {
160
+ content: [{ type: 'text', text: `Error: ${errorMessage}` }],
161
+ isError: true,
162
+ };
163
+ }
164
+ });
165
+ // Start server with stdio transport
166
+ const transport = new stdio_js_1.StdioServerTransport();
167
+ await server.connect(transport);
168
+ // Log to stderr (stdout is for MCP protocol)
169
+ console.error('GopherHole MCP server started');
170
+ }
171
+ // Run
172
+ main().catch((error) => {
173
+ console.error('Fatal error:', error);
174
+ process.exit(1);
175
+ });
176
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AACA;;;;;GAKG;;AAEH,wEAAmE;AACnE,wEAAiF;AACjF,iEAG4C;AAE5C,2CAA+C;AAC/C,yCAAuC;AAEvC,sDAAsD;AACtD,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,QAAQ,CAAC;AAExE;;GAEG;AACH,SAAS,kBAAkB,CAAC,OAAe,EAAE,IAAe;IAC1D,IAAI,OAAO,GAAG,qBAAqB,OAAO,EAAE,CAAC;IAC7C,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;QACjB,OAAO,IAAI,aAAa,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAC5C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,KAAa,EAAE,KAAc;IACxD,IAAI,OAAO,GAAG,wBAAwB,KAAK,EAAE,CAAC;IAC9C,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,IAAI,YAAY,KAAK,GAAG,CAAC;IAClC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,IAAI;IACjB,+BAA+B;IAC/B,IAAI,MAAwB,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,GAAG,4BAAgB,CAAC,OAAO,EAAE,CAAC;IACtC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC5E,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,oBAAoB;IACpB,MAAM,MAAM,GAAG,IAAI,iBAAM,CACvB;QACE,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE;SACV;KACF,CACF,CAAC;IAEF,oBAAoB;IACpB,MAAM,CAAC,iBAAiB,CAAC,iCAAsB,EAAE,KAAK,IAAI,EAAE;QAC1D,OAAO,EAAE,KAAK,EAAE,oBAAS,EAAE,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,oBAAoB;IACpB,MAAM,CAAC,iBAAiB,CAAC,gCAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAChE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;QAEjD,IAAI,CAAC;YACH,QAAQ,IAAI,EAAE,CAAC;gBACb,KAAK,cAAc,CAAC,CAAC,CAAC;oBACpB,MAAM,OAAO,GAAG,IAAI,EAAE,OAAiB,CAAC;oBACxC,MAAM,IAAI,GAAG,IAAI,EAAE,IAA4B,CAAC;oBAEhD,IAAI,CAAC,OAAO,EAAE,CAAC;wBACb,OAAO;4BACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,4BAA4B,EAAE,CAAC;4BAC/D,OAAO,EAAE,IAAI;yBACd,CAAC;oBACJ,CAAC;oBAED,MAAM,OAAO,GAAG,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;oBAClD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;oBAEhE,OAAO;wBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,IAAI,4BAA4B,EAAE,CAAC;qBAC5E,CAAC;gBACJ,CAAC;gBAED,KAAK,eAAe,CAAC,CAAC,CAAC;oBACrB,MAAM,KAAK,GAAG,IAAI,EAAE,KAAe,CAAC;oBACpC,MAAM,KAAK,GAAG,IAAI,EAAE,KAA2B,CAAC;oBAEhD,IAAI,CAAC,KAAK,EAAE,CAAC;wBACX,OAAO;4BACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,0BAA0B,EAAE,CAAC;4BAC7D,OAAO,EAAE,IAAI;yBACd,CAAC;oBACJ,CAAC;oBAED,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;oBAClD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;oBAEhE,OAAO;wBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,IAAI,mBAAmB,EAAE,CAAC;qBACnE,CAAC;gBACJ,CAAC;gBAED,KAAK,eAAe,CAAC,CAAC,CAAC;oBACrB,MAAM,KAAK,GAAG,IAAI,EAAE,KAAe,CAAC;oBACpC,MAAM,aAAa,GAAG,IAAI,EAAE,aAAwB,CAAC;oBAErD,IAAI,CAAC,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;wBAC7B,OAAO;4BACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kDAAkD,EAAE,CAAC;4BACrF,OAAO,EAAE,IAAI;yBACd,CAAC;oBACJ,CAAC;oBAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,6BAA6B,KAAK,EAAE,CAAC,CAAC;oBAE7F,OAAO;wBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,IAAI,kBAAkB,EAAE,CAAC;qBAClE,CAAC;gBACJ,CAAC;gBAED,KAAK,aAAa,CAAC,CAAC,CAAC;oBACnB,MAAM,KAAK,GAAG,IAAI,EAAE,KAAe,IAAI,EAAE,CAAC;oBAC1C,MAAM,MAAM,GAAG,IAAI,EAAE,MAAgB,IAAI,CAAC,CAAC;oBAE3C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CACnC,eAAe,EACf,mCAAmC,KAAK,aAAa,MAAM,GAAG,CAC/D,CAAC;oBAEF,OAAO;wBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,IAAI,mBAAmB,EAAE,CAAC;qBACnE,CAAC;gBACJ,CAAC;gBAED,KAAK,gBAAgB,CAAC,CAAC,CAAC;oBACtB,MAAM,KAAK,GAAG,IAAI,EAAE,KAAe,CAAC;oBACpC,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAkB,CAAC;oBAC1C,MAAM,KAAK,GAAG,IAAI,EAAE,KAAe,CAAC;oBAEpC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;oBAEjE,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;wBAC/B,OAAO;4BACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,wCAAwC,EAAE,CAAC;yBAC5E,CAAC;oBACJ,CAAC;oBAED,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CACtC,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,WAAW,IAAI,gBAAgB,eAAe,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,WAAW,CACtI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBAEf,OAAO;wBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,CAAC,KAAK,eAAe,SAAS,EAAE,EAAE,CAAC;qBACnF,CAAC;gBACJ,CAAC;gBAED,KAAK,eAAe,CAAC,CAAC,CAAC;oBACrB,MAAM,OAAO,GAAG,IAAI,EAAE,OAAiB,CAAC;oBACxC,MAAM,OAAO,GAAG,IAAI,EAAE,OAAiB,CAAC;oBAExC,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;wBACzB,OAAO;4BACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,yCAAyC,EAAE,CAAC;4BAC5E,OAAO,EAAE,IAAI;yBACd,CAAC;oBACJ,CAAC;oBAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;oBAExD,OAAO;wBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,IAAI,wBAAwB,EAAE,CAAC;qBACxE,CAAC;gBACJ,CAAC;gBAED;oBACE,OAAO;wBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,IAAI,EAAE,EAAE,CAAC;wBAC1D,OAAO,EAAE,IAAI;qBACd,CAAC;YACN,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5E,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,YAAY,EAAE,EAAE,CAAC;gBAC3D,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,oCAAoC;IACpC,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,6CAA6C;IAC7C,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;AACjD,CAAC;AAED,MAAM;AACN,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * MCP Tool Definitions for GopherHole
3
+ */
4
+ import type { Tool } from '@modelcontextprotocol/sdk/types.js';
5
+ /**
6
+ * Phase 1 Tools - Memory
7
+ */
8
+ export declare const MEMORY_TOOLS: Tool[];
9
+ /**
10
+ * Phase 2 Tools - Extended Memory
11
+ */
12
+ export declare const EXTENDED_MEMORY_TOOLS: Tool[];
13
+ /**
14
+ * Phase 2 Tools - Agent Discovery & Messaging
15
+ */
16
+ export declare const AGENT_TOOLS: Tool[];
17
+ /**
18
+ * All tools combined
19
+ */
20
+ export declare const ALL_TOOLS: Tool[];
21
+ /**
22
+ * Get tool by name
23
+ */
24
+ export declare function getTool(name: string): Tool | undefined;
25
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAE/D;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,IAAI,EAsC9B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,IAAI,EAoCvC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,IAAI,EAwC7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,IAAI,EAK3B,CAAC;AAEF;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAEtD"}
package/dist/tools.js ADDED
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ /**
3
+ * MCP Tool Definitions for GopherHole
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ALL_TOOLS = exports.AGENT_TOOLS = exports.EXTENDED_MEMORY_TOOLS = exports.MEMORY_TOOLS = void 0;
7
+ exports.getTool = getTool;
8
+ /**
9
+ * Phase 1 Tools - Memory
10
+ */
11
+ exports.MEMORY_TOOLS = [
12
+ {
13
+ name: 'memory_store',
14
+ description: 'Store a memory for later recall. Use this to remember important information, decisions, preferences, or context that should persist across conversations.',
15
+ inputSchema: {
16
+ type: 'object',
17
+ properties: {
18
+ content: {
19
+ type: 'string',
20
+ description: 'What to remember. Be specific and include relevant context.',
21
+ },
22
+ tags: {
23
+ type: 'array',
24
+ items: { type: 'string' },
25
+ description: 'Optional tags to categorize the memory (e.g., "project", "preference", "decision")',
26
+ },
27
+ },
28
+ required: ['content'],
29
+ },
30
+ },
31
+ {
32
+ name: 'memory_recall',
33
+ description: 'Recall memories about a topic. Search through stored memories to find relevant information.',
34
+ inputSchema: {
35
+ type: 'object',
36
+ properties: {
37
+ query: {
38
+ type: 'string',
39
+ description: 'What to search for. Can be a topic, keyword, or question.',
40
+ },
41
+ limit: {
42
+ type: 'number',
43
+ description: 'Maximum number of memories to return (default: 10)',
44
+ },
45
+ },
46
+ required: ['query'],
47
+ },
48
+ },
49
+ ];
50
+ /**
51
+ * Phase 2 Tools - Extended Memory
52
+ */
53
+ exports.EXTENDED_MEMORY_TOOLS = [
54
+ {
55
+ name: 'memory_forget',
56
+ description: 'Forget/delete memories matching a query. Use carefully - this permanently removes memories.',
57
+ inputSchema: {
58
+ type: 'object',
59
+ properties: {
60
+ query: {
61
+ type: 'string',
62
+ description: 'Query to match memories to forget',
63
+ },
64
+ confirmDelete: {
65
+ type: 'boolean',
66
+ description: 'Must be true to confirm deletion',
67
+ },
68
+ },
69
+ required: ['query', 'confirmDelete'],
70
+ },
71
+ },
72
+ {
73
+ name: 'memory_list',
74
+ description: 'List recent memories without searching. Good for reviewing what has been stored.',
75
+ inputSchema: {
76
+ type: 'object',
77
+ properties: {
78
+ limit: {
79
+ type: 'number',
80
+ description: 'Maximum number of memories to return (default: 20)',
81
+ },
82
+ offset: {
83
+ type: 'number',
84
+ description: 'Pagination offset',
85
+ },
86
+ },
87
+ },
88
+ },
89
+ ];
90
+ /**
91
+ * Phase 2 Tools - Agent Discovery & Messaging
92
+ */
93
+ exports.AGENT_TOOLS = [
94
+ {
95
+ name: 'agent_discover',
96
+ description: 'Find agents on GopherHole by capability, category, or search query.',
97
+ inputSchema: {
98
+ type: 'object',
99
+ properties: {
100
+ query: {
101
+ type: 'string',
102
+ description: 'Search query to find agents',
103
+ },
104
+ category: {
105
+ type: 'string',
106
+ description: 'Filter by category (e.g., "memory", "search", "code")',
107
+ },
108
+ limit: {
109
+ type: 'number',
110
+ description: 'Maximum number of agents to return (default: 10)',
111
+ },
112
+ },
113
+ },
114
+ },
115
+ {
116
+ name: 'agent_message',
117
+ description: 'Send a message to any GopherHole agent and get a response.',
118
+ inputSchema: {
119
+ type: 'object',
120
+ properties: {
121
+ agentId: {
122
+ type: 'string',
123
+ description: 'The agent ID (e.g., "memory", "search", or a full agent ID)',
124
+ },
125
+ message: {
126
+ type: 'string',
127
+ description: 'Message to send to the agent',
128
+ },
129
+ },
130
+ required: ['agentId', 'message'],
131
+ },
132
+ },
133
+ ];
134
+ /**
135
+ * All tools combined
136
+ */
137
+ exports.ALL_TOOLS = [
138
+ ...exports.MEMORY_TOOLS,
139
+ // Phase 2: Uncomment when ready
140
+ // ...EXTENDED_MEMORY_TOOLS,
141
+ // ...AGENT_TOOLS,
142
+ ];
143
+ /**
144
+ * Get tool by name
145
+ */
146
+ function getTool(name) {
147
+ return exports.ALL_TOOLS.find(t => t.name === name);
148
+ }
149
+ //# 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,47 @@
1
+ {
2
+ "name": "@gopherhole/mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for GopherHole - Access AI agents from Claude Code, Cursor, and other MCP-compatible IDEs",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "gopherhole-mcp": "./dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsc --watch",
13
+ "start": "node dist/index.js",
14
+ "test": "echo '{\"jsonrpc\":\"2.0\",\"method\":\"tools/list\",\"id\":1}' | node dist/index.js",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "keywords": [
18
+ "mcp",
19
+ "gopherhole",
20
+ "ai",
21
+ "agents",
22
+ "a2a",
23
+ "claude",
24
+ "cursor",
25
+ "model-context-protocol"
26
+ ],
27
+ "author": "GopherHole",
28
+ "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/gopherhole/mcp"
32
+ },
33
+ "dependencies": {
34
+ "@modelcontextprotocol/sdk": "^1.0.0"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^20.11.0",
38
+ "typescript": "^5.3.0"
39
+ },
40
+ "engines": {
41
+ "node": ">=18.0.0"
42
+ },
43
+ "files": [
44
+ "dist",
45
+ "README.md"
46
+ ]
47
+ }