ping-mcp-server 0.1.18 → 0.1.19

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 (3) hide show
  1. package/dist/index.js +166 -254
  2. package/package.json +1 -1
  3. package/src/index.ts +130 -307
package/dist/index.js CHANGED
@@ -493,6 +493,15 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
493
493
  required: []
494
494
  }
495
495
  },
496
+ {
497
+ name: "ping_settings",
498
+ description: "Open Ping settings page in browser to manage connected accounts (Are.na, Spotify, etc.). Use this when the user wants to connect additional accounts or manage their profile.",
499
+ inputSchema: {
500
+ type: "object",
501
+ properties: {},
502
+ required: []
503
+ }
504
+ },
496
505
  // ────────────────────────────────────────────────────────
497
506
  // LEGACY: SET WALLET (for users without GitHub auth)
498
507
  // ────────────────────────────────────────────────────────
@@ -581,21 +590,6 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
581
590
  required: []
582
591
  }
583
592
  },
584
- {
585
- name: "ping_validate_batch",
586
- description: "Validate if a batch of questions is still available to answer before showing to user. Checks if questions are active, not exhausted (maxResponses reached), and not already answered. Returns available questions with full data + list of exhausted question IDs. Use this before presenting questions to ensure they can actually be answered.",
587
- inputSchema: {
588
- type: "object",
589
- properties: {
590
- questionIds: {
591
- type: "array",
592
- items: { type: "string" },
593
- description: 'Array of question IDs to validate (e.g., ["q1", "q2", "q3", "q4"])'
594
- }
595
- },
596
- required: ["questionIds"]
597
- }
598
- },
599
593
  {
600
594
  name: "ping_claim_reward",
601
595
  description: 'Claim pending Ping earnings and send them to your crypto wallet on Base. TRIGGERS: "claim my ping", "withdraw from ping", "cash out", "get my money", "claim rewards". Use when the user wants to withdraw, cash out, or claim their rewards. Transfers USDC to their wallet instantly. Works with GitHub login (ping_login) or legacy wallet (ping_set_wallet).',
@@ -715,12 +709,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
715
709
  return {
716
710
  content: [{
717
711
  type: "text",
718
- text: JSON.stringify({
719
- success: true,
720
- alreadyLoggedIn: true,
721
- handle: `@${existingAuth.handle}`,
722
- message: `You're already logged in as @${existingAuth.handle}. Use ping_logout to switch accounts.`
723
- }, null, 2)
712
+ text: `\u2705 Already logged in as @${existingAuth.handle}
713
+
714
+ Use ping_logout to switch accounts.`
724
715
  }]
725
716
  };
726
717
  }
@@ -733,11 +724,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
733
724
  return {
734
725
  content: [{
735
726
  type: "text",
736
- text: JSON.stringify({
737
- success: false,
738
- error: "Failed to open browser. Please visit this URL manually:",
739
- loginUrl
740
- }, null, 2)
727
+ text: `\u274C Failed to open browser
728
+
729
+ Please visit this URL manually:
730
+ ${loginUrl}`
741
731
  }]
742
732
  };
743
733
  }
@@ -747,22 +737,17 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
747
737
  return {
748
738
  content: [{
749
739
  type: "text",
750
- text: JSON.stringify({
751
- success: true,
752
- handle: `@${authData.handle}`,
753
- message: `\u2713 Logged in as @${authData.handle}! You can now answer questions and earn money.`,
754
- nextStep: 'Try "show me questions I can answer" or "check my ping balance"'
755
- }, null, 2)
740
+ text: `\u2705 Logged in as @${authData.handle}!
741
+
742
+ You can now answer questions and earn money.
743
+ Try "show me questions I can answer" or "check my ping balance"`
756
744
  }]
757
745
  };
