horizon-mcp 0.0.0-development

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 (99) hide show
  1. package/README.md +138 -0
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +7 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/prompts/debug-connection.d.ts +3 -0
  7. package/dist/prompts/debug-connection.d.ts.map +1 -0
  8. package/dist/prompts/debug-connection.js +17 -0
  9. package/dist/prompts/debug-connection.js.map +1 -0
  10. package/dist/prompts/explain-feature.d.ts +3 -0
  11. package/dist/prompts/explain-feature.d.ts.map +1 -0
  12. package/dist/prompts/explain-feature.js +32 -0
  13. package/dist/prompts/explain-feature.js.map +1 -0
  14. package/dist/prompts/index.d.ts +6 -0
  15. package/dist/prompts/index.d.ts.map +1 -0
  16. package/dist/prompts/index.js +14 -0
  17. package/dist/prompts/index.js.map +1 -0
  18. package/dist/prompts/integrate-feature.d.ts +3 -0
  19. package/dist/prompts/integrate-feature.d.ts.map +1 -0
  20. package/dist/prompts/integrate-feature.js +35 -0
  21. package/dist/prompts/integrate-feature.js.map +1 -0
  22. package/dist/prompts/setup-auth.d.ts +3 -0
  23. package/dist/prompts/setup-auth.d.ts.map +1 -0
  24. package/dist/prompts/setup-auth.js +26 -0
  25. package/dist/prompts/setup-auth.js.map +1 -0
  26. package/dist/resources/index.d.ts +6 -0
  27. package/dist/resources/index.d.ts.map +1 -0
  28. package/dist/resources/index.js +208 -0
  29. package/dist/resources/index.js.map +1 -0
  30. package/dist/server.d.ts +3 -0
  31. package/dist/server.d.ts.map +1 -0
  32. package/dist/server.js +15 -0
  33. package/dist/server.js.map +1 -0
  34. package/dist/tools/__tests__/api-client.test.d.ts +2 -0
  35. package/dist/tools/__tests__/api-client.test.d.ts.map +1 -0
  36. package/dist/tools/__tests__/api-client.test.js +156 -0
  37. package/dist/tools/__tests__/api-client.test.js.map +1 -0
  38. package/dist/tools/api-client.d.ts +25 -0
  39. package/dist/tools/api-client.d.ts.map +1 -0
  40. package/dist/tools/api-client.js +78 -0
  41. package/dist/tools/api-client.js.map +1 -0
  42. package/dist/tools/auth.d.ts +3 -0
  43. package/dist/tools/auth.d.ts.map +1 -0
  44. package/dist/tools/auth.js +123 -0
  45. package/dist/tools/auth.js.map +1 -0
  46. package/dist/tools/cloud-save.d.ts +3 -0
  47. package/dist/tools/cloud-save.d.ts.map +1 -0
  48. package/dist/tools/cloud-save.js +50 -0
  49. package/dist/tools/cloud-save.js.map +1 -0
  50. package/dist/tools/connection.d.ts +3 -0
  51. package/dist/tools/connection.d.ts.map +1 -0
  52. package/dist/tools/connection.js +20 -0
  53. package/dist/tools/connection.js.map +1 -0
  54. package/dist/tools/feedback.d.ts +3 -0
  55. package/dist/tools/feedback.d.ts.map +1 -0
  56. package/dist/tools/feedback.js +36 -0
  57. package/dist/tools/feedback.js.map +1 -0
  58. package/dist/tools/gift-codes.d.ts +3 -0
  59. package/dist/tools/gift-codes.d.ts.map +1 -0
  60. package/dist/tools/gift-codes.js +52 -0
  61. package/dist/tools/gift-codes.js.map +1 -0
  62. package/dist/tools/index.d.ts +6 -0
  63. package/dist/tools/index.d.ts.map +1 -0
  64. package/dist/tools/index.js +24 -0
  65. package/dist/tools/index.js.map +1 -0
  66. package/dist/tools/leaderboard.d.ts +3 -0
  67. package/dist/tools/leaderboard.d.ts.map +1 -0
  68. package/dist/tools/leaderboard.js +96 -0
  69. package/dist/tools/leaderboard.js.map +1 -0
  70. package/dist/tools/news.d.ts +3 -0
  71. package/dist/tools/news.d.ts.map +1 -0
  72. package/dist/tools/news.js +29 -0
  73. package/dist/tools/news.js.map +1 -0
  74. package/dist/tools/remote-config.d.ts +3 -0
  75. package/dist/tools/remote-config.d.ts.map +1 -0
  76. package/dist/tools/remote-config.js +42 -0
  77. package/dist/tools/remote-config.js.map +1 -0
  78. package/dist/tools/tool-helpers.d.ts +24 -0
  79. package/dist/tools/tool-helpers.d.ts.map +1 -0
  80. package/dist/tools/tool-helpers.js +54 -0
  81. package/dist/tools/tool-helpers.js.map +1 -0
  82. package/dist/tools/user-logs.d.ts +3 -0
  83. package/dist/tools/user-logs.d.ts.map +1 -0
  84. package/dist/tools/user-logs.js +30 -0
  85. package/dist/tools/user-logs.js.map +1 -0
  86. package/package.json +52 -0
  87. package/src/resources/api/app-api.md +495 -0
  88. package/src/resources/docs/auth.md +280 -0
  89. package/src/resources/docs/cloud-save.md +180 -0
  90. package/src/resources/docs/feedback.md +126 -0
  91. package/src/resources/docs/gift-codes.md +153 -0
  92. package/src/resources/docs/leaderboard.md +201 -0
  93. package/src/resources/docs/news.md +114 -0
  94. package/src/resources/docs/overview.md +80 -0
  95. package/src/resources/docs/remote-config.md +149 -0
  96. package/src/resources/docs/user-logs.md +144 -0
  97. package/src/resources/quickstart/godot.md +224 -0
  98. package/src/resources/quickstart/unity.md +317 -0
  99. package/src/resources/quickstart/unreal.md +390 -0
