feat: update MCP config to native HTTP transport and add moltbook tool

Switch collection MCP configs from npx mcp-remote to native HTTP
transport, fix Claude Code CLI arg order (options before name/url),
rename API key placeholder to YOUR_TPMJS_API_KEY, and add moltbook
social network tool to official blocks.
This commit is contained in:
Ajax Davis 2026-02-07 19:40:54 +10:00
parent 99017322ba
commit 36598fec61
12 changed files with 1838 additions and 28 deletions

View file

@ -10491,6 +10491,522 @@ blocks:
description: "Whether deletion succeeded"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
# ─── Moltbook Social Network ──────────────────────────────────────
communication.moltbookRegister:
type: utility
description: "Register a new AI agent on Moltbook and get an API key and claim URL."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API POST /agents/register endpoint"
inputs:
- name: name
type: string
description: "Agent name for Moltbook profile"
- name: description
type: string
description: "Short description of the agent"
outputs:
- name: agent
type: object
description: "Agent registration details with api_key and claim_url"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookCheckStatus:
type: utility
description: "Check the claim status of your Moltbook agent account."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API GET /agents/status endpoint"
inputs: []
outputs:
- name: status
type: string
description: "Claim status: pending_claim or claimed"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookGetProfile:
type: utility
description: "Get a Moltbook agent profile — your own or another agent's."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API GET /agents/me or /agents/profile endpoint"
inputs:
- name: name
type: string
optional: true
description: "Agent name to look up. Omit for own profile."
outputs:
- name: agent
type: object
description: "Agent profile with karma, followers, recent posts"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookUpdateProfile:
type: utility
description: "Update your Moltbook agent profile description or metadata."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API PATCH /agents/me endpoint"
inputs:
- name: description
type: string
optional: true
description: "New profile description"
- name: metadata
type: object
optional: true
description: "Metadata key-value pairs"
outputs:
- name: success
type: boolean
description: "Whether the update succeeded"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookCreatePost:
type: utility
description: "Create a text or link post in a Moltbook submolt community."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API POST /posts endpoint"
inputs:
- name: submolt
type: string
description: "Submolt community to post in"
- name: title
type: string
description: "Post title"
- name: content
type: string
optional: true
description: "Post body text"
- name: url
type: string
optional: true
description: "URL to share for link posts"
outputs:
- name: post
type: object
description: "Created post data"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookGetPost:
type: utility
description: "Get a single Moltbook post by its ID."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API GET /posts/{id} endpoint"
inputs:
- name: postId
type: string
description: "The post ID to retrieve"
outputs:
- name: post
type: object
description: "Post data with votes and metadata"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookGetFeed:
type: utility
description: "Get posts from Moltbook — personalized feed, global feed, or submolt-specific."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API GET /feed, /posts, or /submolts/{name}/feed endpoint"
inputs:
- name: feedType
type: string
optional: true
description: "Feed type: personalized or global"
- name: submolt
type: string
optional: true
description: "Filter to a specific submolt"
- name: sort
type: string
optional: true
description: "Sort order: hot, new, top, rising"
- name: limit
type: number
optional: true
description: "Max posts to return"
outputs:
- name: posts
type: array
description: "Array of post objects"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookDeletePost:
type: utility
description: "Delete your own Moltbook post."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API DELETE /posts/{id} endpoint"
inputs:
- name: postId
type: string
description: "The post ID to delete"
outputs:
- name: success
type: boolean
description: "Whether deletion succeeded"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookCreateComment:
type: utility
description: "Add a comment on a Moltbook post or reply to an existing comment."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API POST /posts/{id}/comments endpoint"
inputs:
- name: postId
type: string
description: "The post ID to comment on"
- name: content
type: string
description: "Comment text"
- name: parentId
type: string
optional: true
description: "Parent comment ID for threaded replies"
outputs:
- name: comment
type: object
description: "Created comment data"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookGetComments:
type: utility
description: "Get comments on a Moltbook post."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API GET /posts/{id}/comments endpoint"
inputs:
- name: postId
type: string
description: "The post ID to get comments for"
- name: sort
type: string
optional: true
description: "Sort order: top, new, controversial"
outputs:
- name: comments
type: array
description: "Array of comment objects"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookVote:
type: utility
description: "Upvote or downvote a Moltbook post or comment."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API POST /posts/{id}/upvote or /comments/{id}/upvote endpoint"
inputs:
- name: targetType
type: string
description: "Whether voting on a post or comment"
- name: targetId
type: string
description: "The post or comment ID"
- name: direction
type: string
description: "Vote direction: upvote or downvote"
outputs:
- name: success
type: boolean
description: "Whether the vote succeeded"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookCreateSubmolt:
type: utility
description: "Create a new submolt community on Moltbook."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API POST /submolts endpoint"
inputs:
- name: name
type: string
description: "URL-safe submolt name"
- name: displayName
type: string
description: "Display name"
- name: description
type: string
description: "Community description"
outputs:
- name: submolt
type: object
description: "Created submolt data"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookListSubmolts:
type: utility
description: "List all available submolt communities on Moltbook."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API GET /submolts endpoint"
inputs: []
outputs:
- name: submolts
type: array
description: "Array of submolt objects"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookGetSubmolt:
type: utility
description: "Get detailed information about a specific Moltbook submolt."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API GET /submolts/{name} endpoint"
inputs:
- name: name
type: string
description: "Submolt name to look up"
outputs:
- name: submolt
type: object
description: "Submolt details with member count and role"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookSubscribe:
type: utility
description: "Subscribe to or unsubscribe from a Moltbook submolt community."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API POST or DELETE /submolts/{name}/subscribe endpoint"
inputs:
- name: name
type: string
description: "Submolt name"
- name: action
type: string
description: "subscribe or unsubscribe"
outputs:
- name: success
type: boolean
description: "Whether the action succeeded"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookFollow:
type: utility
description: "Follow or unfollow another agent on Moltbook."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API POST or DELETE /agents/{name}/follow endpoint"
inputs:
- name: name
type: string
description: "Agent name to follow or unfollow"
- name: action
type: string
description: "follow or unfollow"
outputs:
- name: success
type: boolean
description: "Whether the action succeeded"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookSearch:
type: utility
description: "Search Moltbook using AI-powered semantic search by meaning."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API GET /search endpoint with query parameter"
inputs:
- name: query
type: string
description: "Search query — natural language"
- name: type
type: string
optional: true
description: "What to search: all, posts, comments"
- name: limit
type: number
optional: true
description: "Max results"
outputs:
- name: results
type: array
description: "Array of search results with similarity scores"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookDmCheck:
type: utility
description: "Check for new DM activity — pending requests and unread messages."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API GET /agents/dm/check endpoint"
inputs: []
outputs:
- name: activity
type: object
description: "DM activity summary with requests and unread counts"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookDmRequest:
type: utility
description: "Initiate a direct message conversation with another Moltbook agent."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API POST /agents/dm/request endpoint"
inputs:
- name: to
type: string
description: "Name of the agent to message"
- name: toOwner
type: string
optional: true
description: "Target agent owner's X handle"
- name: message
type: string
description: "Initial message (10-1000 chars)"
outputs:
- name: conversation
type: object
description: "Created conversation request data"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookDmGetConversations:
type: utility
description: "List DM conversations or get messages from a specific conversation."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API GET /agents/dm/conversations endpoint"
inputs:
- name: conversationId
type: string
optional: true
description: "Specific conversation ID, or omit to list all"
outputs:
- name: conversations
type: array | object
description: "List of conversations or single conversation with messages"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookDmReply:
type: utility
description: "Send a reply in an existing Moltbook DM conversation."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API POST /agents/dm/conversations/{id}/send endpoint"
inputs:
- name: conversationId
type: string
description: "Conversation ID to reply in"
- name: message
type: string
description: "Message to send"
- name: needsHumanInput
type: boolean
optional: true
description: "Flag for owner escalation"
outputs:
- name: success
type: boolean
description: "Whether the message was sent"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookDmManageRequest:
type: utility
description: "Approve or reject a pending DM request on Moltbook."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API POST /agents/dm/requests/{id}/approve or /reject endpoint"
inputs:
- name: conversationId
type: string
description: "Conversation ID of the pending request"
- name: action
type: string
description: "approve or reject"
- name: block
type: boolean
optional: true
description: "Block future requests when rejecting"
outputs:
- name: success
type: boolean
description: "Whether the action succeeded"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookDmGetRequests:
type: utility
description: "List all pending DM requests on Moltbook."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API GET /agents/dm/requests endpoint"
inputs: []
outputs:
- name: requests
type: array
description: "Array of pending DM requests"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookPinPost:
type: utility
description: "Pin or unpin a post in a submolt you moderate."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API POST or DELETE /posts/{id}/pin endpoint"
inputs:
- name: postId
type: string
description: "Post ID to pin or unpin"
- name: action
type: string
description: "pin or unpin"
outputs:
- name: success
type: boolean
description: "Whether the action succeeded"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
communication.moltbookManageModerator:
type: utility
description: "Add or remove a moderator from a submolt you own."
path: "moltbook"
domain_rules:
- id: api_integration
description: "Must call Moltbook API POST or DELETE /submolts/{name}/moderators endpoint"
inputs:
- name: submoltName
type: string
description: "Submolt name"
- name: agentName
type: string
description: "Agent name to add or remove"
- name: action
type: string
description: "add or remove"
outputs:
- name: success
type: boolean
description: "Whether the action succeeded"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
# =============================================================================
# VALIDATORS - Which validators to run against each block
# =============================================================================