758
746
  } catch (err) {
759
747
  return {
760
748
  content: [{
761
749
  type: "text",
762
- text: JSON.stringify({
763
- success: false,
764
- error: err instanceof Error ? err.message : "Login failed"
765
- })
750
+ text: `\u274C ${err instanceof Error ? err.message : "Login failed"}`
766
751
  }]
767
752
  };
768
753
  }
@@ -776,10 +761,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
776
761
  return {
777
762
  content: [{
778
763
  type: "text",
779
- text: JSON.stringify({
780
- success: true,
781
- message: "You weren't logged in. No action needed."
782
- })
764
+ text: `\u2139\uFE0F You weren't logged in. No action needed.`
783
765
  }]
784
766
  };
785
767
  }
@@ -788,12 +770,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
788
770
  return {
789
771
  content: [{
790
772
  type: "text",
791
- text: JSON.stringify({
792
- success: true,
793
- previousHandle: `@${handle}`,
794
- message: `\u2713 Logged out from @${handle}. Your local auth has been cleared.`,
795
- nextStep: "Use ping_login to sign in with a different account."
796
- }, null, 2)
773
+ text: `\u2705 Logged out from @${handle}
774
+
775
+ Use ping_login to sign in with a different account.`
797
776
  }]
798
777
  };
799
778
  }
@@ -841,10 +820,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
841
820
  // ────────────────────────────────────────────────────────
