anilist-mcp
Version:
AniList MCP server for accessing AniList API data
208 lines (207 loc) • 6.82 kB
JavaScript
import { z } from "zod";
import { requireAuth } from "../utils/auth.js";
import { UserOptionsInputSchema } from "../utils/schemas.js";
export function registerUserTools(server, anilist, config) {
// anilist.user.all()
server.tool("get_full_user_info", "Get a user's complete profile and stats information", {
user: z.union([z.number(), z.string()]).describe("Username or user ID"),
}, {
title: "Get Full User Info",
readOnlyHint: true,
openWorldHint: true,
}, async ({ user }) => {
try {
const userInfo = await anilist.user.all(user);
return {
content: [
{
type: "text",
text: JSON.stringify(userInfo, null, 2),
},
],
};
}
catch (error) {
return {
content: [{ type: "text", text: `Error: ${error.message}` }],
isError: true,
};
}
});
// anilist.user.follow()
server.tool("follow_user", "[Requires Login] Follow or unfollow a user by their ID", {
userID: z
.number()
.describe("The user ID of the account to follow/unfollow"),
}, {
title: "Follow/Unfollow User",
readOnlyHint: false,
destructiveHint: true,
idempotentHint: false,
openWorldHint: true,
}, async ({ userID }) => {
try {
const auth = requireAuth(config.anilistToken);
if (!auth.isAuthorized) {
return auth.errorResponse;
}
const result = await anilist.user.follow(userID);
return {
content: [
{
type: "text",
text: result
? `Successfully followed user with ID ${userID}.`
: `User with ID ${userID} was unfollowed or operation failed.`,
},
],
};
}
catch (error) {
return {
content: [{ type: "text", text: `Error: ${error.message}` }],
isError: true,
};
}
});
// anilist.user.getAuthorized()
server.tool("get_authorized_user", "[Requires Login] Get profile information of the currently authorized user", {}, {
title: "Get Authorized User",
readOnlyHint: true,
openWorldHint: true,
}, async () => {
try {
const auth = requireAuth(config.anilistToken);
if (!auth.isAuthorized) {
return auth.errorResponse;
}
const profile = await anilist.user.getAuthorized();
return {
content: [
{
type: "text",
text: JSON.stringify(profile, null, 2),
},
],
};
}
catch (error) {
return {
content: [{ type: "text", text: `Error: ${error.message}` }],
isError: true,
};
}
});
// anilist.user.getRecentActivity()
server.tool("get_user_recent_activity", "Get recent activity from a user", {
user: z
.number()
.describe("The user's AniList ID (Number ID only, DO NOT use username, any kind of string or other types except for numbers.)"),
}, {
title: "Get User Recent Activity",
readOnlyHint: true,
openWorldHint: true,
}, async ({ user }) => {
try {
const activities = await anilist.user.getRecentActivity(user);
return {
content: [
{
type: "text",
text: JSON.stringify(activities, null, 2),
},
],
};
}
catch (error) {
return {
content: [{ type: "text", text: `Error: ${error.message}` }],
isError: true,
};
}
});
// anilist.user.profile()
server.tool("get_user_profile", "Get a user's AniList profile", {
user: z.union([z.number(), z.string()]).describe("Username or user ID"),
}, {
title: "Get User Profile",
readOnlyHint: true,
openWorldHint: true,
}, async ({ user }) => {
try {
const profile = await anilist.user.profile(user);
return {
content: [
{
type: "text",
text: JSON.stringify(profile, null, 2),
},
],
};
}
catch (error) {
return {
content: [{ type: "text", text: `Error: ${error.message}` }],
isError: true,
};
}
});
// anilist.user.stats()
server.tool("get_user_stats", "Get a user's AniList statistics", {
user: z.union([z.number(), z.string()]).describe("Username or user ID"),
}, {
title: "Get User Stats",
readOnlyHint: true,
openWorldHint: true,
}, async ({ user }) => {
try {
const stats = await anilist.user.stats(user);
return {
content: [
{
type: "text",
text: JSON.stringify(stats, null, 2),
},
],
};
}
catch (error) {
return {
content: [{ type: "text", text: `Error: ${error.message}` }],
isError: true,
};
}
});
// anilist.user.update()
server.tool("update_user", "[Requires Login] Update user settings", {
options: UserOptionsInputSchema.describe("User options to update"),
}, {
title: "Update User Settings",
readOnlyHint: false,
destructiveHint: true,
idempotentHint: true,
openWorldHint: true,
}, async ({ options }) => {
try {
const auth = requireAuth(config.anilistToken);
if (!auth.isAuthorized) {
return auth.errorResponse;
}
const updatedOptions = await anilist.user.update(options);
return {
content: [
{
type: "text",
text: JSON.stringify(updatedOptions, null, 2),
},
],
};
}
catch (error) {
return {
content: [{ type: "text", text: `Error: ${error.message}` }],
isError: true,
};
}
});
}