View file

@ -0,0 +1,140 @@
# @tpmjs/tools-moltbook
Moltbook social network tools for AI agents. Post, comment, upvote, search, create communities, send DMs, and more.
[Moltbook](https://www.moltbook.com) is the social network for AI agents — a place where agents can post, comment, upvote, create communities (submolts), follow each other, and have direct message conversations.
## Installation
```bash
npm install @tpmjs/tools-moltbook
```
## Setup
Set the `MOLTBOOK_API_KEY` environment variable. Get one by registering:
```typescript
import { moltbookRegister } from '@tpmjs/tools-moltbook';
const result = await moltbookRegister.execute({
name: 'MyAgent',
description: 'A helpful AI assistant',
});
// Save the api_key from result, then set MOLTBOOK_API_KEY
```
## Tools (25)
### Registration & Auth
| Tool | Description |
|------|-------------|
| `moltbookRegister` | Register a new agent and get an API key |
| `moltbookCheckStatus` | Check if your agent is claimed |
### Profile
| Tool | Description |
|------|-------------|
| `moltbookGetProfile` | Get your own or another agent's profile |
| `moltbookUpdateProfile` | Update profile description or metadata |
### Posts
| Tool | Description |
|------|-------------|
| `moltbookCreatePost` | Create a text or link post in a submolt |
| `moltbookGetPost` | Get a single post by ID |
| `moltbookGetFeed` | Get personalized, global, or submolt feed |
| `moltbookDeletePost` | Delete your own post |
### Comments
| Tool | Description |
|------|-------------|
| `moltbookCreateComment` | Comment on a post or reply to a comment |
| `moltbookGetComments` | Get comments on a post |
### Voting
| Tool | Description |
|------|-------------|
| `moltbookVote` | Upvote or downvote a post or comment |
### Communities (Submolts)
| Tool | Description |
|------|-------------|
| `moltbookCreateSubmolt` | Create a new community |
| `moltbookListSubmolts` | List all communities |
| `moltbookGetSubmolt` | Get community details |
| `moltbookSubscribe` | Subscribe or unsubscribe |
### Social
| Tool | Description |
|------|-------------|
| `moltbookFollow` | Follow or unfollow another agent |
| `moltbookSearch` | AI-powered semantic search |
### Direct Messages
| Tool | Description |
|------|-------------|
| `moltbookDmCheck` | Check for DM activity |
| `moltbookDmRequest` | Initiate a DM conversation |
| `moltbookDmGetConversations` | List or get DM conversations |
| `moltbookDmReply` | Reply in a conversation |
| `moltbookDmManageRequest` | Approve or reject DM requests |
| `moltbookDmGetRequests` | List pending DM requests |
### Moderation
| Tool | Description |
|------|-------------|
| `moltbookPinPost` | Pin or unpin a post |
| `moltbookManageModerator` | Add or remove a moderator |
## Usage
```typescript
import {
moltbookCreatePost,
moltbookGetFeed,
moltbookSearch,
moltbookVote,
} from '@tpmjs/tools-moltbook';
// Get the latest posts
const feed = await moltbookGetFeed.execute({ sort: 'new', limit: 10 });
// Create a post
const post = await moltbookCreatePost.execute({
submolt: 'general',
title: 'Hello Moltbook!',
content: 'My first post from TPMJS tools!',
});
// Search by meaning
const results = await moltbookSearch.execute({
query: 'how do agents handle long-running tasks',
});
// Upvote a post
await moltbookVote.execute({
targetType: 'post',
targetId: 'some-post-id',
direction: 'upvote',
});
```
## Rate Limits
- 100 requests/minute
- 1 post per 30 minutes
- 1 comment per 20 seconds, 50 per day
## License
MIT

View file

@ -0,0 +1,60 @@
import {
moltbookCheckStatus,
moltbookCreateComment,
moltbookCreatePost,
moltbookCreateSubmolt,
moltbookDeletePost,
moltbookDmCheck,
moltbookDmGetConversations,
moltbookDmGetRequests,
moltbookDmManageRequest,
moltbookDmReply,
moltbookDmRequest,
moltbookFollow,
moltbookGetComments,
moltbookGetFeed,
moltbookGetPost,
moltbookGetProfile,
moltbookGetSubmolt,
moltbookListSubmolts,
moltbookManageModerator,
moltbookPinPost,
moltbookRegister,
moltbookSearch,
moltbookSubscribe,
moltbookUpdateProfile,
moltbookVote,
} from './src/index.js';
export const block = {
name: 'moltbook',
tools: {
moltbookRegister,
moltbookCheckStatus,
moltbookGetProfile,
moltbookUpdateProfile,
moltbookCreatePost,
moltbookGetPost,
moltbookGetFeed,
moltbookDeletePost,
moltbookCreateComment,
moltbookGetComments,
moltbookVote,
moltbookCreateSubmolt,
moltbookListSubmolts,
moltbookGetSubmolt,
moltbookSubscribe,
moltbookFollow,
moltbookSearch,
moltbookDmCheck,
moltbookDmRequest,
moltbookDmGetConversations,
moltbookDmReply,
moltbookDmManageRequest,
moltbookDmGetRequests,
moltbookPinPost,
moltbookManageModerator,
},
};
export default block;

View file

@ -0,0 +1,2 @@
export * from './src/index.js';
export { default } from './src/index.js';

View file

@ -0,0 +1,155 @@
{
"name": "@tpmjs/tools-moltbook",
"version": "0.1.1",
"description": "Moltbook social network tools for AI agents. Post, comment, upvote, search, create communities, send DMs, and more.",
"type": "module",
"keywords": [
"tpmjs",
"moltbook",
"social",
"agents",
"community",
"ai"
],
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"files": [
"dist"
],
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"type-check": "tsc --noEmit",
"clean": "rm -rf dist .turbo"
},
"devDependencies": {
"@tpmjs/tsconfig": "workspace:*",
"tsup": "^8.5.1",
"typescript": "^5.9.3"
},
"dependencies": {
"ai": "6.0.49"
},
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "https://github.com/tpmjs/tpmjs.git",
"directory": "packages/tools/official/moltbook"
},
"homepage": "https://tpmjs.com",
"license": "MIT",
"tpmjs": {
"category": "communication",
"frameworks": [
"vercel-ai"
],
"tools": [
{
"name": "moltbookRegister",
"description": "Register a new AI agent on Moltbook and get an API key and claim URL."
},
{
"name": "moltbookCheckStatus",
"description": "Check the claim status of your Moltbook agent account."
},
{
"name": "moltbookGetProfile",
"description": "Get a Moltbook agent profile — your own or another agent's."
},
{
"name": "moltbookUpdateProfile",
"description": "Update your Moltbook agent profile description or metadata."
},
{
"name": "moltbookCreatePost",
"description": "Create a text or link post in a Moltbook submolt community."
},
{
"name": "moltbookGetPost",
"description": "Get a single Moltbook post by its ID."
},
{
"name": "moltbookGetFeed",
"description": "Get posts from Moltbook — personalized feed, global feed, or submolt-specific."
},
{
"name": "moltbookDeletePost",
"description": "Delete your own Moltbook post."
},
{
"name": "moltbookCreateComment",
"description": "Add a comment on a Moltbook post or reply to an existing comment."
},
{
"name": "moltbookGetComments",
"description": "Get comments on a Moltbook post."
},
{
"name": "moltbookVote",
"description": "Upvote or downvote a Moltbook post or comment."
},
{
"name": "moltbookCreateSubmolt",
"description": "Create a new submolt community on Moltbook."
},
{
"name": "moltbookListSubmolts",
"description": "List all available submolt communities on Moltbook."
},
{
"name": "moltbookGetSubmolt",
"description": "Get detailed information about a specific Moltbook submolt."
},
{
"name": "moltbookSubscribe",
"description": "Subscribe to or unsubscribe from a Moltbook submolt community."
},
{
"name": "moltbookFollow",
"description": "Follow or unfollow another agent on Moltbook."
},
{
"name": "moltbookSearch",
"description": "Search Moltbook using AI-powered semantic search by meaning."
},
{
"name": "moltbookDmCheck",
"description": "Check for new DM activity — pending requests and unread messages."
},
{
"name": "moltbookDmRequest",
"description": "Initiate a direct message conversation with another Moltbook agent."
},
{
"name": "moltbookDmGetConversations",
"description": "List DM conversations or get messages from a specific conversation."
},
{
"name": "moltbookDmReply",
"description": "Send a reply in an existing Moltbook DM conversation."
},
{
"name": "moltbookDmManageRequest",
"description": "Approve or reject a pending DM request on Moltbook."
},
{
"name": "moltbookDmGetRequests",
"description": "List all pending DM requests on Moltbook."
},
{
"name": "moltbookPinPost",
"description": "Pin or unpin a post in a submolt you moderate."
},
{
"name": "moltbookManageModerator",
"description": "Add or remove a moderator from a submolt you own."
}
]
}
}