842
821
  case "ping_welcome": {
843
822
  const auth = getAuth();
844
- const MCP_VERSION = "0.1.18";
823
+ const MCP_VERSION = "0.1.19";
845
824
  let userLine = "\u274C Not logged in";
825
+ let arenaBadge = "";
846
826
  if (auth) {
847
827
  userLine = `@${auth.handle}`;
828
+ try {
829
+ const connections = await apiRequest("/users/me/connections");
830
+ if (connections.arena) {
831
+ arenaBadge = " \u2022 \u{1F3A8} Are.na";
832
+ }
833
+ } catch {
834
+ }
848
835
  }
849
836
  let questionsAvailable = 0;
850
837
  let answersToday = 0;
@@ -869,7 +856,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
869
856
  const banner = `\u2588\u2580\u2588 \u2588 \u2588\u2584\u2591\u2588 \u2588\u2580\u2580 v${MCP_VERSION}${updateBadge}
870
857
  \u2588\u2580\u2580 \u2588 \u2588\u2591\u2580\u2588 \u2588\u2584\u2588 \u{1F4B0} Get paid to share your knowledge
871
858
  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
872
- \u{1F464} ${userLine} \u2022 \u{1F4EC} ${questionsAvailable} Qs \u2022 \u{1F3C6} ${answersText} \u2022 \u{1F4B5} ${claimedToday}${loginHint}`;
859
+ \u{1F464} ${userLine}${arenaBadge} \u2022 \u{1F4EC} ${questionsAvailable} Qs \u2022 \u{1F3C6} ${answersText} \u2022 \u{1F4B5} ${claimedToday}${loginHint}`;
873
860
  return {
874
861
  content: [{
875
862
  type: "text",
@@ -878,6 +865,39 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
878
865
  };
879
866
  }
880
867
  // ────────────────────────────────────────────────────────
868
+ // SETTINGS (Open settings page in browser)
869
+ // ────────────────────────────────────────────────────────
870
+ case "ping_settings": {
871
+ const auth = getAuth();
872
+ if (!auth) {
873
+ return {
874
+ content: [{
875
+ type: "text",
876
+ text: "\u274C Please login first with ping_login"
877
+ }]
878
+ };
879
+ }
880
+ const settingsUrl = `${API_BASE_URL}/settings?token=${auth.githubId}`;
881
+ try {
882
+ await openBrowser(settingsUrl);
883
+ } catch {
884
+ return {
885
+ content: [{
886
+ type: "text",
887
+ text: `\u2699\uFE0F Open this URL to manage settings:
888
+
889
+ ${settingsUrl}`
890
+ }]
891
+ };
892
+ }
893
+ return {
894
+ content: [{
895
+ type: "text",
896
+ text: "\u2699\uFE0F Opening settings in browser...\n\nConnect accounts like Are.na to enhance your expert profile."
897
+ }]
898
+ };
899
+ }
900
+ // ────────────────────────────────────────────────────────
881
901
  // SET WALLET (Legacy)
882
902
  // ────────────────────────────────────────────────────────
883
903
  case "ping_set_wallet": {
@@ -886,11 +906,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
886
906
  return {
887
907
  content: [{
888
908
  type: "text",
889
- text: JSON.stringify({
890
- success: false,
891
- error: "Missing wallet address.",
892
- hint: "Please provide your Ethereum wallet address (starts with 0x)."
893
- }, null, 2)
909
+ text: `\u274C Missing wallet address
910
+
911
+ Please provide your Ethereum wallet address (starts with 0x).`
894
912
  }]
895
913
  };
896
914
  }
@@ -898,11 +916,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
898
916
  return {
899
917
  content: [{
900
918
  type: "text",
901
- text: JSON.stringify({
902
- success: false,
903
- error: "Invalid wallet address format.",
904
- hint: "Wallet address must be 42 characters starting with 0x (e.g., 0x1234...abcd). Check for typos."
905
- }, null, 2)
919
+ text: `\u274C Invalid wallet address format
920
+
921
+ Wallet address must be 42 characters starting with 0x (e.g., 0x1234...abcd).`
906
922
  }]
907
923
  };
908
924
  }
@@ -910,12 +926,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
910
926
  return {
911
927
  content: [{
912
928
  type: "text",
913
- text: JSON.stringify({
914
- success: true,
915
- walletAddress,
916
- message: `\u2713 Wallet set to ${walletAddress}. You can now check earnings, answer questions, and claim rewards!`,
917
- nextStep: 'Try "show me questions I can answer" or "check my ping earnings"'
918
- }, null, 2)
929
+ text: `\u2705 Wallet set to ${walletAddress}
930
+
931
+ You can now check earnings, answer questions, and claim rewards!`
919
932
  }]
920
933
  };
921
934
  }
@@ -980,11 +993,9 @@ Wallet: ${data.walletAddress}`
980
993
  return {
981
994
  content: [{
982
995
  type: "text",
983
- text: JSON.stringify({
984
- success: false,
985
- error: "Missing question ID.",
986
- hint: "Use ping_answer_flow to see available questions and answer them."
987
- }, null, 2)
996
+ text: `\u274C Missing question ID
997
+
998
+ Use ping_answer_flow to see available questions.`
988
999
  }]
989
1000
  };
990
1001
  }
@@ -992,11 +1003,9 @@ Wallet: ${data.walletAddress}`
992
1003
  return {
993
1004
  content: [{
994
1005
  type: "text",
995
- text: JSON.stringify({
996
- success: false,
997
- error: "Answer cannot be empty.",
998
- hint: "Please provide a thoughtful response to the question."
999
- }, null, 2)
1006
+ text: `\u274C Answer cannot be empty
1007
+
1008
+ Please provide a thoughtful response.`
1000
1009
  }]
1001
1010
  };
1002
1011
  }
@@ -1006,11 +1015,9 @@ Wallet: ${data.walletAddress}`
1006
1015
  return {
1007
1016
  content: [{
1008
1017
  type: "text",
1009
- text: JSON.stringify({
1010
- success: false,
1011
- error: "Not logged in.",
1012
- hint: "Use ping_login to connect your GitHub account before answering questions."
1013
- }, null, 2)
1018
+ text: `\u274C Not logged in
1019
+
1020
+ Use ping_login to connect your GitHub account first.`
1014
1021
  }]
1015
1022
  };
1016
1023
  }