@@ -0,0 +1,390 @@
1
+ # Unreal Engine Quickstart Guide
2
+
3
+ ## Overview
4
+
5
+ There is **no official horizOn SDK for Unreal Engine**. Instead, you use the REST API directly via HTTP requests. This guide shows how to integrate horizOn using either:
6
+
7
+ - **VaRest Plugin** — Marketplace plugin for Blueprint-friendly HTTP requests
8
+ - **FHttpModule** — Unreal's built-in C++ HTTP module
9
+
10
+ ## Requirements
11
+
12
+ - **Unreal Engine 5.x**
13
+ - horizOn API key (get one at [horizon.pm](https://horizon.pm))
14
+ - HTTP request capability (VaRest plugin or FHttpModule)
15
+
16
+ ## API Configuration
17
+
18
+ All requests use these common settings:
19
+
20
+ | Setting | Value |
21
+ |---------|-------|
22
+ | Base URL | `https://horizon.pm` |
23
+ | API Key Header | `X-API-Key: YOUR_API_KEY` |
24
+ | Content Type | `Content-Type: application/json` |
25
+ | Rate Limit | 10 requests/minute per client |
26
+
27
+ ## Option A: VaRest Plugin (Blueprint-Friendly)
28
+
29
+ Install VaRest from the Unreal Marketplace, then use it in Blueprints or C++.
30
+
31
+ ### C++ Setup with VaRest
32
+
33
+ ```cpp
34
+ // MyHorizonManager.h
35
+ #pragma once
36
+ #include "CoreMinimal.h"
37
+ #include "VaRestSubsystem.h"
38
+
39
+ UCLASS()
40
+ class UMyHorizonManager : public UObject
41
+ {
42
+ GENERATED_BODY()
43
+
44
+ public:
45
+ void SetApiKey(const FString& InApiKey) { ApiKey = InApiKey; }
46
+
47
+ void SignUpAnonymous(const FString& Username);
48
+ void SubmitScore(const FString& UserId, int64 Score);
49
+ void GetRemoteConfig(const FString& Key);
50
+
51
+ private:
52
+ FString BaseUrl = TEXT("https://horizon.pm");
53
+ FString ApiKey;
54
+
55
+ UVaRestJsonObject* CreateRequestWithHeaders();
56
+ };
57
+ ```
58
+
59
+ ## Option B: FHttpModule (Built-in C++)
60
+
61
+ No plugins required. Uses Unreal's native HTTP module.
62
+
63
+ ### Base HTTP Helper
64
+
65
+ ```cpp
66
+ // HorizonAPI.h
67
+ #pragma once
68
+ #include "CoreMinimal.h"
69
+ #include "Http.h"
70
+ #include "Json.h"
71
+
72
+ class FHorizonAPI
73
+ {
74
+ public:
75
+ static FString BaseUrl;
76
+ static FString ApiKey;
77
+
78
+ // POST request helper
79
+ static void Post(
80
+ const FString& Endpoint,
81
+ const TSharedRef<FJsonObject>& Body,
82
+ TFunction<void(bool bSuccess, TSharedPtr<FJsonObject> Response)> Callback)
83
+ {
84
+ FHttpModule& Http = FHttpModule::Get();
85
+ TSharedRef<IHttpRequest> Request = Http.CreateRequest();
86
+
87
+ Request->SetURL(BaseUrl + Endpoint);
88
+ Request->SetVerb(TEXT("POST"));
89
+ Request->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
90
+ Request->SetHeader(TEXT("X-API-Key"), ApiKey);
91
+
92
+ FString BodyString;
93
+ TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&BodyString);
94
+ FJsonSerializer::Serialize(Body, Writer);
95
+ Request->SetContentAsString(BodyString);
96
+
97
+ Request->OnProcessRequestComplete().BindLambda(
98
+ [Callback](FHttpRequestPtr Req, FHttpResponsePtr Resp, bool bConnected)
99
+ {
100
+ if (bConnected && Resp.IsValid() && Resp->GetResponseCode() == 200)
101
+ {
102
+ TSharedPtr<FJsonObject> JsonResponse;
103
+ TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Resp->GetContentAsString());
104
+ FJsonSerializer::Deserialize(Reader, JsonResponse);
105
+ Callback(true, JsonResponse);
106
+ }
107
+ else
108
+ {
109
+ Callback(false, nullptr);
110
+ }
111
+ });
112
+
113
+ Request->ProcessRequest();
114
+ }
115
+
116
+ // GET request helper
117
+ static void Get(
118
+ const FString& Endpoint,
119
+ TFunction<void(bool bSuccess, TSharedPtr<FJsonObject> Response)> Callback)
120
+ {
121
+ FHttpModule& Http = FHttpModule::Get();
122
+ TSharedRef<IHttpRequest> Request = Http.CreateRequest();
123
+
124
+ Request->SetURL(BaseUrl + Endpoint);
125
+ Request->SetVerb(TEXT("GET"));
126
+ Request->SetHeader(TEXT("X-API-Key"), ApiKey);
127
+
128
+ Request->OnProcessRequestComplete().BindLambda(
129
+ [Callback](FHttpRequestPtr Req, FHttpResponsePtr Resp, bool bConnected)
130
+ {
131
+ if (bConnected && Resp.IsValid() && Resp->GetResponseCode() == 200)
132
+ {
133
+ TSharedPtr<FJsonObject> JsonResponse;
134
+ TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Resp->GetContentAsString());
135
+ FJsonSerializer::Deserialize(Reader, JsonResponse);
136
+ Callback(true, JsonResponse);
137
+ }
138
+ else
139
+ {
140
+ Callback(false, nullptr);
141
+ }
142
+ });
143
+
144
+ Request->ProcessRequest();
145
+ }
146
+ };
147
+
148
+ // HorizonAPI.cpp
149
+ FString FHorizonAPI::BaseUrl = TEXT("https://horizon.pm");
150
+ FString FHorizonAPI::ApiKey = TEXT("");
151
+ ```
152
+
153
+ ## Feature Examples
154
+
155
+ ### Anonymous Signup
156
+
157
+ ```cpp
158
+ void SignUpAnonymous(const FString& Username)
159
+ {
160
+ TSharedRef<FJsonObject> Body = MakeShared<FJsonObject>();
161
+ Body->SetStringField(TEXT("type"), TEXT("ANONYMOUS"));
162
+ Body->SetStringField(TEXT("username"), Username);
163
+
164
+ // Generate a unique anonymous token (max 32 chars)
165
+ FString Token = FGuid::NewGuid().ToString(EGuidFormats::DigitsLower).Left(32);
166
+ Body->SetStringField(TEXT("anonymousToken"), Token);
167
+
168
+ FHorizonAPI::Post(TEXT("/api/v1/app/user-management/signup"), Body,
169
+ [](bool bSuccess, TSharedPtr<FJsonObject> Response)
170
+ {
171
+ if (bSuccess && Response.IsValid())
172
+ {
173
+ FString UserId = Response->GetStringField(TEXT("userId"));
174
+ FString Name = Response->GetStringField(TEXT("username"));
175
+ UE_LOG(LogTemp, Log, TEXT("Signed up: %s (%s)"), *Name, *UserId);
176
+ }
177
+ else
178
+ {
179
+ UE_LOG(LogTemp, Error, TEXT("Signup failed"));
180
+ }
181
+ });
182
+ }
183
+ ```
184
+
185
+ ### Email Sign-In
186
+
187
+ ```cpp
188
+ void SignInEmail(const FString& Email, const FString& Password)
189
+ {
190
+ TSharedRef<FJsonObject> Body = MakeShared<FJsonObject>();
191
+ Body->SetStringField(TEXT("type"), TEXT("EMAIL"));
192
+ Body->SetStringField(TEXT("email"), Email);
193
+ Body->SetStringField(TEXT("password"), Password);
194
+
195
+ FHorizonAPI::Post(TEXT("/api/v1/app/user-management/signin"), Body,
196
+ [](bool bSuccess, TSharedPtr<FJsonObject> Response)
197
+ {
198
+ if (bSuccess && Response.IsValid())
199
+ {
200
+ FString Status = Response->GetStringField(TEXT("authStatus"));
201
+ if (Status == TEXT("AUTHENTICATED"))
202
+ {
203
+ FString AccessToken = Response->GetStringField(TEXT("accessToken"));
204
+ UE_LOG(LogTemp, Log, TEXT("Signed in successfully"));
205
+ }
206
+ }
207
+ });
208
+ }
209
+ ```
210
+
211
+ ### Submit Leaderboard Score
212
+
213
+ ```cpp
214
+ void SubmitScore(const FString& UserId, int64 Score)
215
+ {
216
+ TSharedRef<FJsonObject> Body = MakeShared<FJsonObject>();
217
+ Body->SetStringField(TEXT("userId"), UserId);
218
+ Body->SetNumberField(TEXT("score"), Score);
219
+
220
+ FHorizonAPI::Post(TEXT("/api/v1/app/leaderboard/submit"), Body,
221
+ [Score](bool bSuccess, TSharedPtr<FJsonObject> Response)
222
+ {
223
+ if (bSuccess)
224
+ {
225
+ UE_LOG(LogTemp, Log, TEXT("Score submitted: %lld"), Score);
226
+ }
227
+ });
228
+ }
229
+ ```
230
+
231
+ ### Get Top Leaderboard
232
+
233
+ ```cpp
234
+ void GetTopLeaderboard(const FString& UserId, int32 Limit)
235
+ {
236
+ FString Endpoint = FString::Printf(
237
+ TEXT("/api/v1/app/leaderboard/top?userId=%s&limit=%d"),
238
+ *UserId, Limit);
239
+
240
+ FHorizonAPI::Get(Endpoint,
241
+ [](bool bSuccess, TSharedPtr<FJsonObject> Response)
242
+ {
243
+ if (bSuccess && Response.IsValid())
244
+ {
245
+ const TArray<TSharedPtr<FJsonValue>>* Entries;
246
+ if (Response->TryGetArrayField(TEXT("entries"), Entries))
247
+ {
248
+ for (const auto& Entry : *Entries)
249
+ {
250
+ auto Obj = Entry->AsObject();
251
+ int32 Position = Obj->GetIntegerField(TEXT("position"));
252
+ FString Username = Obj->GetStringField(TEXT("username"));
253
+ int64 Score = Obj->GetIntegerField(TEXT("score"));
254
+ UE_LOG(LogTemp, Log, TEXT("#%d %s: %lld"), Position, *Username, Score);
255
+ }
256
+ }
257
+ }
258
+ });
259
+ }
260
+ ```
261
+
262
+ ### Save and Load Cloud Data
263
+
264
+ ```cpp
265
+ void SaveCloudData(const FString& UserId, const FString& SaveData)
266
+ {
267
+ TSharedRef<FJsonObject> Body = MakeShared<FJsonObject>();
268
+ Body->SetStringField(TEXT("userId"), UserId);
269
+ Body->SetStringField(TEXT("saveData"), SaveData);
270
+
271
+ FHorizonAPI::Post(TEXT("/api/v1/app/cloud-save/save"), Body,
272
+ [](bool bSuccess, TSharedPtr<FJsonObject> Response)
273
+ {
274
+ if (bSuccess && Response.IsValid())
275
+ {
276
+ bool Success = Response->GetBoolField(TEXT("success"));
277
+ int32 Size = Response->GetIntegerField(TEXT("dataSizeBytes"));
278
+ UE_LOG(LogTemp, Log, TEXT("Saved: %d bytes"), Size);
279
+ }
280
+ });
281
+ }
282
+
283
+ void LoadCloudData(const FString& UserId)
284
+ {
285
+ TSharedRef<FJsonObject> Body = MakeShared<FJsonObject>();
286
+ Body->SetStringField(TEXT("userId"), UserId);
287
+
288
+ FHorizonAPI::Post(TEXT("/api/v1/app/cloud-save/load"), Body,
289
+ [](bool bSuccess, TSharedPtr<FJsonObject> Response)
290
+ {
291
+ if (bSuccess && Response.IsValid())
292
+ {
293
+ bool Found = Response->GetBoolField(TEXT("found"));
294
+ if (Found)
295
+ {
296
+ FString Data = Response->GetStringField(TEXT("saveData"));
297
+ UE_LOG(LogTemp, Log, TEXT("Loaded: %s"), *Data);
298
+ }
299
+ }
300
+ });
301
+ }
302
+ ```
303
+
304
+ ### Get Remote Config
305
+
306
+ ```cpp
307
+ void GetAllRemoteConfigs()
308
+ {
309
+ FHorizonAPI::Get(TEXT("/api/v1/app/remote-config/all"),
310
+ [](bool bSuccess, TSharedPtr<FJsonObject> Response)
311
+ {
312
+ if (bSuccess && Response.IsValid())
313
+ {
314
+ const TSharedPtr<FJsonObject>* Configs;
315
+ if (Response->TryGetObjectField(TEXT("configs"), Configs))
316
+ {
317
+ for (const auto& Pair : (*Configs)->Values)
318
+ {
319
+ UE_LOG(LogTemp, Log, TEXT("Config: %s = %s"),
320
+ *Pair.Key, *Pair.Value->AsString());
321
+ }
322
+ }
323
+ }
324
+ });
325
+ }
326
+ ```
327
+
328
+ ## REST Examples (cURL)
329
+
330
+ These cURL examples show the raw HTTP requests. Translate them to your preferred Unreal HTTP method.
331
+
332
+ ```bash
333
+ # Anonymous signup
334
+ curl -X POST https://horizon.pm/api/v1/app/user-management/signup \
335
+ -H "X-API-Key: YOUR_API_KEY" \
336
+ -H "Content-Type: application/json" \
337
+ -d '{"type": "ANONYMOUS", "username": "Player1", "anonymousToken": "unique32chartoken"}'
338
+
339
+ # Submit score
340
+ curl -X POST https://horizon.pm/api/v1/app/leaderboard/submit \
341
+ -H "X-API-Key: YOUR_API_KEY" \
342
+ -H "Content-Type: application/json" \
343
+ -d '{"userId": "user123", "score": 12500}'
344
+
345
+ # Get remote config
346
+ curl "https://horizon.pm/api/v1/app/remote-config/all" \
347
+ -H "X-API-Key: YOUR_API_KEY"
348
+
349
+ # Save cloud data
350
+ curl -X POST https://horizon.pm/api/v1/app/cloud-save/save \
351
+ -H "X-API-Key: YOUR_API_KEY" \
352
+ -H "Content-Type: application/json" \
353
+ -d '{"userId": "user123", "saveData": "{\"level\":5}"}'
354
+
355
+ # Load cloud data
356
+ curl -X POST https://horizon.pm/api/v1/app/cloud-save/load \
357
+ -H "X-API-Key: YOUR_API_KEY" \
358
+ -H "Content-Type: application/json" \
359
+ -d '{"userId": "user123"}'
360
+
361
+ # Get news
362
+ curl "https://horizon.pm/api/v1/app/news?limit=10&languageCode=en" \
363
+ -H "X-API-Key: YOUR_API_KEY"
364
+
365
+ # Redeem gift code
366
+ curl -X POST https://horizon.pm/api/v1/app/gift-codes/redeem \
367
+ -H "X-API-Key: YOUR_API_KEY" \
368
+ -H "Content-Type: application/json" \
369
+ -d '{"code": "ABCD-1234", "userId": "user123"}'
370
+
371
+ # Submit feedback
372
+ curl -X POST https://horizon.pm/api/v1/app/user-feedback/submit \
373
+ -H "X-API-Key: YOUR_API_KEY" \
374
+ -H "Content-Type: application/json" \
375
+ -d '{"title": "Bug Report", "message": "Description", "userId": "user123", "category": "BUG"}'
376
+
377
+ # Create user log
378
+ curl -X POST https://horizon.pm/api/v1/app/user-logs/create \
379
+ -H "X-API-Key: YOUR_API_KEY" \
380
+ -H "Content-Type: application/json" \
381
+ -d '{"message": "Level complete", "type": "INFO", "userId": "user123"}'
382
+ ```
383
+
384
+ ## Best Practices for Unreal
385
+
386
+ - **Cache API key** — Store the API key in a config file or game settings, not hardcoded.
387
+ - **Handle async properly** — All HTTP requests are asynchronous. Use delegates or lambdas for responses.
388
+ - **Rate limit** — 10 requests/minute. Cache responses and batch operations.
389
+ - **Error handling** — Always check HTTP status codes and handle 429 (rate limit) with exponential backoff.
390
+ - **Store session tokens** — After sign-in, cache the `accessToken` and `userId` for subsequent requests.