Skip to content

Commit e421a1f

Browse files
authored
Merge pull request #9 from crup/next
fix(mcp): handle client notifications
2 parents 748d585 + df5fa7c commit e421a1f

File tree

5 files changed

+39
-16
lines changed

5 files changed

+39
-16
lines changed

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ The default import stays small. Add the other pieces only when that screen needs
257257
| 📡 Schedules | `@crup/react-timer-hook/schedules` | Polling, cadence callbacks, overdue timing context | 8.62 kB | 3.02 kB | 2.78 kB |
258258
| 🧩 Duration | `@crup/react-timer-hook/duration` | `days`, `hours`, `minutes`, `seconds`, `milliseconds` | 318 B | 224 B | 192 B |
259259
| 🔎 Diagnostics | `@crup/react-timer-hook/diagnostics` | Optional lifecycle and schedule event logging | 105 B | 115 B | 90 B |
260-
| 🤖 MCP docs server | `react-timer-hook-mcp` | Optional local docs context for MCP clients and coding agents | 6.69 kB | 2.60 kB | 2.25 kB |
260+
| 🤖 MCP docs server | `react-timer-hook-mcp` | Optional local docs context for MCP clients and coding agents | 6.95 kB | 2.72 kB | 2.36 kB |
261261

262262
CI writes a size summary to the GitHub Actions UI and posts bundle-size reports on pull requests.
263263

@@ -308,11 +308,11 @@ react-timer-hook://recipes
308308

309309
It also exposes MCP tools that editors are more likely to call directly:
310310

311-
```txt
312-
get_api_docs
313-
get_recipe
314-
search_docs
315-
```
311+
| Tool | Title | Description |
312+
| --- | --- | --- |
313+
| `get_api_docs` | Get API docs | Returns compact API notes for `@crup/react-timer-hook`. |
314+
| `get_recipe` | Get recipe | Returns guidance for a named recipe or use case. |
315+
| `search_docs` | Search docs | Searches API and recipe notes for a query. |
316316

317317
## Contributing
318318

docs-site/docs/ai.mdx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ react-timer-hook://recipes
6666

6767
It also exposes callable tools for MCP clients that prefer tool calls over resource reads:
6868

69-
```txt
70-
get_api_docs
71-
get_recipe
72-
search_docs
73-
```
69+
| Tool | Title | Description |
70+
| --- | --- | --- |
71+
| `get_api_docs` | Get API docs | Returns compact API notes for `@crup/react-timer-hook`. |
72+
| `get_recipe` | Get recipe | Returns guidance for a named recipe or use case. |
73+
| `search_docs` | Search docs | Searches API and recipe notes for a query. |
7474

7575
Verify locally:
7676

docs-site/static/llms-full.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ Local docs MCP server:
105105
The package bundles the MCP server at node_modules/@crup/react-timer-hook/dist/mcp/server.js and exposes it through the react-timer-hook-mcp bin.
106106

107107
MCP tools:
108-
- get_api_docs
109-
- get_recipe
110-
- search_docs
108+
- get_api_docs: Get API docs. Returns compact API notes for @crup/react-timer-hook.
109+
- get_recipe: Get recipe. Returns guidance for a named recipe or use case.
110+
- search_docs: Search docs. Searches API and recipe notes for a query.
111111

112112
## Boundaries
113113

mcp/server.mjs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ const recipes = {
9494
const tools = [
9595
{
9696
name: 'get_api_docs',
97+
title: 'Get API docs',
9798
description: 'Return the compact API notes for @crup/react-timer-hook.',
9899
inputSchema: {
99100
type: 'object',
@@ -103,6 +104,7 @@ const tools = [
103104
},
104105
{
105106
name: 'get_recipe',
107+
title: 'Get recipe',
106108
description: 'Return guidance for a named recipe or use case.',
107109
inputSchema: {
108110
type: 'object',
@@ -118,6 +120,7 @@ const tools = [
118120
},
119121
{
120122
name: 'search_docs',
123+
title: 'Search docs',
121124
description: 'Search API and recipe notes for a query.',
122125
inputSchema: {
123126
type: 'object',
@@ -146,6 +149,12 @@ rl.on('line', line => {
146149
}
147150

148151
const { id, method, params } = request;
152+
const hasId = Object.hasOwn(request, 'id');
153+
154+
if (!method) {
155+
if (hasId) respondError(id, -32600, 'Invalid request: missing method.');
156+
return;
157+
}
149158

150159
if (method === 'initialize') {
151160
respond(id, {
@@ -156,6 +165,15 @@ rl.on('line', line => {
156165
return;
157166
}
158167

168+
if (method === 'notifications/initialized' || method.startsWith('notifications/')) {
169+
return;
170+
}
171+
172+
if (method === 'ping') {
173+
if (hasId) respond(id, {});
174+
return;
175+
}
176+
159177
if (method === 'resources/list') {
160178
respond(id, {
161179
resources: Object.entries(resources).map(([uri, resource]) => ({
@@ -231,7 +249,7 @@ rl.on('line', line => {
231249
return;
232250
}
233251

234-
respondError(id, -32601, `Method not found: ${method}`);
252+
if (hasId) respondError(id, -32601, `Method not found: ${method}`);
235253
});
236254

237255
function respond(id, result) {
@@ -243,6 +261,7 @@ function respondTool(id, text) {
243261
}
244262

245263
function respondError(id, code, message) {
264+
if (id === undefined) return;
246265
process.stdout.write(`${JSON.stringify({ jsonrpc: '2.0', id, error: { code, message } })}\n`);
247266
}
248267

scripts/check-mcp-server.mjs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ child.stderr.on('data', chunk => {
2626
child.stdin.end(
2727
[
2828
JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'initialize', params: {} }),
29+
JSON.stringify({ jsonrpc: '2.0', method: 'notifications/initialized', params: {} }),
2930
JSON.stringify({ jsonrpc: '2.0', id: 2, method: 'resources/list', params: {} }),
3031
JSON.stringify({
3132
jsonrpc: '2.0',
@@ -86,7 +87,10 @@ child.on('close', code => {
8687
process.exit(1);
8788
}
8889

89-
if (!tools.some(tool => tool.name === 'get_recipe') || !tools.some(tool => tool.name === 'search_docs')) {
90+
if (
91+
!tools.some(tool => tool.name === 'get_recipe' && tool.title === 'Get recipe') ||
92+
!tools.some(tool => tool.name === 'search_docs' && tool.title === 'Search docs')
93+
) {
9094
console.error('MCP tools list is missing expected docs tools.');
9195
process.exit(1);
9296
}

0 commit comments

Comments
 (0)