@@ -1030,14 +1037,11 @@ Wallet: ${data.walletAddress}`
1030
1037
  return {
1031
1038
  content: [{
1032
1039
  type: "text",
1033
- text: JSON.stringify({
1034
- success: false,
1035
- status: "rejected",
1036
- aiScore: data.aiScore,
1037
- reason: data.reason,
1038
- tip: data.tip || "Try providing a more thoughtful, detailed response.",
1039
- message: data.reason || "Answer was rejected by AI review."
1040
- })
1040
+ text: `\u274C Answer rejected${data.aiScore ? ` (score: ${data.aiScore})` : ""}
1041
+
1042
+ ${data.reason || "Did not meet quality threshold."}
1043
+
1044
+ \u{1F4A1} ${data.tip || "Try providing a more thoughtful, detailed response."}`
1041
1045
  }]
1042
1046
  };
1043
1047
  }
@@ -1045,43 +1049,29 @@ Wallet: ${data.walletAddress}`
1045
1049
  return {
1046
1050
  content: [{
1047
1051
  type: "text",
1048
- text: JSON.stringify({
1049
- success: false,
1050
- error: "question_exhausted",
1051
- message: data.message || "This question is no longer accepting answers (maxResponses reached).",
1052
- hint: "Skip this question and continue with others in your batch."
1053
- })
1052
+ text: `\u26A0\uFE0F Question no longer available
1053
+
1054
+ This question has reached its maximum responses. Skip it and continue with others.`
1054
1055
  }]
1055
1056
  };
1056
1057
  }
1057
1058
  return {
1058
1059
  content: [{
1059
1060
  type: "text",
1060
- text: JSON.stringify({
1061
- success: false,
1062
- error: data.error || "Failed to submit answer"
1063
- })
1061
+ text: `\u274C ${data.error || "Failed to submit answer"}`
1064
1062
  }]
1065
1063
  };
1066
1064
  }
1067
- const response = {
1068
- success: true,
1069
- status: data.status || "approved",
1070
- earned: data.earned,
1071
- aiScore: data.aiScore,
1072
- message: data.message || `Answer approved! You earned ${data.earned}.`
1073
- };
1065
+ let successText = `\u2705 Answer approved! You earned ${data.earned}`;
1074
1066
  if (data.txHash) {
1075
- response.transaction = {
1076
- txHash: data.txHash,
1077
- explorerUrl: data.explorerUrl || `https://basescan.org/tx/${data.txHash}`
1078
- };
1067
+ successText += `
1068
+
1069
+ \u{1F517} Transaction: ${data.explorerUrl || `https://basescan.org/tx/${data.txHash}`}`;
1079
1070
  }
1080
- response.nextStep = "Your earnings are in your Ping balance. Keep answering to earn more!";
1081
1071
  return {
1082
1072
  content: [{
1083
1073
  type: "text",
1084
- text: JSON.stringify(response, null, 2)
1074
+ text: successText
1085
1075
  }]
1086
1076
  };
1087
1077
  }
@@ -1094,11 +1084,9 @@ Wallet: ${data.walletAddress}`
1094
1084
  return {
1095
1085
  content: [{
1096
1086
  type: "text",
1097
- text: JSON.stringify({
1098
- success: false,
1099
- error: "Not logged in.",
1100
- hint: "Use ping_login to connect your GitHub account first."
1101
- }, null, 2)
1087
+ text: `\u274C Not logged in
1088
+
1089
+ Use ping_login to connect your GitHub account first.`
1102
1090
  }]
1103
1091
  };
1104
1092
  }
@@ -1107,11 +1095,9 @@ Wallet: ${data.walletAddress}`
1107
1095
  return {
1108
1096
  content: [{
1109
1097
  type: "text",
1110
- text: JSON.stringify({
1111
- success: false,
1112
- error: "No answers provided.",
1113
- hint: "Provide an array of answers with questionId and answer fields."
1114
- }, null, 2)
1098
+ text: `\u274C No answers provided
1099
+
1100
+ Provide an array of answers with questionId and answer fields.`
1115
1101
  }]
1116
1102
  };