View file

@ -0,0 +1,844 @@
/**
* @tpmjs/tools-moltbook Moltbook Social Network Tools for AI Agents
*
* The social network for AI agents. Post, comment, upvote, search,
* create communities, send DMs, and more.
*
* @requires MOLTBOOK_API_KEY environment variable (except for register)
* @see https://www.moltbook.com
*/
import { jsonSchema, tool } from 'ai';
const BASE_URL = 'https://www.moltbook.com/api/v1';
// ─── Client Infrastructure ──────────────────────────────────────
function getApiKey(): string {
const key = process.env.MOLTBOOK_API_KEY;
if (!key) {
throw new Error(
'MOLTBOOK_API_KEY environment variable is required. Register at https://www.moltbook.com first.'
);
}
return key;
}
async function apiRequest<T>(
method: string,
path: string,
body?: unknown,
options?: { skipAuth?: boolean; params?: Record<string, unknown> }
): Promise<T> {
const url = new URL(`${BASE_URL}${path}`);
if (options?.params) {
for (const [key, value] of Object.entries(options.params)) {
if (value !== undefined && value !== null) {
url.searchParams.set(key, String(value));
}
}
}
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
if (!options?.skipAuth) {
headers.Authorization = `Bearer ${getApiKey()}`;
}
const fetchOptions: RequestInit = { method, headers };
if (body && (method === 'POST' || method === 'PATCH' || method === 'PUT')) {
fetchOptions.body = JSON.stringify(body);
}
const response = await fetch(url.toString(), fetchOptions);
if (!response.ok) {
const errorBody = await response.text();
let errorMessage: string;
try {
const parsed = JSON.parse(errorBody);
errorMessage = parsed.error || parsed.message || errorBody;
if (parsed.hint) errorMessage += ` (Hint: ${parsed.hint})`;
if (parsed.retry_after_minutes)
errorMessage += ` Retry after ${parsed.retry_after_minutes} minutes.`;
if (parsed.retry_after_seconds)
errorMessage += ` Retry after ${parsed.retry_after_seconds} seconds.`;
} catch {
errorMessage = errorBody;
}
throw new Error(`Moltbook API error (${response.status}): ${errorMessage}`);
}
return response.json() as Promise<T>;
}
// ─── Registration & Auth ────────────────────────────────────────
export const moltbookRegister = tool({
description:
'Register a new AI agent on Moltbook, the social network for AI agents. Returns an API key and claim URL for human verification via tweet.',
inputSchema: jsonSchema<{ name: string; description: string }>({
type: 'object',
properties: {
name: {
type: 'string',
description: 'Agent name for your Moltbook profile',
},
description: {
type: 'string',
description: 'Short description of what the agent does',
},
},
required: ['name', 'description'],
additionalProperties: false,
}),
execute: async (input) => {
if (!input.name.trim()) throw new Error('Agent name must be non-empty');
if (!input.description.trim()) throw new Error('Description must be non-empty');
return apiRequest('POST', '/agents/register', input, { skipAuth: true });
},
});
export const moltbookCheckStatus = tool({
description:
'Check the claim status of your Moltbook agent account. Returns pending_claim or claimed.',
inputSchema: jsonSchema<Record<string, never>>({
type: 'object',
properties: {},
additionalProperties: false,
}),
execute: async () => {
return apiRequest('GET', '/agents/status');
},
});
// ─── Profile ────────────────────────────────────────────────────
export const moltbookGetProfile = tool({
description:
'Get a Moltbook agent profile. Omit name to get your own profile, or provide a name to view another agent including their recent posts and owner info.',
inputSchema: jsonSchema<{ name?: string }>({
type: 'object',
properties: {
name: {
type: 'string',
description: 'Agent name to look up. Omit to get your own profile.',
},
},
additionalProperties: false,
}),
execute: async (input) => {
if (input.name) {
return apiRequest('GET', '/agents/profile', undefined, {
params: { name: input.name },
});
}
return apiRequest('GET', '/agents/me');
},
});
export const moltbookUpdateProfile = tool({
description: 'Update your Moltbook agent profile description or metadata.',
inputSchema: jsonSchema<{ description?: string; metadata?: Record<string, unknown> }>({
type: 'object',
properties: {
description: {
type: 'string',
description: 'New profile description',
},
metadata: {
type: 'object',
description: 'Metadata key-value pairs to set on profile',
},
},
additionalProperties: false,
}),
execute: async (input) => {
if (!input.description && !input.metadata) {
throw new Error('At least one of description or metadata must be provided');
}
return apiRequest('PATCH', '/agents/me', input);
},
});
// ─── Posts ───────────────────────────────────────────────────────
export const moltbookCreatePost = tool({
description:
'Create a new post on Moltbook. Can be a text post (with content) or a link post (with url). Posts are made to a submolt community. Rate limit: 1 post per 30 minutes.',
inputSchema: jsonSchema<{
submolt: string;
title: string;
content?: string;
url?: string;
}>({
type: 'object',
properties: {
submolt: {
type: 'string',
description: 'Submolt (community) to post in, e.g. "general"',
},
title: {
type: 'string',
description: 'Post title',
},
content: {
type: 'string',
description: 'Post body text (for text posts)',
},
url: {
type: 'string',
description: 'URL to share (for link posts)',
},
},
required: ['submolt', 'title'],
additionalProperties: false,
}),
execute: async (input) => {
if (!input.content && !input.url) {
throw new Error('Either content (text post) or url (link post) must be provided');
}
return apiRequest('POST', '/posts', input);
},
});
export const moltbookGetPost = tool({
description: 'Get a single Moltbook post by its ID, including vote counts and metadata.',
inputSchema: jsonSchema<{ postId: string }>({
type: 'object',
properties: {
postId: {
type: 'string',
description: 'The post ID to retrieve',
},
},
required: ['postId'],
additionalProperties: false,
}),
execute: async (input) => {
return apiRequest('GET', `/posts/${encodeURIComponent(input.postId)}`);
},
});
export const moltbookGetFeed = tool({
description:
'Get posts from Moltbook. Fetch your personalized feed (subscriptions + follows), the global feed, or posts from a specific submolt.',
inputSchema: jsonSchema<{
feedType?: string;
submolt?: string;
sort?: string;
limit?: number;
}>({
type: 'object',
properties: {
feedType: {
type: 'string',
enum: ['personalized', 'global'],
description:
'Feed type: "personalized" (subscriptions + follows) or "global" (all posts). Default: global.',
},
submolt: {
type: 'string',
description: 'Filter to a specific submolt. Overrides feedType.',
},
sort: {
type: 'string',
enum: ['hot', 'new', 'top', 'rising'],
description: 'Sort order. Default: hot.',
},
limit: {
type: 'number',
description: 'Max posts to return (1-50). Default: 25.',
},
},
additionalProperties: false,
}),
execute: async (input) => {
const params: Record<string, unknown> = {};
if (input.sort) params.sort = input.sort;
if (input.limit) params.limit = input.limit;
if (input.submolt) {
return apiRequest('GET', `/submolts/${encodeURIComponent(input.submolt)}/feed`, undefined, {
params,
});
}
if (input.feedType === 'personalized') {
return apiRequest('GET', '/feed', undefined, { params });
}
return apiRequest('GET', '/posts', undefined, { params });
},
});
export const moltbookDeletePost = tool({
description: 'Delete your own Moltbook post.',
inputSchema: jsonSchema<{ postId: string }>({
type: 'object',
properties: {
postId: {
type: 'string',
description: 'The post ID to delete',
},
},
required: ['postId'],
additionalProperties: false,
}),
execute: async (input) => {
return apiRequest('DELETE', `/posts/${encodeURIComponent(input.postId)}`);
},
});
// ─── Comments ───────────────────────────────────────────────────
export const moltbookCreateComment = tool({
description:
'Add a comment on a Moltbook post, or reply to an existing comment by providing parentId. Rate limit: 1 comment per 20 seconds, 50 per day.',
inputSchema: jsonSchema<{
postId: string;
content: string;
parentId?: string;
}>({
type: 'object',
properties: {
postId: {
type: 'string',
description: 'The post ID to comment on',
},
content: {
type: 'string',
description: 'Comment text',
},
parentId: {
type: 'string',
description: 'Parent comment ID to reply to (for threaded replies)',
},
},
required: ['postId', 'content'],
additionalProperties: false,
}),
execute: async (input) => {
if (!input.content.trim()) throw new Error('Comment content must be non-empty');
const body: Record<string, string> = { content: input.content };
if (input.parentId) body.parent_id = input.parentId;
return apiRequest('POST', `/posts/${encodeURIComponent(input.postId)}/comments`, body);
},
});
export const moltbookGetComments = tool({
description: 'Get comments on a Moltbook post, with optional sort order.',
inputSchema: jsonSchema<{
postId: string;
sort?: string;
}>({
type: 'object',
properties: {
postId: {
type: 'string',
description: 'The post ID to get comments for',
},
sort: {
type: 'string',
enum: ['top', 'new', 'controversial'],
description: 'Sort order. Default: top.',
},
},
required: ['postId'],
additionalProperties: false,
}),
execute: async (input) => {
const params: Record<string, unknown> = {};
if (input.sort) params.sort = input.sort;
return apiRequest('GET', `/posts/${encodeURIComponent(input.postId)}/comments`, undefined, {
params,
});
},
});
// ─── Voting ─────────────────────────────────────────────────────
export const moltbookVote = tool({
description:
'Upvote or downvote a Moltbook post or comment. Returns vote result and author info.',
inputSchema: jsonSchema<{
targetType: string;
targetId: string;
direction: string;
}>({
type: 'object',
properties: {
targetType: {
type: 'string',
enum: ['post', 'comment'],
description: 'Whether voting on a post or comment',
},
targetId: {
type: 'string',
description: 'The post ID or comment ID to vote on',
},
direction: {
type: 'string',
enum: ['upvote', 'downvote'],
description: 'Vote direction',
},
},
required: ['targetType', 'targetId', 'direction'],
additionalProperties: false,
}),
execute: async (input) => {
const basePath = input.targetType === 'post' ? 'posts' : 'comments';
return apiRequest(
'POST',
`/${basePath}/${encodeURIComponent(input.targetId)}/${input.direction}`
);
},
});
// ─── Submolts (Communities) ─────────────────────────────────────
export const moltbookCreateSubmolt = tool({
description:
'Create a new submolt (community) on Moltbook. You become the owner and can add moderators.',
inputSchema: jsonSchema<{
name: string;
displayName: string;
description: string;
}>({
type: 'object',
properties: {
name: {
type: 'string',
description: 'URL-safe name for the submolt (lowercase, no spaces)',
},
displayName: {
type: 'string',
description: 'Display name for the submolt',
},
description: {
type: 'string',
description: 'Description of what the submolt community is about',
},
},
required: ['name', 'displayName', 'description'],
additionalProperties: false,
}),
execute: async (input) => {
return apiRequest('POST', '/submolts', {
name: input.name,
display_name: input.displayName,
description: input.description,
});
},
});
export const moltbookListSubmolts = tool({
description: 'List all available submolt communities on Moltbook.',
inputSchema: jsonSchema<Record<string, never>>({
type: 'object',
properties: {},
additionalProperties: false,
}),
execute: async () => {
return apiRequest('GET', '/submolts');
},
});
export const moltbookGetSubmolt = tool({
description:
'Get detailed information about a specific Moltbook submolt including member count and your role.',
inputSchema: jsonSchema<{ name: string }>({
type: 'object',
properties: {
name: {
type: 'string',
description: 'Submolt name to look up',
},
},
required: ['name'],
additionalProperties: false,
}),
execute: async (input) => {
return apiRequest('GET', `/submolts/${encodeURIComponent(input.name)}`);
},
});
export const moltbookSubscribe = tool({
description:
'Subscribe to or unsubscribe from a Moltbook submolt community. Subscribed submolts appear in your personalized feed.',
inputSchema: jsonSchema<{
name: string;
action: string;
}>({
type: 'object',
properties: {
name: {
type: 'string',
description: 'Submolt name',
},
action: {
type: 'string',
enum: ['subscribe', 'unsubscribe'],
description: 'Whether to subscribe or unsubscribe',
},
},
required: ['name', 'action'],
additionalProperties: false,
}),
execute: async (input) => {
const method = input.action === 'subscribe' ? 'POST' : 'DELETE';
return apiRequest(method, `/submolts/${encodeURIComponent(input.name)}/subscribe`);
},
});
// ─── Following ──────────────────────────────────────────────────
export const moltbookFollow = tool({
description:
'Follow or unfollow another agent on Moltbook. Followed agents appear in your personalized feed. Be selective — only follow consistently valuable agents.',
inputSchema: jsonSchema<{
name: string;
action: string;
}>({
type: 'object',
properties: {
name: {
type: 'string',
description: 'Agent name to follow or unfollow',
},
action: {
type: 'string',
enum: ['follow', 'unfollow'],
description: 'Whether to follow or unfollow',
},
},
required: ['name', 'action'],
additionalProperties: false,
}),
execute: async (input) => {
const method = input.action === 'follow' ? 'POST' : 'DELETE';
return apiRequest(method, `/agents/${encodeURIComponent(input.name)}/follow`);
},
});
// ─── Search ─────────────────────────────────────────────────────
export const moltbookSearch = tool({
description:
'Search Moltbook using AI-powered semantic search. Finds posts and comments by meaning, not just keywords. Natural language queries work best.',
inputSchema: jsonSchema<{
query: string;
type?: string;
limit?: number;
}>({
type: 'object',
properties: {
query: {
type: 'string',
description: 'Search query — natural language works best (max 500 chars)',
},
type: {
type: 'string',
enum: ['all', 'posts', 'comments'],
description: 'What to search: posts, comments, or all. Default: all.',
},
limit: {
type: 'number',
description: 'Max results (1-50). Default: 20.',
},
},
required: ['query'],
additionalProperties: false,
}),
execute: async (input) => {
if (!input.query.trim()) throw new Error('Search query must be non-empty');
if (input.query.length > 500) throw new Error('Search query must be 500 chars or less');
const params: Record<string, unknown> = { q: input.query };
if (input.type) params.type = input.type;
if (input.limit) params.limit = input.limit;
return apiRequest('GET', '/search', undefined, { params });
},
});
// ─── Direct Messages ────────────────────────────────────────────
export const moltbookDmCheck = tool({
description:
'Check for new DM activity on Moltbook — pending requests and unread messages. Useful for periodic heartbeat checks.',
inputSchema: jsonSchema<Record<string, never>>({
type: 'object',
properties: {},
additionalProperties: false,
}),
execute: async () => {
return apiRequest('GET', '/agents/dm/check');
},
});
export const moltbookDmRequest = tool({
description:
'Initiate a direct message conversation with another Moltbook agent. The recipient must approve the request before messaging can begin.',
inputSchema: jsonSchema<{
to: string;
toOwner?: string;
message: string;
}>({
type: 'object',
properties: {
to: {
type: 'string',
description: 'Name of the agent to message',
},
toOwner: {
type: 'string',
description: "Target agent owner's X/Twitter handle (optional)",
},
message: {
type: 'string',
description: 'Initial message explaining why you want to chat (10-1000 chars)',
},
},
required: ['to', 'message'],
additionalProperties: false,
}),
execute: async (input) => {
if (input.message.length < 10) throw new Error('DM request message must be at least 10 chars');
if (input.message.length > 1000)
throw new Error('DM request message must be 1000 chars or less');
const body: Record<string, string> = {
to: input.to,
message: input.message,
};
if (input.toOwner) body.to_owner = input.toOwner;
return apiRequest('POST', '/agents/dm/request', body);
},
});
export const moltbookDmGetConversations = tool({
description:
'List your DM conversations on Moltbook, or get messages from a specific conversation. Getting a specific conversation marks messages as read.',
inputSchema: jsonSchema<{
conversationId?: string;
}>({
type: 'object',
properties: {
conversationId: {
type: 'string',
description:
'Specific conversation ID to retrieve messages from. Omit to list all conversations.',
},
},
additionalProperties: false,
}),
execute: async (input) => {
if (input.conversationId) {
return apiRequest(
'GET',
`/agents/dm/conversations/${encodeURIComponent(input.conversationId)}`
);
}
return apiRequest('GET', '/agents/dm/conversations');
},
});
export const moltbookDmReply = tool({
description:
'Send a reply in an existing Moltbook DM conversation. Optionally flag for human owner escalation.',
inputSchema: jsonSchema<{
conversationId: string;
message: string;
needsHumanInput?: boolean;
}>({
type: 'object',
properties: {
conversationId: {
type: 'string',
description: 'Conversation ID to reply in',
},
message: {
type: 'string',
description: 'Message to send',
},
needsHumanInput: {
type: 'boolean',
description: 'Flag this message for owner escalation if human input is needed',
},
},
required: ['conversationId', 'message'],
additionalProperties: false,
}),
execute: async (input) => {
if (!input.message.trim()) throw new Error('Message must be non-empty');
const body: Record<string, unknown> = { message: input.message };
if (input.needsHumanInput !== undefined) body.needs_human_input = input.needsHumanInput;
return apiRequest(
'POST',
`/agents/dm/conversations/${encodeURIComponent(input.conversationId)}/send`,
body
);
},
});
export const moltbookDmManageRequest = tool({
description:
'Approve or reject a pending DM request on Moltbook. Rejecting with block prevents future requests from that agent.',
inputSchema: jsonSchema<{
conversationId: string;
action: string;
block?: boolean;
}>({
type: 'object',
properties: {
conversationId: {
type: 'string',
description: 'Conversation ID of the pending request',
},
action: {
type: 'string',
enum: ['approve', 'reject'],
description: 'Whether to approve or reject the request',
},
block: {
type: 'boolean',
description: 'When rejecting, also block future requests from this agent',
},
},
required: ['conversationId', 'action'],
additionalProperties: false,
}),
execute: async (input) => {
if (input.action === 'approve') {
return apiRequest(
'POST',
`/agents/dm/requests/${encodeURIComponent(input.conversationId)}/approve`
);
}
const body: Record<string, unknown> = {};
if (input.block) body.block = true;
return apiRequest(
'POST',
`/agents/dm/requests/${encodeURIComponent(input.conversationId)}/reject`,
Object.keys(body).length > 0 ? body : undefined
);
},
});
export const moltbookDmGetRequests = tool({
description: 'List all pending DM requests on Moltbook waiting for your approval.',
inputSchema: jsonSchema<Record<string, never>>({
type: 'object',
properties: {},
additionalProperties: false,
}),
execute: async () => {
return apiRequest('GET', '/agents/dm/requests');
},
});
// ─── Moderation ─────────────────────────────────────────────────
export const moltbookPinPost = tool({
description: 'Pin or unpin a post in a submolt you moderate. Maximum 3 pinned posts per submolt.',
inputSchema: jsonSchema<{
postId: string;
action: string;
}>({
type: 'object',
properties: {
postId: {
type: 'string',
description: 'Post ID to pin or unpin',
},
action: {
type: 'string',
enum: ['pin', 'unpin'],
description: 'Whether to pin or unpin the post',
},
},
required: ['postId', 'action'],
additionalProperties: false,
}),
execute: async (input) => {
const method = input.action === 'pin' ? 'POST' : 'DELETE';
return apiRequest(method, `/posts/${encodeURIComponent(input.postId)}/pin`);
},
});
export const moltbookManageModerator = tool({
description: 'Add or remove a moderator from a submolt you own on Moltbook.',
inputSchema: jsonSchema<{
submoltName: string;
agentName: string;
action: string;
}>({
type: 'object',
properties: {
submoltName: {
type: 'string',
description: 'Submolt name',
},
agentName: {
type: 'string',
description: 'Agent name to add or remove as moderator',
},
action: {
type: 'string',
enum: ['add', 'remove'],
description: 'Whether to add or remove the moderator',
},
},
required: ['submoltName', 'agentName', 'action'],
additionalProperties: false,
}),
execute: async (input) => {
if (input.action === 'add') {
return apiRequest('POST', `/submolts/${encodeURIComponent(input.submoltName)}/moderators`, {
agent_name: input.agentName,
role: 'moderator',
});
}
return apiRequest('DELETE', `/submolts/${encodeURIComponent(input.submoltName)}/moderators`, {
agent_name: input.agentName,
});
},
});
// ─── Default Export ─────────────────────────────────────────────
export default {
// Registration & Auth
moltbookRegister,
moltbookCheckStatus,
// Profile
moltbookGetProfile,
moltbookUpdateProfile,
// Posts
moltbookCreatePost,
moltbookGetPost,
moltbookGetFeed,
moltbookDeletePost,
// Comments
moltbookCreateComment,
moltbookGetComments,
// Voting
moltbookVote,
// Submolts
moltbookCreateSubmolt,
moltbookListSubmolts,
moltbookGetSubmolt,
moltbookSubscribe,
// Social
moltbookFollow,
moltbookSearch,
// Direct Messages
moltbookDmCheck,
moltbookDmRequest,
moltbookDmGetConversations,
moltbookDmReply,
moltbookDmManageRequest,
moltbookDmGetRequests,
// Moderation
moltbookPinPost,
moltbookManageModerator,
};

View file

@ -0,0 +1,11 @@
{
"extends": "@tpmjs/tsconfig/base.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
"incremental": false,
"composite": false
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}

View file

@ -0,0 +1,10 @@
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
dts: true,
clean: true,
treeshake: true,
splitting: false,
});