horizon-mcp 1.3.1 → 1.4.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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"leaderboard.d.ts","sourceRoot":"","sources":["../../src/tools/leaderboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"leaderboard.d.ts","sourceRoot":"","sources":["../../src/tools/leaderboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAqCpE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAgIhE"}
|
|
@@ -1,24 +1,55 @@
|
|
|
1
1
|
import { z } from "zod/v4";
|
|
2
2
|
import { createApiClientFromEnv } from "./api-client.js";
|
|
3
3
|
import { noApiKeyResponse, errorResponse, jsonResponse } from "./tool-helpers.js";
|
|
4
|
+
/**
|
|
5
|
+
* Slug constraint mirrors the server-side validator on
|
|
6
|
+
* `SubmitScoreRequest.leaderboardKey` and `Leaderboard.key`.
|
|
7
|
+
*/
|
|
8
|
+
const leaderboardKeySchema = z
|
|
9
|
+
.string()
|
|
10
|
+
.min(1)
|
|
11
|
+
.max(64)
|
|
12
|
+
.regex(/^[a-z0-9_-]+$/, "Lowercase alphanumeric with - or _")
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Leaderboard key — selects a named board on the API key. Omit to use the default board.");
|
|
15
|
+
function topPath(leaderboardKey) {
|
|
16
|
+
return leaderboardKey
|
|
17
|
+
? `/api/v1/app/leaderboards/${encodeURIComponent(leaderboardKey)}/top`
|
|
18
|
+
: "/api/v1/app/leaderboard/top";
|
|
19
|
+
}
|
|
20
|
+
function rankPath(leaderboardKey) {
|
|
21
|
+
return leaderboardKey
|
|
22
|
+
? `/api/v1/app/leaderboards/${encodeURIComponent(leaderboardKey)}/rank`
|
|
23
|
+
: "/api/v1/app/leaderboard/rank";
|
|
24
|
+
}
|
|
25
|
+
function aroundPath(leaderboardKey) {
|
|
26
|
+
return leaderboardKey
|
|
27
|
+
? `/api/v1/app/leaderboards/${encodeURIComponent(leaderboardKey)}/around`
|
|
28
|
+
: "/api/v1/app/leaderboard/around";
|
|
29
|
+
}
|
|
4
30
|
export function registerLeaderboardTools(server) {
|
|
5
31
|
// --- Submit score ---
|
|
6
32
|
server.registerTool("horizon_submit_score", {
|
|
7
33
|
title: "Submit Score",
|
|
8
|
-
description: "Submits a score to
|
|
34
|
+
description: "Submits a score to a horizOn leaderboard for a given user. Pass leaderboardKey to target a specific board; omit it for the default board.",
|
|
9
35
|
inputSchema: {
|
|
10
36
|
userId: z.string().uuid().describe("User ID (UUID)"),
|
|
11
|
-
score: z
|
|
37
|
+
score: z
|
|
38
|
+
.number()
|
|
39
|
+
.int()
|
|
40
|
+
.min(0)
|
|
41
|
+
.describe("Score to submit (non-negative integer)"),
|
|
42
|
+
leaderboardKey: leaderboardKeySchema,
|
|
12
43
|
},
|
|
13
|
-
}, async ({ userId, score }) => {
|
|
44
|
+
}, async ({ userId, score, leaderboardKey }) => {
|
|
14
45
|
const client = createApiClientFromEnv();
|
|
15
46
|
if (!client)
|
|
16
47
|
return noApiKeyResponse();
|
|
17
48
|
try {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
});
|
|
49
|
+
const path = leaderboardKey
|
|
50
|
+
? `/api/v1/app/leaderboards/${encodeURIComponent(leaderboardKey)}/submit`
|
|
51
|
+
: "/api/v1/app/leaderboard/submit";
|
|
52
|
+
const result = await client.post(path, { userId, score });
|
|
22
53
|
return jsonResponse(result);
|
|
23
54
|
}
|
|
24
55
|
catch (error) {
|
|
@@ -28,17 +59,24 @@ export function registerLeaderboardTools(server) {
|
|
|
28
59
|
// --- Get leaderboard top ---
|
|
29
60
|
server.registerTool("horizon_get_leaderboard_top", {
|
|
30
61
|
title: "Get Leaderboard Top",
|
|
31
|
-
description: "Gets the top entries from
|
|
62
|
+
description: "Gets the top entries from a horizOn leaderboard. Pass leaderboardKey to target a specific board.",
|
|
32
63
|
inputSchema: {
|
|
33
64
|
userId: z.string().uuid().describe("User ID (UUID)"),
|
|
34
|
-
limit: z
|
|
65
|
+
limit: z
|
|
66
|
+
.number()
|
|
67
|
+
.int()
|
|
68
|
+
.min(1)
|
|
69
|
+
.max(100)
|
|
70
|
+
.default(10)
|
|
71
|
+
.describe("Number of top entries to return (1-100, default 10)"),
|
|
72
|
+
leaderboardKey: leaderboardKeySchema,
|
|
35
73
|
},
|
|
36
|
-
}, async ({ userId, limit }) => {
|
|
74
|
+
}, async ({ userId, limit, leaderboardKey }) => {
|
|
37
75
|
const client = createApiClientFromEnv();
|
|
38
76
|
if (!client)
|
|
39
77
|
return noApiKeyResponse();
|
|
40
78
|
try {
|
|
41
|
-
const result = await client.get(
|
|
79
|
+
const result = await client.get(topPath(leaderboardKey), {
|
|
42
80
|
userId,
|
|
43
81
|
limit: String(limit),
|
|
44
82
|
});
|
|
@@ -51,18 +89,17 @@ export function registerLeaderboardTools(server) {
|
|
|
51
89
|
// --- Get user rank ---
|
|
52
90
|
server.registerTool("horizon_get_user_rank", {
|
|
53
91
|
title: "Get User Rank",
|
|
54
|
-
description: "Gets the rank of a specific user on
|
|
92
|
+
description: "Gets the rank of a specific user on a horizOn leaderboard. Pass leaderboardKey to target a specific board.",
|
|
55
93
|
inputSchema: {
|
|
56
94
|
userId: z.string().uuid().describe("User ID (UUID)"),
|
|
95
|
+
leaderboardKey: leaderboardKeySchema,
|
|
57
96
|
},
|
|
58
|
-
}, async ({ userId }) => {
|
|
97
|
+
}, async ({ userId, leaderboardKey }) => {
|
|
59
98
|
const client = createApiClientFromEnv();
|
|
60
99
|
if (!client)
|
|
61
100
|
return noApiKeyResponse();
|
|
62
101
|
try {
|
|
63
|
-
const result = await client.get(
|
|
64
|
-
userId,
|
|
65
|
-
});
|
|
102
|
+
const result = await client.get(rankPath(leaderboardKey), { userId });
|
|
66
103
|
return jsonResponse(result);
|
|
67
104
|
}
|
|
68
105
|
catch (error) {
|
|
@@ -72,17 +109,24 @@ export function registerLeaderboardTools(server) {
|
|
|
72
109
|
// --- Get leaderboard around user ---
|
|
73
110
|
server.registerTool("horizon_get_leaderboard_around", {
|
|
74
111
|
title: "Get Leaderboard Around User",
|
|
75
|
-
description: "Gets leaderboard entries around a specific user's position on horizOn.",
|
|
112
|
+
description: "Gets leaderboard entries around a specific user's position on a horizOn leaderboard. Pass leaderboardKey to target a specific board.",
|
|
76
113
|
inputSchema: {
|
|
77
114
|
userId: z.string().uuid().describe("User ID (UUID)"),
|
|
78
|
-
range: z
|
|
115
|
+
range: z
|
|
116
|
+
.number()
|
|
117
|
+
.int()
|
|
118
|
+
.min(1)
|
|
119
|
+
.max(50)
|
|
120
|
+
.default(10)
|
|
121
|
+
.describe("Number of entries around the user (1-50, default 10)"),
|
|
122
|
+
leaderboardKey: leaderboardKeySchema,
|
|
79
123
|
},
|
|
80
|
-
}, async ({ userId, range }) => {
|
|
124
|
+
}, async ({ userId, range, leaderboardKey }) => {
|
|
81
125
|
const client = createApiClientFromEnv();
|
|
82
126
|
if (!client)
|
|
83
127
|
return noApiKeyResponse();
|
|
84
128
|
try {
|
|
85
|
-
const result = await client.get(
|
|
129
|
+
const result = await client.get(aroundPath(leaderboardKey), {
|
|
86
130
|
userId,
|
|
87
131
|
range: String(range),
|
|
88
132
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"leaderboard.js","sourceRoot":"","sources":["../../src/tools/leaderboard.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAElF,MAAM,UAAU,wBAAwB,CAAC,MAAiB;IACxD,uBAAuB;IACvB,MAAM,CAAC,YAAY,
|
|
1
|
+
{"version":3,"file":"leaderboard.js","sourceRoot":"","sources":["../../src/tools/leaderboard.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "horizon-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "MCP server for horizOn Backend-as-a-Service — documentation, live API tools, and workflow prompts for Godot, Unity, and Unreal Engine integration.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|