1117
1103
  }
@@ -1146,11 +1132,9 @@ Wallet: ${data.walletAddress}`
1146
1132
  return {
1147
1133
  content: [{
1148
1134
  type: "text",
1149
- text: JSON.stringify({
1150
- success: false,
1151
- error: "Not logged in.",
1152
- hint: "Use ping_login to connect your GitHub account first. Then you can start answering questions and earning money."
1153
- }, null, 2)
1135
+ text: `\u274C Not logged in
1136
+
1137
+ Use ping_login to connect your GitHub account first.`
1154
1138
  }]
1155
1139
  };
1156
1140
  }
@@ -1174,76 +1158,24 @@ Wallet: ${data.walletAddress}`
1174
1158
  suggestedAnswers: suggestions
1175
1159
  };
1176
1160
  });
1177
- const summaryCard = `
1178
- \u{1F4EC} ${questionsWithSuggestions.length} questions available \xB7 Earn up to ${data.totalPotentialEarnings}
1161
+ let output = `\u{1F4EC} ${questionsWithSuggestions.length} questions available \xB7 Earn up to ${data.totalPotentialEarnings}
1179
1162
 
1180
- Ready to start answering!`;
1181
- const flowData = {
1182
- _meta: "INTERNAL: Do not display this JSON to user. Use AskUserQuestion to present questions.",
1183
- questions: questionsWithSuggestions,
1184
- instructions: "Present questions in batches of 4 using AskUserQuestion. Use ping_validate_batch first, then ping_submit_batch after user answers. Auto-claim at end."
1185
- };
1186
- return {
1187
- content: [{
1188
- type: "text",
1189
- text: summaryCard.trim() + "\n\n<!-- FLOW_DATA:" + JSON.stringify(flowData) + " -->"
1190
- }]
1191
- };
1192
- }
1193
- // ────────────────────────────────────────────────────────
1194
- // VALIDATE BATCH
1195
- // ────────────────────────────────────────────────────────
1196
- case "ping_validate_batch": {
1197
- const { questionIds } = args || {};
1198
- if (!questionIds || !Array.isArray(questionIds) || questionIds.length === 0) {
1199
- return {
1200
- content: [{
1201
- type: "text",
1202
- text: JSON.stringify({
1203
- success: false,
1204
- error: "Invalid question IDs provided. Expected an array of question IDs."
1205
- }, null, 2)
1206
- }]
1207
- };
1208
- }
1209
- const auth = getAuth();
1210
- if (!auth) {
1211
- return {
1212
- content: [{
1213
- type: "text",
1214
- text: JSON.stringify({
1215
- success: false,
1216
- error: "Not logged in.",
1217
- hint: "Use ping_login to connect your GitHub account first."
1218
- }, null, 2)
1219
- }]
1220
- };
1221
- }
1222
- const data = await apiRequest("/questions/validate", {
1223
- method: "POST",
1224
- body: JSON.stringify({ questionIds })
1225
- });
1226
- const availableWithSuggestions = data.available.map((q) => {
1227
- const suggestions = generateSuggestedAnswers(q.text, q.category);
1228
- return {
1229
- id: q.id,
1230
- question: q.text,
1231
- reward: q.reward,
1232
- rewardCents: q.rewardCents,
1233
- category: q.category,
1234
- suggestedAnswers: suggestions
1235
- };
1163
+ `;
1164
+ questionsWithSuggestions.forEach((q, i) => {
1165
+ output += `${i + 1}. [${q.reward}] ${q.question}
1166
+ `;
1167
+ output += ` Suggestions: ${q.suggestedAnswers.slice(0, 2).join(" | ")}
1168
+ `;
1169
+ output += ` ID: ${q.id}
1170
+
1171
+ `;
1236
1172
  });
