Skip to content

Commit 58dbc6b

Browse files
committed
feat(mcp): add get_space_by_slug method
1 parent 4ca271b commit 58dbc6b

2 files changed

Lines changed: 151 additions & 6 deletions

File tree

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
---
2+
name: hypha-web-mcp
3+
description: Uses the local hypha-web MCP server to fetch and summarize Hypha space context by slug. Use when the user asks to query space data, run get_space_by_slug, verify MCP connectivity, or produce structured summaries of a Hypha space.
4+
---
5+
6+
# Hypha Web MCP
7+
8+
Use this skill to query Hypha space data through the local MCP endpoint and present clean, grounded summaries.
9+
10+
## Scope
11+
12+
- Query one space by slug via `get_space_by_slug`
13+
- Validate MCP connectivity for local development
14+
- Render returned structured data in a human-friendly format
15+
- Diagnose common local MCP setup issues
16+
17+
## Preconditions
18+
19+
Before any MCP call:
20+
21+
1. Confirm app is running locally (`pnpm dev` in repo root)
22+
2. Confirm Cursor MCP config includes:
23+
- `hypha-web-mcp` -> `http://localhost:3000/mcp`
24+
3. Treat `/mcp` as protocol endpoint (not a browser page)
25+
26+
## Primary Workflow
27+
28+
Copy this checklist and update progress:
29+
30+
```txt
31+
Hypha MCP Workflow
32+
- [ ] Verify endpoint reachability
33+
- [ ] Call get_space_by_slug
34+
- [ ] Validate found/not found
35+
- [ ] Present structured summary
36+
```
37+
38+
### 1) Verify endpoint reachability
39+
40+
- Prefer MCP client usage (Cursor tools).
41+
- If debugging manually, initialize over JSON-RPC and check server info is returned.
42+
43+
### 2) Call tool
44+
45+
- Tool: `get_space_by_slug`
46+
- Arguments:
47+
- `slug` (string, required)
48+
49+
### 3) Validate response
50+
51+
- If `structuredContent.found` is `true`, use `structuredContent.space`.
52+
- If `false`, report clearly that slug was not found.
53+
- If `isError` is `true`, diagnose with troubleshooting section.
54+
55+
### 4) Present output
56+
57+
When user asks for "actual data", return raw JSON.
58+
When user asks for "properly rendered", use this format:
59+
60+
- **Title**: `space.title`
61+
- **Identity**: `id`, `slug`, `web3SpaceId`
62+
- **Hierarchy**: `parentId`, `subspaceCount`
63+
- **Activity signals**: `memberCount`, `documentCount`
64+
- **Description**: verbatim, unedited
65+
- **Timestamps**: `createdAt`, `updatedAt`
66+
67+
## Response Templates
68+
69+
### Data-first template
70+
71+
```markdown
72+
## <title> Space
73+
- ID: `<id>`
74+
- Slug: `<slug>`
75+
- Web3 Space ID: `<web3SpaceId>`
76+
- Parent ID: `<parentId>`
77+
- Member Count: `<memberCount>`
78+
- Document Count: `<documentCount>`
79+
- Subspace Count: `<subspaceCount>`
80+
- Created At: `<createdAt>`
81+
- Updated At: `<updatedAt>`
82+
83+
<description>
84+
```
85+
86+
### Not found template
87+
88+
```markdown
89+
No space found for slug `<slug>`.
90+
```
91+
92+
## Troubleshooting
93+
94+
### `ECONNREFUSED localhost:3000`
95+
96+
- Dev server not running or wrong port.
97+
- Start/restart `pnpm dev` and re-test.
98+
99+
### MCP says auth required
100+
101+
- Usually a transport or server error surfaced as generic auth.
102+
- Check `/mcp` initialize call and server logs before adding auth.
103+
104+
### `Module not found: zod/v3`
105+
106+
- MCP SDK and zod version mismatch.
107+
- Ensure workspace uses compatible `zod` (>= 3.25).
108+
109+
### `/mcp` opens with browser/devtools errors
110+
111+
- Expected if treated as page navigation.
112+
- Use MCP client calls, not browser page rendering.
113+
114+
## Guardrails
115+
116+
- Do not invent fields not returned by MCP.
117+
- Keep summaries grounded in returned JSON.
118+
- If counts are zero or look surprising, report them as-is and call out uncertainty.
119+
- Prefer concise output unless user asks for detailed analysis.

apps/web/src/app/mcp/route.ts

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { getSpaceBySlug } from '@hypha-platform/core/server';
21
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
32
import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';
3+
import { getSpaceBySlug } from '@hypha-platform/core/server';
44
import { z } from 'zod';
55

66
export const runtime = 'nodejs';
@@ -86,11 +86,23 @@ function createMcpServer(): McpServer {
8686
description: space.description ?? null,
8787
parentId: space.parentId ?? null,
8888
web3SpaceId: space.web3SpaceId ?? null,
89-
memberCount: space.memberCount ?? 0,
90-
documentCount: space.documentCount ?? 0,
91-
subspaceCount: space.subspaces?.length ?? 0,
92-
createdAt: space.createdAt.toISOString(),
93-
updatedAt: space.updatedAt.toISOString(),
89+
memberCount:
90+
typeof space.memberCount === 'number'
91+
? space.memberCount
92+
: Array.isArray(space.members)
93+
? space.members.length
94+
: 0,
95+
documentCount:
96+
typeof space.documentCount === 'number'
97+
? space.documentCount
98+
: Array.isArray(space.documents)
99+
? space.documents.length
100+
: 0,
101+
subspaceCount: Array.isArray(space.subspaces)
102+
? space.subspaces.length
103+
: 0,
104+
createdAt: new Date(space.createdAt).toISOString(),
105+
updatedAt: new Date(space.updatedAt).toISOString(),
94106
},
95107
};
96108

@@ -144,6 +156,20 @@ export async function POST(request: Request): Promise<Response> {
144156
}
145157

146158
export async function GET(request: Request): Promise<Response> {
159+
const isLikelyBrowserNavigation =
160+
request.headers.get('mcp-protocol-version') === null &&
161+
(request.headers.get('accept')?.includes('text/html') ?? false);
162+
163+
if (isLikelyBrowserNavigation) {
164+
return Response.json({
165+
ok: true,
166+
message:
167+
'This is an MCP endpoint. Use an MCP client (for example Cursor), not a browser tab navigation.',
168+
endpoint: '/mcp',
169+
methods: ['POST', 'GET', 'DELETE'],
170+
});
171+
}
172+
147173
return handleMcpRequest(request);
148174
}
149175

0 commit comments

Comments
 (0)