@opengolfapi/mcp-server 2.3.2 → 2.3.4

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 (2) hide show
  1. package/dist/index.js +41 -6
  2. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -337,20 +337,28 @@ server.tool('log_shot', 'Contribute a golf shot to OpenGolfAPI (your own data +
337
337
  return { content: [{ type: 'text', text: `Error: ${e instanceof Error ? e.message : String(e)}` }] };
338
338
  }
339
339
  });
340
- server.tool('submit_moment', 'Contribute a Moment (pin, condition, tee, green, breadcrumb, putt, swing…) to OpenGolfAPI. Requires OPENGOLFAPI_KEY.', {
341
- moment_type: z.enum(['pin', 'condition', 'tee', 'green', 'breadcrumb', 'shot', 'motion', 'swing', 'putt', 'biometric', 'club', 'score'])
342
- .describe('The event kind: pin/condition/tee/green = course sightings; breadcrumb = a GPS point; putt/swing/motion/biometric/club/score = sensor events (data in `note` or payload)'),
340
+ server.tool('submit_moment', 'Contribute a Moment from any sensor/wearable/phone. The whole sensor spectrum rides through here — type-specific data goes in `payload`. Requires OPENGOLFAPI_KEY.', {
341
+ moment_type: z.enum(['shot', 'breadcrumb', 'pin', 'presence', 'condition', 'tee', 'green', 'motion', 'swing', 'putt', 'biometric', 'club', 'score'])
342
+ .describe('Event kind: breadcrumb/tee/green = GPS points; pin/condition = course sightings; presence = live location (find fellow golfers); motion/swing/putt/biometric/club/score = sensor events (data in `payload`)'),
343
343
  lat: z.number().optional().describe('GPS latitude where the event happened'),
344
344
  lng: z.number().optional().describe('GPS longitude where the event happened'),
345
+ accuracy_m: z.number().optional().describe('GPS accuracy in meters'),
346
+ recorded_at: z.string().optional().describe('ISO 8601 timestamp the event happened'),
345
347
  course_id: z.string().optional().describe('OpenGolfAPI course id, if known'),
346
348
  hole: z.number().optional().describe('Hole number, 1-18'),
347
349
  player_id: z.string().optional().describe('Your pseudonymous player id'),
350
+ session_id: z.string().optional().describe('Session id (one round or range session)'),
351
+ device: z.string().optional().describe("Source device, e.g. 'apple_watch', 'hackmotion', 'arccos'"),
348
352
  note: z.string().optional().describe('Free-text detail (e.g. a condition report or pin note)'),
353
+ payload: z.record(z.any()).optional().describe('Type-specific sensor data. swing:{tempo,wrist_angle,plane}; putt:{speed,path,face,roll_pct}; biometric:{heart_rate,exertion}; club:{club,event,specs}; score:{strokes,putts,penalties}; motion:{accel,gyro,sample_hz}; presence:{visibility}'),
349
354
  }, async (a) => {
350
355
  if (!OPENGOLFAPI_KEY)
351
356
  return { content: [{ type: 'text', text: 'Set OPENGOLFAPI_KEY (free at courses.opengolfapi.org/api-keys) to contribute moments.' }] };
352
357
  try {
353
- const moment = { moment_type: a.moment_type, lat: a.lat, lng: a.lng, course_id: a.course_id, hole: a.hole, player_id: a.player_id, payload: a.note ? { note: a.note } : undefined };
358
+ const payload = { ...(a.payload ?? {}), ...(a.note ? { note: a.note } : {}) };
359
+ const moment = { moment_type: a.moment_type, lat: a.lat, lng: a.lng, accuracy_m: a.accuracy_m, recorded_at: a.recorded_at,
360
+ course_id: a.course_id, hole: a.hole, player_id: a.player_id, session_id: a.session_id,
361
+ device: a.device ? { model: a.device } : undefined, payload: Object.keys(payload).length ? payload : undefined };
354
362
  await apiPost('/api/v1/moments', moment);
355
363
  return { content: [{ type: 'text', text: `Submitted ${a.moment_type}.` }] };
356
364
  }
@@ -382,12 +390,39 @@ server.tool('get_my_shots', 'Read back your own contributed shots (by player or
382
390
  return { content: [{ type: 'text', text: `Error: ${e instanceof Error ? e.message : String(e)}` }] };
383
391
  }
384
392
  });
393
+ server.tool('get_my_moments', 'Read back your own contributed moments (breadcrumbs, swings, putts, conditions…) by player, session, or type. Requires OPENGOLFAPI_KEY.', {
394
+ player_id: z.string().optional().describe('Return moments for this pseudonymous player id'),
395
+ session_id: z.string().optional().describe('Return moments for this session id'),
396
+ type: z.string().optional().describe('Filter to one moment_type (e.g. swing, breadcrumb)'),
397
+ limit: z.number().optional().describe('Max moments to return'),
398
+ }, async (a) => {
399
+ if (!OPENGOLFAPI_KEY)
400
+ return { content: [{ type: 'text', text: 'Set OPENGOLFAPI_KEY to read your moments.' }] };
401
+ if (!a.player_id && !a.session_id)
402
+ return { content: [{ type: 'text', text: 'Provide player_id or session_id.' }] };
403
+ try {
404
+ const qs = new URLSearchParams();
405
+ if (a.player_id)
406
+ qs.set('player', a.player_id);
407
+ if (a.session_id)
408
+ qs.set('session', a.session_id);
409
+ if (a.type)
410
+ qs.set('type', a.type);
411
+ if (a.limit)
412
+ qs.set('limit', String(a.limit));
413
+ const data = await apiGet(`/api/v1/moments?${qs.toString()}`);
414
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
415
+ }
416
+ catch (e) {
417
+ return { content: [{ type: 'text', text: `Error: ${e instanceof Error ? e.message : String(e)}` }] };
418
+ }
419
+ });
385
420
  // ── Start ──
386
421
  async function main() {
387
422
  // Greet developers in stderr — visible in Claude Desktop / Cursor MCP logs.
388
423
  // Helps anyone debugging or evaluating the server know how to reach us.
389
- console.error('OpenGolfAPI MCP server — 14,708 US golf courses, ODbL.');
390
- console.error('Building something? We want to hear about it: hello@opengolfapi.org');
424
+ console.error('OpenGolfAPI MCP server — 16,845 US golf courses, ODbL.');
425
+ console.error('Building something? We want to hear about it: info@opengolfapi.org');
391
426
  console.error('Free key for higher rate limits: https://courses.opengolfapi.org/api-keys');
392
427
  const transport = new StdioServerTransport();
393
428
  await server.connect(transport);
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@opengolfapi/mcp-server",
3
- "version": "2.3.2",
4
- "description": "Open MCP server for AI agents to query the OpenGolfAPI dataset (14,708 US golf courses, ODbL)",
3
+ "version": "2.3.4",
4
+ "description": "Open MCP server for AI agents: every US golf course (16,845, ODbL) search, scorecards, tees, weather, nearby — plus contribute shots & moments to the open OpenShot standard.",
5
+ "mcpName": "io.github.opengolfapi/mcp-server",
5
6
  "type": "module",
6
7
  "bin": {
7
8
  "opengolfapi-mcp": "dist/index.js"