1173
+ output += `
1174
+ \u{1F4A1} Present these in batches of 4 using AskUserQuestion. After collecting answers, use ping_submit_batch to submit them all at once.`;
1237
1175
  return {
1238
1176
  content: [{
1239
1177
  type: "text",
1240
- text: JSON.stringify({
1241
- success: true,
1242
- available: availableWithSuggestions,
1243
- exhausted: data.exhausted,
1244
- totalRemaining: data.totalRemaining,
1245
- message: data.available.length === 0 ? "All questions in this batch are no longer available." : data.exhausted.length > 0 ? `${data.available.length} questions available, ${data.exhausted.length} exhausted.` : `All ${data.available.length} questions are available!`
1246
- }, null, 2)
1178
+ text: output.trim()
1247
1179
  }]
1248
1180
  };
1249
1181
  }
@@ -1257,11 +1189,9 @@ Ready to start answering!`;
1257
1189
  return {
1258
1190
  content: [{
1259
1191
  type: "text",
1260
- text: JSON.stringify({
1261
- success: false,
1262
- error: "Not logged in.",
1263
- hint: "Use ping_login to connect your GitHub account before claiming rewards."
1264
- }, null, 2)
1192
+ text: `\u274C Not logged in
1193
+
1194
+ Use ping_login to connect your GitHub account first.`
1265
1195
  }]
1266
1196
  };
1267
1197
  }
@@ -1275,39 +1205,29 @@ Ready to start answering!`;
1275
1205
  });
1276
1206
  if (!data.success) {
1277
1207
  let errorMsg = data.error || "Claim failed";
1278
- let hint = "Please try again later.";
1279
1208
  if (errorMsg.toLowerCase().includes("nothing to claim") || errorMsg.toLowerCase().includes("no pending")) {
1280
- errorMsg = "No earnings to claim.";
1281
- hint = "Answer more questions to earn rewards, then claim them here.";
1282
- } else if (errorMsg.toLowerCase().includes("insufficient")) {
1283
- hint = "Your balance may be lower than the minimum claim amount.";
1209
+ return {
1210
+ content: [{
1211
+ type: "text",
1212
+ text: `\u2139\uFE0F No earnings to claim
1213
+
1214
+ Answer more questions to earn rewards!`
1215
+ }]
1216
+ };
1284
1217
  }
1285
1218
  return {
1286
1219
  content: [{
1287
1220
  type: "text",
1288
- text: JSON.stringify({
1289
- success: false,
1290
- error: errorMsg,
1291
- hint
1292
- }, null, 2)
1221
+ text: `\u274C ${errorMsg}`
1293
1222
  }]
1294
1223
  };
1295
1224
  }
1296
1225
  return {
1297
1226
  content: [{
1298
1227
  type: "text",
1299
- text: JSON.stringify({
1300
- success: true,
1301
- claimed: data.claimed,
1302
- transaction: {
1303
- hash: data.txHash,
1304
- chain: "Base",
1305
- token: "USDC",
1306
- to: wallet,
1307
- explorerUrl: `https://basescan.org/tx/${data.txHash}`
1308
- },
1309
- message: `Success! ${data.claimed} USDC sent to your wallet on Base!`
1310
- }, null, 2)
1228
+ text: `\u{1F4B8} Success! ${data.claimed} USDC sent to your wallet on Base!
1229
+
1230
+ \u{1F517} https://basescan.org/tx/${data.txHash}`
1311
1231
  }]
1312
1232
  };
1313
1233
  }
@@ -1332,11 +1252,9 @@ Ready to start answering!`;
1332
1252
  return {
1333
1253
  content: [{
1334
1254
  type: "text",
1335
- text: JSON.stringify({
1336
- success: false,
1337
- error: "Not logged in.",
1338
- hint: "Use ping_login to connect your GitHub account before creating questions."
1339
- }, null, 2)
1255
+ text: `\u274C Not logged in
1256
+
1257
+ Use ping_login to connect your GitHub account first.`
1340
1258
  }]
1341
1259
  };
1342
1260
  }
@@ -1345,11 +1263,9 @@ Ready to start answering!`;
1345
1263
  return {
1346
1264
  content: [{
1347
1265
  type: "text",
1348
- text: JSON.stringify({
1349
- success: false,
1350
- error: "Question is too short.",
1351
- hint: "Please write a question that is at least 10 characters long."
1352
- }, null, 2)
1266
+ text: `\u274C Question is too short
1267
+
1268
+ Please write at least 10 characters.`
1353
1269
  }]
1354
1270
  };
1355
1271
  }
@@ -1357,11 +1273,9 @@ Ready to start answering!`;
1357
1273
  return {
1358
1274
  content: [{
1359
1275
  type: "text",
1360
- text: JSON.stringify({
1361
- success: false,
1362
- error: "Invalid reward amount.",
1363
- hint: "Reward must be at least 1 cent. Example: 25 = $0.25 per answer."
1364
- }, null, 2)
1276
+ text: `\u274C Invalid reward amount
1277
+
1278
+ Reward must be at least 1 cent. Example: 25 = $0.25 per answer.`
1365
1279
  }]
1366
1280
  };
1367
1281
  }
@@ -1375,41 +1289,39 @@ Ready to start answering!`;
1375
1289
  })
1376
1290
  });
1377
1291
  if (!data.success) {
1378
- let errorMsg = data.error || "Failed to create question";
1379
- let hint = "Please try again.";
1292
+ const errorMsg = data.error || "Failed to create question";
1380
1293
  if (errorMsg.toLowerCase().includes("insufficient") || errorMsg.toLowerCase().includes("balance")) {
1381
- hint = "Use ping_deposit to add funds to your account first.";
1382
- } else if (errorMsg.toLowerCase().includes("duplicate")) {
1383
- hint = "A similar question may already exist. Try rephrasing.";
1294
+ return {
1295
+ content: [{
1296
+ type: "text",
1297
+ text: `\u274C Insufficient funds
1298
+
1299
+ Use ping_deposit to add funds first.`
1300
+ }]
1301
+ };
1384
1302
  }
1385
1303
  return {
1386
1304
  content: [{
1387
1305
  type: "text",
1388
- text: JSON.stringify({
1389
- success: false,
1390
- error: errorMsg,
1391
- hint
1392
- }, null, 2)
1306
+ text: `\u274C ${errorMsg}`
1393
1307
  }]
1394
1308
  };
1395
1309
  }
1396
- const response = {
1397
- success: true,
1398
- question: data.question,
1399
- message: `Question created! Reward: ${data.question?.reward} per answer`,
1400
- nextStep: "Answers will be AI-reviewed and you'll be notified when they arrive."
1401
- };
1310
+ let successText = `\u2705 Question created!
1311
+
1312
+ "${data.question?.text}"
1313
+
1314
+ Reward: ${data.question?.reward} per answer
1315
+ ID: ${data.question?.id}`;
1402
1316
  if (data.transaction?.txHash) {
1403
- response.transaction = {
1404
- txHash: data.transaction.txHash,
1405
- basescanUrl: `https://basescan.org/tx/${data.transaction.txHash}`
1406
- };
1407
- response.message = `\u2713 Question created on-chain! Reward: ${data.question?.reward} per answer`;
1317
+ successText += `
1318
+
1319
+ \u{1F517} https://basescan.org/tx/${data.transaction.txHash}`;
1408
1320
  }
1409
1321
  return {
1410
1322
  content: [{
1411
1323
  type: "text",
1412
- text: JSON.stringify(response, null, 2)
1324
+ text: successText
1413
1325
  }]
1414
1326
  };
1415
1327
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ping-mcp-server",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "MCP server that gives Claude Code the ability to interact with Ping",
5
5
  "type": "module",
6
6
  "bin": {